forked from ScoDoc/ScoDoc
Accepte codage boursiers O/N (USPN), fonction de resynchro globale, table de tous les étudiants courants avec état boursier.
This commit is contained in:
parent
60109bb513
commit
568c8681ba
@ -7,7 +7,7 @@
|
||||
"""
|
||||
ScoDoc 9 API : accès aux départements
|
||||
|
||||
Note: les routes /departement[s] sont publiées sur l'API (/ScoDoc/api/),
|
||||
Note: les routes /departement[s] sont publiées sur l'API (/ScoDoc/api/),
|
||||
mais évidemment pas sur l'API web (/ScoDoc/<dept>/api).
|
||||
"""
|
||||
from datetime import datetime
|
||||
@ -271,23 +271,11 @@ def dept_formsemestres_courants(acronym: str):
|
||||
"""
|
||||
dept = Departement.query.filter_by(acronym=acronym).first_or_404()
|
||||
date_courante = request.args.get("date_courante")
|
||||
if date_courante:
|
||||
test_date = datetime.fromisoformat(date_courante)
|
||||
else:
|
||||
test_date = app.db.func.now()
|
||||
# Les semestres en cours de ce département
|
||||
formsemestres = FormSemestre.query.filter(
|
||||
FormSemestre.dept_id == dept.id,
|
||||
FormSemestre.date_debut <= test_date,
|
||||
FormSemestre.date_fin >= test_date,
|
||||
)
|
||||
date_courante = datetime.fromisoformat(date_courante) if date_courante else None
|
||||
return [
|
||||
d.to_dict_api()
|
||||
for d in formsemestres.order_by(
|
||||
FormSemestre.date_debut.desc(),
|
||||
FormSemestre.modalite,
|
||||
FormSemestre.semestre_id,
|
||||
FormSemestre.titre,
|
||||
formsemestre.to_dict_api()
|
||||
for formsemestre in FormSemestre.get_dept_formsemestres_courants(
|
||||
dept, date_courante
|
||||
)
|
||||
]
|
||||
|
||||
|
@ -30,6 +30,7 @@ from app.models.but_refcomp import (
|
||||
parcours_formsemestre,
|
||||
)
|
||||
from app.models.config import ScoDocSiteConfig
|
||||
from app.models.departements import Departement
|
||||
from app.models.etudiants import Identite
|
||||
from app.models.evaluations import Evaluation
|
||||
from app.models.formations import Formation
|
||||
@ -521,7 +522,7 @@ class FormSemestre(db.Model):
|
||||
mois_pivot_periode=scu.MONTH_DEBUT_PERIODE2,
|
||||
jour_pivot_annee=1,
|
||||
jour_pivot_periode=1,
|
||||
):
|
||||
) -> tuple[int, int]:
|
||||
"""Calcule la session associée à un formsemestre commençant en date_debut
|
||||
sous la forme (année, période)
|
||||
année: première année de l'année scolaire
|
||||
@ -571,6 +572,26 @@ class FormSemestre(db.Model):
|
||||
mois_pivot_periode=ScoDocSiteConfig.get_month_debut_periode2(),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_dept_formsemestres_courants(
|
||||
cls, dept: Departement, date_courante: datetime.datetime | None = None
|
||||
) -> db.Query:
|
||||
"""Liste (query) ordonnée des formsemestres courants, c'est
|
||||
à dire contenant la date courant (si None, la date actuelle)"""
|
||||
date_courante = date_courante or db.func.now()
|
||||
# Les semestres en cours de ce département
|
||||
formsemestres = FormSemestre.query.filter(
|
||||
FormSemestre.dept_id == dept.id,
|
||||
FormSemestre.date_debut <= date_courante,
|
||||
FormSemestre.date_fin >= date_courante,
|
||||
)
|
||||
return formsemestres.order_by(
|
||||
FormSemestre.date_debut.desc(),
|
||||
FormSemestre.modalite,
|
||||
FormSemestre.semestre_id,
|
||||
FormSemestre.titre,
|
||||
)
|
||||
|
||||
def etapes_apo_vdi(self) -> list[ApoEtapeVDI]:
|
||||
"Liste des vdis"
|
||||
# was read_formsemestre_etapes
|
||||
|
@ -149,21 +149,49 @@ def index_html(showcodes=0, showsemtable=0):
|
||||
</p>"""
|
||||
)
|
||||
#
|
||||
if current_user.has_permission(Permission.EtudInscrit):
|
||||
H.append(
|
||||
"""<hr>
|
||||
H.append(
|
||||
"""<hr>
|
||||
<h3>Gestion des étudiants</h3>
|
||||
<ul>
|
||||
<li><a class="stdlink" href="etudident_create_form">créer <em>un</em> nouvel étudiant</a>
|
||||
"""
|
||||
)
|
||||
if current_user.has_permission(Permission.EtudInscrit):
|
||||
H.append(
|
||||
f"""
|
||||
<li><a class="stdlink" href="{
|
||||
url_for("scolar.etudident_create_form", scodoc_dept=g.scodoc_dept)
|
||||
}">créer <em>un</em> nouvel étudiant</a>
|
||||
</li>
|
||||
<li><a class="stdlink" href="form_students_import_excel">importer de nouveaux étudiants</a>
|
||||
(ne pas utiliser sauf cas particulier, utilisez plutôt le lien dans
|
||||
<li><a class="stdlink" href="{
|
||||
url_for("scolar.form_students_import_excel", scodoc_dept=g.scodoc_dept)
|
||||
}">importer de nouveaux étudiants</a>
|
||||
(<em>ne pas utiliser</em> sauf cas particulier : utilisez plutôt le lien dans
|
||||
le tableau de bord semestre si vous souhaitez inscrire les
|
||||
étudiants importés à un semestre)
|
||||
</li>
|
||||
</ul>
|
||||
"""
|
||||
)
|
||||
H.append(
|
||||
f"""
|
||||
<li><a class="stdlink" href="{
|
||||
url_for("scolar.export_etudiants_courants", scodoc_dept=g.scodoc_dept)
|
||||
}">exporter tableau des étudiants des semestres en cours</a>
|
||||
</li>
|
||||
"""
|
||||
)
|
||||
if current_user.has_permission(
|
||||
Permission.EtudInscrit
|
||||
) and sco_preferences.get_preference("portal_url"):
|
||||
H.append(
|
||||
f"""
|
||||
<li><a class="stdlink" href="{
|
||||
url_for("scolar.formsemestre_import_etud_admission",
|
||||
scodoc_dept=g.scodoc_dept, tous_courants=1)
|
||||
}">resynchroniser les données étudiants des semestres en cours depuis le portail</a>
|
||||
</li>
|
||||
"""
|
||||
)
|
||||
H.append("</ul>")
|
||||
#
|
||||
if current_user.has_permission(Permission.EditApogee):
|
||||
H.append(
|
||||
|
@ -793,21 +793,25 @@ def update_etape_formsemestre_inscription(ins, etud):
|
||||
|
||||
|
||||
def formsemestre_import_etud_admission(
|
||||
formsemestre_id, import_identite=True, import_email=False
|
||||
):
|
||||
formsemestre_id: int, import_identite=True, import_email=False
|
||||
) -> tuple[list[Identite], list[Identite], list[tuple[Identite, str]]]:
|
||||
"""Tente d'importer les données admission depuis le portail
|
||||
pour tous les étudiants du semestre.
|
||||
Si import_identite==True, recopie l'identité (nom/prenom/sexe/date_naissance)
|
||||
de chaque étudiant depuis le portail.
|
||||
N'affecte pas les etudiants inconnus sur le portail.
|
||||
Renvoie:
|
||||
- etuds_no_nip: liste d'étudiants sans code NIP
|
||||
- etuds_unknown: etudiants avec NIP mais inconnus du portail
|
||||
- changed_mails: (etudiant, old_mail) pour ceux dont le mail a changé
|
||||
"""
|
||||
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
||||
ins = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(
|
||||
{"formsemestre_id": formsemestre_id}
|
||||
)
|
||||
log(f"formsemestre_import_etud_admission: {formsemestre_id} ({len(ins)} etuds)")
|
||||
no_nip = [] # liste d'etudids sans code NIP
|
||||
unknowns = [] # etudiants avec NIP mais inconnus du portail
|
||||
etuds_no_nip: list[Identite] = []
|
||||
etuds_unknown: list[Identite] = []
|
||||
changed_mails: list[tuple[Identite, str]] = [] # modification d'adresse mails
|
||||
|
||||
# Essaie de recuperer les etudiants des étapes, car
|
||||
@ -828,7 +832,7 @@ def formsemestre_import_etud_admission(
|
||||
etud: Identite = Identite.query.get_or_404(etudid)
|
||||
code_nip = etud.code_nip
|
||||
if not code_nip:
|
||||
no_nip.append(etudid)
|
||||
etuds_no_nip.append(etud)
|
||||
else:
|
||||
data_apo = apo_etuds.get(code_nip)
|
||||
if not data_apo:
|
||||
@ -865,7 +869,7 @@ def formsemestre_import_etud_admission(
|
||||
if adresse.email != data_apo["mail"]:
|
||||
changed_mails.append((etud, old_mail))
|
||||
else:
|
||||
unknowns.append(code_nip)
|
||||
etuds_unknown.append(etud)
|
||||
db.session.commit()
|
||||
sco_cache.invalidate_formsemestre(formsemestre_id=sem["formsemestre_id"])
|
||||
return no_nip, unknowns, changed_mails
|
||||
return etuds_no_nip, etuds_unknown, changed_mails
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* DataTables style for ScoDoc gen_tables
|
||||
* generated using https://datatables.net/manual/styling/theme-creator
|
||||
* and customized by hand
|
||||
@ -138,111 +138,111 @@ table.dataTable.display tbody tr:hover.selected {
|
||||
background-color: #a9b7d1;
|
||||
}
|
||||
|
||||
table.dataTable.order-column tbody tr>.sorting_1,
|
||||
table.dataTable.order-column tbody tr>.sorting_2,
|
||||
table.dataTable.order-column tbody tr>.sorting_3,
|
||||
table.dataTable.display tbody tr>.sorting_1,
|
||||
table.dataTable.display tbody tr>.sorting_2,
|
||||
table.dataTable.display tbody tr>.sorting_3 {
|
||||
table.dataTable.order-column tbody tr > .sorting_1,
|
||||
table.dataTable.order-column tbody tr > .sorting_2,
|
||||
table.dataTable.order-column tbody tr > .sorting_3,
|
||||
table.dataTable.display tbody tr > .sorting_1,
|
||||
table.dataTable.display tbody tr > .sorting_2,
|
||||
table.dataTable.display tbody tr > .sorting_3 {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
table.dataTable.order-column tbody tr.selected>.sorting_1,
|
||||
table.dataTable.order-column tbody tr.selected>.sorting_2,
|
||||
table.dataTable.order-column tbody tr.selected>.sorting_3,
|
||||
table.dataTable.display tbody tr.selected>.sorting_1,
|
||||
table.dataTable.display tbody tr.selected>.sorting_2,
|
||||
table.dataTable.display tbody tr.selected>.sorting_3 {
|
||||
table.dataTable.order-column tbody tr.selected > .sorting_1,
|
||||
table.dataTable.order-column tbody tr.selected > .sorting_2,
|
||||
table.dataTable.order-column tbody tr.selected > .sorting_3,
|
||||
table.dataTable.display tbody tr.selected > .sorting_1,
|
||||
table.dataTable.display tbody tr.selected > .sorting_2,
|
||||
table.dataTable.display tbody tr.selected > .sorting_3 {
|
||||
background-color: #acbad4;
|
||||
}
|
||||
|
||||
table.dataTable.display tbody tr.odd>.sorting_1,
|
||||
table.dataTable.order-column.stripe tbody tr.odd>.sorting_1 {
|
||||
table.dataTable.display tbody tr.odd > .sorting_1,
|
||||
table.dataTable.order-column.stripe tbody tr.odd > .sorting_1 {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
table.dataTable.display tbody tr.odd>.sorting_2,
|
||||
table.dataTable.order-column.stripe tbody tr.odd>.sorting_2 {
|
||||
table.dataTable.display tbody tr.odd > .sorting_2,
|
||||
table.dataTable.order-column.stripe tbody tr.odd > .sorting_2 {
|
||||
background-color: #f3f3f3;
|
||||
}
|
||||
|
||||
table.dataTable.display tbody tr.odd>.sorting_3,
|
||||
table.dataTable.order-column.stripe tbody tr.odd>.sorting_3 {
|
||||
table.dataTable.display tbody tr.odd > .sorting_3,
|
||||
table.dataTable.order-column.stripe tbody tr.odd > .sorting_3 {
|
||||
background-color: whitesmoke;
|
||||
}
|
||||
|
||||
table.dataTable.display tbody tr.odd.selected>.sorting_1,
|
||||
table.dataTable.order-column.stripe tbody tr.odd.selected>.sorting_1 {
|
||||
table.dataTable.display tbody tr.odd.selected > .sorting_1,
|
||||
table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_1 {
|
||||
background-color: #a6b3cd;
|
||||
}
|
||||
|
||||
table.dataTable.display tbody tr.odd.selected>.sorting_2,
|
||||
table.dataTable.order-column.stripe tbody tr.odd.selected>.sorting_2 {
|
||||
table.dataTable.display tbody tr.odd.selected > .sorting_2,
|
||||
table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_2 {
|
||||
background-color: #a7b5ce;
|
||||
}
|
||||
|
||||
table.dataTable.display tbody tr.odd.selected>.sorting_3,
|
||||
table.dataTable.order-column.stripe tbody tr.odd.selected>.sorting_3 {
|
||||
table.dataTable.display tbody tr.odd.selected > .sorting_3,
|
||||
table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_3 {
|
||||
background-color: #a9b6d0;
|
||||
}
|
||||
|
||||
table.dataTable.display tbody tr.even>.sorting_1,
|
||||
table.dataTable.order-column.stripe tbody tr.even>.sorting_1 {
|
||||
table.dataTable.display tbody tr.even > .sorting_1,
|
||||
table.dataTable.order-column.stripe tbody tr.even > .sorting_1 {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
table.dataTable.display tbody tr.even>.sorting_2,
|
||||
table.dataTable.order-column.stripe tbody tr.even>.sorting_2 {
|
||||
table.dataTable.display tbody tr.even > .sorting_2,
|
||||
table.dataTable.order-column.stripe tbody tr.even > .sorting_2 {
|
||||
background-color: #fbfbfb;
|
||||
}
|
||||
|
||||
table.dataTable.display tbody tr.even>.sorting_3,
|
||||
table.dataTable.order-column.stripe tbody tr.even>.sorting_3 {
|
||||
table.dataTable.display tbody tr.even > .sorting_3,
|
||||
table.dataTable.order-column.stripe tbody tr.even > .sorting_3 {
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
|
||||
table.dataTable.display tbody tr.even.selected>.sorting_1,
|
||||
table.dataTable.order-column.stripe tbody tr.even.selected>.sorting_1 {
|
||||
table.dataTable.display tbody tr.even.selected > .sorting_1,
|
||||
table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_1 {
|
||||
background-color: #acbad4;
|
||||
}
|
||||
|
||||
table.dataTable.display tbody tr.even.selected>.sorting_2,
|
||||
table.dataTable.order-column.stripe tbody tr.even.selected>.sorting_2 {
|
||||
table.dataTable.display tbody tr.even.selected > .sorting_2,
|
||||
table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_2 {
|
||||
background-color: #adbbd6;
|
||||
}
|
||||
|
||||
table.dataTable.display tbody tr.even.selected>.sorting_3,
|
||||
table.dataTable.order-column.stripe tbody tr.even.selected>.sorting_3 {
|
||||
table.dataTable.display tbody tr.even.selected > .sorting_3,
|
||||
table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_3 {
|
||||
background-color: #afbdd8;
|
||||
}
|
||||
|
||||
table.dataTable.display tbody tr:hover>.sorting_1,
|
||||
table.dataTable.order-column.hover tbody tr:hover>.sorting_1 {
|
||||
table.dataTable.display tbody tr:hover > .sorting_1,
|
||||
table.dataTable.order-column.hover tbody tr:hover > .sorting_1 {
|
||||
background-color: #eaeaea;
|
||||
}
|
||||
|
||||
table.dataTable.display tbody tr:hover>.sorting_2,
|
||||
table.dataTable.order-column.hover tbody tr:hover>.sorting_2 {
|
||||
table.dataTable.display tbody tr:hover > .sorting_2,
|
||||
table.dataTable.order-column.hover tbody tr:hover > .sorting_2 {
|
||||
background-color: #ebebeb;
|
||||
}
|
||||
|
||||
table.dataTable.display tbody tr:hover>.sorting_3,
|
||||
table.dataTable.order-column.hover tbody tr:hover>.sorting_3 {
|
||||
table.dataTable.display tbody tr:hover > .sorting_3,
|
||||
table.dataTable.order-column.hover tbody tr:hover > .sorting_3 {
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
|
||||
table.dataTable.display tbody tr:hover.selected>.sorting_1,
|
||||
table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_1 {
|
||||
table.dataTable.display tbody tr:hover.selected > .sorting_1,
|
||||
table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_1 {
|
||||
background-color: #a1aec7;
|
||||
}
|
||||
|
||||
table.dataTable.display tbody tr:hover.selected>.sorting_2,
|
||||
table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_2 {
|
||||
table.dataTable.display tbody tr:hover.selected > .sorting_2,
|
||||
table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_2 {
|
||||
background-color: #a2afc8;
|
||||
}
|
||||
|
||||
table.dataTable.display tbody tr:hover.selected>.sorting_3,
|
||||
table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_3 {
|
||||
table.dataTable.display tbody tr:hover.selected > .sorting_3,
|
||||
table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_3 {
|
||||
background-color: #a4b2cb;
|
||||
}
|
||||
|
||||
@ -419,7 +419,13 @@ table.dataTable td {
|
||||
color: #333333 !important;
|
||||
border: 1px solid #979797;
|
||||
background-color: white;
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, white), color-stop(100%, gainsboro));
|
||||
background: -webkit-gradient(
|
||||
linear,
|
||||
left top,
|
||||
left bottom,
|
||||
color-stop(0%, white),
|
||||
color-stop(100%, gainsboro)
|
||||
);
|
||||
/* Chrome,Safari4+ */
|
||||
background: -webkit-linear-gradient(top, white 0%, gainsboro 100%);
|
||||
/* Chrome10+,Safari5.1+ */
|
||||
@ -447,7 +453,13 @@ table.dataTable td {
|
||||
color: white !important;
|
||||
border: 1px solid #111111;
|
||||
background-color: #585858;
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111111));
|
||||
background: -webkit-gradient(
|
||||
linear,
|
||||
left top,
|
||||
left bottom,
|
||||
color-stop(0%, #585858),
|
||||
color-stop(100%, #111111)
|
||||
);
|
||||
/* Chrome,Safari4+ */
|
||||
background: -webkit-linear-gradient(top, #585858 0%, #111111 100%);
|
||||
/* Chrome10+,Safari5.1+ */
|
||||
@ -464,7 +476,13 @@ table.dataTable td {
|
||||
.dataTables_wrapper .dataTables_paginate .paginate_button:active {
|
||||
outline: none;
|
||||
background-color: #2b2b2b;
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #2b2b2b), color-stop(100%, #0c0c0c));
|
||||
background: -webkit-gradient(
|
||||
linear,
|
||||
left top,
|
||||
left bottom,
|
||||
color-stop(0%, #2b2b2b),
|
||||
color-stop(100%, #0c0c0c)
|
||||
);
|
||||
/* Chrome,Safari4+ */
|
||||
background: -webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
|
||||
/* Chrome10+,Safari5.1+ */
|
||||
@ -495,12 +513,50 @@ table.dataTable td {
|
||||
text-align: center;
|
||||
font-size: 1.2em;
|
||||
background-color: white;
|
||||
background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(25%, rgba(255, 255, 255, 0.9)), color-stop(75%, rgba(255, 255, 255, 0.9)), color-stop(100%, rgba(255, 255, 255, 0)));
|
||||
background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
|
||||
background: -moz-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
|
||||
background: -ms-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
|
||||
background: -o-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
|
||||
background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
|
||||
background: -webkit-gradient(
|
||||
linear,
|
||||
left top,
|
||||
right top,
|
||||
color-stop(0%, rgba(255, 255, 255, 0)),
|
||||
color-stop(25%, rgba(255, 255, 255, 0.9)),
|
||||
color-stop(75%, rgba(255, 255, 255, 0.9)),
|
||||
color-stop(100%, rgba(255, 255, 255, 0))
|
||||
);
|
||||
background: -webkit-linear-gradient(
|
||||
left,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0.9) 25%,
|
||||
rgba(255, 255, 255, 0.9) 75%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
background: -moz-linear-gradient(
|
||||
left,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0.9) 25%,
|
||||
rgba(255, 255, 255, 0.9) 75%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
background: -ms-linear-gradient(
|
||||
left,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0.9) 25%,
|
||||
rgba(255, 255, 255, 0.9) 75%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
background: -o-linear-gradient(
|
||||
left,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0.9) 25%,
|
||||
rgba(255, 255, 255, 0.9) 75%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0.9) 25%,
|
||||
rgba(255, 255, 255, 0.9) 75%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.dataTables_wrapper .dataTables_length,
|
||||
@ -520,17 +576,69 @@ table.dataTable td {
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th,
|
||||
.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td,
|
||||
.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th,
|
||||
.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td {
|
||||
.dataTables_wrapper
|
||||
.dataTables_scroll
|
||||
div.dataTables_scrollBody
|
||||
> table
|
||||
> thead
|
||||
> tr
|
||||
> th,
|
||||
.dataTables_wrapper
|
||||
.dataTables_scroll
|
||||
div.dataTables_scrollBody
|
||||
> table
|
||||
> thead
|
||||
> tr
|
||||
> td,
|
||||
.dataTables_wrapper
|
||||
.dataTables_scroll
|
||||
div.dataTables_scrollBody
|
||||
> table
|
||||
> tbody
|
||||
> tr
|
||||
> th,
|
||||
.dataTables_wrapper
|
||||
.dataTables_scroll
|
||||
div.dataTables_scrollBody
|
||||
> table
|
||||
> tbody
|
||||
> tr
|
||||
> td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th>div.dataTables_sizing,
|
||||
.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td>div.dataTables_sizing,
|
||||
.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th>div.dataTables_sizing,
|
||||
.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td>div.dataTables_sizing {
|
||||
.dataTables_wrapper
|
||||
.dataTables_scroll
|
||||
div.dataTables_scrollBody
|
||||
> table
|
||||
> thead
|
||||
> tr
|
||||
> th
|
||||
> div.dataTables_sizing,
|
||||
.dataTables_wrapper
|
||||
.dataTables_scroll
|
||||
div.dataTables_scrollBody
|
||||
> table
|
||||
> thead
|
||||
> tr
|
||||
> td
|
||||
> div.dataTables_sizing,
|
||||
.dataTables_wrapper
|
||||
.dataTables_scroll
|
||||
div.dataTables_scrollBody
|
||||
> table
|
||||
> tbody
|
||||
> tr
|
||||
> th
|
||||
> div.dataTables_sizing,
|
||||
.dataTables_wrapper
|
||||
.dataTables_scroll
|
||||
div.dataTables_scrollBody
|
||||
> table
|
||||
> tbody
|
||||
> tr
|
||||
> td
|
||||
> div.dataTables_sizing {
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
margin: 0 !important;
|
||||
@ -541,8 +649,8 @@ table.dataTable td {
|
||||
border-bottom: 1px solid #111111;
|
||||
}
|
||||
|
||||
.dataTables_wrapper.no-footer div.dataTables_scrollHead>table,
|
||||
.dataTables_wrapper.no-footer div.dataTables_scrollBody>table {
|
||||
.dataTables_wrapper.no-footer div.dataTables_scrollHead > table,
|
||||
.dataTables_wrapper.no-footer div.dataTables_scrollBody > table {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
@ -555,7 +663,6 @@ table.dataTable td {
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
|
||||
.dataTables_wrapper .dataTables_info,
|
||||
.dataTables_wrapper .dataTables_paginate {
|
||||
float: none;
|
||||
@ -568,7 +675,6 @@ table.dataTable td {
|
||||
}
|
||||
|
||||
@media screen and (max-width: 640px) {
|
||||
|
||||
.dataTables_wrapper .dataTables_length,
|
||||
.dataTables_wrapper .dataTables_filter {
|
||||
float: none;
|
||||
@ -580,8 +686,7 @@ table.dataTable td {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------ Ajouts spécifiques pour ScoDoc:
|
||||
/* ------ Ajouts spécifiques pour ScoDoc:
|
||||
*/
|
||||
|
||||
table.gt_table td {
|
||||
@ -624,7 +729,6 @@ table.dataTable.stripe.hover tbody tr.odd:hover td,
|
||||
table.dataTable.stripe.hover tbody tr.odd:hover td.sorting_1,
|
||||
table.dataTable.order-column.stripe.hover tbody tr.odd:hover td.sorting_1 {
|
||||
background-color: rgb(80%, 85%, 80%);
|
||||
;
|
||||
}
|
||||
|
||||
/* Lignes paires */
|
||||
@ -638,7 +742,6 @@ table.dataTable.stripe.hover tbody tr.even:hover td,
|
||||
table.dataTable.stripe.hover tbody tr.even:hover td.sorting_1,
|
||||
table.dataTable.order-column.stripe.hover tbody tr.even:hover td.sorting_1 {
|
||||
background-color: rgb(85%, 85%, 85%);
|
||||
;
|
||||
}
|
||||
|
||||
/* Reglage largeur de la table */
|
||||
@ -652,4 +755,9 @@ table.dataTable.gt_table {
|
||||
/* Tables non centrées (inutile) */
|
||||
table.dataTable.gt_table.gt_left {
|
||||
margin-left: 16px;
|
||||
}
|
||||
}
|
||||
table.dataTable.gt_table.gt_left td,
|
||||
table.dataTable.gt_table.gt_left th {
|
||||
text-align: left;
|
||||
}
|
||||
scodoc;css
|
||||
|
@ -1133,7 +1133,8 @@ a.redlink:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a.discretelink {
|
||||
a.discretelink,
|
||||
a:discretelink:visited {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
}
|
||||
@ -1567,6 +1568,7 @@ h2.formsemestre,
|
||||
#gtrcontent h2 {
|
||||
margin-top: 2px;
|
||||
font-size: 130%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.formsemestre_page_title table.semtitle,
|
||||
|
@ -7,8 +7,7 @@
|
||||
"""Liste simple d'étudiants
|
||||
"""
|
||||
|
||||
from flask import g, url_for
|
||||
from app.models import Identite
|
||||
from app.models import FormSemestre, FormSemestreInscription, Identite
|
||||
from app.tables import table_builder as tb
|
||||
|
||||
|
||||
@ -26,6 +25,7 @@ class TableEtud(tb.Table):
|
||||
with_foot_titles=False,
|
||||
**kwargs,
|
||||
):
|
||||
etuds = etuds or []
|
||||
self.rows: list["RowEtud"] = [] # juste pour que VSCode nous aide sur .rows
|
||||
classes = classes or ["gt_table", "gt_left"]
|
||||
super().__init__(
|
||||
@ -46,10 +46,12 @@ class TableEtud(tb.Table):
|
||||
|
||||
class RowEtud(tb.Row):
|
||||
"Ligne de la table d'étudiants"
|
||||
|
||||
# pour le moment très simple, extensible (codes, liens bulletins, ...)
|
||||
def __init__(self, table: TableEtud, etud: Identite, *args, **kwargs):
|
||||
super().__init__(table, etud.id, *args, **kwargs)
|
||||
self.etud = etud
|
||||
self.target_url = etud.url_fiche()
|
||||
|
||||
def add_etud_cols(self):
|
||||
"""Ajoute colonnes étudiant: codes, noms"""
|
||||
@ -85,7 +87,7 @@ class RowEtud(tb.Row):
|
||||
etud.nom_disp(),
|
||||
"identite_detail",
|
||||
data={"order": etud.sort_key},
|
||||
target=url_bulletin,
|
||||
target=self.target_url,
|
||||
target_attrs={"class": "etudinfo discretelink", "id": str(etud.id)},
|
||||
)
|
||||
self.add_cell("prenom", "Prénom", etud.prenom, "identite_detail")
|
||||
@ -115,3 +117,70 @@ def html_table_etuds(etudids) -> str:
|
||||
etuds = etuds_sorted_from_ids(etudids)
|
||||
table = TableEtud(etuds)
|
||||
return table.html()
|
||||
|
||||
|
||||
class RowEtudWithInfos(RowEtud):
|
||||
"""Ligne de la table d'étudiants avec plus d'informations:
|
||||
département, formsemestre, codes, boursier
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
table: TableEtud,
|
||||
etud: Identite,
|
||||
formsemestre: FormSemestre,
|
||||
inscription: FormSemestreInscription,
|
||||
*args,
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(table, etud, *args, **kwargs)
|
||||
self.formsemestre = formsemestre
|
||||
self.inscription = inscription
|
||||
|
||||
def add_etud_cols(self):
|
||||
"""Ajoute colonnes étudiant: codes, noms"""
|
||||
self.add_cell("dept", "Dépt.", self.etud.departement.acronym, "identite_detail")
|
||||
self.add_cell(
|
||||
"formsemestre",
|
||||
"Semestre",
|
||||
f"""{self.formsemestre.titre_formation()} {
|
||||
('S'+str(self.formsemestre.semestre_id))
|
||||
if self.formsemestre.semestre_id > 0 else ''}
|
||||
""",
|
||||
"identite_detail",
|
||||
)
|
||||
super().add_etud_cols()
|
||||
self.add_cell(
|
||||
"etat",
|
||||
"État",
|
||||
self.inscription.etat,
|
||||
"inscription",
|
||||
)
|
||||
self.add_cell(
|
||||
"boursier",
|
||||
"Boursier",
|
||||
"O" if self.etud.boursier else "N",
|
||||
"identite_infos",
|
||||
)
|
||||
|
||||
|
||||
class TableEtudWithInfos(TableEtud):
|
||||
"""Table d'étudiants avec formsemestre et inscription"""
|
||||
|
||||
def add_formsemestre(self, formsemestre: FormSemestre):
|
||||
"Ajoute les étudiants de ce semestre à la table"
|
||||
etuds = formsemestre.get_inscrits(order=True, include_demdef=True)
|
||||
for etud in etuds:
|
||||
row = self.row_class(
|
||||
self, etud, formsemestre, formsemestre.etuds_inscriptions.get(etud.id)
|
||||
)
|
||||
row.add_etud_cols()
|
||||
self.add_row(row)
|
||||
|
||||
|
||||
def table_etudiants_courants(formsemestres: list[FormSemestre]) -> TableEtud:
|
||||
"""Table des étudiants des formsemestres indiqués"""
|
||||
table = TableEtudWithInfos(row_class=RowEtudWithInfos)
|
||||
for formsemestre in formsemestres:
|
||||
table.add_formsemestre(formsemestre)
|
||||
return table
|
||||
|
@ -105,6 +105,7 @@ from app.scodoc import sco_synchro_etuds
|
||||
from app.scodoc import sco_trombino
|
||||
from app.scodoc import sco_trombino_tours
|
||||
from app.scodoc import sco_up_to_date
|
||||
from app.tables import list_etuds
|
||||
|
||||
|
||||
def sco_publish(route, function, permission, methods=["GET"]):
|
||||
@ -2071,6 +2072,21 @@ def check_group_apogee(group_id, etat=None, fix=False, fixmail=False):
|
||||
return "\n".join(H) + html_sco_header.sco_footer()
|
||||
|
||||
|
||||
@bp.route("/export_etudiants_courants")
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoView)
|
||||
def export_etudiants_courants():
|
||||
"""Table export de tous les étudiants des formsemestres en cours."""
|
||||
departement = Departement.query.get(g.scodoc_dept_id)
|
||||
if not departement:
|
||||
raise ScoValueError("département invalide")
|
||||
formsemestres = FormSemestre.get_dept_formsemestres_courants(departement)
|
||||
table = list_etuds.table_etudiants_courants(formsemestres)
|
||||
return render_template(
|
||||
"scolar/export_etudiants_courants.j2", sco=ScoData(), table=table
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/form_students_import_excel", methods=["GET", "POST"])
|
||||
@scodoc
|
||||
@permission_required(Permission.EtudInscrit)
|
||||
@ -2361,35 +2377,57 @@ def form_students_import_infos_admissions(formsemestre_id=None):
|
||||
@scodoc
|
||||
@permission_required(Permission.EtudChangeAdr)
|
||||
@scodoc7func
|
||||
def formsemestre_import_etud_admission(formsemestre_id, import_email=True):
|
||||
"""Ré-importe donnees admissions par synchro Portail Apogée"""
|
||||
(
|
||||
no_nip,
|
||||
unknowns,
|
||||
changed_mails,
|
||||
) = sco_synchro_etuds.formsemestre_import_etud_admission(
|
||||
formsemestre_id, import_identite=True, import_email=import_email
|
||||
)
|
||||
H = [
|
||||
html_sco_header.html_sem_header("Ré-import données admission"),
|
||||
"<h3>Opération effectuée</h3>",
|
||||
]
|
||||
if no_nip:
|
||||
H.append("<p>Attention: étudiants sans NIP: " + str(no_nip) + "</p>")
|
||||
if unknowns:
|
||||
H.append(
|
||||
"<p>Attention: étudiants inconnus du portail: codes NIP="
|
||||
+ str(unknowns)
|
||||
+ "</p>"
|
||||
def formsemestre_import_etud_admission(
|
||||
formsemestre_id=None, import_email=True, tous_courants=False
|
||||
):
|
||||
"""Ré-importe donnees admissions par synchro Portail Apogée.
|
||||
Si tous_courants, le fait pour tous les formsemestres courants du département
|
||||
"""
|
||||
if tous_courants:
|
||||
departement = Departement.query.get(g.scodoc_dept_id)
|
||||
formsemestres = FormSemestre.get_dept_formsemestres_courants(departement)
|
||||
else:
|
||||
formsemestres = [FormSemestre.get_formsemestre(formsemestre_id)]
|
||||
|
||||
diag_by_sem = {}
|
||||
for formsemestre in formsemestres:
|
||||
(
|
||||
etuds_no_nip,
|
||||
etuds_unknown,
|
||||
changed_mails,
|
||||
) = sco_synchro_etuds.formsemestre_import_etud_admission(
|
||||
formsemestre.id, import_identite=True, import_email=import_email
|
||||
)
|
||||
if changed_mails:
|
||||
H.append("<h3>Adresses mails modifiées:</h3><ul>")
|
||||
for etud, old_mail in changed_mails:
|
||||
H.append(
|
||||
f"""<li>{etud.nom}: <tt>{old_mail}</tt> devient <tt>{etud.email}</tt></li>"""
|
||||
)
|
||||
H.append("</ul>")
|
||||
return "\n".join(H) + html_sco_header.sco_footer()
|
||||
diag = ""
|
||||
if etuds_no_nip:
|
||||
diag += f"""<p>Attention: étudiants sans NIP:
|
||||
{', '.join([e.html_link_fiche() for e in etuds_no_nip])}
|
||||
</p>"""
|
||||
|
||||
if etuds_unknown:
|
||||
diag += f"""<p>Attention: étudiants inconnus du portail:
|
||||
{', '.join([(e.html_link_fiche() + ' (nip= ' + e.code_nip + ')')
|
||||
for e in etuds_unknown])}
|
||||
</p>"""
|
||||
|
||||
if changed_mails:
|
||||
diag += """<p>Adresses mails modifiées:</p><ul>"""
|
||||
for etud, old_mail in changed_mails:
|
||||
diag += f"""<li>{etud.nom}: <tt>{old_mail}</tt> devient <tt>{etud.email}</tt></li>"""
|
||||
diag += "</ul>"
|
||||
diag_by_sem[formsemestre.id] = diag
|
||||
|
||||
return f"""
|
||||
{ html_sco_header.html_sem_header("Ré-import données admission") }
|
||||
<h3>Opération effectuée</h3>
|
||||
<p>Sur le(s) semestres(s):</p>
|
||||
<ul>
|
||||
<li>
|
||||
{ '</li><li>'.join( [(s.html_link_status() + diag_by_sem[s.id]) for s in formsemestres ]) }
|
||||
</li>
|
||||
</ul>
|
||||
{ html_sco_header.sco_footer() }
|
||||
"""
|
||||
|
||||
|
||||
sco_publish(
|
||||
|
Loading…
Reference in New Issue
Block a user