WIP: intégration bulletins

This commit is contained in:
Emmanuel Viennet 2022-03-07 21:49:11 +01:00
parent 8f911234b2
commit 2220b617b8
16 changed files with 193 additions and 77 deletions

View File

@ -111,9 +111,10 @@ class BulletinBUT:
d["modules"] = self.etud_mods_results(etud, modimpls_spo) d["modules"] = self.etud_mods_results(etud, modimpls_spo)
return d return d
def etud_mods_results(self, etud, modimpls) -> dict: def etud_mods_results(self, etud, modimpls, version="long") -> dict:
"""dict synthèse résultats des modules indiqués, """dict synthèse résultats des modules indiqués,
avec évaluations de chacun.""" avec évaluations de chacun (sauf si version == "short")
"""
res = self.res res = self.res
d = {} d = {}
# etud_idx = self.etud_index[etud.id] # etud_idx = self.etud_index[etud.id]
@ -154,12 +155,14 @@ class BulletinBUT:
"evaluations": [ "evaluations": [
self.etud_eval_results(etud, e) self.etud_eval_results(etud, e)
for e in modimpl.evaluations for e in modimpl.evaluations
if e.visibulletin if (e.visibulletin or version == "long")
and ( and (
modimpl_results.evaluations_etat[e.id].is_complete modimpl_results.evaluations_etat[e.id].is_complete
or self.prefs["bul_show_all_evals"] or self.prefs["bul_show_all_evals"]
) )
], ]
if version != "short"
else [],
} }
return d return d
@ -217,9 +220,17 @@ class BulletinBUT:
return f"Bonus de {fmt_note(bonus_vect.iloc[0])}" return f"Bonus de {fmt_note(bonus_vect.iloc[0])}"
def bulletin_etud( def bulletin_etud(
self, etud: Identite, formsemestre: FormSemestre, force_publishing=False self,
etud: Identite,
formsemestre: FormSemestre,
force_publishing=False,
version="long",
) -> dict: ) -> dict:
"""Le bulletin de l'étudiant dans ce semestre: dict pour la version JSON / HTML. """Le bulletin de l'étudiant dans ce semestre: dict pour la version JSON / HTML.
- version:
"long", "selectedevals": toutes les infos (notes des évaluations)
"short" : ne descend pas plus bas que les modules.
- Si force_publishing, rempli le bulletin même si bul_hide_xml est vrai - Si force_publishing, rempli le bulletin même si bul_hide_xml est vrai
(bulletins non publiés). (bulletins non publiés).
""" """
@ -282,8 +293,10 @@ class BulletinBUT:
) )
d.update( d.update(
{ {
"ressources": self.etud_mods_results(etud, res.ressources), "ressources": self.etud_mods_results(
"saes": self.etud_mods_results(etud, res.saes), etud, res.ressources, version=version
),
"saes": self.etud_mods_results(etud, res.saes, version=version),
"ues": { "ues": {
ue.acronyme: self.etud_ue_results(etud, ue) ue.acronyme: self.etud_ue_results(etud, ue)
for ue in res.ues for ue in res.ues

View File

@ -160,6 +160,7 @@ class Identite(db.Model):
"etudid": self.id, "etudid": self.id,
"nom": self.nom_disp(), "nom": self.nom_disp(),
"prenom": self.prenom, "prenom": self.prenom,
"nomprenom": self.nomprenom,
} }
if include_urls: if include_urls:
d["fiche_url"] = url_for( d["fiche_url"] = url_for(

View File

@ -22,6 +22,7 @@ from app.scodoc import sco_codes_parcours
from app.scodoc import sco_preferences from app.scodoc import sco_preferences
from app.scodoc.sco_vdi import ApoEtapeVDI from app.scodoc.sco_vdi import ApoEtapeVDI
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission
from app.scodoc.sco_utils import MONTH_NAMES_ABBREV
class FormSemestre(db.Model): class FormSemestre(db.Model):
@ -162,8 +163,8 @@ class FormSemestre(db.Model):
d["periode"] = 2 # typiquement, début en février: S2, S4... d["periode"] = 2 # typiquement, début en février: S2, S4...
d["titre_num"] = self.titre_num() d["titre_num"] = self.titre_num()
d["titreannee"] = self.titre_annee() d["titreannee"] = self.titre_annee()
d["mois_debut"] = f"{self.date_debut.month} {self.date_debut.year}" d["mois_debut"] = self.mois_debut()
d["mois_fin"] = f"{self.date_fin.month} {self.date_fin.year}" d["mois_fin"] = self.mois_fin()
d["titremois"] = "%s %s (%s - %s)" % ( d["titremois"] = "%s %s (%s - %s)" % (
d["titre_num"], d["titre_num"],
self.modalite or "", self.modalite or "",
@ -293,6 +294,7 @@ class FormSemestre(db.Model):
"""chaîne "J. Dupond, X. Martin" """chaîne "J. Dupond, X. Martin"
ou "Jacques Dupond, Xavier Martin" ou "Jacques Dupond, Xavier Martin"
""" """
# was "nomcomplet"
if not self.responsables: if not self.responsables:
return "" return ""
if abbrev_prenom: if abbrev_prenom:
@ -304,6 +306,14 @@ class FormSemestre(db.Model):
"2021 - 2022" "2021 - 2022"
return scu.annee_scolaire_repr(self.date_debut.year, self.date_debut.month) return scu.annee_scolaire_repr(self.date_debut.year, self.date_debut.month)
def mois_debut(self) -> str:
"Oct 2021"
return f"{MONTH_NAMES_ABBREV[self.date_debut.month - 1]} {self.date_debut.year}"
def mois_fin(self) -> str:
"Jul 2022"
return f"{MONTH_NAMES_ABBREV[self.date_fin.month - 1]} {self.date_debut.year}"
def session_id(self) -> str: def session_id(self) -> str:
"""identifiant externe de semestre de formation """identifiant externe de semestre de formation
Exemple: RT-DUT-FI-S1-ANNEE Exemple: RT-DUT-FI-S1-ANNEE

View File

@ -793,13 +793,14 @@ def etud_descr_situation_semestre(
def formsemestre_bulletinetud( def formsemestre_bulletinetud(
etudid=None, etudid=None,
formsemestre_id=None, formsemestre_id=None,
format="html", format=None,
version="long", version="long",
xml_with_decisions=False, xml_with_decisions=False,
force_publishing=False, # force publication meme si semestre non publie sur "portail" force_publishing=False, # force publication meme si semestre non publie sur "portail"
prefer_mail_perso=False, prefer_mail_perso=False,
): ):
"page bulletin de notes" "page bulletin de notes"
format = format or "html"
etud: Identite = Identite.query.get_or_404(etudid) etud: Identite = Identite.query.get_or_404(etudid)
formsemestre: FormSemestre = FormSemestre.query.get(formsemestre_id) formsemestre: FormSemestre = FormSemestre.query.get(formsemestre_id)
if not formsemestre: if not formsemestre:
@ -879,7 +880,7 @@ def do_formsemestre_bulletinetud(
formsemestre: FormSemestre, formsemestre: FormSemestre,
etudid: int, etudid: int,
version="long", # short, long, selectedevals version="long", # short, long, selectedevals
format="html", format=None,
nohtml=False, nohtml=False,
xml_with_decisions=False, # force décisions dans XML xml_with_decisions=False, # force décisions dans XML
force_publishing=False, # force publication meme si semestre non publié sur "portail" force_publishing=False, # force publication meme si semestre non publié sur "portail"
@ -890,6 +891,7 @@ def do_formsemestre_bulletinetud(
bul est str ou bytes au format demandé (html, pdf, pdfmail, pdfpart, xml, json) bul est str ou bytes au format demandé (html, pdf, pdfmail, pdfpart, xml, json)
et filigranne est un message à placer en "filigranne" (eg "Provisoire"). et filigranne est un message à placer en "filigranne" (eg "Provisoire").
""" """
format = format or "html"
if format == "xml": if format == "xml":
bul = sco_bulletins_xml.make_xml_formsemestre_bulletinetud( bul = sco_bulletins_xml.make_xml_formsemestre_bulletinetud(
formsemestre.id, formsemestre.id,
@ -1258,7 +1260,7 @@ def make_menu_autres_operations(
"enabled": sco_permissions_check.can_validate_sem(formsemestre.id), "enabled": sco_permissions_check.can_validate_sem(formsemestre.id),
}, },
{ {
"title": "Editer PV jury", "title": "Éditer PV jury",
"endpoint": "notes.formsemestre_pvjury_pdf", "endpoint": "notes.formsemestre_pvjury_pdf",
"args": { "args": {
"formsemestre_id": formsemestre.id, "formsemestre_id": formsemestre.id,

View File

@ -297,7 +297,11 @@ def register_bulletin_class(klass):
def bulletin_class_descriptions(): def bulletin_class_descriptions():
return [x.description for x in BULLETIN_CLASSES.values()] return [
BULLETIN_CLASSES[class_name].description
for class_name in BULLETIN_CLASSES
if BULLETIN_CLASSES[class_name].list_in_menu
]
def bulletin_class_names() -> list[str]: def bulletin_class_names() -> list[str]:

View File

@ -31,7 +31,7 @@
from flask import current_app from flask import current_app
from flask import g from flask import g
from flask import request from flask import request
from flask import url_for from flask import render_template, url_for
from flask_login import current_user from flask_login import current_user
from app import log from app import log
@ -411,7 +411,7 @@ def formsemestre_status_menubar(sem):
"enabled": sco_permissions_check.can_validate_sem(formsemestre_id), "enabled": sco_permissions_check.can_validate_sem(formsemestre_id),
}, },
{ {
"title": "Editer les PV et archiver les résultats", "title": "Éditer les PV et archiver les résultats",
"endpoint": "notes.formsemestre_archive", "endpoint": "notes.formsemestre_archive",
"args": {"formsemestre_id": formsemestre_id}, "args": {"formsemestre_id": formsemestre_id},
"enabled": sco_permissions_check.can_edit_pv(formsemestre_id), "enabled": sco_permissions_check.can_edit_pv(formsemestre_id),
@ -445,6 +445,7 @@ def retreive_formsemestre_from_request() -> int:
"""Cherche si on a de quoi déduire le semestre affiché à partir des """Cherche si on a de quoi déduire le semestre affiché à partir des
arguments de la requête: arguments de la requête:
formsemestre_id ou moduleimpl ou evaluation ou group_id ou partition_id formsemestre_id ou moduleimpl ou evaluation ou group_id ou partition_id
Returns None si pas défini.
""" """
if request.method == "GET": if request.method == "GET":
args = request.args args = request.args
@ -505,34 +506,17 @@ def formsemestre_page_title():
return "" return ""
try: try:
formsemestre_id = int(formsemestre_id) formsemestre_id = int(formsemestre_id)
sem = sco_formsemestre.get_formsemestre(formsemestre_id).copy() formsemestre = FormSemestre.query.get(formsemestre_id)
except: except:
log("can't find formsemestre_id %s" % formsemestre_id) log("can't find formsemestre_id %s" % formsemestre_id)
return "" return ""
fill_formsemestre(sem) h = render_template(
"formsemestre_page_title.html",
h = f"""<div class="formsemestre_page_title"> formsemestre=formsemestre,
<div class="infos"> scu=scu,
<span class="semtitle"><a class="stdlink" title="{sem['session_id']}" sem_menu_bar=formsemestre_status_menubar(formsemestre.to_dict()),
href="{url_for('notes.formsemestre_status', )
scodoc_dept=g.scodoc_dept, formsemestre_id=sem['formsemestre_id'])}"
>{sem['titre']}</a><a
title="{sem['etape_apo_str']}">{sem['num_sem']}</a>{sem['modalitestr']}</span><span
class="dates"><a
title="du {sem['date_debut']} au {sem['date_fin']} "
>{sem['mois_debut']} - {sem['mois_fin']}</a></span><span
class="resp"><a title="{sem['nomcomplet']}">{sem['resp']}</a></span><span
class="nbinscrits"><a class="discretelink"
href="{url_for("scolar.groups_view",
scodoc_dept=g.scodoc_dept, formsemestre_id=sem['formsemestre_id'])}"
>{sem['nbinscrits']} inscrits</a></span><span
class="lock">{sem['locklink']}</span><span
class="eye">{sem['eyelink']}</span>
</div>
{formsemestre_status_menubar(sem)}
</div>
"""
return h return h

View File

@ -175,7 +175,7 @@ def etud_photo_is_local(etud: dict, size="small"):
return photo_pathname(etud["photo_filename"], size=size) return photo_pathname(etud["photo_filename"], size=size)
def etud_photo_html(etud=None, etudid=None, title=None, size="small"): def etud_photo_html(etud: dict = None, etudid=None, title=None, size="small"):
"""HTML img tag for the photo, either in small size (h90) """HTML img tag for the photo, either in small size (h90)
or original size (size=="orig") or original size (size=="orig")
""" """

View File

@ -619,7 +619,7 @@ def bul_filename_old(sem: dict, etud: dict, format):
def bul_filename(formsemestre, etud, format): def bul_filename(formsemestre, etud, format):
"""Build a filename for this bulletin""" """Build a filename for this bulletin"""
dt = time.strftime("%Y-%m-%d") dt = time.strftime("%Y-%m-%d")
filename = f"bul-{formsemestre.sem.titre_num}-{dt}-{etud.nom}.{format}" filename = f"bul-{formsemestre.titre_num()}-{dt}-{etud.nom}.{format}"
filename = make_filename(filename) filename = make_filename(filename)
return filename return filename

View File

@ -14,16 +14,25 @@
} }
main{ main{
--couleurPrincipale: rgb(240,250,255); --couleurPrincipale: rgb(240,250,255);
--couleurFondTitresUE: rgb(206,255,235); --couleurFondTitresUE: #b6ebff;
--couleurFondTitresRes: rgb(125, 170, 255); --couleurFondTitresRes: #f8c844;
--couleurFondTitresSAE: rgb(211, 255, 255); --couleurFondTitresSAE: #c6ffab;
--couleurSecondaire: #fec; --couleurSecondaire: #fec;
--couleurIntense: #c09; --couleurIntense: rgb(4, 16, 159);;
--couleurSurlignage: rgba(232, 255, 132, 0.47); --couleurSurlignage: rgba(255, 253, 110, 0.49);
max-width: 1000px; max-width: 1000px;
margin: auto; margin: auto;
display: none; display: none;
} }
.releve a, .releve a:visited {
color: navy;
text-decoration: none;
}
.releve a:hover {
color: red;
text-decoration: underline;
}
.ready .wait{display: none;} .ready .wait{display: none;}
.ready main{display: block;} .ready main{display: block;}
h2{ h2{
@ -152,12 +161,14 @@ section>div:nth-child(1){
column-gap: 4px; column-gap: 4px;
flex: none; flex: none;
} }
.infoSemestre>div:nth-child(1){
margin-right: auto;
}
.infoSemestre>div>div:nth-child(even){ .infoSemestre>div>div:nth-child(even){
text-align: right; text-align: right;
} }
.photo {
border: none;
margin-left: auto;
}
.rang{ .rang{
font-weight: bold; font-weight: bold;
} }
@ -213,7 +224,6 @@ section>div:nth-child(1){
scroll-margin-top: 60px; scroll-margin-top: 60px;
} }
.module, .ue { .module, .ue {
background: var(--couleurSecondaire);
color: #000; color: #000;
padding: 4px 32px; padding: 4px 32px;
border-radius: 4px; border-radius: 4px;
@ -225,6 +235,15 @@ section>div:nth-child(1){
cursor: pointer; cursor: pointer;
position: relative; position: relative;
} }
.ue {
background: var(--couleurFondTitresRes);
}
.module {
background: var(--couleurFondTitresRes);
}
.module h3 {
background: var(--couleurFondTitresRes);
}
.module::before, .ue::before { .module::before, .ue::before {
content:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='26px' height='26px' fill='white'><path d='M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z' /></svg>"); content:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='26px' height='26px' fill='white'><path d='M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z' /></svg>");
width: 26px; width: 26px;

View File

@ -1963,7 +1963,9 @@ table.notes_recapcomplet a:hover {
div.notes_bulletin { div.notes_bulletin {
margin-right: 5px; margin-right: 5px;
} }
div.bulletin_menubar {
margin-right: 2em;
}
table.notes_bulletin { table.notes_bulletin {
border-collapse: collapse; border-collapse: collapse;
border: 2px solid rgb(100,100,240); border: 2px solid rgb(100,100,240);

View File

@ -79,8 +79,8 @@ class releveBUT extends HTMLElement {
<!-- Semestre --> <!-- Semestre -->
<!---------------------------> <!--------------------------->
<section> <section>
<h2>Semestre </h2> <h2 id="identite_etudiant"></h2>
<div class=flex> <div>
<div class=infoSemestre></div> <div class=infoSemestre></div>
<div> <div>
<div class=decision></div> <div class=decision></div>
@ -97,7 +97,7 @@ class releveBUT extends HTMLElement {
<section> <section>
<div> <div>
<div> <div>
<h2>Synthèse</h2> <h2>Unités d'enseignement</h2>
<em>La moyenne des ressources dans une UE dépend des poids donnés aux évaluations.</em> <em>La moyenne des ressources dans une UE dépend des poids donnés aux évaluations.</em>
</div> </div>
<div class=CTA_Liste> <div class=CTA_Liste>
@ -126,7 +126,7 @@ class releveBUT extends HTMLElement {
<section> <section>
<div> <div>
<h2>S</h2> <h2>Situations d'apprentissage et d'évaluation (S)</h2>
<div class=CTA_Liste> <div class=CTA_Liste>
Liste <svg xmlns="http://www.w3.org/2000/svg" width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> Liste <svg xmlns="http://www.w3.org/2000/svg" width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M18 15l-6-6-6 6" /> <path d="M18 15l-6-6-6 6" />
@ -192,7 +192,8 @@ class releveBUT extends HTMLElement {
/* Information sur le semestre */ /* Information sur le semestre */
/*******************************/ /*******************************/
showSemestre(data) { showSemestre(data) {
this.shadow.querySelector("h2").innerHTML += data.semestre.numero;
this.shadow.querySelector("#identite_etudiant").innerHTML = ` ${data.etudiant.nomprenom} `;
this.shadow.querySelector(".dateInscription").innerHTML += this.ISOToDate(data.semestre.inscription); this.shadow.querySelector(".dateInscription").innerHTML += this.ISOToDate(data.semestre.inscription);
let output = ` let output = `
<div> <div>
@ -206,7 +207,9 @@ class releveBUT extends HTMLElement {
<div class=enteteSemestre>Absences</div> <div class=enteteSemestre>Absences</div>
<div class=enteteSemestre>N.J. ${data.semestre.absences?.injustifie ?? "-"}</div> <div class=enteteSemestre>N.J. ${data.semestre.absences?.injustifie ?? "-"}</div>
<div style="grid-column: 2">Total ${data.semestre.absences?.total ?? "-"}</div> <div style="grid-column: 2">Total ${data.semestre.absences?.total ?? "-"}</div>
</div>`; </div>
<a class=photo href="${data.etudiant.fiche_url}"><img src="${data.etudiant.photo_url || "default_Student.svg"}" alt="photo de l'étudiant" title="fiche de l'étudiant" height="120" border="0"></a>
`;
/*${data.semestre.groupes.map(groupe => { /*${data.semestre.groupes.map(groupe => {
return ` return `
<div> <div>

View File

@ -5,10 +5,12 @@
<table class="bull_head"> <table class="bull_head">
<tr> <tr>
<td> <td>
{% if not is_apc %}
<h2><a class="discretelink" href="{{ <h2><a class="discretelink" href="{{
url_for( url_for(
"scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etudid, "scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etudid,
)}}">{{etud.nomprenom}}</a></h2> )}}">{{etud.nomprenom}}</a></h2>
{% endif %}
<form name="f" method="GET" action="{{request.base_url}}"> <form name="f" method="GET" action="{{request.base_url}}">
Bulletin <span class="bull_liensemestre"><a href="{{ Bulletin <span class="bull_liensemestre"><a href="{{
url_for("notes.formsemestre_status", url_for("notes.formsemestre_status",
@ -50,9 +52,11 @@
</table> </table>
</form> </form>
</td> </td>
{% if not is_apc %}
<td class="bull_photo"><a href="{{ <td class="bull_photo"><a href="{{
url_for("scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etud.id) url_for("scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etud.id)
}}">{{etud.photo_html(title="fiche de " + etud["nom"])|safe}}</a> }}">{{etud.photo_html(title="fiche de " + etud["nom"])|safe}}</a>
</td> </td>
{% endif %}
</tr> </tr>
</table> </table>

View File

@ -6,8 +6,8 @@
{% endblock %} {% endblock %}
{% block app_content %} {% block app_content %}
<h2>Totoro</h2>
{% include 'bul_head.html' %}
<releve-but></releve-but> <releve-but></releve-but>
<script src="/ScoDoc/static/js/releve-but.js"></script> <script src="/ScoDoc/static/js/releve-but.js"></script>

View File

@ -0,0 +1,50 @@
{# -*- mode: jinja-html -*- #}
{# Element HTML decrivant un semestre (barre de menu et infos) #}
{# was formsemestre_page_title #}
<div class="formsemestre_page_title">
<div class="infos">
<span class="semtitle"><a class="stdlink"
title="{{formsemestre.session_id}}"
href="{{url_for('notes.formsemestre_status',
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre.id)}}"
>TATO {{formsemestre.titre}}</a>
{%- if formsemestre.semestre_id != -1 -%}
<a
title="{{formsemestre.etapes_apo_str()
}}">, {{
formsemestre.formation.get_parcours().SESSION_NAME}}
{{formsemestre.semestre_id}}</a>
{%- endif -%}
{%- if formsemestre.modalite %} en {{formsemestre.modalite}}
{%- endif %}</span><span
class="dates"><a
title="du {{formsemestre.date_debut.strftime('%d/%m/%Y')}}
au {{formsemestre.date_fin.strftime('%d/%m/%Y')}} "
>{{formsemestre.mois_debut()}} - {{formsemestre.mois_fin()}}</a></span><span
class="resp"><a title="{{formsemestre.responsables_str(abbrev_prenom=False)}}">{{formsemestre.responsables_str()}}</a></span><span
class="nbinscrits"><a class="discretelink"
href="{{url_for('scolar.groups_view',
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre.id)
}}"
>{{formsemestre.etuds_inscriptions|length}} inscrits</a></span><span
class="lock">
{%-if formsemestre.etat -%}
<a href="{{ url_for( 'notes.formsemestre_change_lock',
scodoc_dept=scodoc_dept, formsemestre_id=formsemestre.id )}}">{{
scu.icontag("lock_img", border="0", title="Semestre verrouillé")|safe
}}</a>
{%- endif -%}
</span><span class="eye"><a href="{{
url_for('notes.formsemestre_change_publication_bul',
scodoc_dept=scodoc_dept, formsemestre_id=formsemestre.id )
}}">{%-
if formsemestre.bul_hide_xml -%}}
{{scu.icontag("hide_img", border="0", title="Bulletins NON publiés")|safe}}
{%- else -%}
{{scu.icontag("eye_img", border="0", title="Bulletins publiés")|safe}}
{%- endif -%}
</a></span>
</div>
{{sem_menu_bar|safe}}
</div>

View File

@ -50,27 +50,29 @@ def close_dept_db_connection(arg):
class ScoData: class ScoData:
"""Classe utilisée pour passer des valeurs aux vues (templates)""" """Classe utilisée pour passer des valeurs aux vues (templates)"""
def __init__(self): def __init__(self, etud=None, formsemestre=None):
# Champs utilisés par toutes les pages ScoDoc (sidebar, en-tête) # Champs utilisés par toutes les pages ScoDoc (sidebar, en-tête)
self.Permission = Permission self.Permission = Permission
self.scu = scu self.scu = scu
self.SCOVERSION = sco_version.SCOVERSION self.SCOVERSION = sco_version.SCOVERSION
# -- Informations étudiant courant, si sélectionné: # -- Informations étudiant courant, si sélectionné:
if etud is None:
etudid = g.get("etudid", None) etudid = g.get("etudid", None)
if not etudid: if etudid is None:
if request.method == "GET": if request.method == "GET":
etudid = request.args.get("etudid", None) etudid = request.args.get("etudid", None)
elif request.method == "POST": elif request.method == "POST":
etudid = request.form.get("etudid", None) etudid = request.form.get("etudid", None)
if etudid is not None:
if etudid: etud = Identite.query.get_or_404(etudid)
self.etud = etud
if etud is not None:
# Infos sur l'étudiant courant # Infos sur l'étudiant courant
self.etud = Identite.query.get_or_404(etudid)
ins = self.etud.inscription_courante() ins = self.etud.inscription_courante()
if ins: if ins:
self.etud_cur_sem = ins.formsemestre self.etud_cur_sem = ins.formsemestre
self.nbabs, self.nbabsjust = sco_abs.get_abs_count_in_interval( self.nbabs, self.nbabsjust = sco_abs.get_abs_count_in_interval(
etudid, etud.id,
self.etud_cur_sem.date_debut.isoformat(), self.etud_cur_sem.date_debut.isoformat(),
self.etud_cur_sem.date_fin.isoformat(), self.etud_cur_sem.date_fin.isoformat(),
) )
@ -80,17 +82,22 @@ class ScoData:
else: else:
self.etud = None self.etud = None
# --- Informations sur semestre courant, si sélectionné # --- Informations sur semestre courant, si sélectionné
formsemestre_id = sco_formsemestre_status.retreive_formsemestre_from_request() if formsemestre is None:
if formsemestre_id is None: formsemestre_id = (
sco_formsemestre_status.retreive_formsemestre_from_request()
)
if formsemestre_id is not None:
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
if formsemestre is None:
self.sem = None self.sem = None
self.sem_menu_bar = None self.sem_menu_bar = None
else: else:
self.sem = FormSemestre.query.get_or_404(formsemestre_id) self.sem = formsemestre
self.sem_menu_bar = sco_formsemestre_status.formsemestre_status_menubar( self.sem_menu_bar = sco_formsemestre_status.formsemestre_status_menubar(
self.sem.to_dict() self.sem.to_dict()
) )
# --- Préférences # --- Préférences
self.prefs = sco_preferences.SemPreferences(formsemestre_id) self.prefs = sco_preferences.SemPreferences(formsemestre.id)
from app.views import scodoc, notes, scolar, absences, users, pn_modules, refcomp from app.views import scodoc, notes, scolar, absences, users, pn_modules, refcomp

View File

@ -32,6 +32,7 @@ Emmanuel Viennet, 2021
""" """
from operator import itemgetter from operator import itemgetter
import time
from xml.etree import ElementTree from xml.etree import ElementTree
import flask import flask
@ -276,7 +277,7 @@ sco_publish(
def formsemestre_bulletinetud( def formsemestre_bulletinetud(
etudid=None, etudid=None,
formsemestre_id=None, formsemestre_id=None,
format="html", format=None,
version="long", version="long",
xml_with_decisions=False, xml_with_decisions=False,
force_publishing=False, force_publishing=False,
@ -284,6 +285,7 @@ def formsemestre_bulletinetud(
code_nip=None, code_nip=None,
code_ine=None, code_ine=None,
): ):
format = format or "html"
if not formsemestre_id: if not formsemestre_id:
flask.abort(404, "argument manquant: formsemestre_id") flask.abort(404, "argument manquant: formsemestre_id")
if not isinstance(formsemestre_id, int): if not isinstance(formsemestre_id, int):
@ -311,12 +313,16 @@ def formsemestre_bulletinetud(
if format == "json": if format == "json":
r = bulletin_but.BulletinBUT(formsemestre) r = bulletin_but.BulletinBUT(formsemestre)
return jsonify( return jsonify(
r.bulletin_etud(etud, formsemestre, force_publishing=force_publishing) r.bulletin_etud(
etud,
formsemestre,
force_publishing=force_publishing,
version=version,
)
) )
elif format == "html": elif format == "html":
return render_template( return render_template(
"but/bulletin.html", "but/bulletin.html",
title=f"Bul. {etud.nom} - BUT",
bul_url=url_for( bul_url=url_for(
"notes.formsemestre_bulletinetud", "notes.formsemestre_bulletinetud",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
@ -324,8 +330,19 @@ def formsemestre_bulletinetud(
etudid=etudid, etudid=etudid,
format="json", format="json",
force_publishing=1, # pour ScoDoc lui même force_publishing=1, # pour ScoDoc lui même
version=version,
), ),
sco=ScoData(), etud=etud,
formsemestre=formsemestre,
is_apc=formsemestre.formation.is_apc(),
menu_autres_operations=sco_bulletins.make_menu_autres_operations(
formsemestre, etud, "notes.formsemestre_bulletinetud", version
),
sco=ScoData(etud=etud),
scu=scu,
time=time,
title=f"Bul. {etud.nom} - BUT",
version=version,
) )
if not (etudid or code_nip or code_ine): if not (etudid or code_nip or code_ine):