From 612b62227cac763b9898e2b4a758ff19c564042a Mon Sep 17 00:00:00 2001 From: viennet Date: Sat, 12 Dec 2020 17:22:54 +0100 Subject: [PATCH] API: export JSOn des bulletins des semestres d'une annee scolaire. --- ZNotes.py | 3 +++ sco_formsemestre.py | 36 +++++++++++++--------------- sco_permissions.py | 3 ++- sco_recapcomplet.py | 58 +++++++++++++++++++++++++++++++++++++++------ 4 files changed, 73 insertions(+), 27 deletions(-) diff --git a/ZNotes.py b/ZNotes.py index f88a9042e..d2dd87a2f 100644 --- a/ZNotes.py +++ b/ZNotes.py @@ -249,6 +249,9 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl security.declareProtected(ScoView, "formsemestre_recapcomplet") formsemestre_recapcomplet = sco_recapcomplet.formsemestre_recapcomplet + security.declareProtected(ScoObservateur, "formsemestres_bulletins") + formsemestres_bulletins = sco_recapcomplet.formsemestres_bulletins + security.declareProtected(ScoView, "moduleimpl_status") moduleimpl_status = sco_moduleimpl_status.moduleimpl_status diff --git a/sco_formsemestre.py b/sco_formsemestre.py index 140530f81..e7ad4a18c 100644 --- a/sco_formsemestre.py +++ b/sco_formsemestre.py @@ -124,8 +124,7 @@ def do_formsemestre_list(context, *a, **kw): def formsemestre_enrich(context, sem): - """Ajoute champs souvent utiles: titre + annee et dateord (pour tris) - """ + """Ajoute champs souvent utiles: titre + annee et dateord (pour tris)""" # imports ici pour eviter refs circulaires import sco_formsemestre_edit import scolars @@ -294,8 +293,7 @@ class ApoEtapeVDI: _ETAPE_VDI_SEP = "!" def __init__(self, etape_vdi=None, etape="", vdi=""): - """Build from string representation, e.g. 'V1RT!111' - """ + """Build from string representation, e.g. 'V1RT!111'""" if etape_vdi: self.etape_vdi = etape_vdi self.etape, self.vdi = self.split_etape_vdi(etape_vdi) @@ -371,11 +369,11 @@ def sem_set_responsable_name(context, sem): def sem_in_semestre_scolaire(context, sem, year=False, saison=0, REQUEST=None): """n'utilise que la date de debut, pivot au 1er aout si annee non specifiée, année scolaire courante - Patch Jmp: ajout du parametre optionnel saison + Patch Jmp: ajout du parametre optionnel saison 1 = sept, 0 = janvier, None = année complète si saison non spécifiée: année complète pivot de saison au 1er décembre - XXX TODO: la période (ici appelée "saison" devrait être éditable + XXX TODO: la période (ici appelée "saison" devrait être éditable manuellement dans le formsemestre_edit afin de couvrir els cas particulier comme un semestre S2 qui commecerait en décembre... voire novembre. ) @@ -417,17 +415,20 @@ def sem_une_annee(context, sem): pivot au 1er août. """ if sem["date_debut_iso"] > sem["date_fin_iso"]: - log('Warning: semestre %(formsemestre_id)s begins after ending !' % sem) + log("Warning: semestre %(formsemestre_id)s begins after ending !" % sem) return False - + debut = int(sem["annee_debut"]) - if sem["mois_debut_ord"] < 8: # considere que debut sur l'anne scolaire precedente + if sem["mois_debut_ord"] < 8: # considere que debut sur l'anne scolaire precedente debut -= 1 fin = int(sem["annee_fin"]) - if sem["mois_fin_ord"] < 9: # 9 (sept) pour autoriser un début en sept et une fin en aout + if ( + sem["mois_fin_ord"] < 9 + ): # 9 (sept) pour autoriser un début en sept et une fin en aout fin -= 1 return debut == fin + def scodoc_get_all_unlocked_sems(context): """Liste de tous les semestres non verrouillés de tous les départements""" depts = context.list_depts() @@ -450,8 +451,7 @@ def table_formsemestres( html_next_section="", REQUEST=None, ): - """Une table presentant des semestres - """ + """Une table presentant des semestres""" for sem in sems: sem_set_responsable_name(context, sem) sem["_titre_num_target"] = ( @@ -498,17 +498,16 @@ def table_formsemestres( def list_formsemestre_by_etape( - context, etape_apo=None, annee_scolaire=False, REQUEST=None + context, etape_apo=False, annee_scolaire=False, REQUEST=None ): - """Liste des semestres de cette etape, pour l'annee scolaire indiquée (sinon, pour toutes) - """ + """Liste des semestres de cette etape, pour l'annee scolaire indiquée (sinon, pour toutes)""" ds = {} # formsemestre_id : sem if etape_apo: sems = do_formsemestre_list(context, args={"etape_apo": etape_apo}) for sem in sems: if annee_scolaire: # restriction annee scolaire if sem_in_annee_scolaire( - context, sem, year=annee_scolaire, REQUEST=REQUEST + context, sem, year=int(annee_scolaire), REQUEST=REQUEST ): ds[sem["formsemestre_id"]] = sem sems = ds.values() @@ -519,7 +518,7 @@ def list_formsemestre_by_etape( sem for sem in sems if sem_in_annee_scolaire( - context, sem, year=annee_scolaire, REQUEST=REQUEST + context, sem, year=int(annee_scolaire), REQUEST=REQUEST ) ] @@ -528,8 +527,7 @@ def list_formsemestre_by_etape( def view_formsemestre_by_etape(context, etape_apo=None, format="html", REQUEST=None): - """Affiche table des semestres correspondants à l'étape - """ + """Affiche table des semestres correspondants à l'étape""" if etape_apo: html_title = ( """

Semestres courants de l'étape %s

""" % etape_apo diff --git a/sco_permissions.py b/sco_permissions.py index b656db15d..9ec7f1147 100644 --- a/sco_permissions.py +++ b/sco_permissions.py @@ -35,7 +35,7 @@ ScoEditFormationTags = ( ScoView = "Sco View" ScoEnsView = "Sco View Ens" # parties visibles par enseignants slt - +ScoObservateur = "Sco Observateur" # accès lecture restreint aux bulletins ScoUsersAdmin = "Sco Users Manage" ScoUsersView = "Sco Users View" @@ -51,6 +51,7 @@ ScoSuperAdmin = "Sco Super Admin" # Default permissions for default roles # (set once on instance creation): Sco_Default_Permissions = { + ScoObservateur: ("Ens", "Secr", "Admin", "RespPe"), ScoView: ("Ens", "Secr", "Admin", "RespPe"), ScoEnsView: ("Ens", "Admin", "RespPe"), ScoUsersView: ("Ens", "Secr", "Admin", "RespPe"), diff --git a/sco_recapcomplet.py b/sco_recapcomplet.py index fb28e8715..22bdc89eb 100644 --- a/sco_recapcomplet.py +++ b/sco_recapcomplet.py @@ -51,6 +51,7 @@ def formsemestre_recapcomplet( xml_with_decisions=False, # XML avec decisions rank_partition_id=None, # si None, calcul rang global pref_override=True, # si vrai, les prefs ont la priorite sur le param hidebac + force_publishing=True, # publie les XML/JSON meme si bulletins non publiés REQUEST=None, ): """Page récapitulant les notes d'un semestre. @@ -72,6 +73,7 @@ def formsemestre_recapcomplet( else: hidebac = int(hidebac) xml_with_decisions = int(xml_with_decisions) + force_publishing = int(force_publishing) isFile = tabformat in ("csv", "xls", "xml", "xlsall", "json") H = [] if not isFile: @@ -144,6 +146,7 @@ def formsemestre_recapcomplet( sortcol=sortcol, xml_with_decisions=xml_with_decisions, rank_partition_id=rank_partition_id, + force_publishing=force_publishing, ) ) @@ -191,6 +194,7 @@ def do_formsemestre_recapcomplet( xml_with_decisions=False, disable_etudlink=False, rank_partition_id=None, # si None, calcul rang global + force_publishing=True, ): """Calcule et renvoie le tableau récapitulatif.""" data, filename, format = make_formsemestre_recapcomplet(**vars()) @@ -219,6 +223,7 @@ def make_formsemestre_recapcomplet( xml_with_decisions=False, disable_etudlink=False, rank_partition_id=None, # si None, calcul rang global + force_publishing=True, # donne bulletins JSON/XML meme si non publiés ): """Grand tableau récapitulatif avec toutes les notes de modules pour tous les étudiants, les moyennes par UE et générale, @@ -226,11 +231,19 @@ def make_formsemestre_recapcomplet( """ if format == "xml": return _formsemestre_recapcomplet_xml( - context, formsemestre_id, xml_nodate, xml_with_decisions=xml_with_decisions + context, + formsemestre_id, + xml_nodate, + xml_with_decisions=xml_with_decisions, + force_publishing=force_publishing, ) elif format == "json": return _formsemestre_recapcomplet_json( - context, formsemestre_id, xml_nodate, xml_with_decisions=xml_with_decisions + context, + formsemestre_id, + xml_nodate=xml_nodate, + xml_with_decisions=xml_with_decisions, + force_publishing=force_publishing, ) if format[:3] == "xls": keep_numeric = True # pas de conversion des notes en strings @@ -791,7 +804,11 @@ def _list_notes_evals_stats(context, evals, key): def _formsemestre_recapcomplet_xml( - context, formsemestre_id, xml_nodate, xml_with_decisions=False + context, + formsemestre_id, + xml_nodate, + xml_with_decisions=False, + force_publishing=True, ): "XML export: liste tous les bulletins XML." @@ -825,7 +842,7 @@ def _formsemestre_recapcomplet_xml( formsemestre_id, etudid, doc=doc, - force_publishing=True, + force_publishing=force_publishing, xml_nodate=xml_nodate, xml_with_decisions=xml_with_decisions, ) @@ -834,9 +851,17 @@ def _formsemestre_recapcomplet_xml( def _formsemestre_recapcomplet_json( - context, formsemestre_id, xml_nodate, xml_with_decisions=False + context, + formsemestre_id, + xml_nodate=False, + xml_with_decisions=False, + force_publishing=True, ): - "JSON export: liste tous les bulletins JSON" + """JSON export: liste tous les bulletins JSON + :param xml_nodate(bool): indique la date courante (attribut docdate) + :param force_publishing: donne les bulletins même si non "publiés sur portail" + :returns: dict, "", "json" + """ if xml_nodate: docdate = "" else: @@ -865,8 +890,27 @@ def _formsemestre_recapcomplet_json( context, formsemestre_id, etudid, - force_publishing=True, + force_publishing=force_publishing, xml_with_decisions=xml_with_decisions, ) ) return J, "", "json" + + +def formsemestres_bulletins(context, annee_scolaire, REQUEST=None): + """Tous les bulletins des semestres publiés des semestres de l'année indiquée. + :param annee_scolaire(int): année de début de l'année scoalaire + :returns: JSON + """ + jslist = [] + sems = sco_formsemestre.list_formsemestre_by_etape( + context, annee_scolaire=annee_scolaire + ) + log("formsemestres_bulletins(%s): %d sems" % (annee_scolaire, len(sems))) + for sem in sems: + J, _, _ = _formsemestre_recapcomplet_json( + context, sem["formsemestre_id"], force_publishing=False + ) + jslist.append(J) + + return sendJSON(REQUEST, jslist)