forked from ScoDoc/ScoDoc
Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
5bd60d9c34 | |||
b165bc2659 | |||
60a77b8ba7 |
@ -20,10 +20,10 @@ Flask, SQLAlchemy, au lien de Python2/Zope dans les versions précédentes).
|
||||
|
||||
### État actuel (26 jan 22)
|
||||
|
||||
- 9.1 (master) reproduit l'ensemble des fonctions de ScoDoc 7 (donc pas de BUT), sauf:
|
||||
- 9.1.5x (master) reproduit l'ensemble des fonctions de ScoDoc 7 (donc pas de BUT), sauf:
|
||||
- ancien module "Entreprises" (obsolète) et ajoute la gestion du BUT.
|
||||
|
||||
- 9.2 (branche refactor_nt) est la version de développement.
|
||||
- 9.2 (branche dev92) est la version de développement.
|
||||
|
||||
|
||||
### Lignes de commandes
|
||||
|
@ -9,14 +9,15 @@
|
||||
|
||||
import datetime
|
||||
from flask import url_for, g
|
||||
from app.models.formsemestre import FormSemestre
|
||||
|
||||
from app.comp.res_but import ResultatsSemestreBUT
|
||||
from app.models import FormSemestre, Identite
|
||||
from app.scodoc import sco_utils as scu
|
||||
from app.scodoc import sco_bulletins_json
|
||||
from app.scodoc import sco_bulletins_pdf
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc.sco_codes_parcours import UE_SPORT
|
||||
from app.scodoc.sco_utils import fmt_note
|
||||
from app.comp.res_but import ResultatsSemestreBUT
|
||||
|
||||
|
||||
class BulletinBUT:
|
||||
@ -28,6 +29,7 @@ class BulletinBUT:
|
||||
def __init__(self, formsemestre: FormSemestre):
|
||||
""" """
|
||||
self.res = ResultatsSemestreBUT(formsemestre)
|
||||
self.prefs = sco_preferences.SemPreferences(formsemestre.id)
|
||||
|
||||
def etud_ue_mod_results(self, etud, ue, modimpls) -> dict:
|
||||
"dict synthèse résultats dans l'UE pour les modules indiqués"
|
||||
@ -84,7 +86,7 @@ class BulletinBUT:
|
||||
"saes": self.etud_ue_mod_results(etud, ue, res.saes),
|
||||
}
|
||||
if ue.type != UE_SPORT:
|
||||
if sco_preferences.get_preference("bul_show_ue_rangs", res.formsemestre.id):
|
||||
if self.prefs["bul_show_ue_rangs"]:
|
||||
rangs, effectif = res.ue_rangs[ue.id]
|
||||
rang = rangs[etud.id]
|
||||
else:
|
||||
@ -155,9 +157,7 @@ class BulletinBUT:
|
||||
if e.visibulletin
|
||||
and (
|
||||
modimpl_results.evaluations_etat[e.id].is_complete
|
||||
or sco_preferences.get_preference(
|
||||
"bul_show_all_evals", res.formsemestre.id
|
||||
)
|
||||
or self.prefs["bul_show_all_evals"]
|
||||
)
|
||||
],
|
||||
}
|
||||
@ -216,9 +216,11 @@ class BulletinBUT:
|
||||
else:
|
||||
return f"Bonus de {fmt_note(bonus_vect.iloc[0])}"
|
||||
|
||||
def bulletin_etud(self, etud, formsemestre, force_publishing=False) -> dict:
|
||||
"""Le bulletin de l'étudiant dans ce semestre.
|
||||
Si force_publishing, rempli le bulletin même si bul_hide_xml est vrai
|
||||
def bulletin_etud(
|
||||
self, etud: Identite, formsemestre, force_publishing=False
|
||||
) -> dict:
|
||||
"""Le bulletin de l'étudiant dans ce semestre: dict pour la version JSON / HTML.
|
||||
- Si force_publishing, rempli le bulletin même si bul_hide_xml est vrai
|
||||
(bulletins non publiés).
|
||||
"""
|
||||
res = self.res
|
||||
@ -239,7 +241,9 @@ class BulletinBUT:
|
||||
},
|
||||
"formsemestre_id": formsemestre.id,
|
||||
"etat_inscription": etat_inscription,
|
||||
"options": sco_preferences.bulletin_option_affichage(formsemestre.id),
|
||||
"options": sco_preferences.bulletin_option_affichage(
|
||||
formsemestre.id, self.prefs
|
||||
),
|
||||
}
|
||||
if not published:
|
||||
return d
|
||||
@ -312,3 +316,12 @@ class BulletinBUT:
|
||||
)
|
||||
|
||||
return d
|
||||
|
||||
def bulletin_etud_complet(self, etud) -> dict:
|
||||
"""Bulletin dict complet avec toutes les infos pour les bulletins pdf"""
|
||||
d = self.bulletin_etud(force_publishing=True)
|
||||
d["filigranne"] = sco_bulletins_pdf.get_filigranne(
|
||||
self.res.get_etud_etat(etud.id), self.prefs
|
||||
)
|
||||
# XXX TODO A COMPLETER
|
||||
raise NotImplementedError()
|
||||
|
@ -117,6 +117,7 @@ class FormSemestre(db.Model):
|
||||
return f"<{self.__class__.__name__} {self.id} {self.titre_num()}>"
|
||||
|
||||
def to_dict(self):
|
||||
"dict (compatible ScoDoc7)"
|
||||
d = dict(self.__dict__)
|
||||
d.pop("_sa_instance_state", None)
|
||||
# ScoDoc7 output_formators: (backward compat)
|
||||
|
@ -28,30 +28,21 @@
|
||||
"""Génération des bulletins de notes
|
||||
|
||||
"""
|
||||
from app.models import formsemestre
|
||||
import time
|
||||
import pprint
|
||||
import email
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.base import MIMEBase
|
||||
from email.header import Header
|
||||
from reportlab.lib.colors import Color
|
||||
import urllib
|
||||
import pprint
|
||||
import time
|
||||
|
||||
from flask import g, request
|
||||
from flask import url_for
|
||||
from flask_login import current_user
|
||||
from flask_mail import Message
|
||||
from app.models.moduleimpls import ModuleImplInscription
|
||||
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc.sco_utils import ModuleType
|
||||
import app.scodoc.notesdb as ndb
|
||||
from app import email
|
||||
from app import log
|
||||
from app.but import bulletin_but
|
||||
from app.comp import res_sem
|
||||
from app.comp.res_common import NotesTableCompat
|
||||
from app.models import FormSemestre
|
||||
from app.models import FormSemestre, Identite, ModuleImplInscription
|
||||
from app.scodoc.sco_permissions import Permission
|
||||
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError
|
||||
from app.scodoc import html_sco_header
|
||||
@ -60,9 +51,9 @@ from app.scodoc import sco_abs
|
||||
from app.scodoc import sco_abs_views
|
||||
from app.scodoc import sco_bulletins_generator
|
||||
from app.scodoc import sco_bulletins_json
|
||||
from app.scodoc import sco_bulletins_pdf
|
||||
from app.scodoc import sco_bulletins_xml
|
||||
from app.scodoc import sco_codes_parcours
|
||||
from app.scodoc import sco_cache
|
||||
from app.scodoc import sco_etud
|
||||
from app.scodoc import sco_evaluation_db
|
||||
from app.scodoc import sco_formations
|
||||
@ -73,7 +64,9 @@ from app.scodoc import sco_photos
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc import sco_pvjury
|
||||
from app.scodoc import sco_users
|
||||
from app import email
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc.sco_utils import ModuleType
|
||||
import app.scodoc.notesdb as ndb
|
||||
|
||||
# ----- CLASSES DE BULLETINS DE NOTES
|
||||
from app.scodoc import sco_bulletins_standard
|
||||
@ -190,28 +183,18 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"):
|
||||
show_mention=prefs["bul_show_mention"],
|
||||
)
|
||||
|
||||
if dpv:
|
||||
I["decision_sem"] = dpv["decisions"][0]["decision_sem"]
|
||||
else:
|
||||
I["decision_sem"] = ""
|
||||
I.update(infos)
|
||||
|
||||
I["etud_etat_html"] = _get_etud_etat_html(
|
||||
formsemestre.etuds_inscriptions[etudid].etat
|
||||
)
|
||||
I["etud_etat"] = nt.get_etud_etat(etudid)
|
||||
I["filigranne"] = ""
|
||||
I["filigranne"] = sco_bulletins_pdf.get_filigranne(I["etud_etat"], prefs)
|
||||
I["demission"] = ""
|
||||
if I["etud_etat"] == "D":
|
||||
if I["etud_etat"] == scu.DEMISSION:
|
||||
I["demission"] = "(Démission)"
|
||||
I["filigranne"] = "Démission"
|
||||
elif I["etud_etat"] == sco_codes_parcours.DEF:
|
||||
I["demission"] = "(Défaillant)"
|
||||
I["filigranne"] = "Défaillant"
|
||||
elif (prefs["bul_show_temporary"] and not I["decision_sem"]) or prefs[
|
||||
"bul_show_temporary_forced"
|
||||
]:
|
||||
I["filigranne"] = prefs["bul_temporary_txt"]
|
||||
|
||||
# --- Appreciations
|
||||
cnx = ndb.GetDBConnexion()
|
||||
@ -687,6 +670,7 @@ def etud_descr_situation_semestre(
|
||||
descr_defaillance : "Défaillant" ou vide si non défaillant.
|
||||
decision_jury : "Validé", "Ajourné", ... (code semestre)
|
||||
descr_decision_jury : "Décision jury: Validé" (une phrase)
|
||||
decision_sem :
|
||||
decisions_ue : noms (acronymes) des UE validées, séparées par des virgules.
|
||||
descr_decisions_ue : ' UE acquises: UE1, UE2', ou vide si pas de dec. ou si pas show_uevalid
|
||||
descr_mention : 'Mention Bien', ou vide si pas de mention ou si pas show_mention
|
||||
@ -696,7 +680,7 @@ def etud_descr_situation_semestre(
|
||||
|
||||
# --- Situation et décisions jury
|
||||
|
||||
# demission/inscription ?
|
||||
# démission/inscription ?
|
||||
events = sco_etud.scolar_events_list(
|
||||
cnx, args={"etudid": etudid, "formsemestre_id": formsemestre_id}
|
||||
)
|
||||
@ -763,11 +747,15 @@ def etud_descr_situation_semestre(
|
||||
infos["situation"] += " " + infos["descr_defaillance"]
|
||||
|
||||
dpv = sco_pvjury.dict_pvjury(formsemestre_id, etudids=[etudid])
|
||||
if dpv:
|
||||
infos["decision_sem"] = dpv["decisions"][0]["decision_sem"]
|
||||
else:
|
||||
infos["decision_sem"] = ""
|
||||
|
||||
if not show_decisions:
|
||||
return infos, dpv
|
||||
|
||||
# Decisions de jury:
|
||||
# Décisions de jury:
|
||||
pv = dpv["decisions"][0]
|
||||
dec = ""
|
||||
if pv["decision_sem_descr"]:
|
||||
@ -819,11 +807,15 @@ def formsemestre_bulletinetud(
|
||||
except:
|
||||
sco_etud.log_unknown_etud()
|
||||
raise ScoValueError("étudiant inconnu")
|
||||
# API, donc erreurs admises en ScoValueError
|
||||
sem = sco_formsemestre.get_formsemestre(formsemestre_id, raise_soft_exc=True)
|
||||
|
||||
formsemestre: FormSemestre = FormSemestre.query.get(formsemestre_id)
|
||||
if not formsemestre:
|
||||
# API, donc erreurs admises
|
||||
raise ScoValueError(f"semestre {formsemestre_id} inconnu !")
|
||||
sem = formsemestre.to_dict()
|
||||
|
||||
bulletin = do_formsemestre_bulletinetud(
|
||||
formsemestre_id,
|
||||
formsemestre,
|
||||
etudid,
|
||||
format=format,
|
||||
version=version,
|
||||
@ -835,7 +827,6 @@ def formsemestre_bulletinetud(
|
||||
filename = scu.bul_filename(sem, etud, format)
|
||||
return scu.send_file(bulletin, filename, mime=scu.get_mime_suffix(format)[0])
|
||||
|
||||
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
||||
H = [
|
||||
_formsemestre_bulletinetud_header_html(
|
||||
etud, etudid, sem, formsemestre_id, format, version
|
||||
@ -892,14 +883,14 @@ def can_send_bulletin_by_mail(formsemestre_id):
|
||||
|
||||
|
||||
def do_formsemestre_bulletinetud(
|
||||
formsemestre_id,
|
||||
etudid,
|
||||
formsemestre: FormSemestre,
|
||||
etudid: int,
|
||||
version="long", # short, long, selectedevals
|
||||
format="html",
|
||||
nohtml=False,
|
||||
xml_with_decisions=False, # force decisions dans XML
|
||||
force_publishing=False, # force publication meme si semestre non publie sur "portail"
|
||||
prefer_mail_perso=False, # mails envoyes sur adresse perso si non vide
|
||||
xml_with_decisions=False, # force décisions dans XML
|
||||
force_publishing=False, # force publication meme si semestre non publié sur "portail"
|
||||
prefer_mail_perso=False, # mails envoyés sur adresse perso si non vide
|
||||
):
|
||||
"""Génère le bulletin au format demandé.
|
||||
Retourne: (bul, filigranne)
|
||||
@ -908,7 +899,7 @@ def do_formsemestre_bulletinetud(
|
||||
"""
|
||||
if format == "xml":
|
||||
bul = sco_bulletins_xml.make_xml_formsemestre_bulletinetud(
|
||||
formsemestre_id,
|
||||
formsemestre.id,
|
||||
etudid,
|
||||
xml_with_decisions=xml_with_decisions,
|
||||
force_publishing=force_publishing,
|
||||
@ -919,7 +910,7 @@ def do_formsemestre_bulletinetud(
|
||||
|
||||
elif format == "json":
|
||||
bul = sco_bulletins_json.make_json_formsemestre_bulletinetud(
|
||||
formsemestre_id,
|
||||
formsemestre.id,
|
||||
etudid,
|
||||
xml_with_decisions=xml_with_decisions,
|
||||
force_publishing=force_publishing,
|
||||
@ -927,8 +918,13 @@ def do_formsemestre_bulletinetud(
|
||||
)
|
||||
return bul, ""
|
||||
|
||||
I = formsemestre_bulletinetud_dict(formsemestre_id, etudid)
|
||||
etud = I["etud"]
|
||||
if formsemestre.formation.is_apc():
|
||||
etud = Identite.query.get(etudid)
|
||||
r = bulletin_but.BulletinBUT(formsemestre)
|
||||
I = r.bulletin_etud_complet(etud, formsemestre)
|
||||
else:
|
||||
I = formsemestre_bulletinetud_dict(formsemestre.id, etudid)
|
||||
etud = I["etud"]
|
||||
|
||||
if format == "html":
|
||||
htm, _ = sco_bulletins_generator.make_formsemestre_bulletinetud(
|
||||
@ -954,7 +950,7 @@ def do_formsemestre_bulletinetud(
|
||||
elif format == "pdfmail":
|
||||
# format pdfmail: envoie le pdf par mail a l'etud, et affiche le html
|
||||
# check permission
|
||||
if not can_send_bulletin_by_mail(formsemestre_id):
|
||||
if not can_send_bulletin_by_mail(formsemestre.id):
|
||||
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
||||
|
||||
if nohtml:
|
||||
@ -983,7 +979,7 @@ def do_formsemestre_bulletinetud(
|
||||
) + htm
|
||||
return h, I["filigranne"]
|
||||
#
|
||||
mail_bulletin(formsemestre_id, I, pdfdata, filename, recipient_addr)
|
||||
mail_bulletin(formsemestre.id, I, pdfdata, filename, recipient_addr)
|
||||
emaillink = '<a class="stdlink" href="mailto:%s">%s</a>' % (
|
||||
recipient_addr,
|
||||
recipient_addr,
|
||||
|
@ -99,7 +99,7 @@ def bulletin_get_class_name_displayed(formsemestre_id):
|
||||
return "invalide ! (voir paramètres)"
|
||||
|
||||
|
||||
class BulletinGenerator(object):
|
||||
class BulletinGenerator:
|
||||
"Virtual superclass for PDF bulletin generators" ""
|
||||
# Here some helper methods
|
||||
# see sco_bulletins_standard.BulletinGeneratorStandard subclass for real methods
|
||||
|
@ -61,12 +61,10 @@ from reportlab.platypus.doctemplate import BaseDocTemplate
|
||||
from flask import g, request
|
||||
|
||||
from app import log, ScoValueError
|
||||
from app.comp import res_sem
|
||||
from app.comp.res_common import NotesTableCompat
|
||||
from app.models import FormSemestre
|
||||
|
||||
from app.scodoc import sco_cache
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_codes_parcours
|
||||
from app.scodoc import sco_pdf
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc import sco_etud
|
||||
@ -190,7 +188,7 @@ def get_formsemestre_bulletins_pdf(formsemestre_id, version="selectedevals"):
|
||||
i = 1
|
||||
for etud in formsemestre.get_inscrits(include_demdef=True, order=True):
|
||||
frag, filigranne = sco_bulletins.do_formsemestre_bulletinetud(
|
||||
formsemestre_id,
|
||||
formsemestre,
|
||||
etud.id,
|
||||
format="pdfpart",
|
||||
version=version,
|
||||
@ -239,8 +237,9 @@ def get_etud_bulletins_pdf(etudid, version="selectedevals"):
|
||||
filigrannes = {}
|
||||
i = 1
|
||||
for sem in etud["sems"]:
|
||||
formsemestre = FormSemestre.query.get(sem["formsemestre_id"])
|
||||
frag, filigranne = sco_bulletins.do_formsemestre_bulletinetud(
|
||||
sem["formsemestre_id"],
|
||||
formsemestre,
|
||||
etudid,
|
||||
format="pdfpart",
|
||||
version=version,
|
||||
@ -275,3 +274,16 @@ def get_etud_bulletins_pdf(etudid, version="selectedevals"):
|
||||
)
|
||||
|
||||
return pdfdoc, filename
|
||||
|
||||
|
||||
def get_filigranne(etud_etat: str, prefs) -> str:
|
||||
"""Texte à placer en "filigranne" sur le bulletin pdf"""
|
||||
if etud_etat == scu.DEMISSION:
|
||||
return "Démission"
|
||||
elif etud_etat == sco_codes_parcours.DEF:
|
||||
return "Défaillant"
|
||||
elif (prefs["bul_show_temporary"] and not I["decision_sem"]) or prefs[
|
||||
"bul_show_temporary_forced"
|
||||
]:
|
||||
return prefs["bul_temporary_txt"]
|
||||
return ""
|
||||
|
@ -2114,7 +2114,7 @@ class BasePreferences(object):
|
||||
return form
|
||||
|
||||
|
||||
class SemPreferences(object):
|
||||
class SemPreferences:
|
||||
"""Preferences for a formsemestre"""
|
||||
|
||||
def __init__(self, formsemestre_id=None):
|
||||
@ -2270,9 +2270,8 @@ def doc_preferences():
|
||||
return "\n".join([" | ".join(x) for x in L])
|
||||
|
||||
|
||||
def bulletin_option_affichage(formsemestre_id: int) -> dict:
|
||||
def bulletin_option_affichage(formsemestre_id: int, prefs: SemPreferences) -> dict:
|
||||
"dict avec les options d'affichages (préférences) pour ce semestre"
|
||||
prefs = SemPreferences(formsemestre_id)
|
||||
fields = (
|
||||
"bul_show_abs",
|
||||
"bul_show_abs_modules",
|
||||
|
@ -97,7 +97,8 @@ section>div:nth-child(1){
|
||||
.hide_coef .synthese em,
|
||||
.hide_coef .eval>em,
|
||||
.hide_date_inscr .dateInscription,
|
||||
.hide_ects .ects{
|
||||
.hide_ects .ects,
|
||||
.hide_rangs .rang{
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -158,7 +159,10 @@ section>div:nth-child(1){
|
||||
text-align: right;
|
||||
}
|
||||
.rang{
|
||||
text-decoration: underline var(--couleurIntense);
|
||||
font-weight: bold;
|
||||
}
|
||||
.ue .rang{
|
||||
font-weight: 400;
|
||||
}
|
||||
.decision{
|
||||
margin: 5px 0;
|
||||
@ -186,6 +190,9 @@ section>div:nth-child(1){
|
||||
.synthese h3{
|
||||
background: var(--couleurFondTitresUE);
|
||||
}
|
||||
.synthese .ue>div{
|
||||
text-align: right;
|
||||
}
|
||||
.synthese em,
|
||||
.eval em{
|
||||
opacity: 0.6;
|
||||
@ -308,6 +315,14 @@ h3{
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 700px) {
|
||||
section{
|
||||
padding: 16px;
|
||||
}
|
||||
.syntheseModule, .eval {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
/*.absences{
|
||||
display: grid;
|
||||
grid-template-columns: auto auto;
|
||||
|
@ -254,6 +254,7 @@ class releveBUT extends HTMLElement {
|
||||
</h3>
|
||||
<div>
|
||||
<div class=moyenne>Moyenne : ${dataUE.moyenne?.value || "-"}</div>
|
||||
<div class=rang>Rang : ${dataUE.moyenne?.rang} / ${dataUE.moyenne?.total}</div>
|
||||
<div class=info>
|
||||
Bonus : ${dataUE.bonus || 0} -
|
||||
Malus : ${dataUE.malus || 0}
|
||||
|
@ -1925,7 +1925,7 @@ def formsemestre_bulletins_mailetuds(
|
||||
nb_send = 0
|
||||
for etudid in etudids:
|
||||
h, _ = sco_bulletins.do_formsemestre_bulletinetud(
|
||||
formsemestre_id,
|
||||
formsemestre,
|
||||
etudid,
|
||||
version=version,
|
||||
prefer_mail_perso=prefer_mail_perso,
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- mode: python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
SCOVERSION = "9.1.56"
|
||||
SCOVERSION = "9.2a-57"
|
||||
|
||||
SCONAME = "ScoDoc"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user