forked from ScoDoc/ScoDoc
Compare commits
No commits in common. "4b00a5c8fff04e7cd24d15caa4058f48fe27ebb5" and "0db3acf2719ed4f1c1a27c0d298273884e688753" have entirely different histories.
4b00a5c8ff
...
0db3acf271
@ -70,9 +70,7 @@ def form_ue_choix_niveau(formation: Formation, ue: UniteEns) -> str:
|
|||||||
<div class="ue_choix_niveau">
|
<div class="ue_choix_niveau">
|
||||||
<form id="form_ue_choix_niveau">
|
<form id="form_ue_choix_niveau">
|
||||||
<b>Niveau de compétence associé:</b>
|
<b>Niveau de compétence associé:</b>
|
||||||
<select onchange="set_ue_niveau_competence(this);"
|
<select onchange="set_ue_niveau_competence();" data-setter="{
|
||||||
data-ue_id="{ue.id}"
|
|
||||||
data-setter="{
|
|
||||||
url_for( "notes.set_ue_niveau_competence", scodoc_dept=g.scodoc_dept)
|
url_for( "notes.set_ue_niveau_competence", scodoc_dept=g.scodoc_dept)
|
||||||
}">
|
}">
|
||||||
<option value="" {'selected' if ue.niveau_competence is None else ''}>aucun</option>
|
<option value="" {'selected' if ue.niveau_competence is None else ''}>aucun</option>
|
||||||
@ -85,6 +83,7 @@ def form_ue_choix_niveau(formation: Formation, ue: UniteEns) -> str:
|
|||||||
|
|
||||||
def set_ue_niveau_competence(ue_id: int, niveau_id: int):
|
def set_ue_niveau_competence(ue_id: int, niveau_id: int):
|
||||||
"""Associe le niveau et l'UE"""
|
"""Associe le niveau et l'UE"""
|
||||||
|
log(f"set_ue_niveau_competence( {ue_id}, {niveau_id} )")
|
||||||
ue = UniteEns.query.get_or_404(ue_id)
|
ue = UniteEns.query.get_or_404(ue_id)
|
||||||
|
|
||||||
autres_ues = ue.formation.ues.filter_by(semestre_idx=ue.semestre_idx)
|
autres_ues = ue.formation.ues.filter_by(semestre_idx=ue.semestre_idx)
|
||||||
@ -97,7 +96,6 @@ def set_ue_niveau_competence(ue_id: int, niveau_id: int):
|
|||||||
)
|
)
|
||||||
return "", 409 # conflict
|
return "", 409 # conflict
|
||||||
if niveau_id == "":
|
if niveau_id == "":
|
||||||
niveau = ""
|
|
||||||
# suppression de l'association
|
# suppression de l'association
|
||||||
ue.niveau_competence = None
|
ue.niveau_competence = None
|
||||||
else:
|
else:
|
||||||
@ -105,6 +103,4 @@ def set_ue_niveau_competence(ue_id: int, niveau_id: int):
|
|||||||
ue.niveau_competence = niveau
|
ue.niveau_competence = niveau
|
||||||
db.session.add(ue)
|
db.session.add(ue)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
log(f"set_ue_niveau_competence( {ue}, {niveau} )")
|
|
||||||
|
|
||||||
return "", 204
|
return "", 204
|
||||||
|
@ -326,7 +326,10 @@ class BulletinBUT:
|
|||||||
semestre_infos["ECTS"] = {"acquis": ects_acquis, "total": ects_tot}
|
semestre_infos["ECTS"] = {"acquis": ects_acquis, "total": ects_tot}
|
||||||
if sco_preferences.get_preference("bul_show_decision", formsemestre.id):
|
if sco_preferences.get_preference("bul_show_decision", formsemestre.id):
|
||||||
semestre_infos.update(
|
semestre_infos.update(
|
||||||
sco_bulletins_json.dict_decision_jury(etud, formsemestre)
|
sco_bulletins_json.dict_decision_jury(etud.id, formsemestre.id)
|
||||||
|
)
|
||||||
|
semestre_infos.update(
|
||||||
|
but_validations.dict_decision_jury(etud, formsemestre)
|
||||||
)
|
)
|
||||||
if etat_inscription == scu.INSCRIT:
|
if etat_inscription == scu.INSCRIT:
|
||||||
# moyenne des moyennes générales du semestre
|
# moyenne des moyennes générales du semestre
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
##############################################################################
|
|
||||||
# ScoDoc
|
|
||||||
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
|
||||||
# See LICENSE
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
"""Cursus en BUT
|
|
||||||
|
|
||||||
Classe raccordant avec ScoDoc 7:
|
|
||||||
ScoDoc 7 utilisait sco_cursus_dut.SituationEtudCursus
|
|
||||||
|
|
||||||
Ce module définit une classe SituationEtudCursusBUT
|
|
||||||
avec la même interface.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import Union
|
|
||||||
|
|
||||||
from flask import g, url_for
|
|
||||||
|
|
||||||
from app import db
|
|
||||||
from app import log
|
|
||||||
from app.comp.res_but import ResultatsSemestreBUT
|
|
||||||
from app.comp.res_compat import NotesTableCompat
|
|
||||||
|
|
||||||
from app.comp import res_sem
|
|
||||||
from app.models import formsemestre
|
|
||||||
|
|
||||||
from app.models.but_refcomp import (
|
|
||||||
ApcAnneeParcours,
|
|
||||||
ApcCompetence,
|
|
||||||
ApcNiveau,
|
|
||||||
ApcParcours,
|
|
||||||
ApcParcoursNiveauCompetence,
|
|
||||||
)
|
|
||||||
from app.models import Scolog, ScolarAutorisationInscription
|
|
||||||
from app.models.but_validations import (
|
|
||||||
ApcValidationAnnee,
|
|
||||||
ApcValidationRCUE,
|
|
||||||
RegroupementCoherentUE,
|
|
||||||
)
|
|
||||||
from app.models.etudiants import Identite
|
|
||||||
from app.models.formations import Formation
|
|
||||||
from app.models.formsemestre import FormSemestre, FormSemestreInscription
|
|
||||||
from app.models.ues import UniteEns
|
|
||||||
from app.models.validations import ScolarFormSemestreValidation
|
|
||||||
from app.scodoc import sco_codes_parcours as sco_codes
|
|
||||||
from app.scodoc.sco_codes_parcours import RED, UE_STANDARD
|
|
||||||
from app.scodoc import sco_utils as scu
|
|
||||||
from app.scodoc.sco_exceptions import ScoException, ScoValueError
|
|
||||||
|
|
||||||
from app.scodoc import sco_cursus_dut
|
|
||||||
|
|
||||||
|
|
||||||
class SituationEtudCursusBUT(sco_cursus_dut.SituationEtudCursusClassic):
|
|
||||||
def __init__(self, etud: dict, formsemestre_id: int, res: ResultatsSemestreBUT):
|
|
||||||
super().__init__(etud, formsemestre_id, res)
|
|
||||||
# Ajustements pour le BUT
|
|
||||||
self.can_compensate_with_prev = False # jamais de compensation à la mode DUT
|
|
||||||
|
|
||||||
def check_compensation_dut(self, semc: dict, ntc: NotesTableCompat):
|
|
||||||
"Jamais de compensation façon DUT"
|
|
||||||
return False
|
|
||||||
|
|
||||||
def parcours_validated(self):
|
|
||||||
"True si le parcours est validé"
|
|
||||||
return False # XXX TODO
|
|
@ -101,17 +101,10 @@ def formsemestre_saisie_jury_but(
|
|||||||
f"""<h3>Décisions de jury enregistrées pour les étudiants de ce semestre</h3>
|
f"""<h3>Décisions de jury enregistrées pour les étudiants de ce semestre</h3>
|
||||||
<div class="table_jury_but_links">
|
<div class="table_jury_but_links">
|
||||||
<div>
|
<div>
|
||||||
<ul>
|
<a href="{url_for(
|
||||||
<li><a href="{url_for(
|
|
||||||
"notes.pvjury_table_but",
|
"notes.pvjury_table_but",
|
||||||
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre2.id)
|
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre2.id)
|
||||||
}" class="stdlink">Tableau PV de jury</a>
|
}" class="stdlink">tableau PV de jury</a>
|
||||||
</li>
|
|
||||||
<li><a href="{url_for(
|
|
||||||
"notes.formsemestre_lettres_individuelles",
|
|
||||||
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre2.id)
|
|
||||||
}" class="stdlink">Courriers individuels (classeur pdf)</a>
|
|
||||||
</li>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
@ -118,7 +118,7 @@ class ApcReferentielCompetences(db.Model, XMLModel):
|
|||||||
# self.formations = formations
|
# self.formations = formations
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<ApcReferentielCompetences {self.id} {self.specialite!r} {self.departement!r}>"
|
return f"<ApcReferentielCompetences {self.id} {self.specialite!r}>"
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
"""Représentation complète du ref. de comp.
|
"""Représentation complète du ref. de comp.
|
||||||
@ -348,7 +348,7 @@ class ApcNiveau(db.Model, XMLModel):
|
|||||||
self.app_critiques = app_critiques
|
self.app_critiques = app_critiques
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"""<{self.__class__.__name__} {self.id} ordre={self.ordre!r} annee={
|
return f"""<{self.__class__.__name__} ordre={self.ordre!r} annee={
|
||||||
self.annee!r} {self.competence!r}>"""
|
self.annee!r} {self.competence!r}>"""
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
@ -451,6 +451,7 @@ class ApcAppCritique(db.Model, XMLModel):
|
|||||||
if competence is not None:
|
if competence is not None:
|
||||||
query = query.filter(ApcNiveau.competence == competence)
|
query = query.filter(ApcNiveau.competence == competence)
|
||||||
return query
|
return query
|
||||||
|
<<<<<<< HEAD
|
||||||
|
|
||||||
def __init__(self, id, niveau_id, code, libelle, modules):
|
def __init__(self, id, niveau_id, code, libelle, modules):
|
||||||
self.id = id
|
self.id = id
|
||||||
@ -458,6 +459,8 @@ class ApcAppCritique(db.Model, XMLModel):
|
|||||||
self.code = code
|
self.code = code
|
||||||
self.libelle = libelle
|
self.libelle = libelle
|
||||||
self.modules = modules
|
self.modules = modules
|
||||||
|
=======
|
||||||
|
>>>>>>> 7c340c798ad59c41653efc83bfd079f11fce1938
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
return {"libelle": self.libelle}
|
return {"libelle": self.libelle}
|
||||||
@ -526,7 +529,7 @@ class ApcParcours(db.Model, XMLModel):
|
|||||||
self.annes = annes
|
self.annes = annes
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<{self.__class__.__name__} {self.id} {self.code!r} ref={self.referentiel}>"
|
return f"<{self.__class__.__name__} {self.code!r}>"
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
return {
|
return {
|
||||||
@ -544,14 +547,17 @@ class ApcAnneeParcours(db.Model, XMLModel):
|
|||||||
)
|
)
|
||||||
ordre = db.Column(db.Integer)
|
ordre = db.Column(db.Integer)
|
||||||
"numéro de l'année: 1, 2, 3"
|
"numéro de l'année: 1, 2, 3"
|
||||||
|
<<<<<<< HEAD
|
||||||
|
|
||||||
def __init__(self, id, parcours_id, ordre):
|
def __init__(self, id, parcours_id, ordre):
|
||||||
self.id = id
|
self.id = id
|
||||||
self.parcours_id = parcours_id
|
self.parcours_id = parcours_id
|
||||||
self.ordre = ordre
|
self.ordre = ordre
|
||||||
|
=======
|
||||||
|
>>>>>>> 7c340c798ad59c41653efc83bfd079f11fce1938
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<{self.__class__.__name__} {self.id} ordre={self.ordre!r} parcours={self.parcours.code!r}>"
|
return f"<{self.__class__.__name__} ordre={self.ordre!r} parcours={self.parcours.code!r}>"
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
return {
|
return {
|
||||||
|
@ -67,7 +67,7 @@ class ApcValidationRCUE(db.Model):
|
|||||||
return self.ue2.niveau_competence
|
return self.ue2.niveau_competence
|
||||||
|
|
||||||
def to_dict_bul(self) -> dict:
|
def to_dict_bul(self) -> dict:
|
||||||
"Export dict pour bulletins: le code et le niveau de compétence"
|
"Export dict pour bulletins"
|
||||||
return {"code": self.code, "niveau": self.niveau().to_dict_bul()}
|
return {"code": self.code, "niveau": self.niveau().to_dict_bul()}
|
||||||
|
|
||||||
|
|
||||||
@ -309,9 +309,7 @@ class ApcValidationAnnee(db.Model):
|
|||||||
|
|
||||||
def dict_decision_jury(etud: Identite, formsemestre: FormSemestre) -> dict:
|
def dict_decision_jury(etud: Identite, formsemestre: FormSemestre) -> dict:
|
||||||
"""
|
"""
|
||||||
Un dict avec les décisions de jury BUT enregistrées:
|
Un dict avec les décisions de jury BUT enregistrées.
|
||||||
- decision_rcue : list[dict]
|
|
||||||
- decision_annee : dict
|
|
||||||
Ne reprend pas les décisions d'UE, non spécifiques au BUT.
|
Ne reprend pas les décisions d'UE, non spécifiques au BUT.
|
||||||
"""
|
"""
|
||||||
decisions = {}
|
decisions = {}
|
||||||
@ -322,19 +320,8 @@ def dict_decision_jury(etud: Identite, formsemestre: FormSemestre) -> dict:
|
|||||||
etudid=etud.id, formsemestre_id=formsemestre.id
|
etudid=etud.id, formsemestre_id=formsemestre.id
|
||||||
)
|
)
|
||||||
decisions["decision_rcue"] = [v.to_dict_bul() for v in validations_rcues]
|
decisions["decision_rcue"] = [v.to_dict_bul() for v in validations_rcues]
|
||||||
decisions["descr_decisions_rcue"] = ", ".join(
|
|
||||||
[
|
|
||||||
f"""{dec_rcue["niveau"]["competence"]["titre"]} {dec_rcue["niveau"]["ordre"]}: {dec_rcue["code"]}"""
|
|
||||||
for dec_rcue in decisions["decision_rcue"]
|
|
||||||
]
|
|
||||||
)
|
|
||||||
decisions["descr_decisions_niveaux"] = (
|
|
||||||
"Niveaux de compétences: " + decisions["descr_decisions_rcue"]
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
decisions["decision_rcue"] = []
|
decisions["decision_rcue"] = []
|
||||||
decisions["descr_decisions_rcue"] = ""
|
|
||||||
decisions["descr_decisions_niveaux"] = ""
|
|
||||||
# --- Année: prend la validation pour l'année scolaire de ce semestre
|
# --- Année: prend la validation pour l'année scolaire de ce semestre
|
||||||
validation = (
|
validation = (
|
||||||
ApcValidationAnnee.query.filter_by(
|
ApcValidationAnnee.query.filter_by(
|
||||||
|
@ -31,9 +31,6 @@ class Departement(db.Model):
|
|||||||
"ScoPreference", lazy="dynamic", backref="departement"
|
"ScoPreference", lazy="dynamic", backref="departement"
|
||||||
)
|
)
|
||||||
semsets = db.relationship("NotesSemSet", lazy="dynamic", backref="departement")
|
semsets = db.relationship("NotesSemSet", lazy="dynamic", backref="departement")
|
||||||
referentiels = db.relationship(
|
|
||||||
"ApcReferentielCompetences", lazy="dynamic", backref="departement"
|
|
||||||
)
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<{self.__class__.__name__}(id={self.id}, acronym='{self.acronym}')>"
|
return f"<{self.__class__.__name__}(id={self.id}, acronym='{self.acronym}')>"
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
import datetime
|
import datetime
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
|
|
||||||
from flask import flash, g
|
from flask import flash
|
||||||
import flask_sqlalchemy
|
import flask_sqlalchemy
|
||||||
from sqlalchemy.sql import text
|
from sqlalchemy.sql import text
|
||||||
|
|
||||||
@ -19,11 +19,11 @@ from app.models.but_refcomp import (
|
|||||||
ApcNiveau,
|
ApcNiveau,
|
||||||
ApcParcours,
|
ApcParcours,
|
||||||
ApcParcoursNiveauCompetence,
|
ApcParcoursNiveauCompetence,
|
||||||
ApcReferentielCompetences,
|
|
||||||
)
|
)
|
||||||
from app.models.groups import GroupDescr, Partition
|
from app.models.groups import GroupDescr, Partition
|
||||||
|
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
|
from app.models.but_refcomp import ApcParcours
|
||||||
from app.models.but_refcomp import parcours_formsemestre
|
from app.models.but_refcomp import parcours_formsemestre
|
||||||
from app.models.etudiants import Identite
|
from app.models.etudiants import Identite
|
||||||
from app.models.modules import Module
|
from app.models.modules import Module
|
||||||
@ -599,11 +599,7 @@ class FormSemestre(db.Model):
|
|||||||
)
|
)
|
||||||
# Inscrit les étudiants des groupes de parcours:
|
# Inscrit les étudiants des groupes de parcours:
|
||||||
for group in partition.groups:
|
for group in partition.groups:
|
||||||
query = (
|
query = ApcParcours.query.filter_by(code=group.group_name)
|
||||||
ApcParcours.query.filter_by(code=group.group_name)
|
|
||||||
.join(ApcReferentielCompetences)
|
|
||||||
.filter_by(dept_id=g.scodoc_dept_id)
|
|
||||||
)
|
|
||||||
if query.count() != 1:
|
if query.count() != 1:
|
||||||
log(
|
log(
|
||||||
f"""update_inscriptions_parcours_from_groups: {
|
f"""update_inscriptions_parcours_from_groups: {
|
||||||
|
@ -57,11 +57,6 @@ class ScolarFormSemestreValidation(db.Model):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"{self.__class__.__name__}({self.formsemestre_id}, {self.etudid}, code={self.code}, ue={self.ue}, moy_ue={self.moy_ue})"
|
return f"{self.__class__.__name__}({self.formsemestre_id}, {self.etudid}, code={self.code}, ue={self.ue}, moy_ue={self.moy_ue})"
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
|
||||||
d = dict(self.__dict__)
|
|
||||||
d.pop("_sa_instance_state", None)
|
|
||||||
return d
|
|
||||||
|
|
||||||
|
|
||||||
class ScolarAutorisationInscription(db.Model):
|
class ScolarAutorisationInscription(db.Model):
|
||||||
"""Autorisation d'inscription dans un semestre"""
|
"""Autorisation d'inscription dans un semestre"""
|
||||||
@ -83,11 +78,6 @@ class ScolarAutorisationInscription(db.Model):
|
|||||||
db.ForeignKey("notes_formsemestre.id"),
|
db.ForeignKey("notes_formsemestre.id"),
|
||||||
)
|
)
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
|
||||||
d = dict(self.__dict__)
|
|
||||||
d.pop("_sa_instance_state", None)
|
|
||||||
return d
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def autorise_etud(
|
def autorise_etud(
|
||||||
cls,
|
cls,
|
||||||
@ -156,8 +146,3 @@ class ScolarEvent(db.Model):
|
|||||||
db.Integer,
|
db.Integer,
|
||||||
db.ForeignKey("notes_formsemestre.id"),
|
db.ForeignKey("notes_formsemestre.id"),
|
||||||
)
|
)
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
|
||||||
d = dict(self.__dict__)
|
|
||||||
d.pop("_sa_instance_state", None)
|
|
||||||
return d
|
|
||||||
|
@ -54,22 +54,22 @@ from app.scodoc.sco_codes_parcours import (
|
|||||||
ue_is_fondamentale,
|
ue_is_fondamentale,
|
||||||
ue_is_professionnelle,
|
ue_is_professionnelle,
|
||||||
)
|
)
|
||||||
from app.scodoc import sco_cache
|
from app.scodoc.sco_parcours_dut import formsemestre_get_etud_capitalisation
|
||||||
from app.scodoc import sco_codes_parcours
|
from app.scodoc import sco_codes_parcours
|
||||||
from app.scodoc import sco_compute_moy
|
from app.scodoc import sco_compute_moy
|
||||||
from app.scodoc.sco_cursus import formsemestre_get_etud_capitalisation
|
from app.scodoc import sco_cache
|
||||||
from app.scodoc import sco_cursus_dut
|
|
||||||
from app.scodoc import sco_edit_matiere
|
from app.scodoc import sco_edit_matiere
|
||||||
from app.scodoc import sco_edit_module
|
from app.scodoc import sco_edit_module
|
||||||
from app.scodoc import sco_edit_ue
|
from app.scodoc import sco_edit_ue
|
||||||
from app.scodoc import sco_etud
|
|
||||||
from app.scodoc import sco_evaluations
|
from app.scodoc import sco_evaluations
|
||||||
from app.scodoc import sco_formations
|
from app.scodoc import sco_formations
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
from app.scodoc import sco_formsemestre_inscriptions
|
from app.scodoc import sco_formsemestre_inscriptions
|
||||||
from app.scodoc import sco_groups
|
from app.scodoc import sco_groups
|
||||||
from app.scodoc import sco_moduleimpl
|
from app.scodoc import sco_moduleimpl
|
||||||
|
from app.scodoc import sco_parcours_dut
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
|
from app.scodoc import sco_etud
|
||||||
|
|
||||||
|
|
||||||
def comp_ranks(T):
|
def comp_ranks(T):
|
||||||
@ -1175,7 +1175,7 @@ class NotesTable:
|
|||||||
):
|
):
|
||||||
if not cnx:
|
if not cnx:
|
||||||
cnx = ndb.GetDBConnexion()
|
cnx = ndb.GetDBConnexion()
|
||||||
sco_cursus_dut.do_formsemestre_validate_ue(
|
sco_parcours_dut.do_formsemestre_validate_ue(
|
||||||
cnx,
|
cnx,
|
||||||
nt_cap,
|
nt_cap,
|
||||||
ue_cap["formsemestre_id"],
|
ue_cap["formsemestre_id"],
|
||||||
|
@ -265,9 +265,9 @@ def DBUpdateArgs(cnx, table, vals, where=None, commit=False, convert_empty_to_nu
|
|||||||
cursor.execute(req, vals)
|
cursor.execute(req, vals)
|
||||||
# log('req=%s\n'%req)
|
# log('req=%s\n'%req)
|
||||||
# log('vals=%s\n'%vals)
|
# log('vals=%s\n'%vals)
|
||||||
except psycopg2.errors.StringDataRightTruncation as exc:
|
except psycopg2.errors.StringDataRightTruncation:
|
||||||
cnx.rollback()
|
cnx.rollback()
|
||||||
raise ScoValueError("champs de texte trop long !") from exc
|
raise ScoValueError("champs de texte trop long !")
|
||||||
except:
|
except:
|
||||||
cnx.rollback() # get rid of this transaction
|
cnx.rollback() # get rid of this transaction
|
||||||
log('Exception in DBUpdateArgs:\n\treq="%s"\n\tvals="%s"\n' % (req, vals))
|
log('Exception in DBUpdateArgs:\n\treq="%s"\n\tvals="%s"\n' % (req, vals))
|
||||||
|
@ -112,8 +112,8 @@ from app.scodoc.sco_codes_parcours import (
|
|||||||
NAR,
|
NAR,
|
||||||
RAT,
|
RAT,
|
||||||
)
|
)
|
||||||
from app.scodoc import sco_cursus
|
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
|
from app.scodoc import sco_parcours_dut
|
||||||
from app.scodoc import sco_etud
|
from app.scodoc import sco_etud
|
||||||
|
|
||||||
APO_PORTAL_ENCODING = (
|
APO_PORTAL_ENCODING = (
|
||||||
@ -413,7 +413,7 @@ class ApoEtud(dict):
|
|||||||
export_res_etape = self.export_res_etape
|
export_res_etape = self.export_res_etape
|
||||||
if (not export_res_etape) and cur_sem:
|
if (not export_res_etape) and cur_sem:
|
||||||
# exporte toujours le résultat de l'étape si l'étudiant est diplômé
|
# exporte toujours le résultat de l'étape si l'étudiant est diplômé
|
||||||
Se = sco_cursus.get_situation_etud_cursus(
|
Se = sco_parcours_dut.SituationEtudParcours(
|
||||||
self.etud, cur_sem["formsemestre_id"]
|
self.etud, cur_sem["formsemestre_id"]
|
||||||
)
|
)
|
||||||
export_res_etape = Se.all_other_validated()
|
export_res_etape = Se.all_other_validated()
|
||||||
|
@ -434,7 +434,7 @@ def _get_etud_etat_html(etat: str) -> str:
|
|||||||
elif etat == scu.DEF: # "DEF"
|
elif etat == scu.DEF: # "DEF"
|
||||||
return ' <font color="red">(DEFAILLANT)</font> '
|
return ' <font color="red">(DEFAILLANT)</font> '
|
||||||
else:
|
else:
|
||||||
return f' <font color="red">({etat})</font> '
|
return ' <font color="red">(%s)</font> ' % etat
|
||||||
|
|
||||||
|
|
||||||
def _sort_mod_by_matiere(modlist, nt, etudid):
|
def _sort_mod_by_matiere(modlist, nt, etudid):
|
||||||
@ -707,7 +707,6 @@ def etud_descr_situation_semestre(
|
|||||||
descr_decisions_ue : ' UE acquises: UE1, UE2', ou vide si pas de dec. ou si pas show_uevalid
|
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
|
descr_mention : 'Mention Bien', ou vide si pas de mention ou si pas show_mention
|
||||||
"""
|
"""
|
||||||
# Fonction utilisée par tous les bulletins (APC ou classiques)
|
|
||||||
cnx = ndb.GetDBConnexion()
|
cnx = ndb.GetDBConnexion()
|
||||||
infos = scu.DictDefault(defaultvalue="")
|
infos = scu.DictDefault(defaultvalue="")
|
||||||
|
|
||||||
@ -729,7 +728,8 @@ def etud_descr_situation_semestre(
|
|||||||
# il y a eu une erreur qui a laissé un event 'inscription'
|
# il y a eu une erreur qui a laissé un event 'inscription'
|
||||||
# on l'efface:
|
# on l'efface:
|
||||||
log(
|
log(
|
||||||
f"etud_descr_situation_semestre: removing duplicate INSCRIPTION event for etudid={etudid} !"
|
"etud_descr_situation_semestre: removing duplicate INSCRIPTION event for etudid=%s !"
|
||||||
|
% etudid
|
||||||
)
|
)
|
||||||
sco_etud.scolar_events_delete(cnx, event["event_id"])
|
sco_etud.scolar_events_delete(cnx, event["event_id"])
|
||||||
else:
|
else:
|
||||||
@ -738,7 +738,8 @@ def etud_descr_situation_semestre(
|
|||||||
# assert date_dem == None, 'plusieurs démissions !'
|
# assert date_dem == None, 'plusieurs démissions !'
|
||||||
if date_dem: # cela ne peut pas arriver sauf bug (signale a Evry 2013?)
|
if date_dem: # cela ne peut pas arriver sauf bug (signale a Evry 2013?)
|
||||||
log(
|
log(
|
||||||
f"etud_descr_situation_semestre: removing duplicate DEMISSION event for etudid={etudid} !"
|
"etud_descr_situation_semestre: removing duplicate DEMISSION event for etudid=%s !"
|
||||||
|
% etudid
|
||||||
)
|
)
|
||||||
sco_etud.scolar_events_delete(cnx, event["event_id"])
|
sco_etud.scolar_events_delete(cnx, event["event_id"])
|
||||||
else:
|
else:
|
||||||
@ -746,7 +747,8 @@ def etud_descr_situation_semestre(
|
|||||||
elif event_type == "DEFAILLANCE":
|
elif event_type == "DEFAILLANCE":
|
||||||
if date_def:
|
if date_def:
|
||||||
log(
|
log(
|
||||||
f"etud_descr_situation_semestre: removing duplicate DEFAILLANCE event for etudid={etudid} !"
|
"etud_descr_situation_semestre: removing duplicate DEFAILLANCE event for etudid=%s !"
|
||||||
|
% etudid
|
||||||
)
|
)
|
||||||
sco_etud.scolar_events_delete(cnx, event["event_id"])
|
sco_etud.scolar_events_delete(cnx, event["event_id"])
|
||||||
else:
|
else:
|
||||||
@ -754,10 +756,10 @@ def etud_descr_situation_semestre(
|
|||||||
if show_date_inscr:
|
if show_date_inscr:
|
||||||
if not date_inscr:
|
if not date_inscr:
|
||||||
infos["date_inscription"] = ""
|
infos["date_inscription"] = ""
|
||||||
infos["descr_inscription"] = f"Pas inscrit{ne}."
|
infos["descr_inscription"] = "Pas inscrit%s." % ne
|
||||||
else:
|
else:
|
||||||
infos["date_inscription"] = date_inscr
|
infos["date_inscription"] = date_inscr
|
||||||
infos["descr_inscription"] = f"Inscrit{ne} le {date_inscr}."
|
infos["descr_inscription"] = "Inscrit%s le %s." % (ne, date_inscr)
|
||||||
else:
|
else:
|
||||||
infos["date_inscription"] = ""
|
infos["date_inscription"] = ""
|
||||||
infos["descr_inscription"] = ""
|
infos["descr_inscription"] = ""
|
||||||
@ -765,15 +767,15 @@ def etud_descr_situation_semestre(
|
|||||||
infos["situation"] = infos["descr_inscription"]
|
infos["situation"] = infos["descr_inscription"]
|
||||||
|
|
||||||
if date_dem:
|
if date_dem:
|
||||||
infos["descr_demission"] = f"Démission le {date_dem}."
|
infos["descr_demission"] = "Démission le %s." % date_dem
|
||||||
infos["date_demission"] = date_dem
|
infos["date_demission"] = date_dem
|
||||||
infos["descr_decision_jury"] = "Démission"
|
infos["descr_decision_jury"] = "Démission"
|
||||||
infos["situation"] += " " + infos["descr_demission"]
|
infos["situation"] += " " + infos["descr_demission"]
|
||||||
return infos, None # ne donne pas les dec. de jury pour les demissionnaires
|
return infos, None # ne donne pas les dec. de jury pour les demissionnaires
|
||||||
if date_def:
|
if date_def:
|
||||||
infos["descr_defaillance"] = f"Défaillant{ne}"
|
infos["descr_defaillance"] = "Défaillant%s" % ne
|
||||||
infos["date_defaillance"] = date_def
|
infos["date_defaillance"] = date_def
|
||||||
infos["descr_decision_jury"] = f"Défaillant{ne}"
|
infos["descr_decision_jury"] = "Défaillant%s" % ne
|
||||||
infos["situation"] += " " + infos["descr_defaillance"]
|
infos["situation"] += " " + infos["descr_defaillance"]
|
||||||
|
|
||||||
dpv = sco_pvjury.dict_pvjury(formsemestre_id, etudids=[etudid])
|
dpv = sco_pvjury.dict_pvjury(formsemestre_id, etudids=[etudid])
|
||||||
@ -796,7 +798,6 @@ def etud_descr_situation_semestre(
|
|||||||
dec = infos["descr_decision_jury"]
|
dec = infos["descr_decision_jury"]
|
||||||
else:
|
else:
|
||||||
infos["descr_decision_jury"] = ""
|
infos["descr_decision_jury"] = ""
|
||||||
infos["decision_jury"] = ""
|
|
||||||
|
|
||||||
if pv["decisions_ue_descr"] and show_uevalid:
|
if pv["decisions_ue_descr"] and show_uevalid:
|
||||||
infos["decisions_ue"] = pv["decisions_ue_descr"]
|
infos["decisions_ue"] = pv["decisions_ue_descr"]
|
||||||
@ -808,25 +809,14 @@ def etud_descr_situation_semestre(
|
|||||||
|
|
||||||
infos["mention"] = pv["mention"]
|
infos["mention"] = pv["mention"]
|
||||||
if pv["mention"] and show_mention:
|
if pv["mention"] and show_mention:
|
||||||
dec += f"Mention {pv['mention']}."
|
dec += "Mention " + pv["mention"] + ". "
|
||||||
|
|
||||||
# Décisions APC / BUT
|
|
||||||
if pv.get("decision_annee", {}):
|
|
||||||
infos["descr_decision_annee"] = "Décision année: " + pv.get(
|
|
||||||
"decision_annee", {}
|
|
||||||
).get("code", "")
|
|
||||||
else:
|
|
||||||
infos["descr_decision_annee"] = ""
|
|
||||||
|
|
||||||
infos["descr_decisions_rcue"] = pv.get("descr_decisions_rcue", "")
|
|
||||||
infos["descr_decisions_niveaux"] = pv.get("descr_decisions_niveaux", "")
|
|
||||||
|
|
||||||
infos["situation"] += " " + dec
|
infos["situation"] += " " + dec
|
||||||
if not pv["validation_parcours"]: # parcours non terminé
|
if not pv["validation_parcours"]: # parcours non terminé
|
||||||
if pv["autorisations_descr"]:
|
if pv["autorisations_descr"]:
|
||||||
infos[
|
infos["situation"] += (
|
||||||
"situation"
|
" Autorisé à s'inscrire en %s." % pv["autorisations_descr"]
|
||||||
] += f" Autorisé à s'inscrire en {pv['autorisations_descr']}."
|
)
|
||||||
else:
|
else:
|
||||||
infos["situation"] += " Diplôme obtenu."
|
infos["situation"] += " Diplôme obtenu."
|
||||||
return infos, dpv
|
return infos, dpv
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
"""Génération du bulletin en format JSON
|
"""Génération du bulletin en format JSON (beta, non completement testé)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import datetime
|
import datetime
|
||||||
@ -33,9 +33,8 @@ import json
|
|||||||
|
|
||||||
from app.comp import res_sem
|
from app.comp import res_sem
|
||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.models import but_validations
|
|
||||||
from app.models.etudiants import Identite
|
|
||||||
from app.models.formsemestre import FormSemestre
|
from app.models.formsemestre import FormSemestre
|
||||||
|
from app.models.etudiants import Identite
|
||||||
|
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
import app.scodoc.notesdb as ndb
|
import app.scodoc.notesdb as ndb
|
||||||
@ -140,7 +139,7 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
|
|
||||||
etat_inscription = etud.inscription_etat(formsemestre.id)
|
etat_inscription = etud.inscription_etat(formsemestre.id)
|
||||||
if etat_inscription != scu.INSCRIT:
|
if etat_inscription != scu.INSCRIT:
|
||||||
d.update(dict_decision_jury(etud, formsemestre, with_decisions=True))
|
d.update(dict_decision_jury(etudid, formsemestre_id, with_decisions=True))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
# Groupes:
|
# Groupes:
|
||||||
@ -344,7 +343,9 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
d["absences"] = dict(nbabs=nbabs, nbabsjust=nbabsjust)
|
d["absences"] = dict(nbabs=nbabs, nbabsjust=nbabsjust)
|
||||||
|
|
||||||
# --- Decision Jury
|
# --- Decision Jury
|
||||||
d.update(dict_decision_jury(etud, formsemestre, with_decisions=xml_with_decisions))
|
d.update(
|
||||||
|
dict_decision_jury(etudid, formsemestre_id, with_decisions=xml_with_decisions)
|
||||||
|
)
|
||||||
# --- Appreciations
|
# --- Appreciations
|
||||||
cnx = ndb.GetDBConnexion()
|
cnx = ndb.GetDBConnexion()
|
||||||
apprecs = sco_etud.appreciations_list(
|
apprecs = sco_etud.appreciations_list(
|
||||||
@ -363,9 +364,7 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
def dict_decision_jury(
|
def dict_decision_jury(etudid, formsemestre_id, with_decisions=False) -> dict:
|
||||||
etud: Identite, formsemestre: FormSemestre, with_decisions: bool = False
|
|
||||||
) -> dict:
|
|
||||||
"""dict avec decision pour bulletins json
|
"""dict avec decision pour bulletins json
|
||||||
- decision : décision semestre
|
- decision : décision semestre
|
||||||
- decision_ue : list des décisions UE
|
- decision_ue : list des décisions UE
|
||||||
@ -373,8 +372,6 @@ def dict_decision_jury(
|
|||||||
|
|
||||||
with_decision donne les décision même si bul_show_decision est faux.
|
with_decision donne les décision même si bul_show_decision est faux.
|
||||||
|
|
||||||
Si formation APC, indique aussi validations année et RCUEs
|
|
||||||
|
|
||||||
Exemple:
|
Exemple:
|
||||||
{
|
{
|
||||||
'autorisation_inscription': [{'semestre_id': 4}],
|
'autorisation_inscription': [{'semestre_id': 4}],
|
||||||
@ -400,14 +397,14 @@ def dict_decision_jury(
|
|||||||
|
|
||||||
d = {}
|
d = {}
|
||||||
if (
|
if (
|
||||||
sco_preferences.get_preference("bul_show_decision", formsemestre.id)
|
sco_preferences.get_preference("bul_show_decision", formsemestre_id)
|
||||||
or with_decisions
|
or with_decisions
|
||||||
):
|
):
|
||||||
infos, dpv = sco_bulletins.etud_descr_situation_semestre(
|
infos, dpv = sco_bulletins.etud_descr_situation_semestre(
|
||||||
etud.id,
|
etudid,
|
||||||
formsemestre.id,
|
formsemestre_id,
|
||||||
show_uevalid=sco_preferences.get_preference(
|
show_uevalid=sco_preferences.get_preference(
|
||||||
"bul_show_uevalid", formsemestre.id
|
"bul_show_uevalid", formsemestre_id
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
d["situation"] = infos["situation"]
|
d["situation"] = infos["situation"]
|
||||||
@ -459,7 +456,4 @@ def dict_decision_jury(
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
d["decision"] = dict(code="", etat="DEM")
|
d["decision"] = dict(code="", etat="DEM")
|
||||||
# Ajout jury BUT:
|
|
||||||
if formsemestre.formation.is_apc():
|
|
||||||
d.update(but_validations.dict_decision_jury(etud, formsemestre))
|
|
||||||
return d
|
return d
|
||||||
|
@ -140,23 +140,12 @@ def process_field(field, cdict, style, suppress_empty_pars=False, format="pdf"):
|
|||||||
text = (field or "") % scu.WrapDict(
|
text = (field or "") % scu.WrapDict(
|
||||||
cdict
|
cdict
|
||||||
) # note that None values are mapped to empty strings
|
) # note that None values are mapped to empty strings
|
||||||
except KeyError as exc:
|
except:
|
||||||
log(
|
|
||||||
f"""process_field: KeyError on field={field!r}
|
|
||||||
values={pprint.pformat(cdict)}
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
if len(exc.args) > 0:
|
|
||||||
missing_field = exc.args[0]
|
|
||||||
text = f"""<para><i>format invalide: champs</i> {missing_field} <i>inexistant !</i></para>"""
|
|
||||||
except: # pylint: disable=bare-except
|
|
||||||
log(
|
log(
|
||||||
f"""process_field: invalid format. field={field!r}
|
f"""process_field: invalid format. field={field!r}
|
||||||
values={pprint.pformat(cdict)}
|
values={pprint.pformat(cdict)}
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
# ne sera pas visible si lien vers pdf:
|
|
||||||
scu.flash_once(f"Attention: format PDF invalide (champs {field}")
|
|
||||||
text = (
|
text = (
|
||||||
"<para><i>format invalide !</i></para><para>"
|
"<para><i>format invalide !</i></para><para>"
|
||||||
+ traceback.format_exc()
|
+ traceback.format_exc()
|
||||||
|
@ -231,7 +231,7 @@ def invalidate_formsemestre( # was inval_cache(formsemestre_id=None, pdfonly=Fa
|
|||||||
"""expire cache pour un semestre (ou tous si formsemestre_id non spécifié).
|
"""expire cache pour un semestre (ou tous si formsemestre_id non spécifié).
|
||||||
Si pdfonly, n'expire que les bulletins pdf cachés.
|
Si pdfonly, n'expire que les bulletins pdf cachés.
|
||||||
"""
|
"""
|
||||||
from app.scodoc import sco_cursus
|
from app.scodoc import sco_parcours_dut
|
||||||
|
|
||||||
if getattr(g, "defer_cache_invalidation", False):
|
if getattr(g, "defer_cache_invalidation", False):
|
||||||
g.sem_to_invalidate.add(formsemestre_id)
|
g.sem_to_invalidate.add(formsemestre_id)
|
||||||
@ -252,7 +252,7 @@ def invalidate_formsemestre( # was inval_cache(formsemestre_id=None, pdfonly=Fa
|
|||||||
else:
|
else:
|
||||||
formsemestre_ids = [
|
formsemestre_ids = [
|
||||||
formsemestre_id
|
formsemestre_id
|
||||||
] + sco_cursus.list_formsemestre_utilisateurs_uecap(formsemestre_id)
|
] + sco_parcours_dut.list_formsemestre_utilisateurs_uecap(formsemestre_id)
|
||||||
log(f"----- invalidate_formsemestre: clearing {formsemestre_ids} -----")
|
log(f"----- invalidate_formsemestre: clearing {formsemestre_ids} -----")
|
||||||
|
|
||||||
if not pdfonly:
|
if not pdfonly:
|
||||||
|
@ -216,7 +216,7 @@ def code_semestre_attente(code: str) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
def code_ue_validant(code: str) -> bool:
|
def code_ue_validant(code: str) -> bool:
|
||||||
"Vrai si ce code d'UE est validant (ie attribue les ECTS)"
|
"Vrai si ce code entraine la validation des UEs du semestre."
|
||||||
return CODES_UE_VALIDES.get(code, False)
|
return CODES_UE_VALIDES.get(code, False)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,134 +0,0 @@
|
|||||||
# -*- mode: python -*-
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
##############################################################################
|
|
||||||
#
|
|
||||||
# Gestion scolarite IUT
|
|
||||||
#
|
|
||||||
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
#
|
|
||||||
# Emmanuel Viennet emmanuel.viennet@viennet.net
|
|
||||||
#
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
"""Gestion des cursus (jurys suivant la formation)
|
|
||||||
"""
|
|
||||||
|
|
||||||
from app.but import cursus_but
|
|
||||||
from app.scodoc import sco_cursus_dut
|
|
||||||
|
|
||||||
from app.comp.res_compat import NotesTableCompat
|
|
||||||
from app.comp import res_sem
|
|
||||||
from app.models import FormSemestre
|
|
||||||
from app.scodoc import sco_formsemestre
|
|
||||||
from app.scodoc import sco_formations
|
|
||||||
import app.scodoc.notesdb as ndb
|
|
||||||
|
|
||||||
# SituationEtudParcours -> get_situation_etud_cursus
|
|
||||||
def get_situation_etud_cursus(
|
|
||||||
etud: dict, formsemestre_id: int
|
|
||||||
) -> sco_cursus_dut.SituationEtudCursus:
|
|
||||||
"""renvoie une instance de SituationEtudCursus (ou sous-classe spécialisée)"""
|
|
||||||
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
|
||||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
|
||||||
|
|
||||||
if formsemestre.formation.is_apc():
|
|
||||||
return cursus_but.SituationEtudCursusBUT(etud, formsemestre_id, nt)
|
|
||||||
|
|
||||||
parcours = nt.parcours
|
|
||||||
if parcours.ECTS_ONLY:
|
|
||||||
return sco_cursus_dut.SituationEtudCursusECTS(etud, formsemestre_id, nt)
|
|
||||||
return sco_cursus_dut.SituationEtudCursusClassic(etud, formsemestre_id, nt)
|
|
||||||
|
|
||||||
|
|
||||||
def formsemestre_get_etud_capitalisation(
|
|
||||||
formation_id: int, semestre_idx: int, date_debut, etudid: int
|
|
||||||
) -> list[dict]:
|
|
||||||
"""Liste des UE capitalisées (ADM) correspondant au semestre sem et à l'étudiant.
|
|
||||||
|
|
||||||
Recherche dans les semestres de la même formation (code) avec le même
|
|
||||||
semestre_id et une date de début antérieure à celle du semestre mentionné.
|
|
||||||
Et aussi les UE externes validées.
|
|
||||||
|
|
||||||
Resultat: [ { 'formsemestre_id' :
|
|
||||||
'ue_id' : ue_id dans le semestre origine
|
|
||||||
'ue_code' :
|
|
||||||
'moy_ue' :
|
|
||||||
'event_date' :
|
|
||||||
'is_external'
|
|
||||||
} ]
|
|
||||||
"""
|
|
||||||
cnx = ndb.GetDBConnexion()
|
|
||||||
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
|
||||||
cursor.execute(
|
|
||||||
"""
|
|
||||||
SELECT DISTINCT SFV.*, ue.ue_code
|
|
||||||
FROM notes_ue ue, notes_formations nf,
|
|
||||||
notes_formations nf2, scolar_formsemestre_validation SFV, notes_formsemestre sem
|
|
||||||
|
|
||||||
WHERE ue.formation_id = nf.id
|
|
||||||
and nf.formation_code = nf2.formation_code
|
|
||||||
and nf2.id=%(formation_id)s
|
|
||||||
|
|
||||||
and SFV.ue_id = ue.id
|
|
||||||
and SFV.code = 'ADM'
|
|
||||||
and SFV.etudid = %(etudid)s
|
|
||||||
|
|
||||||
and ( (sem.id = SFV.formsemestre_id
|
|
||||||
and sem.date_debut < %(date_debut)s
|
|
||||||
and sem.semestre_id = %(semestre_id)s )
|
|
||||||
or (
|
|
||||||
((SFV.formsemestre_id is NULL) OR (SFV.is_external)) -- les UE externes ou "anterieures"
|
|
||||||
AND (SFV.semestre_id is NULL OR SFV.semestre_id=%(semestre_id)s)
|
|
||||||
) )
|
|
||||||
""",
|
|
||||||
{
|
|
||||||
"etudid": etudid,
|
|
||||||
"formation_id": formation_id,
|
|
||||||
"semestre_id": semestre_idx,
|
|
||||||
"date_debut": date_debut,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
return cursor.dictfetchall()
|
|
||||||
|
|
||||||
|
|
||||||
def list_formsemestre_utilisateurs_uecap(formsemestre_id):
|
|
||||||
"""Liste des formsemestres pouvant utiliser une UE capitalisee de ce semestre
|
|
||||||
(et qui doivent donc etre sortis du cache si l'on modifie ce
|
|
||||||
semestre): meme code formation, meme semestre_id, date posterieure"""
|
|
||||||
cnx = ndb.GetDBConnexion()
|
|
||||||
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
|
||||||
F = sco_formations.formation_list(args={"formation_id": sem["formation_id"]})[0]
|
|
||||||
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
|
||||||
cursor.execute(
|
|
||||||
"""SELECT sem.id
|
|
||||||
FROM notes_formsemestre sem, notes_formations F
|
|
||||||
WHERE sem.formation_id = F.id
|
|
||||||
and F.formation_code = %(formation_code)s
|
|
||||||
and sem.semestre_id = %(semestre_id)s
|
|
||||||
and sem.date_debut >= %(date_debut)s
|
|
||||||
and sem.id != %(formsemestre_id)s;
|
|
||||||
""",
|
|
||||||
{
|
|
||||||
"formation_code": F["formation_code"],
|
|
||||||
"semestre_id": sem["semestre_id"],
|
|
||||||
"formsemestre_id": formsemestre_id,
|
|
||||||
"date_debut": ndb.DateDMYtoISO(sem["date_debut"]),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
return [x[0] for x in cursor.fetchall()]
|
|
@ -31,7 +31,6 @@ from flask import g, request
|
|||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
|
|
||||||
from app import db
|
from app import db
|
||||||
from app.but import apc_edit_ue
|
|
||||||
from app.models import Formation, UniteEns, Matiere, Module, FormSemestre, ModuleImpl
|
from app.models import Formation, UniteEns, Matiere, Module, FormSemestre, ModuleImpl
|
||||||
from app.models.validations import ScolarFormSemestreValidation
|
from app.models.validations import ScolarFormSemestreValidation
|
||||||
from app.scodoc.sco_codes_parcours import UE_SPORT
|
from app.scodoc.sco_codes_parcours import UE_SPORT
|
||||||
@ -110,7 +109,6 @@ def html_edit_formation_apc(
|
|||||||
icons=icons,
|
icons=icons,
|
||||||
ues_by_sem=ues_by_sem,
|
ues_by_sem=ues_by_sem,
|
||||||
ects_by_sem=ects_by_sem,
|
ects_by_sem=ects_by_sem,
|
||||||
form_ue_choix_niveau=apc_edit_ue.form_ue_choix_niveau,
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
for semestre_idx in semestre_ids:
|
for semestre_idx in semestre_ids:
|
||||||
|
@ -292,25 +292,21 @@ def do_formation_create(args):
|
|||||||
|
|
||||||
def do_formation_edit(args):
|
def do_formation_edit(args):
|
||||||
"edit a formation"
|
"edit a formation"
|
||||||
|
# log('do_formation_edit( args=%s )'%args)
|
||||||
|
|
||||||
|
# On autorise la modif de la formation meme si elle est verrouillee
|
||||||
|
# car cela ne change que du cosmetique, (sauf eventuellement le code formation ?)
|
||||||
|
# mais si verrouillée on ne peut changer le type de parcours
|
||||||
|
if sco_formations.formation_has_locked_sems(args["formation_id"]):
|
||||||
|
if "type_parcours" in args:
|
||||||
|
del args["type_parcours"]
|
||||||
# On ne peut jamais supprimer le code formation:
|
# On ne peut jamais supprimer le code formation:
|
||||||
if "formation_code" in args and not args["formation_code"]:
|
if "formation_code" in args and not args["formation_code"]:
|
||||||
del args["formation_code"]
|
del args["formation_code"]
|
||||||
|
|
||||||
formation: Formation = Formation.query.get_or_404(args["formation_id"])
|
cnx = ndb.GetDBConnexion()
|
||||||
# On autorise la modif de la formation meme si elle est verrouillee
|
sco_formations._formationEditor.edit(cnx, args)
|
||||||
# car cela ne change que du cosmetique, (sauf eventuellement le code formation ?)
|
formation: Formation = Formation.query.get(args["formation_id"])
|
||||||
# mais si verrouillée on ne peut changer le type de parcours
|
|
||||||
if formation.has_locked_sems():
|
|
||||||
if "type_parcours" in args:
|
|
||||||
del args["type_parcours"]
|
|
||||||
|
|
||||||
for field in formation.__dict__:
|
|
||||||
if field and field[0] != "_" and field in args:
|
|
||||||
setattr(formation, field, args[field])
|
|
||||||
|
|
||||||
db.session.add(formation)
|
|
||||||
db.session.commit()
|
|
||||||
formation.invalidate_cached_sems()
|
formation.invalidate_cached_sems()
|
||||||
|
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ def do_ue_create(args):
|
|||||||
|
|
||||||
def do_ue_delete(ue_id, delete_validations=False, force=False):
|
def do_ue_delete(ue_id, delete_validations=False, force=False):
|
||||||
"delete UE and attached matieres (but not modules)"
|
"delete UE and attached matieres (but not modules)"
|
||||||
from app.scodoc import sco_cursus_dut
|
from app.scodoc import sco_parcours_dut
|
||||||
|
|
||||||
ue = UniteEns.query.get_or_404(ue_id)
|
ue = UniteEns.query.get_or_404(ue_id)
|
||||||
formation = ue.formation
|
formation = ue.formation
|
||||||
@ -164,7 +164,7 @@ def do_ue_delete(ue_id, delete_validations=False, force=False):
|
|||||||
# raise ScoLockedFormError()
|
# raise ScoLockedFormError()
|
||||||
# Il y a-t-il des etudiants ayant validé cette UE ?
|
# Il y a-t-il des etudiants ayant validé cette UE ?
|
||||||
# si oui, propose de supprimer les validations
|
# si oui, propose de supprimer les validations
|
||||||
validations = sco_cursus_dut.scolar_formsemestre_validation_list(
|
validations = sco_parcours_dut.scolar_formsemestre_validation_list(
|
||||||
cnx, args={"ue_id": ue.id}
|
cnx, args={"ue_id": ue.id}
|
||||||
)
|
)
|
||||||
if validations and not delete_validations and not force:
|
if validations and not delete_validations and not force:
|
||||||
@ -466,7 +466,7 @@ def ue_edit(ue_id=None, create=False, formation_id=None, default_semestre_idx=No
|
|||||||
+ ue_div
|
+ ue_div
|
||||||
+ html_sco_header.sco_footer()
|
+ html_sco_header.sco_footer()
|
||||||
)
|
)
|
||||||
elif tf[0] == 1:
|
elif tf[2]:
|
||||||
if create:
|
if create:
|
||||||
if not tf[2]["ue_code"]:
|
if not tf[2]["ue_code"]:
|
||||||
del tf[2]["ue_code"]
|
del tf[2]["ue_code"]
|
||||||
@ -684,7 +684,6 @@ def ue_table(formation_id=None, semestre_idx=1, msg=""): # was ue_list
|
|||||||
javascripts=[
|
javascripts=[
|
||||||
"libjs/jinplace-1.2.1.min.js",
|
"libjs/jinplace-1.2.1.min.js",
|
||||||
"js/ue_list.js",
|
"js/ue_list.js",
|
||||||
"js/edit_ue.js",
|
|
||||||
"libjs/jQuery-tagEditor/jquery.tag-editor.min.js",
|
"libjs/jQuery-tagEditor/jquery.tag-editor.min.js",
|
||||||
"libjs/jQuery-tagEditor/jquery.caret.min.js",
|
"libjs/jQuery-tagEditor/jquery.caret.min.js",
|
||||||
"js/module_tag_editor.js",
|
"js/module_tag_editor.js",
|
||||||
|
@ -45,7 +45,6 @@ from openpyxl.worksheet.worksheet import Worksheet
|
|||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app import log
|
from app import log
|
||||||
from app.scodoc.sco_exceptions import ScoValueError
|
from app.scodoc.sco_exceptions import ScoValueError
|
||||||
from app.scodoc import notesdb, sco_preferences
|
|
||||||
|
|
||||||
|
|
||||||
class COLORS(Enum):
|
class COLORS(Enum):
|
||||||
@ -794,7 +793,7 @@ def excel_feuille_listeappel(
|
|||||||
|
|
||||||
# ligne 3
|
# ligne 3
|
||||||
cell_2 = ws.make_cell("Enseignant :", style2)
|
cell_2 = ws.make_cell("Enseignant :", style2)
|
||||||
cell_6 = ws.make_cell(f"Groupe {groupname}", style3)
|
cell_6 = ws.make_cell(("Groupe %s" % groupname), style3)
|
||||||
ws.append_row([None, cell_2, None, None, None, None, cell_6])
|
ws.append_row([None, cell_2, None, None, None, None, cell_6])
|
||||||
|
|
||||||
# ligne 4: Avertissement pour ne pas confondre avec listes notes
|
# ligne 4: Avertissement pour ne pas confondre avec listes notes
|
||||||
|
@ -101,7 +101,7 @@ def get_formsemestre(formsemestre_id, raise_soft_exc=False):
|
|||||||
return g.stored_get_formsemestre[formsemestre_id]
|
return g.stored_get_formsemestre[formsemestre_id]
|
||||||
if not isinstance(formsemestre_id, int):
|
if not isinstance(formsemestre_id, int):
|
||||||
log(f"get_formsemestre: invalid id '{formsemestre_id}'")
|
log(f"get_formsemestre: invalid id '{formsemestre_id}'")
|
||||||
raise ScoInvalidIdType("get_formsemestre: formsemestre_id must be an integer !")
|
raise ScoInvalidIdType("formsemestre_id must be an integer !")
|
||||||
sems = do_formsemestre_list(args={"formsemestre_id": formsemestre_id})
|
sems = do_formsemestre_list(args={"formsemestre_id": formsemestre_id})
|
||||||
if not sems:
|
if not sems:
|
||||||
log("get_formsemestre: invalid formsemestre_id (%s)" % formsemestre_id)
|
log("get_formsemestre: invalid formsemestre_id (%s)" % formsemestre_id)
|
||||||
|
@ -60,7 +60,7 @@ from app.scodoc import sco_formsemestre
|
|||||||
from app.scodoc import sco_groups_copy
|
from app.scodoc import sco_groups_copy
|
||||||
from app.scodoc import sco_modalites
|
from app.scodoc import sco_modalites
|
||||||
from app.scodoc import sco_moduleimpl
|
from app.scodoc import sco_moduleimpl
|
||||||
from app.scodoc import sco_cursus_dut
|
from app.scodoc import sco_parcours_dut
|
||||||
from app.scodoc import sco_permissions_check
|
from app.scodoc import sco_permissions_check
|
||||||
from app.scodoc import sco_portal_apogee
|
from app.scodoc import sco_portal_apogee
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
@ -1362,14 +1362,14 @@ def _reassociate_moduleimpls(cnx, formsemestre_id, ues_old2new, modules_old2new)
|
|||||||
if e["ue_id"]:
|
if e["ue_id"]:
|
||||||
e["ue_id"] = ues_old2new[e["ue_id"]]
|
e["ue_id"] = ues_old2new[e["ue_id"]]
|
||||||
sco_etud.scolar_events_edit(cnx, e)
|
sco_etud.scolar_events_edit(cnx, e)
|
||||||
validations = sco_cursus_dut.scolar_formsemestre_validation_list(
|
validations = sco_parcours_dut.scolar_formsemestre_validation_list(
|
||||||
cnx, args={"formsemestre_id": formsemestre_id}
|
cnx, args={"formsemestre_id": formsemestre_id}
|
||||||
)
|
)
|
||||||
for e in validations:
|
for e in validations:
|
||||||
if e["ue_id"]:
|
if e["ue_id"]:
|
||||||
e["ue_id"] = ues_old2new[e["ue_id"]]
|
e["ue_id"] = ues_old2new[e["ue_id"]]
|
||||||
# log('e=%s' % e )
|
# log('e=%s' % e )
|
||||||
sco_cursus_dut.scolar_formsemestre_validation_edit(cnx, e)
|
sco_parcours_dut.scolar_formsemestre_validation_edit(cnx, e)
|
||||||
|
|
||||||
|
|
||||||
def formsemestre_delete(formsemestre_id):
|
def formsemestre_delete(formsemestre_id):
|
||||||
|
@ -51,7 +51,7 @@ from app.scodoc import sco_formations
|
|||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
from app.scodoc import sco_formsemestre_inscriptions
|
from app.scodoc import sco_formsemestre_inscriptions
|
||||||
from app.scodoc import sco_formsemestre_validation
|
from app.scodoc import sco_formsemestre_validation
|
||||||
from app.scodoc import sco_cursus_dut
|
from app.scodoc import sco_parcours_dut
|
||||||
from app.scodoc import sco_etud
|
from app.scodoc import sco_etud
|
||||||
|
|
||||||
|
|
||||||
@ -450,7 +450,7 @@ def _list_ue_with_coef_and_validations(sem, etudid):
|
|||||||
else:
|
else:
|
||||||
ue["uecoef"] = {}
|
ue["uecoef"] = {}
|
||||||
# add validation
|
# add validation
|
||||||
validation = sco_cursus_dut.scolar_formsemestre_validation_list(
|
validation = sco_parcours_dut.scolar_formsemestre_validation_list(
|
||||||
cnx,
|
cnx,
|
||||||
args={
|
args={
|
||||||
"formsemestre_id": formsemestre_id,
|
"formsemestre_id": formsemestre_id,
|
||||||
|
@ -59,9 +59,8 @@ from app.scodoc import sco_edit_ue
|
|||||||
from app.scodoc import sco_etud
|
from app.scodoc import sco_etud
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
from app.scodoc import sco_formsemestre_inscriptions
|
from app.scodoc import sco_formsemestre_inscriptions
|
||||||
from app.scodoc import sco_cursus
|
from app.scodoc import sco_parcours_dut
|
||||||
from app.scodoc import sco_cursus_dut
|
from app.scodoc.sco_parcours_dut import etud_est_inscrit_ue
|
||||||
from app.scodoc.sco_cursus_dut import etud_est_inscrit_ue
|
|
||||||
from app.scodoc import sco_photos
|
from app.scodoc import sco_photos
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
from app.scodoc import sco_pvjury
|
from app.scodoc import sco_pvjury
|
||||||
@ -109,7 +108,7 @@ def formsemestre_validation_etud_form(
|
|||||||
check = True
|
check = True
|
||||||
|
|
||||||
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
||||||
Se = sco_cursus.get_situation_etud_cursus(etud, formsemestre_id)
|
Se = sco_parcours_dut.SituationEtudParcours(etud, formsemestre_id)
|
||||||
if not Se.sem["etat"]:
|
if not Se.sem["etat"]:
|
||||||
raise ScoValueError("validation: semestre verrouille")
|
raise ScoValueError("validation: semestre verrouille")
|
||||||
|
|
||||||
@ -275,12 +274,15 @@ def formsemestre_validation_etud_form(
|
|||||||
ass = "non assidu"
|
ass = "non assidu"
|
||||||
H.append("<p>Décision existante du %(event_date)s: %(code)s" % decision_jury)
|
H.append("<p>Décision existante du %(event_date)s: %(code)s" % decision_jury)
|
||||||
H.append(" (%s)" % ass)
|
H.append(" (%s)" % ass)
|
||||||
autorisations = ScolarAutorisationInscription.query.filter_by(
|
auts = sco_parcours_dut.formsemestre_get_autorisation_inscription(
|
||||||
etudid=etudid, origin_formsemestre_id=formsemestre_id
|
etudid, formsemestre_id
|
||||||
).all()
|
)
|
||||||
if autorisations:
|
if auts:
|
||||||
H.append(". Autorisé%s à s'inscrire en " % etud["ne"])
|
H.append(". Autorisé%s à s'inscrire en " % etud["ne"])
|
||||||
H.append(", ".join([f"S{aut.semestre_id}" for aut in autorisations]) + ".")
|
alist = []
|
||||||
|
for aut in auts:
|
||||||
|
alist.append(str(aut["semestre_id"]))
|
||||||
|
H.append(", ".join(["S%s" % x for x in alist]) + ".")
|
||||||
H.append("</p>")
|
H.append("</p>")
|
||||||
|
|
||||||
# Cas particulier pour ATJ: corriger precedent avant de continuer
|
# Cas particulier pour ATJ: corriger precedent avant de continuer
|
||||||
@ -380,7 +382,7 @@ def formsemestre_validation_etud(
|
|||||||
):
|
):
|
||||||
"""Enregistre validation"""
|
"""Enregistre validation"""
|
||||||
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
||||||
Se = sco_cursus.get_situation_etud_cursus(etud, formsemestre_id)
|
Se = sco_parcours_dut.SituationEtudParcours(etud, formsemestre_id)
|
||||||
# retrouve la decision correspondant au code:
|
# retrouve la decision correspondant au code:
|
||||||
choices = Se.get_possible_choices(assiduite=True)
|
choices = Se.get_possible_choices(assiduite=True)
|
||||||
choices += Se.get_possible_choices(assiduite=False)
|
choices += Se.get_possible_choices(assiduite=False)
|
||||||
@ -413,7 +415,7 @@ def formsemestre_validation_etud_manu(
|
|||||||
if assidu:
|
if assidu:
|
||||||
assidu = True
|
assidu = True
|
||||||
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
||||||
Se = sco_cursus.get_situation_etud_cursus(etud, formsemestre_id)
|
Se = sco_parcours_dut.SituationEtudParcours(etud, formsemestre_id)
|
||||||
if code_etat in Se.parcours.UNUSED_CODES:
|
if code_etat in Se.parcours.UNUSED_CODES:
|
||||||
raise ScoValueError("code decision invalide dans ce parcours")
|
raise ScoValueError("code decision invalide dans ce parcours")
|
||||||
# Si code ADC, extrait le semestre utilisé:
|
# Si code ADC, extrait le semestre utilisé:
|
||||||
@ -428,7 +430,7 @@ def formsemestre_validation_etud_manu(
|
|||||||
formsemestre_id_utilise_pour_compenser = None
|
formsemestre_id_utilise_pour_compenser = None
|
||||||
|
|
||||||
# Construit le choix correspondant:
|
# Construit le choix correspondant:
|
||||||
choice = sco_cursus_dut.DecisionSem(
|
choice = sco_parcours_dut.DecisionSem(
|
||||||
code_etat=code_etat,
|
code_etat=code_etat,
|
||||||
new_code_prev=new_code_prev,
|
new_code_prev=new_code_prev,
|
||||||
devenir=devenir,
|
devenir=devenir,
|
||||||
@ -908,7 +910,7 @@ def do_formsemestre_validation_auto(formsemestre_id):
|
|||||||
conflicts = [] # liste des etudiants avec decision differente déjà saisie
|
conflicts = [] # liste des etudiants avec decision differente déjà saisie
|
||||||
for etudid in etudids:
|
for etudid in etudids:
|
||||||
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
||||||
Se = sco_cursus.get_situation_etud_cursus(etud, formsemestre_id)
|
Se = sco_parcours_dut.SituationEtudParcours(etud, formsemestre_id)
|
||||||
ins = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(
|
ins = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(
|
||||||
{"etudid": etudid, "formsemestre_id": formsemestre_id}
|
{"etudid": etudid, "formsemestre_id": formsemestre_id}
|
||||||
)[0]
|
)[0]
|
||||||
@ -930,13 +932,15 @@ def do_formsemestre_validation_auto(formsemestre_id):
|
|||||||
if decision_sem and decision_sem["code"] != ADM:
|
if decision_sem and decision_sem["code"] != ADM:
|
||||||
ok = False
|
ok = False
|
||||||
conflicts.append(etud)
|
conflicts.append(etud)
|
||||||
autorisations = ScolarAutorisationInscription.query.filter_by(
|
autorisations = sco_parcours_dut.formsemestre_get_autorisation_inscription(
|
||||||
etudid=etudid, origin_formsemestre_id=formsemestre_id
|
etudid, formsemestre_id
|
||||||
).all()
|
)
|
||||||
if len(autorisations) != 0:
|
if (
|
||||||
|
len(autorisations) != 0
|
||||||
|
): # accepte le cas ou il n'y a pas d'autorisation : BUG 23/6/7, A RETIRER ENSUITE
|
||||||
if (
|
if (
|
||||||
len(autorisations) > 1
|
len(autorisations) != 1
|
||||||
or autorisations[0].semestre_id != next_semestre_id
|
or autorisations[0]["semestre_id"] != next_semestre_id
|
||||||
):
|
):
|
||||||
if ok:
|
if ok:
|
||||||
conflicts.append(etud)
|
conflicts.append(etud)
|
||||||
@ -1172,7 +1176,7 @@ def do_formsemestre_validate_previous_ue(
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
sco_formsemestre.do_formsemestre_uecoef_delete(cnx, formsemestre_id, ue_id)
|
sco_formsemestre.do_formsemestre_uecoef_delete(cnx, formsemestre_id, ue_id)
|
||||||
sco_cursus_dut.do_formsemestre_validate_ue(
|
sco_parcours_dut.do_formsemestre_validate_ue(
|
||||||
cnx,
|
cnx,
|
||||||
nt,
|
nt,
|
||||||
formsemestre_id, # "importe" cette UE dans le semestre (new 3/2015)
|
formsemestre_id, # "importe" cette UE dans le semestre (new 3/2015)
|
||||||
|
@ -56,9 +56,8 @@ import app.scodoc.notesdb as ndb
|
|||||||
from app import log, cache
|
from app import log, cache
|
||||||
from app.scodoc.scolog import logdb
|
from app.scodoc.scolog import logdb
|
||||||
from app.scodoc import html_sco_header
|
from app.scodoc import html_sco_header
|
||||||
from app.scodoc import sco_cache
|
|
||||||
from app.scodoc import sco_codes_parcours
|
from app.scodoc import sco_codes_parcours
|
||||||
from app.scodoc import sco_cursus
|
from app.scodoc import sco_cache
|
||||||
from app.scodoc import sco_etud
|
from app.scodoc import sco_etud
|
||||||
from app.scodoc import sco_permissions_check
|
from app.scodoc import sco_permissions_check
|
||||||
from app.scodoc import sco_xml
|
from app.scodoc import sco_xml
|
||||||
@ -1490,13 +1489,13 @@ def _get_prev_moy(etudid, formsemestre_id):
|
|||||||
"""Donne la derniere moyenne generale calculee pour cette étudiant,
|
"""Donne la derniere moyenne generale calculee pour cette étudiant,
|
||||||
ou 0 si on n'en trouve pas (nouvel inscrit,...).
|
ou 0 si on n'en trouve pas (nouvel inscrit,...).
|
||||||
"""
|
"""
|
||||||
from app.scodoc import sco_cursus_dut
|
from app.scodoc import sco_parcours_dut
|
||||||
|
|
||||||
info = sco_etud.get_etud_info(etudid=etudid, filled=True)
|
info = sco_etud.get_etud_info(etudid=etudid, filled=True)
|
||||||
if not info:
|
if not info:
|
||||||
raise ScoValueError("etudiant invalide: etudid=%s" % etudid)
|
raise ScoValueError("etudiant invalide: etudid=%s" % etudid)
|
||||||
etud = info[0]
|
etud = info[0]
|
||||||
Se = sco_cursus.get_situation_etud_cursus(etud, formsemestre_id)
|
Se = sco_parcours_dut.SituationEtudParcours(etud, formsemestre_id)
|
||||||
if Se.prev:
|
if Se.prev:
|
||||||
prev_sem = FormSemestre.query.get(Se.prev["formsemestre_id"])
|
prev_sem = FormSemestre.query.get(Se.prev["formsemestre_id"])
|
||||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(prev_sem)
|
nt: NotesTableCompat = res_sem.load_formsemestre_results(prev_sem)
|
||||||
|
@ -49,7 +49,7 @@ from app.scodoc import sco_excel
|
|||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
from app.scodoc import sco_groups
|
from app.scodoc import sco_groups
|
||||||
from app.scodoc import sco_moduleimpl
|
from app.scodoc import sco_moduleimpl
|
||||||
from app.scodoc import sco_cursus
|
from app.scodoc import sco_parcours_dut
|
||||||
from app.scodoc import sco_portal_apogee
|
from app.scodoc import sco_portal_apogee
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
from app.scodoc import sco_etud
|
from app.scodoc import sco_etud
|
||||||
@ -776,7 +776,7 @@ def groups_table(
|
|||||||
m.update(etud)
|
m.update(etud)
|
||||||
sco_etud.etud_add_lycee_infos(etud)
|
sco_etud.etud_add_lycee_infos(etud)
|
||||||
# et ajoute le parcours
|
# et ajoute le parcours
|
||||||
Se = sco_cursus.get_situation_etud_cursus(
|
Se = sco_parcours_dut.SituationEtudParcours(
|
||||||
etud, groups_infos.formsemestre_id
|
etud, groups_infos.formsemestre_id
|
||||||
)
|
)
|
||||||
m["parcours"] = Se.get_parcours_descr()
|
m["parcours"] = Se.get_parcours_descr()
|
||||||
|
@ -121,8 +121,7 @@ def _list_dept_logos(dept_id=None, prefix=scu.LOGO_FILE_PREFIX):
|
|||||||
:return: le résultat de la recherche ou None si aucune image trouvée
|
:return: le résultat de la recherche ou None si aucune image trouvée
|
||||||
"""
|
"""
|
||||||
allowed_ext = "|".join(scu.LOGOS_IMAGES_ALLOWED_TYPES)
|
allowed_ext = "|".join(scu.LOGOS_IMAGES_ALLOWED_TYPES)
|
||||||
# parse filename 'logo_<logoname>.<ext> . be carefull: logoname may include '.'
|
filename_parser = re.compile(f"{prefix}([^.]*).({allowed_ext})")
|
||||||
filename_parser = re.compile(f"{prefix}(([^.]*.)+)({allowed_ext})")
|
|
||||||
logos = {}
|
logos = {}
|
||||||
path_dir = Path(scu.SCODOC_LOGOS_DIR)
|
path_dir = Path(scu.SCODOC_LOGOS_DIR)
|
||||||
if dept_id:
|
if dept_id:
|
||||||
@ -136,7 +135,7 @@ def _list_dept_logos(dept_id=None, prefix=scu.LOGO_FILE_PREFIX):
|
|||||||
if os.access(path_dir.joinpath(entry).absolute(), os.R_OK):
|
if os.access(path_dir.joinpath(entry).absolute(), os.R_OK):
|
||||||
result = filename_parser.match(entry.name)
|
result = filename_parser.match(entry.name)
|
||||||
if result:
|
if result:
|
||||||
logoname = result.group(1)[:-1] # retreive logoname from filename (less final dot)
|
logoname = result.group(1)
|
||||||
logos[logoname] = Logo(logoname=logoname, dept_id=dept_id).select()
|
logos[logoname] = Logo(logoname=logoname, dept_id=dept_id).select()
|
||||||
return logos if len(logos.keys()) > 0 else None
|
return logos if len(logos.keys()) > 0 else None
|
||||||
|
|
||||||
@ -192,9 +191,6 @@ class Logo:
|
|||||||
)
|
)
|
||||||
self.mm = "Not initialized: call the select or create function before access"
|
self.mm = "Not initialized: call the select or create function before access"
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
|
||||||
return f"Logo(logoname='{self.logoname}', filename='{self.filename}')"
|
|
||||||
|
|
||||||
def _set_format(self, fmt):
|
def _set_format(self, fmt):
|
||||||
self.suffix = fmt
|
self.suffix = fmt
|
||||||
self.filepath = self.basepath + "." + fmt
|
self.filepath = self.basepath + "." + fmt
|
||||||
|
@ -39,7 +39,7 @@ from app.models import ModuleImpl
|
|||||||
from app.models.evaluations import Evaluation
|
from app.models.evaluations import Evaluation
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app.scodoc.sco_exceptions import ScoInvalidIdType
|
from app.scodoc.sco_exceptions import ScoInvalidIdType
|
||||||
from app.scodoc.sco_cursus_dut import formsemestre_has_decisions
|
from app.scodoc.sco_parcours_dut import formsemestre_has_decisions
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
|
|
||||||
from app.scodoc import html_sco_header
|
from app.scodoc import html_sco_header
|
||||||
|
@ -46,7 +46,7 @@ from app.scodoc import sco_codes_parcours
|
|||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
from app.scodoc import sco_formsemestre_status
|
from app.scodoc import sco_formsemestre_status
|
||||||
from app.scodoc import sco_groups
|
from app.scodoc import sco_groups
|
||||||
from app.scodoc import sco_cursus
|
from app.scodoc import sco_parcours_dut
|
||||||
from app.scodoc import sco_permissions_check
|
from app.scodoc import sco_permissions_check
|
||||||
from app.scodoc import sco_photos
|
from app.scodoc import sco_photos
|
||||||
from app.scodoc import sco_users
|
from app.scodoc import sco_users
|
||||||
@ -269,7 +269,7 @@ def ficheEtud(etudid=None):
|
|||||||
sem_info[sem["formsemestre_id"]] = grlink
|
sem_info[sem["formsemestre_id"]] = grlink
|
||||||
|
|
||||||
if info["sems"]:
|
if info["sems"]:
|
||||||
Se = sco_cursus.get_situation_etud_cursus(etud, info["last_formsemestre_id"])
|
Se = sco_parcours_dut.SituationEtudParcours(etud, info["last_formsemestre_id"])
|
||||||
info["liste_inscriptions"] = formsemestre_recap_parcours_table(
|
info["liste_inscriptions"] = formsemestre_recap_parcours_table(
|
||||||
Se,
|
Se,
|
||||||
etudid,
|
etudid,
|
||||||
|
@ -28,10 +28,9 @@
|
|||||||
"""Semestres: gestion parcours DUT (Arreté du 13 août 2005)
|
"""Semestres: gestion parcours DUT (Arreté du 13 août 2005)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from app import db
|
|
||||||
from app.comp import res_sem
|
from app.comp import res_sem
|
||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.models import FormSemestre, UniteEns, ScolarAutorisationInscription
|
from app.models import FormSemestre, UniteEns
|
||||||
|
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
import app.scodoc.notesdb as ndb
|
import app.scodoc.notesdb as ndb
|
||||||
@ -106,14 +105,27 @@ class DecisionSem(object):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
# xxx debug
|
||||||
|
# log('%s: %s %s %s %s %s' % (self.codechoice,code_etat,new_code_prev,formsemestre_id_utilise_pour_compenser,devenir,assiduite) )
|
||||||
|
|
||||||
|
|
||||||
class SituationEtudCursus:
|
def SituationEtudParcours(etud: dict, formsemestre_id: int):
|
||||||
"Semestre dans un cursus"
|
"""renvoie une instance de SituationEtudParcours (ou sous-classe spécialisée)"""
|
||||||
pass
|
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
|
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||||
|
|
||||||
|
# if formsemestre.formation.is_apc():
|
||||||
|
# return SituationEtudParcoursBUT(etud, formsemestre_id, nt)
|
||||||
|
|
||||||
|
parcours = nt.parcours
|
||||||
|
#
|
||||||
|
if parcours.ECTS_ONLY:
|
||||||
|
return SituationEtudParcoursECTS(etud, formsemestre_id, nt)
|
||||||
|
else:
|
||||||
|
return SituationEtudParcoursGeneric(etud, formsemestre_id, nt)
|
||||||
|
|
||||||
|
|
||||||
class SituationEtudCursusClassic(SituationEtudCursus):
|
class SituationEtudParcoursGeneric:
|
||||||
"Semestre dans un parcours"
|
"Semestre dans un parcours"
|
||||||
|
|
||||||
def __init__(self, etud: dict, formsemestre_id: int, nt: NotesTableCompat):
|
def __init__(self, etud: dict, formsemestre_id: int, nt: NotesTableCompat):
|
||||||
@ -341,7 +353,9 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
)[0]["formation_code"]
|
)[0]["formation_code"]
|
||||||
# si sem peut servir à compenser le semestre courant, positionne
|
# si sem peut servir à compenser le semestre courant, positionne
|
||||||
# can_compensate
|
# can_compensate
|
||||||
sem["can_compensate"] = self.check_compensation_dut(sem, nt)
|
sem["can_compensate"] = check_compensation(
|
||||||
|
self.etudid, self.sem, self.nt, sem, nt
|
||||||
|
)
|
||||||
|
|
||||||
self.ue_acros = list(ue_acros.keys())
|
self.ue_acros = list(ue_acros.keys())
|
||||||
self.ue_acros.sort()
|
self.ue_acros.sort()
|
||||||
@ -440,7 +454,8 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
break
|
break
|
||||||
if not cur or cur["formsemestre_id"] != self.formsemestre_id:
|
if not cur or cur["formsemestre_id"] != self.formsemestre_id:
|
||||||
log(
|
log(
|
||||||
f"*** SituationEtudCursus: search_prev: cur not found (formsemestre_id={self.formsemestre_id}, etudid={self.etudid})"
|
"*** SituationEtudParcours: search_prev: cur not found (formsemestre_id=%s, etudid=%s)"
|
||||||
|
% (self.formsemestre_id, self.etudid)
|
||||||
)
|
)
|
||||||
return None # pas de semestre courant !!!
|
return None # pas de semestre courant !!!
|
||||||
# Cherche semestre antérieur de même formation (code) et semestre_id precedent
|
# Cherche semestre antérieur de même formation (code) et semestre_id precedent
|
||||||
@ -618,27 +633,31 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
formsemestre_id=self.prev["formsemestre_id"]
|
formsemestre_id=self.prev["formsemestre_id"]
|
||||||
) # > modif decisions jury (sem, UE)
|
) # > modif decisions jury (sem, UE)
|
||||||
|
|
||||||
|
# -- supprime autorisations venant de ce formsemestre
|
||||||
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
try:
|
try:
|
||||||
# -- Supprime autorisations venant de ce formsemestre
|
cursor.execute(
|
||||||
autorisations = ScolarAutorisationInscription.query.filter_by(
|
"""delete from scolar_autorisation_inscription
|
||||||
etudid=self.etudid, origin_formsemestre_id=self.formsemestre_id
|
where etudid = %(etudid)s and origin_formsemestre_id=%(origin_formsemestre_id)s
|
||||||
|
""",
|
||||||
|
{"etudid": self.etudid, "origin_formsemestre_id": self.formsemestre_id},
|
||||||
)
|
)
|
||||||
for autorisation in autorisations:
|
|
||||||
db.session.delete(autorisation)
|
# -- enregistre autorisations inscription
|
||||||
db.session.flush()
|
|
||||||
# -- Enregistre autorisations inscription
|
|
||||||
next_semestre_ids = self.get_next_semestre_ids(decision.devenir)
|
next_semestre_ids = self.get_next_semestre_ids(decision.devenir)
|
||||||
for next_semestre_id in next_semestre_ids:
|
for next_semestre_id in next_semestre_ids:
|
||||||
autorisation = ScolarAutorisationInscription(
|
_scolar_autorisation_inscription_editor.create(
|
||||||
etudid=self.etudid,
|
cnx,
|
||||||
formation_code=self.formation.formation_code,
|
{
|
||||||
semestre_id=next_semestre_id,
|
"etudid": self.etudid,
|
||||||
origin_formsemestre_id=self.formsemestre_id,
|
"formation_code": self.formation.formation_code,
|
||||||
|
"semestre_id": next_semestre_id,
|
||||||
|
"origin_formsemestre_id": self.formsemestre_id,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
db.session.add(autorisation)
|
cnx.commit()
|
||||||
db.session.commit()
|
|
||||||
except:
|
except:
|
||||||
cnx.session.rollback()
|
cnx.rollback()
|
||||||
raise
|
raise
|
||||||
sco_cache.invalidate_formsemestre(
|
sco_cache.invalidate_formsemestre(
|
||||||
formsemestre_id=self.formsemestre_id
|
formsemestre_id=self.formsemestre_id
|
||||||
@ -653,52 +672,12 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
formsemestre_id=formsemestre_id
|
formsemestre_id=formsemestre_id
|
||||||
) # > modif decision jury
|
) # > modif decision jury
|
||||||
|
|
||||||
def check_compensation_dut(self, semc: dict, ntc: NotesTableCompat):
|
|
||||||
"""Compensations DUT
|
|
||||||
Vérifie si le semestre sem peut se compenser en utilisant semc
|
|
||||||
- semc non utilisé par un autre semestre
|
|
||||||
- decision du jury prise ADM ou ADJ ou ATT ou ADC
|
|
||||||
- barres UE (moy ue > 8) dans sem et semc
|
|
||||||
- moyenne des moy_gen > 10
|
|
||||||
Return boolean
|
|
||||||
"""
|
|
||||||
# -- deja utilise ?
|
|
||||||
decc = ntc.get_etud_decision_sem(self.etudid)
|
|
||||||
if (
|
|
||||||
decc
|
|
||||||
and decc["compense_formsemestre_id"]
|
|
||||||
and decc["compense_formsemestre_id"] != self.sem["formsemestre_id"]
|
|
||||||
):
|
|
||||||
return False
|
|
||||||
# -- semestres consecutifs ?
|
|
||||||
if abs(self.sem["semestre_id"] - semc["semestre_id"]) != 1:
|
|
||||||
return False
|
|
||||||
# -- decision jury:
|
|
||||||
if decc and not decc["code"] in (ADM, ADJ, ATT, ADC):
|
|
||||||
return False
|
|
||||||
# -- barres UE et moyenne des moyennes:
|
|
||||||
moy_gen = self.nt.get_etud_moy_gen(self.etudid)
|
|
||||||
moy_genc = ntc.get_etud_moy_gen(self.etudid)
|
|
||||||
try:
|
|
||||||
moy_moy = (moy_gen + moy_genc) / 2
|
|
||||||
except: # un des semestres sans aucune note !
|
|
||||||
return False
|
|
||||||
|
|
||||||
if (
|
class SituationEtudParcoursECTS(SituationEtudParcoursGeneric):
|
||||||
self.nt.etud_check_conditions_ues(self.etudid)[0]
|
|
||||||
and ntc.etud_check_conditions_ues(self.etudid)[0]
|
|
||||||
and moy_moy >= NOTES_BARRE_GEN_COMPENSATION
|
|
||||||
):
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class SituationEtudCursusECTS(SituationEtudCursusClassic):
|
|
||||||
"""Gestion parcours basés sur ECTS"""
|
"""Gestion parcours basés sur ECTS"""
|
||||||
|
|
||||||
def __init__(self, etud, formsemestre_id, nt):
|
def __init__(self, etud, formsemestre_id, nt):
|
||||||
SituationEtudCursusClassic.__init__(self, etud, formsemestre_id, nt)
|
SituationEtudParcoursGeneric.__init__(self, etud, formsemestre_id, nt)
|
||||||
|
|
||||||
def could_be_compensated(self):
|
def could_be_compensated(self):
|
||||||
return False # jamais de compensations dans ce parcours
|
return False # jamais de compensations dans ce parcours
|
||||||
@ -739,6 +718,47 @@ class SituationEtudCursusECTS(SituationEtudCursusClassic):
|
|||||||
return choices
|
return choices
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
def check_compensation(etudid, sem, nt, semc, ntc):
|
||||||
|
"""Verifie si le semestre sem peut se compenser en utilisant semc
|
||||||
|
- semc non utilisé par un autre semestre
|
||||||
|
- decision du jury prise ADM ou ADJ ou ATT ou ADC
|
||||||
|
- barres UE (moy ue > 8) dans sem et semc
|
||||||
|
- moyenne des moy_gen > 10
|
||||||
|
Return boolean
|
||||||
|
"""
|
||||||
|
# -- deja utilise ?
|
||||||
|
decc = ntc.get_etud_decision_sem(etudid)
|
||||||
|
if (
|
||||||
|
decc
|
||||||
|
and decc["compense_formsemestre_id"]
|
||||||
|
and decc["compense_formsemestre_id"] != sem["formsemestre_id"]
|
||||||
|
):
|
||||||
|
return False
|
||||||
|
# -- semestres consecutifs ?
|
||||||
|
if abs(sem["semestre_id"] - semc["semestre_id"]) != 1:
|
||||||
|
return False
|
||||||
|
# -- decision jury:
|
||||||
|
if decc and not decc["code"] in (ADM, ADJ, ATT, ADC):
|
||||||
|
return False
|
||||||
|
# -- barres UE et moyenne des moyennes:
|
||||||
|
moy_gen = nt.get_etud_moy_gen(etudid)
|
||||||
|
moy_genc = ntc.get_etud_moy_gen(etudid)
|
||||||
|
try:
|
||||||
|
moy_moy = (moy_gen + moy_genc) / 2
|
||||||
|
except: # un des semestres sans aucune note !
|
||||||
|
return False
|
||||||
|
|
||||||
|
if (
|
||||||
|
nt.etud_check_conditions_ues(etudid)[0]
|
||||||
|
and ntc.etud_check_conditions_ues(etudid)[0]
|
||||||
|
and moy_moy >= NOTES_BARRE_GEN_COMPENSATION
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
@ -1012,3 +1032,102 @@ def etud_est_inscrit_ue(cnx, etudid, formsemestre_id, ue_id):
|
|||||||
)
|
)
|
||||||
|
|
||||||
return len(cursor.fetchall())
|
return len(cursor.fetchall())
|
||||||
|
|
||||||
|
|
||||||
|
_scolar_autorisation_inscription_editor = ndb.EditableTable(
|
||||||
|
"scolar_autorisation_inscription",
|
||||||
|
"autorisation_inscription_id",
|
||||||
|
("etudid", "formation_code", "semestre_id", "date", "origin_formsemestre_id"),
|
||||||
|
output_formators={"date": ndb.DateISOtoDMY},
|
||||||
|
input_formators={"date": ndb.DateDMYtoISO},
|
||||||
|
)
|
||||||
|
scolar_autorisation_inscription_list = _scolar_autorisation_inscription_editor.list
|
||||||
|
|
||||||
|
|
||||||
|
def formsemestre_get_autorisation_inscription(etudid, origin_formsemestre_id):
|
||||||
|
"""Liste des autorisations d'inscription pour cet étudiant
|
||||||
|
émanant du semestre indiqué.
|
||||||
|
"""
|
||||||
|
cnx = ndb.GetDBConnexion()
|
||||||
|
return scolar_autorisation_inscription_list(
|
||||||
|
cnx, {"origin_formsemestre_id": origin_formsemestre_id, "etudid": etudid}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def formsemestre_get_etud_capitalisation(
|
||||||
|
formation_id: int, semestre_idx: int, date_debut, etudid: int
|
||||||
|
) -> list[dict]:
|
||||||
|
"""Liste des UE capitalisées (ADM) correspondant au semestre sem et à l'étudiant.
|
||||||
|
|
||||||
|
Recherche dans les semestres de la même formation (code) avec le même
|
||||||
|
semestre_id et une date de début antérieure à celle du semestre mentionné.
|
||||||
|
Et aussi les UE externes validées.
|
||||||
|
|
||||||
|
Resultat: [ { 'formsemestre_id' :
|
||||||
|
'ue_id' : ue_id dans le semestre origine
|
||||||
|
'ue_code' :
|
||||||
|
'moy_ue' :
|
||||||
|
'event_date' :
|
||||||
|
'is_external'
|
||||||
|
} ]
|
||||||
|
"""
|
||||||
|
cnx = ndb.GetDBConnexion()
|
||||||
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
|
cursor.execute(
|
||||||
|
"""
|
||||||
|
SELECT DISTINCT SFV.*, ue.ue_code
|
||||||
|
FROM notes_ue ue, notes_formations nf,
|
||||||
|
notes_formations nf2, scolar_formsemestre_validation SFV, notes_formsemestre sem
|
||||||
|
|
||||||
|
WHERE ue.formation_id = nf.id
|
||||||
|
and nf.formation_code = nf2.formation_code
|
||||||
|
and nf2.id=%(formation_id)s
|
||||||
|
|
||||||
|
and SFV.ue_id = ue.id
|
||||||
|
and SFV.code = 'ADM'
|
||||||
|
and SFV.etudid = %(etudid)s
|
||||||
|
|
||||||
|
and ( (sem.id = SFV.formsemestre_id
|
||||||
|
and sem.date_debut < %(date_debut)s
|
||||||
|
and sem.semestre_id = %(semestre_id)s )
|
||||||
|
or (
|
||||||
|
((SFV.formsemestre_id is NULL) OR (SFV.is_external)) -- les UE externes ou "anterieures"
|
||||||
|
AND (SFV.semestre_id is NULL OR SFV.semestre_id=%(semestre_id)s)
|
||||||
|
) )
|
||||||
|
""",
|
||||||
|
{
|
||||||
|
"etudid": etudid,
|
||||||
|
"formation_id": formation_id,
|
||||||
|
"semestre_id": semestre_idx,
|
||||||
|
"date_debut": date_debut,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return cursor.dictfetchall()
|
||||||
|
|
||||||
|
|
||||||
|
def list_formsemestre_utilisateurs_uecap(formsemestre_id):
|
||||||
|
"""Liste des formsemestres pouvant utiliser une UE capitalisee de ce semestre
|
||||||
|
(et qui doivent donc etre sortis du cache si l'on modifie ce
|
||||||
|
semestre): meme code formation, meme semestre_id, date posterieure"""
|
||||||
|
cnx = ndb.GetDBConnexion()
|
||||||
|
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
||||||
|
F = sco_formations.formation_list(args={"formation_id": sem["formation_id"]})[0]
|
||||||
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
|
cursor.execute(
|
||||||
|
"""SELECT sem.id
|
||||||
|
FROM notes_formsemestre sem, notes_formations F
|
||||||
|
WHERE sem.formation_id = F.id
|
||||||
|
and F.formation_code = %(formation_code)s
|
||||||
|
and sem.semestre_id = %(semestre_id)s
|
||||||
|
and sem.date_debut >= %(date_debut)s
|
||||||
|
and sem.id != %(formsemestre_id)s;
|
||||||
|
""",
|
||||||
|
{
|
||||||
|
"formation_code": F["formation_code"],
|
||||||
|
"semestre_id": sem["semestre_id"],
|
||||||
|
"formsemestre_id": formsemestre_id,
|
||||||
|
"date_debut": ndb.DateDMYtoISO(sem["date_debut"]),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return [x[0] for x in cursor.fetchall()]
|
@ -55,7 +55,6 @@ from reportlab.lib import styles
|
|||||||
|
|
||||||
from flask import g
|
from flask import g
|
||||||
|
|
||||||
from app.scodoc import sco_utils as scu
|
|
||||||
from app.scodoc.sco_utils import CONFIG
|
from app.scodoc.sco_utils import CONFIG
|
||||||
from app import log
|
from app import log
|
||||||
from app.scodoc.sco_exceptions import ScoGenError, ScoValueError
|
from app.scodoc.sco_exceptions import ScoGenError, ScoValueError
|
||||||
@ -68,7 +67,7 @@ PAGE_WIDTH = defaultPageSize[0]
|
|||||||
DEFAULT_PDF_FOOTER_TEMPLATE = CONFIG.DEFAULT_PDF_FOOTER_TEMPLATE
|
DEFAULT_PDF_FOOTER_TEMPLATE = CONFIG.DEFAULT_PDF_FOOTER_TEMPLATE
|
||||||
|
|
||||||
|
|
||||||
def SU(s: str) -> str:
|
def SU(s):
|
||||||
"convert s from string to string suitable for ReportLab"
|
"convert s from string to string suitable for ReportLab"
|
||||||
if not s:
|
if not s:
|
||||||
return ""
|
return ""
|
||||||
@ -146,9 +145,9 @@ def makeParas(txt, style, suppress_empty=False):
|
|||||||
) from e
|
) from e
|
||||||
else:
|
else:
|
||||||
raise e
|
raise e
|
||||||
except Exception as exc:
|
except Exception as e:
|
||||||
log(traceback.format_exc())
|
log(traceback.format_exc())
|
||||||
log(f"Invalid pdf para format: {txt}")
|
log("Invalid pdf para format: %s" % txt)
|
||||||
try:
|
try:
|
||||||
result = [
|
result = [
|
||||||
Paragraph(
|
Paragraph(
|
||||||
@ -156,14 +155,13 @@ def makeParas(txt, style, suppress_empty=False):
|
|||||||
style,
|
style,
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
except ValueError as exc2: # probleme font ? essaye sans style
|
except ValueError as e: # probleme font ? essaye sans style
|
||||||
# recupere font en cause ?
|
# recupere font en cause ?
|
||||||
m = re.match(r".*family/bold/italic for (.*)", e.args[0], re.DOTALL)
|
m = re.match(r".*family/bold/italic for (.*)", e.args[0], re.DOTALL)
|
||||||
if m:
|
if m:
|
||||||
message = f"police non disponible: {m[1]}"
|
message = f"police non disponible: {m[1]}"
|
||||||
else:
|
else:
|
||||||
message = "format invalide"
|
message = "format invalide"
|
||||||
scu.flash_once(f"problème génération PDF: {message}")
|
|
||||||
return [
|
return [
|
||||||
Paragraph(
|
Paragraph(
|
||||||
SU(f'<font color="red"><b>Erreur: {message}</b></font>'),
|
SU(f'<font color="red"><b>Erreur: {message}</b></font>'),
|
||||||
|
@ -24,14 +24,14 @@ def can_edit_notes(authuser, moduleimpl_id, allow_ens=True):
|
|||||||
seul le directeur des études peut saisir des notes (et il ne devrait pas).
|
seul le directeur des études peut saisir des notes (et il ne devrait pas).
|
||||||
"""
|
"""
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
from app.scodoc import sco_cursus_dut
|
from app.scodoc import sco_parcours_dut
|
||||||
|
|
||||||
M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=moduleimpl_id)[0]
|
M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=moduleimpl_id)[0]
|
||||||
sem = sco_formsemestre.get_formsemestre(M["formsemestre_id"])
|
sem = sco_formsemestre.get_formsemestre(M["formsemestre_id"])
|
||||||
if not sem["etat"]:
|
if not sem["etat"]:
|
||||||
return False # semestre verrouillé
|
return False # semestre verrouillé
|
||||||
|
|
||||||
if sco_cursus_dut.formsemestre_has_decisions(sem["formsemestre_id"]):
|
if sco_parcours_dut.formsemestre_has_decisions(sem["formsemestre_id"]):
|
||||||
# il y a des décisions de jury dans ce semestre !
|
# il y a des décisions de jury dans ce semestre !
|
||||||
return (
|
return (
|
||||||
authuser.has_permission(Permission.ScoEditAllNotes)
|
authuser.has_permission(Permission.ScoEditAllNotes)
|
||||||
|
@ -37,14 +37,14 @@ from flask_login import current_user
|
|||||||
|
|
||||||
from app.comp import res_sem
|
from app.comp import res_sem
|
||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.models import FormSemestre, Identite, ScolarAutorisationInscription
|
from app.models import FormSemestre, Identite
|
||||||
from app.scodoc import sco_abs
|
from app.scodoc import sco_abs
|
||||||
from app.scodoc import sco_codes_parcours
|
from app.scodoc import sco_codes_parcours
|
||||||
from app.scodoc import sco_groups
|
from app.scodoc import sco_groups
|
||||||
from app.scodoc import sco_etud
|
from app.scodoc import sco_etud
|
||||||
from app.scodoc import sco_excel
|
from app.scodoc import sco_excel
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
from app.scodoc import sco_cursus
|
from app.scodoc import sco_parcours_dut
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
import sco_version
|
import sco_version
|
||||||
@ -78,7 +78,7 @@ def feuille_preparation_jury(formsemestre_id):
|
|||||||
nbabs = {}
|
nbabs = {}
|
||||||
nbabsjust = {}
|
nbabsjust = {}
|
||||||
for etud in etuds:
|
for etud in etuds:
|
||||||
Se = sco_cursus.get_situation_etud_cursus(
|
Se = sco_parcours_dut.SituationEtudParcours(
|
||||||
etud.to_dict_scodoc7(), formsemestre_id
|
etud.to_dict_scodoc7(), formsemestre_id
|
||||||
)
|
)
|
||||||
if Se.prev:
|
if Se.prev:
|
||||||
@ -103,14 +103,14 @@ def feuille_preparation_jury(formsemestre_id):
|
|||||||
moy[etud.id] = nt.get_etud_moy_gen(etud.id)
|
moy[etud.id] = nt.get_etud_moy_gen(etud.id)
|
||||||
for ue in nt.get_ues_stat_dict(filter_sport=True):
|
for ue in nt.get_ues_stat_dict(filter_sport=True):
|
||||||
ue_status = nt.get_etud_ue_status(etud.id, ue["ue_id"])
|
ue_status = nt.get_etud_ue_status(etud.id, ue["ue_id"])
|
||||||
ue_code_s = f'{ue["ue_code"]}_{nt.sem["semestre_id"]}'
|
ue_code_s = ue["ue_code"] + "_%s" % nt.sem["semestre_id"]
|
||||||
moy_ue[ue_code_s][etud.id] = ue_status["moy"] if ue_status else ""
|
moy_ue[ue_code_s][etud.id] = ue_status["moy"] if ue_status else ""
|
||||||
ue_acro[ue_code_s] = (ue["numero"], ue["acronyme"], ue["titre"])
|
ue_acro[ue_code_s] = (ue["numero"], ue["acronyme"], ue["titre"])
|
||||||
|
|
||||||
if Se.prev:
|
if Se.prev:
|
||||||
try:
|
try:
|
||||||
moy_inter[etud.id] = (moy[etud.id] + prev_moy[etud.id]) / 2.0
|
moy_inter[etud.id] = (moy[etud.id] + prev_moy[etud.id]) / 2.0
|
||||||
except (KeyError, TypeError):
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
decision = nt.get_etud_decision_sem(etud.id)
|
decision = nt.get_etud_decision_sem(etud.id)
|
||||||
@ -119,13 +119,10 @@ def feuille_preparation_jury(formsemestre_id):
|
|||||||
if decision["compense_formsemestre_id"]:
|
if decision["compense_formsemestre_id"]:
|
||||||
code[etud.id] += "+" # indique qu'il a servi a compenser
|
code[etud.id] += "+" # indique qu'il a servi a compenser
|
||||||
assidu[etud.id] = {False: "Non", True: "Oui"}.get(decision["assidu"], "")
|
assidu[etud.id] = {False: "Non", True: "Oui"}.get(decision["assidu"], "")
|
||||||
|
aut_list = sco_parcours_dut.formsemestre_get_autorisation_inscription(
|
||||||
autorisations_etud = ScolarAutorisationInscription.query.filter_by(
|
etud.id, formsemestre_id
|
||||||
etudid=etud.id, origin_formsemestre_id=formsemestre_id
|
|
||||||
).all()
|
|
||||||
autorisations[etud.id] = ", ".join(
|
|
||||||
[f"S{x.semestre_id}" for x in autorisations_etud]
|
|
||||||
)
|
)
|
||||||
|
autorisations[etud.id] = ", ".join(["S%s" % x["semestre_id"] for x in aut_list])
|
||||||
# parcours:
|
# parcours:
|
||||||
parcours[etud.id] = Se.get_parcours_descr()
|
parcours[etud.id] = Se.get_parcours_descr()
|
||||||
# groupe principal (td)
|
# groupe principal (td)
|
||||||
@ -156,11 +153,11 @@ def feuille_preparation_jury(formsemestre_id):
|
|||||||
sid = sem["semestre_id"]
|
sid = sem["semestre_id"]
|
||||||
sn = sp = ""
|
sn = sp = ""
|
||||||
if sid >= 0:
|
if sid >= 0:
|
||||||
sn = f"S{sid}"
|
sn = "S%s" % sid
|
||||||
if prev_moy: # si qq chose dans precedent
|
if prev_moy: # si qq chose dans precedent
|
||||||
sp = f"S{sid - 1}"
|
sp = "S%s" % (sid - 1)
|
||||||
|
|
||||||
sheet = sco_excel.ScoExcelSheet(sheet_name=f"Prepa Jury {sn}")
|
ws = sco_excel.ScoExcelSheet(sheet_name="Prepa Jury %s" % sn)
|
||||||
# génération des styles
|
# génération des styles
|
||||||
style_bold = sco_excel.excel_make_style(size=10, bold=True)
|
style_bold = sco_excel.excel_make_style(size=10, bold=True)
|
||||||
style_center = sco_excel.excel_make_style(halign="center")
|
style_center = sco_excel.excel_make_style(halign="center")
|
||||||
@ -176,10 +173,10 @@ def feuille_preparation_jury(formsemestre_id):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Première ligne
|
# Première ligne
|
||||||
sheet.append_single_cell_row(
|
ws.append_single_cell_row(
|
||||||
"Feuille préparation Jury %s" % scu.unescape_html(sem["titreannee"]), style_bold
|
"Feuille préparation Jury %s" % scu.unescape_html(sem["titreannee"]), style_bold
|
||||||
)
|
)
|
||||||
sheet.append_blank_row()
|
ws.append_blank_row()
|
||||||
|
|
||||||
# Ligne de titre
|
# Ligne de titre
|
||||||
titles = ["Rang"]
|
titles = ["Rang"]
|
||||||
@ -201,25 +198,25 @@ def feuille_preparation_jury(formsemestre_id):
|
|||||||
]
|
]
|
||||||
if prev_moy: # si qq chose dans precedent
|
if prev_moy: # si qq chose dans precedent
|
||||||
titles += [prev_ue_acro[x][1] for x in ue_prev_codes] + [
|
titles += [prev_ue_acro[x][1] for x in ue_prev_codes] + [
|
||||||
f"Moy {sp}",
|
"Moy %s" % sp,
|
||||||
f"Décision {sp}",
|
"Décision %s" % sp,
|
||||||
]
|
]
|
||||||
titles += [ue_acro[x][1] for x in ue_codes] + [f"Moy {sn}"]
|
titles += [ue_acro[x][1] for x in ue_codes] + ["Moy %s" % sn]
|
||||||
if moy_inter:
|
if moy_inter:
|
||||||
titles += [f"Moy {sp}-{sn}"]
|
titles += ["Moy %s-%s" % (sp, sn)]
|
||||||
titles += ["Abs", "Abs Injust."]
|
titles += ["Abs", "Abs Injust."]
|
||||||
if code:
|
if code:
|
||||||
titles.append("Proposit. {sn}")
|
titles.append("Proposit. %s" % sn)
|
||||||
if autorisations:
|
if autorisations:
|
||||||
titles.append("Autorisations")
|
titles.append("Autorisations")
|
||||||
# titles.append('Assidu')
|
# titles.append('Assidu')
|
||||||
sheet.append_row(sheet.make_row(titles, style_boldcenter))
|
ws.append_row(ws.make_row(titles, style_boldcenter))
|
||||||
# if prev_moy:
|
if prev_moy:
|
||||||
# tit_prev_moy = "Moy " + sp
|
tit_prev_moy = "Moy " + sp
|
||||||
# # col_prev_moy = titles.index(tit_prev_moy)
|
col_prev_moy = titles.index(tit_prev_moy)
|
||||||
# tit_moy = "Moy " + sn
|
tit_moy = "Moy " + sn
|
||||||
# col_moy = titles.index(tit_moy)
|
col_moy = titles.index(tit_moy)
|
||||||
# col_abs = titles.index("Abs")
|
col_abs = titles.index("Abs")
|
||||||
|
|
||||||
def fmt(x):
|
def fmt(x):
|
||||||
"reduit les notes a deux chiffres"
|
"reduit les notes a deux chiffres"
|
||||||
@ -232,13 +229,13 @@ def feuille_preparation_jury(formsemestre_id):
|
|||||||
i = 1 # numero etudiant
|
i = 1 # numero etudiant
|
||||||
for etud in etuds:
|
for etud in etuds:
|
||||||
cells = []
|
cells = []
|
||||||
cells.append(sheet.make_cell(str(i)))
|
cells.append(ws.make_cell(str(i)))
|
||||||
if sco_preferences.get_preference("prepa_jury_nip"):
|
if sco_preferences.get_preference("prepa_jury_nip"):
|
||||||
cells.append(sheet.make_cell(etud.code_nip))
|
cells.append(ws.make_cell(etud.code_nip))
|
||||||
if sco_preferences.get_preference("prepa_jury_ine"):
|
if sco_preferences.get_preference("prepa_jury_ine"):
|
||||||
cells.append(sheet.make_cell(etud.code_ine))
|
cells.append(ws.make_cell(etud.code_ine))
|
||||||
admission = etud.admission.first()
|
admission = etud.admission.first()
|
||||||
cells += sheet.make_row(
|
cells += ws.make_row(
|
||||||
[
|
[
|
||||||
etud.id,
|
etud.id,
|
||||||
etud.civilite_str,
|
etud.civilite_str,
|
||||||
@ -256,52 +253,50 @@ def feuille_preparation_jury(formsemestre_id):
|
|||||||
if prev_moy:
|
if prev_moy:
|
||||||
for ue_acro in ue_prev_codes:
|
for ue_acro in ue_prev_codes:
|
||||||
cells.append(
|
cells.append(
|
||||||
sheet.make_cell(
|
ws.make_cell(
|
||||||
fmt(prev_moy_ue.get(ue_acro, {}).get(etud.id, "")), style_note
|
fmt(prev_moy_ue.get(ue_acro, {}).get(etud.id, "")), style_note
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
co += 1
|
co += 1
|
||||||
cells.append(
|
cells.append(
|
||||||
sheet.make_cell(fmt(prev_moy.get(etud.id, "")), style_bold)
|
ws.make_cell(fmt(prev_moy.get(etud.id, "")), style_bold)
|
||||||
) # moy gen prev
|
) # moy gen prev
|
||||||
cells.append(
|
cells.append(
|
||||||
sheet.make_cell(fmt(prev_code.get(etud.id, "")), style_moy)
|
ws.make_cell(fmt(prev_code.get(etud.id, "")), style_moy)
|
||||||
) # decision prev
|
) # decision prev
|
||||||
co += 2
|
co += 2
|
||||||
|
|
||||||
for ue_acro in ue_codes:
|
for ue_acro in ue_codes:
|
||||||
cells.append(
|
cells.append(
|
||||||
sheet.make_cell(
|
ws.make_cell(fmt(moy_ue.get(ue_acro, {}).get(etud.id, "")), style_note)
|
||||||
fmt(moy_ue.get(ue_acro, {}).get(etud.id, "")), style_note
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
co += 1
|
co += 1
|
||||||
cells.append(
|
cells.append(
|
||||||
sheet.make_cell(fmt(moy.get(etud.id, "")), style_note_bold)
|
ws.make_cell(fmt(moy.get(etud.id, "")), style_note_bold)
|
||||||
) # moy gen
|
) # moy gen
|
||||||
co += 1
|
co += 1
|
||||||
if moy_inter:
|
if moy_inter:
|
||||||
cells.append(sheet.make_cell(fmt(moy_inter.get(etud.id, "")), style_note))
|
cells.append(ws.make_cell(fmt(moy_inter.get(etud.id, "")), style_note))
|
||||||
cells.append(sheet.make_cell(str(nbabs.get(etud.id, "")), style_center))
|
cells.append(ws.make_cell(str(nbabs.get(etud.id, "")), style_center))
|
||||||
cells.append(sheet.make_cell(str(nbabsjust.get(etud.id, "")), style_center))
|
cells.append(ws.make_cell(str(nbabsjust.get(etud.id, "")), style_center))
|
||||||
if code:
|
if code:
|
||||||
cells.append(sheet.make_cell(code.get(etud.id, ""), style_moy))
|
cells.append(ws.make_cell(code.get(etud.id, ""), style_moy))
|
||||||
cells.append(sheet.make_cell(autorisations.get(etud.id, ""), style_moy))
|
cells.append(ws.make_cell(autorisations.get(etud.id, ""), style_moy))
|
||||||
# l.append(assidu.get(etud.id, ''))
|
# l.append(assidu.get(etud.id, ''))
|
||||||
sheet.append_row(cells)
|
ws.append_row(cells)
|
||||||
i += 1
|
i += 1
|
||||||
#
|
#
|
||||||
sheet.append_blank_row()
|
ws.append_blank_row()
|
||||||
# Explications des codes
|
# Explications des codes
|
||||||
codes = list(sco_codes_parcours.CODES_EXPL.keys())
|
codes = list(sco_codes_parcours.CODES_EXPL.keys())
|
||||||
codes.sort()
|
codes.sort()
|
||||||
sheet.append_single_cell_row("Explication des codes")
|
ws.append_single_cell_row("Explication des codes")
|
||||||
for code in codes:
|
for code in codes:
|
||||||
sheet.append_row(
|
ws.append_row(
|
||||||
sheet.make_row(["", "", "", code, sco_codes_parcours.CODES_EXPL[code]])
|
ws.make_row(["", "", "", code, sco_codes_parcours.CODES_EXPL[code]])
|
||||||
)
|
)
|
||||||
sheet.append_row(
|
ws.append_row(
|
||||||
sheet.make_row(
|
ws.make_row(
|
||||||
[
|
[
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
@ -312,16 +307,16 @@ def feuille_preparation_jury(formsemestre_id):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
# UE : Correspondances acronyme et titre complet
|
# UE : Correspondances acronyme et titre complet
|
||||||
sheet.append_blank_row()
|
ws.append_blank_row()
|
||||||
sheet.append_single_cell_row("Titre des UE")
|
ws.append_single_cell_row("Titre des UE")
|
||||||
if prev_moy:
|
if prev_moy:
|
||||||
for ue in ntp.get_ues_stat_dict(filter_sport=True):
|
for ue in ntp.get_ues_stat_dict(filter_sport=True):
|
||||||
sheet.append_row(sheet.make_row(["", "", "", ue["acronyme"], ue["titre"]]))
|
ws.append_row(ws.make_row(["", "", "", ue["acronyme"], ue["titre"]]))
|
||||||
for ue in nt.get_ues_stat_dict(filter_sport=True):
|
for ue in nt.get_ues_stat_dict(filter_sport=True):
|
||||||
sheet.append_row(sheet.make_row(["", "", "", ue["acronyme"], ue["titre"]]))
|
ws.append_row(ws.make_row(["", "", "", ue["acronyme"], ue["titre"]]))
|
||||||
#
|
#
|
||||||
sheet.append_blank_row()
|
ws.append_blank_row()
|
||||||
sheet.append_single_cell_row(
|
ws.append_single_cell_row(
|
||||||
"Préparé par %s le %s sur %s pour %s"
|
"Préparé par %s le %s sur %s pour %s"
|
||||||
% (
|
% (
|
||||||
sco_version.SCONAME,
|
sco_version.SCONAME,
|
||||||
@ -330,7 +325,7 @@ def feuille_preparation_jury(formsemestre_id):
|
|||||||
current_user,
|
current_user,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
xls = sheet.generate()
|
xls = ws.generate()
|
||||||
flash("Feuille préparation jury générée")
|
flash("Feuille préparation jury générée")
|
||||||
return scu.send_file(
|
return scu.send_file(
|
||||||
xls,
|
xls,
|
||||||
|
@ -57,38 +57,32 @@ from flask import g, request
|
|||||||
|
|
||||||
from app.comp import res_sem
|
from app.comp import res_sem
|
||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.models import (
|
from app.models import FormSemestre, UniteEns
|
||||||
FormSemestre,
|
|
||||||
UniteEns,
|
|
||||||
ScolarAutorisationInscription,
|
|
||||||
but_validations,
|
|
||||||
)
|
|
||||||
from app.models.etudiants import Identite
|
|
||||||
|
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
import app.scodoc.notesdb as ndb
|
import app.scodoc.notesdb as ndb
|
||||||
from app import log
|
from app import log
|
||||||
from app.scodoc import html_sco_header
|
from app.scodoc import html_sco_header
|
||||||
from app.scodoc import sco_codes_parcours
|
from app.scodoc import sco_codes_parcours
|
||||||
from app.scodoc import sco_cursus
|
from app.scodoc import sco_cache
|
||||||
from app.scodoc import sco_cursus_dut
|
|
||||||
from app.scodoc import sco_edit_ue
|
from app.scodoc import sco_edit_ue
|
||||||
from app.scodoc import sco_etud
|
|
||||||
from app.scodoc import sco_formations
|
from app.scodoc import sco_formations
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
from app.scodoc import sco_groups
|
from app.scodoc import sco_groups
|
||||||
from app.scodoc import sco_groups_view
|
from app.scodoc import sco_groups_view
|
||||||
|
from app.scodoc import sco_parcours_dut
|
||||||
from app.scodoc import sco_pdf
|
from app.scodoc import sco_pdf
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
from app.scodoc import sco_pvpdf
|
from app.scodoc import sco_pvpdf
|
||||||
|
from app.scodoc import sco_etud
|
||||||
from app.scodoc.gen_tables import GenTable
|
from app.scodoc.gen_tables import GenTable
|
||||||
from app.scodoc.sco_codes_parcours import NO_SEMESTRE_ID
|
from app.scodoc.sco_codes_parcours import NO_SEMESTRE_ID
|
||||||
from app.scodoc.sco_pdf import PDFLOCK
|
from app.scodoc.sco_pdf import PDFLOCK
|
||||||
from app.scodoc.TrivialFormulator import TrivialFormulator
|
from app.scodoc.TrivialFormulator import TrivialFormulator
|
||||||
|
|
||||||
|
|
||||||
def _descr_decisions_ues(nt, etudid, decisions_ue, decision_sem) -> list[dict]:
|
def _descr_decisions_ues(nt, etudid, decisions_ue, decision_sem):
|
||||||
"""Liste des UE validées dans ce semestre (incluant les UE capitalisées)"""
|
"""Liste des UE validées dans ce semestre"""
|
||||||
if not decisions_ue:
|
if not decisions_ue:
|
||||||
return []
|
return []
|
||||||
uelist = []
|
uelist = []
|
||||||
@ -96,20 +90,17 @@ def _descr_decisions_ues(nt, etudid, decisions_ue, decision_sem) -> list[dict]:
|
|||||||
for ue_id in decisions_ue.keys():
|
for ue_id in decisions_ue.keys():
|
||||||
try:
|
try:
|
||||||
if decisions_ue[ue_id] and (
|
if decisions_ue[ue_id] and (
|
||||||
sco_codes_parcours.code_ue_validant(decisions_ue[ue_id]["code"])
|
decisions_ue[ue_id]["code"] == sco_codes_parcours.ADM
|
||||||
or (
|
or (
|
||||||
# XXX ceci devrait dépendre du parcours et non pas être une option ! #sco8
|
# XXX ceci devrait dépendre du parcours et non pas être une option ! #sco8
|
||||||
decision_sem
|
scu.CONFIG.CAPITALIZE_ALL_UES
|
||||||
and scu.CONFIG.CAPITALIZE_ALL_UES
|
|
||||||
and sco_codes_parcours.code_semestre_validant(decision_sem["code"])
|
and sco_codes_parcours.code_semestre_validant(decision_sem["code"])
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
ue = sco_edit_ue.ue_list(args={"ue_id": ue_id})[0]
|
ue = sco_edit_ue.ue_list(args={"ue_id": ue_id})[0]
|
||||||
uelist.append(ue)
|
uelist.append(ue)
|
||||||
except:
|
except:
|
||||||
log(
|
log("descr_decisions_ues: ue_id=%s decisions_ue=%s" % (ue_id, decisions_ue))
|
||||||
f"Exception in descr_decisions_ues: ue_id={ue_id} decisions_ue={decisions_ue}"
|
|
||||||
)
|
|
||||||
# Les UE capitalisées dans d'autres semestres:
|
# Les UE capitalisées dans d'autres semestres:
|
||||||
if etudid in nt.validations.ue_capitalisees.index:
|
if etudid in nt.validations.ue_capitalisees.index:
|
||||||
for ue_id in nt.validations.ue_capitalisees.loc[[etudid]]["ue_id"]:
|
for ue_id in nt.validations.ue_capitalisees.loc[[etudid]]["ue_id"]:
|
||||||
@ -147,9 +138,12 @@ def _descr_decision_sem_abbrev(etat, decision_sem):
|
|||||||
return decision
|
return decision
|
||||||
|
|
||||||
|
|
||||||
def descr_autorisations(autorisations: list[ScolarAutorisationInscription]) -> str:
|
def descr_autorisations(autorisations):
|
||||||
"résumé textuel des autorisations d'inscription (-> 'S1, S3' )"
|
"résumé textuel des autorisations d'inscription (-> 'S1, S3' )"
|
||||||
return ", ".join([f"S{a.semestre_id}" for a in autorisations])
|
alist = []
|
||||||
|
for aut in autorisations:
|
||||||
|
alist.append("S" + str(aut["semestre_id"]))
|
||||||
|
return ", ".join(alist)
|
||||||
|
|
||||||
|
|
||||||
def _comp_ects_by_ue_code(nt, decision_ues):
|
def _comp_ects_by_ue_code(nt, decision_ues):
|
||||||
@ -239,11 +233,8 @@ def dict_pvjury(
|
|||||||
L = []
|
L = []
|
||||||
D = {} # même chose que L, mais { etudid : dec }
|
D = {} # même chose que L, mais { etudid : dec }
|
||||||
for etudid in etudids:
|
for etudid in etudids:
|
||||||
# etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
||||||
etud: Identite = Identite.query.get(etudid)
|
Se = sco_parcours_dut.SituationEtudParcours(etud, formsemestre_id)
|
||||||
Se = sco_cursus.get_situation_etud_cursus(
|
|
||||||
etud.to_dict_scodoc7(), formsemestre_id
|
|
||||||
)
|
|
||||||
semestre_non_terminal = semestre_non_terminal or Se.semestre_non_terminal
|
semestre_non_terminal = semestre_non_terminal or Se.semestre_non_terminal
|
||||||
d = {}
|
d = {}
|
||||||
d["identite"] = nt.identdict[etudid]
|
d["identite"] = nt.identdict[etudid]
|
||||||
@ -252,8 +243,6 @@ def dict_pvjury(
|
|||||||
) # I|D|DEF (inscription ou démission ou défaillant)
|
) # I|D|DEF (inscription ou démission ou défaillant)
|
||||||
d["decision_sem"] = nt.get_etud_decision_sem(etudid)
|
d["decision_sem"] = nt.get_etud_decision_sem(etudid)
|
||||||
d["decisions_ue"] = nt.get_etud_decision_ues(etudid)
|
d["decisions_ue"] = nt.get_etud_decision_ues(etudid)
|
||||||
if formsemestre.formation.is_apc():
|
|
||||||
d.update(but_validations.dict_decision_jury(etud, formsemestre))
|
|
||||||
d["last_formsemestre_id"] = Se.get_semestres()[
|
d["last_formsemestre_id"] = Se.get_semestres()[
|
||||||
-1
|
-1
|
||||||
] # id du dernier semestre (chronologiquement) dans lequel il a été inscrit
|
] # id du dernier semestre (chronologiquement) dans lequel il a été inscrit
|
||||||
@ -291,18 +280,17 @@ def dict_pvjury(
|
|||||||
else:
|
else:
|
||||||
d["decision_sem_descr"] = _descr_decision_sem(d["etat"], d["decision_sem"])
|
d["decision_sem_descr"] = _descr_decision_sem(d["etat"], d["decision_sem"])
|
||||||
|
|
||||||
autorisations = ScolarAutorisationInscription.query.filter_by(
|
d["autorisations"] = sco_parcours_dut.formsemestre_get_autorisation_inscription(
|
||||||
etudid=etudid, origin_formsemestre_id=formsemestre_id
|
etudid, formsemestre_id
|
||||||
).all()
|
)
|
||||||
d["autorisations"] = [a.to_dict() for a in autorisations]
|
d["autorisations_descr"] = descr_autorisations(d["autorisations"])
|
||||||
d["autorisations_descr"] = descr_autorisations(autorisations)
|
|
||||||
|
|
||||||
d["validation_parcours"] = Se.parcours_validated()
|
d["validation_parcours"] = Se.parcours_validated()
|
||||||
d["parcours"] = Se.get_parcours_descr(filter_futur=True)
|
d["parcours"] = Se.get_parcours_descr(filter_futur=True)
|
||||||
if with_parcours_decisions:
|
if with_parcours_decisions:
|
||||||
d["parcours_decisions"] = Se.get_parcours_decisions()
|
d["parcours_decisions"] = Se.get_parcours_decisions()
|
||||||
# Observations sur les compensations:
|
# Observations sur les compensations:
|
||||||
compensators = sco_cursus_dut.scolar_formsemestre_validation_list(
|
compensators = sco_parcours_dut.scolar_formsemestre_validation_list(
|
||||||
cnx, args={"compense_formsemestre_id": formsemestre_id, "etudid": etudid}
|
cnx, args={"compense_formsemestre_id": formsemestre_id, "etudid": etudid}
|
||||||
)
|
)
|
||||||
obs = []
|
obs = []
|
||||||
@ -319,7 +307,12 @@ def dict_pvjury(
|
|||||||
d["decision_sem"]["compense_formsemestre_id"]
|
d["decision_sem"]["compense_formsemestre_id"]
|
||||||
)
|
)
|
||||||
obs.append(
|
obs.append(
|
||||||
f"""{sem["sem_id_txt"]} compense {compensed["sem_id_txt"]} ({compensed["anneescolaire"]})"""
|
"%s compense %s (%s)"
|
||||||
|
% (
|
||||||
|
sem["sem_id_txt"],
|
||||||
|
compensed["sem_id_txt"],
|
||||||
|
compensed["anneescolaire"],
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
d["observation"] = ", ".join(obs)
|
d["observation"] = ", ".join(obs)
|
||||||
|
@ -30,11 +30,9 @@
|
|||||||
import io
|
import io
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from PIL import Image as PILImage
|
|
||||||
|
|
||||||
import reportlab
|
import reportlab
|
||||||
from reportlab.lib.units import cm, mm
|
from reportlab.lib.units import cm, mm
|
||||||
from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_JUSTIFY
|
from reportlab.lib.enums import TA_RIGHT, TA_JUSTIFY
|
||||||
from reportlab.platypus import Paragraph, Spacer, Frame, PageBreak
|
from reportlab.platypus import Paragraph, Spacer, Frame, PageBreak
|
||||||
from reportlab.platypus import Table, TableStyle, Image
|
from reportlab.platypus import Table, TableStyle, Image
|
||||||
from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate
|
from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate
|
||||||
@ -43,16 +41,16 @@ from reportlab.lib import styles
|
|||||||
from reportlab.lib.colors import Color
|
from reportlab.lib.colors import Color
|
||||||
|
|
||||||
from flask import g
|
from flask import g
|
||||||
from app.models import FormSemestre, Identite
|
|
||||||
|
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app.scodoc import sco_bulletins_pdf
|
from app.scodoc import sco_bulletins_pdf
|
||||||
from app.scodoc import sco_codes_parcours
|
from app.scodoc import sco_codes_parcours
|
||||||
from app.scodoc import sco_etud
|
from app.scodoc import sco_etud
|
||||||
|
from app.scodoc import sco_formsemestre
|
||||||
from app.scodoc import sco_pdf
|
from app.scodoc import sco_pdf
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
from app.scodoc.sco_logos import find_logo
|
from app.scodoc.sco_logos import find_logo
|
||||||
from app.scodoc.sco_cursus_dut import SituationEtudCursus
|
from app.scodoc.sco_parcours_dut import SituationEtudParcours
|
||||||
from app.scodoc.sco_pdf import SU
|
from app.scodoc.sco_pdf import SU
|
||||||
import sco_version
|
import sco_version
|
||||||
|
|
||||||
@ -127,7 +125,6 @@ def page_footer(canvas, doc, logo, preferences, with_page_numbers=True):
|
|||||||
|
|
||||||
|
|
||||||
def page_header(canvas, doc, logo, preferences, only_on_first_page=False):
|
def page_header(canvas, doc, logo, preferences, only_on_first_page=False):
|
||||||
"Ajoute au canvas le frame avec le logo"
|
|
||||||
if only_on_first_page and int(doc.page) > 1:
|
if only_on_first_page and int(doc.page) > 1:
|
||||||
return
|
return
|
||||||
height = doc.pagesize[1]
|
height = doc.pagesize[1]
|
||||||
@ -150,12 +147,12 @@ def page_header(canvas, doc, logo, preferences, only_on_first_page=False):
|
|||||||
|
|
||||||
|
|
||||||
class CourrierIndividuelTemplate(PageTemplate):
|
class CourrierIndividuelTemplate(PageTemplate):
|
||||||
"""Template pour courrier avisant des decisions de jury (1 page par étudiant)"""
|
"""Template pour courrier avisant des decisions de jury (1 page /etudiant)"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
document,
|
document,
|
||||||
pagesbookmarks=None,
|
pagesbookmarks={},
|
||||||
author=None,
|
author=None,
|
||||||
title=None,
|
title=None,
|
||||||
subject=None,
|
subject=None,
|
||||||
@ -166,7 +163,7 @@ class CourrierIndividuelTemplate(PageTemplate):
|
|||||||
template_name="CourrierJuryTemplate",
|
template_name="CourrierJuryTemplate",
|
||||||
):
|
):
|
||||||
"""Initialise our page template."""
|
"""Initialise our page template."""
|
||||||
self.pagesbookmarks = pagesbookmarks or {}
|
self.pagesbookmarks = pagesbookmarks
|
||||||
self.pdfmeta_author = author
|
self.pdfmeta_author = author
|
||||||
self.pdfmeta_title = title
|
self.pdfmeta_title = title
|
||||||
self.pdfmeta_subject = subject
|
self.pdfmeta_subject = subject
|
||||||
@ -240,32 +237,32 @@ class CourrierIndividuelTemplate(PageTemplate):
|
|||||||
width=LOGO_HEADER_WIDTH,
|
width=LOGO_HEADER_WIDTH,
|
||||||
)
|
)
|
||||||
|
|
||||||
def beforeDrawPage(self, canv, doc):
|
def beforeDrawPage(self, canvas, doc):
|
||||||
"""Draws a logo and an contribution message on each page."""
|
"""Draws a logo and an contribution message on each page."""
|
||||||
# ---- Add some meta data and bookmarks
|
# ---- Add some meta data and bookmarks
|
||||||
if self.pdfmeta_author:
|
if self.pdfmeta_author:
|
||||||
canv.setAuthor(SU(self.pdfmeta_author))
|
canvas.setAuthor(SU(self.pdfmeta_author))
|
||||||
if self.pdfmeta_title:
|
if self.pdfmeta_title:
|
||||||
canv.setTitle(SU(self.pdfmeta_title))
|
canvas.setTitle(SU(self.pdfmeta_title))
|
||||||
if self.pdfmeta_subject:
|
if self.pdfmeta_subject:
|
||||||
canv.setSubject(SU(self.pdfmeta_subject))
|
canvas.setSubject(SU(self.pdfmeta_subject))
|
||||||
bm = self.pagesbookmarks.get(doc.page, None)
|
bm = self.pagesbookmarks.get(doc.page, None)
|
||||||
if bm != None:
|
if bm != None:
|
||||||
key = bm
|
key = bm
|
||||||
txt = SU(bm)
|
txt = SU(bm)
|
||||||
canv.bookmarkPage(key)
|
canvas.bookmarkPage(key)
|
||||||
canv.addOutlineEntry(txt, bm)
|
canvas.addOutlineEntry(txt, bm)
|
||||||
|
|
||||||
# ---- Background image
|
# ---- Background image
|
||||||
if self.background_image_filename and self.with_page_background:
|
if self.background_image_filename and self.with_page_background:
|
||||||
canv.drawImage(
|
canvas.drawImage(
|
||||||
self.background_image_filename, 0, 0, doc.pagesize[0], doc.pagesize[1]
|
self.background_image_filename, 0, 0, doc.pagesize[0], doc.pagesize[1]
|
||||||
)
|
)
|
||||||
|
|
||||||
# ---- Header/Footer
|
# ---- Header/Footer
|
||||||
if self.with_header:
|
if self.with_header:
|
||||||
page_header(
|
page_header(
|
||||||
canv,
|
canvas,
|
||||||
doc,
|
doc,
|
||||||
self.logo_header,
|
self.logo_header,
|
||||||
self.preferences,
|
self.preferences,
|
||||||
@ -273,7 +270,7 @@ class CourrierIndividuelTemplate(PageTemplate):
|
|||||||
)
|
)
|
||||||
if self.with_footer:
|
if self.with_footer:
|
||||||
page_footer(
|
page_footer(
|
||||||
canv,
|
canvas,
|
||||||
doc,
|
doc,
|
||||||
self.logo_footer,
|
self.logo_footer,
|
||||||
self.preferences,
|
self.preferences,
|
||||||
@ -335,42 +332,6 @@ class PVTemplate(CourrierIndividuelTemplate):
|
|||||||
# self.__pageNum += 1
|
# self.__pageNum += 1
|
||||||
|
|
||||||
|
|
||||||
def _simulate_br(paragraph_txt: str, para="<para>") -> str:
|
|
||||||
"""Reportlab bug turnaround (could be removed in a future version).
|
|
||||||
p is a string with Reportlab intra-paragraph XML tags.
|
|
||||||
Replaces <br/> (currently ignored by Reportlab) by </para><para>
|
|
||||||
Also replaces <br> by <br/>
|
|
||||||
"""
|
|
||||||
return ("</para>" + para).join(
|
|
||||||
re.split(r"<.*?br.*?/>", paragraph_txt.replace("<br>", "<br/>"))
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _make_signature_image(signature, leftindent, formsemestre_id) -> Table:
|
|
||||||
"crée un paragraphe avec l'image signature"
|
|
||||||
# cree une image PIL pour avoir la taille (W,H)
|
|
||||||
|
|
||||||
f = io.BytesIO(signature)
|
|
||||||
img = PILImage.open(f)
|
|
||||||
width, height = img.size
|
|
||||||
pdfheight = (
|
|
||||||
1.0
|
|
||||||
* sco_preferences.get_preference("pv_sig_image_height", formsemestre_id)
|
|
||||||
* mm
|
|
||||||
)
|
|
||||||
f.seek(0, 0)
|
|
||||||
|
|
||||||
style = styles.ParagraphStyle({})
|
|
||||||
style.leading = 1.0 * sco_preferences.get_preference(
|
|
||||||
"SCOLAR_FONT_SIZE", formsemestre_id
|
|
||||||
) # vertical space
|
|
||||||
style.leftIndent = leftindent
|
|
||||||
return Table(
|
|
||||||
[("", Image(f, width=width * pdfheight / float(height), height=pdfheight))],
|
|
||||||
colWidths=(9 * cm, 7 * cm),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def pdf_lettres_individuelles(
|
def pdf_lettres_individuelles(
|
||||||
formsemestre_id,
|
formsemestre_id,
|
||||||
etudids=None,
|
etudids=None,
|
||||||
@ -391,7 +352,7 @@ def pdf_lettres_individuelles(
|
|||||||
etuds = [x["identite"] for x in dpv["decisions"]]
|
etuds = [x["identite"] for x in dpv["decisions"]]
|
||||||
sco_etud.fill_etuds_info(etuds)
|
sco_etud.fill_etuds_info(etuds)
|
||||||
#
|
#
|
||||||
formsemestre: FormSemestre = FormSemestre.query.get(formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
||||||
prefs = sco_preferences.SemPreferences(formsemestre_id)
|
prefs = sco_preferences.SemPreferences(formsemestre_id)
|
||||||
params = {
|
params = {
|
||||||
"date_jury": date_jury,
|
"date_jury": date_jury,
|
||||||
@ -402,22 +363,18 @@ def pdf_lettres_individuelles(
|
|||||||
}
|
}
|
||||||
# copie preferences
|
# copie preferences
|
||||||
for name in sco_preferences.get_base_preferences().prefs_name:
|
for name in sco_preferences.get_base_preferences().prefs_name:
|
||||||
params[name] = sco_preferences.get_preference(name, formsemestre_id)
|
params[name] = sco_preferences.get_preference(name, sem["formsemestre_id"])
|
||||||
|
|
||||||
bookmarks = {}
|
bookmarks = {}
|
||||||
objects = [] # list of PLATYPUS objects
|
objects = [] # list of PLATYPUS objects
|
||||||
npages = 0
|
npages = 0
|
||||||
for decision in dpv["decisions"]:
|
for e in dpv["decisions"]:
|
||||||
if (
|
if e["decision_sem"]: # decision prise
|
||||||
decision["decision_sem"]
|
etud = sco_etud.get_etud_info(e["identite"]["etudid"], filled=True)[0]
|
||||||
or decision.get("decision_annee")
|
params["nomEtud"] = etud["nomprenom"]
|
||||||
or decision.get("decision_rcue")
|
bookmarks[npages + 1] = scu.suppress_accents(etud["nomprenom"])
|
||||||
): # decision prise
|
|
||||||
etud: Identite = Identite.query.get(decision["identite"]["etudid"])
|
|
||||||
params["nomEtud"] = etud.nomprenom
|
|
||||||
bookmarks[npages + 1] = scu.suppress_accents(etud.nomprenom)
|
|
||||||
objects += pdf_lettre_individuelle(
|
objects += pdf_lettre_individuelle(
|
||||||
dpv["formsemestre"], decision, etud, params, signature
|
dpv["formsemestre"], e, etud, params, signature
|
||||||
)
|
)
|
||||||
objects.append(PageBreak())
|
objects.append(PageBreak())
|
||||||
npages += 1
|
npages += 1
|
||||||
@ -437,8 +394,8 @@ def pdf_lettres_individuelles(
|
|||||||
document.addPageTemplates(
|
document.addPageTemplates(
|
||||||
CourrierIndividuelTemplate(
|
CourrierIndividuelTemplate(
|
||||||
document,
|
document,
|
||||||
author=f"{sco_version.SCONAME} {sco_version.SCOVERSION} (E. Viennet)",
|
author="%s %s (E. Viennet)" % (sco_version.SCONAME, sco_version.SCOVERSION),
|
||||||
title=f"Lettres décision {formsemestre.titre_annee()}",
|
title="Lettres décision %s" % sem["titreannee"],
|
||||||
subject="Décision jury",
|
subject="Décision jury",
|
||||||
margins=margins,
|
margins=margins,
|
||||||
pagesbookmarks=bookmarks,
|
pagesbookmarks=bookmarks,
|
||||||
@ -451,41 +408,36 @@ def pdf_lettres_individuelles(
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def _descr_jury(formsemestre: FormSemestre, diplome):
|
def _descr_jury(sem, diplome):
|
||||||
|
|
||||||
if not diplome:
|
if not diplome:
|
||||||
if formsemestre.formation.is_apc():
|
t = "passage de Semestre %d en Semestre %d" % (
|
||||||
t = f"""BUT{(formsemestre.semestre_id+1)//2}"""
|
sem["semestre_id"],
|
||||||
s = t
|
sem["semestre_id"] + 1,
|
||||||
else:
|
)
|
||||||
t = f"""passage de Semestre {formsemestre.semestre_id} en Semestre {formsemestre.semestre_id + 1}"""
|
s = "passage de semestre"
|
||||||
s = "passage de semestre"
|
|
||||||
else:
|
else:
|
||||||
t = "délivrance du diplôme"
|
t = "délivrance du diplôme"
|
||||||
s = t
|
s = t
|
||||||
return t, s # titre long, titre court
|
return t, s # titre long, titre court
|
||||||
|
|
||||||
|
|
||||||
def pdf_lettre_individuelle(sem, decision, etud: Identite, params, signature=None):
|
def pdf_lettre_individuelle(sem, decision, etud, params, signature=None):
|
||||||
"""
|
"""
|
||||||
Renvoie une liste d'objets PLATYPUS pour intégration
|
Renvoie une liste d'objets PLATYPUS pour intégration
|
||||||
dans un autre document.
|
dans un autre document.
|
||||||
"""
|
"""
|
||||||
#
|
#
|
||||||
formsemestre_id = sem["formsemestre_id"]
|
formsemestre_id = sem["formsemestre_id"]
|
||||||
formsemestre = FormSemestre.query.get(formsemestre_id)
|
Se: SituationEtudParcours = decision["Se"]
|
||||||
Se: SituationEtudCursus = decision["Se"]
|
t, s = _descr_jury(sem, Se.parcours_validated() or not Se.semestre_non_terminal)
|
||||||
t, s = _descr_jury(
|
|
||||||
formsemestre, Se.parcours_validated() or not Se.semestre_non_terminal
|
|
||||||
)
|
|
||||||
objects = []
|
objects = []
|
||||||
style = reportlab.lib.styles.ParagraphStyle({})
|
style = reportlab.lib.styles.ParagraphStyle({})
|
||||||
style.fontSize = 14
|
style.fontSize = 14
|
||||||
style.fontName = sco_preferences.get_preference("PV_FONTNAME", formsemestre_id)
|
style.fontName = sco_preferences.get_preference("PV_FONTNAME", formsemestre_id)
|
||||||
style.leading = 18
|
style.leading = 18
|
||||||
style.alignment = TA_LEFT
|
style.alignment = TA_JUSTIFY
|
||||||
|
|
||||||
params["semestre_id"] = formsemestre.semestre_id
|
params["semestre_id"] = sem["semestre_id"]
|
||||||
params["decision_sem_descr"] = decision["decision_sem_descr"]
|
params["decision_sem_descr"] = decision["decision_sem_descr"]
|
||||||
params["type_jury"] = t # type de jury (passage ou delivrance)
|
params["type_jury"] = t # type de jury (passage ou delivrance)
|
||||||
params["type_jury_abbrv"] = s # idem, abbrégé
|
params["type_jury_abbrv"] = s # idem, abbrégé
|
||||||
@ -498,18 +450,28 @@ def pdf_lettre_individuelle(sem, decision, etud: Identite, params, signature=Non
|
|||||||
params["INSTITUTION_CITY"] = (
|
params["INSTITUTION_CITY"] = (
|
||||||
sco_preferences.get_preference("INSTITUTION_CITY", formsemestre_id) or ""
|
sco_preferences.get_preference("INSTITUTION_CITY", formsemestre_id) or ""
|
||||||
)
|
)
|
||||||
|
|
||||||
if decision["prev_decision_sem"]:
|
if decision["prev_decision_sem"]:
|
||||||
params["prev_semestre_id"] = decision["prev"]["semestre_id"]
|
params["prev_semestre_id"] = decision["prev"]["semestre_id"]
|
||||||
|
params["prev_code_descr"] = decision["prev_code_descr"]
|
||||||
params["prev_decision_sem_txt"] = ""
|
|
||||||
params["decision_orig"] = ""
|
|
||||||
|
|
||||||
params.update(decision["identite"])
|
params.update(decision["identite"])
|
||||||
# fix domicile
|
# fix domicile
|
||||||
if params["domicile"]:
|
if params["domicile"]:
|
||||||
params["domicile"] = params["domicile"].replace("\\n", "<br/>")
|
params["domicile"] = params["domicile"].replace("\\n", "<br/>")
|
||||||
|
|
||||||
|
# Décision semestre courant:
|
||||||
|
if sem["semestre_id"] >= 0:
|
||||||
|
params["decision_orig"] = "du semestre S%s" % sem["semestre_id"]
|
||||||
|
else:
|
||||||
|
params["decision_orig"] = ""
|
||||||
|
|
||||||
|
if decision["prev_decision_sem"]:
|
||||||
|
params["prev_decision_sem_txt"] = (
|
||||||
|
"""<b>Décision du semestre antérieur S%(prev_semestre_id)s :</b> %(prev_code_descr)s"""
|
||||||
|
% params
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
params["prev_decision_sem_txt"] = ""
|
||||||
# UE capitalisées:
|
# UE capitalisées:
|
||||||
if decision["decisions_ue"] and decision["decisions_ue_descr"]:
|
if decision["decisions_ue"] and decision["decisions_ue_descr"]:
|
||||||
params["decision_ue_txt"] = (
|
params["decision_ue_txt"] = (
|
||||||
@ -536,7 +498,7 @@ def pdf_lettre_individuelle(sem, decision, etud: Identite, params, signature=Non
|
|||||||
params[
|
params[
|
||||||
"autorisations_txt"
|
"autorisations_txt"
|
||||||
] = """Vous êtes autorisé%s à continuer dans le%s semestre%s : <b>%s</b>""" % (
|
] = """Vous êtes autorisé%s à continuer dans le%s semestre%s : <b>%s</b>""" % (
|
||||||
etud.e,
|
etud["ne"],
|
||||||
s,
|
s,
|
||||||
s,
|
s,
|
||||||
decision["autorisations_descr"],
|
decision["autorisations_descr"],
|
||||||
@ -551,14 +513,6 @@ def pdf_lettre_individuelle(sem, decision, etud: Identite, params, signature=Non
|
|||||||
else:
|
else:
|
||||||
params["diplome_txt"] = ""
|
params["diplome_txt"] = ""
|
||||||
|
|
||||||
# Les fonctions ci-dessous ajoutent ou modifient des champs:
|
|
||||||
if formsemestre.formation.is_apc():
|
|
||||||
# ajout champs spécifiques PV BUT
|
|
||||||
add_apc_infos(formsemestre, params, decision)
|
|
||||||
else:
|
|
||||||
# ajout champs spécifiques PV DUT
|
|
||||||
add_classic_infos(formsemestre, params, decision)
|
|
||||||
|
|
||||||
# Corps de la lettre:
|
# Corps de la lettre:
|
||||||
objects += sco_bulletins_pdf.process_field(
|
objects += sco_bulletins_pdf.process_field(
|
||||||
sco_preferences.get_preference("PV_LETTER_TEMPLATE", sem["formsemestre_id"]),
|
sco_preferences.get_preference("PV_LETTER_TEMPLATE", sem["formsemestre_id"]),
|
||||||
@ -613,30 +567,39 @@ def pdf_lettre_individuelle(sem, decision, etud: Identite, params, signature=Non
|
|||||||
return objects
|
return objects
|
||||||
|
|
||||||
|
|
||||||
def add_classic_infos(formsemestre: FormSemestre, params: dict, decision: dict):
|
def _simulate_br(p, para="<para>"):
|
||||||
"""Ajoute les champs pour les formations classiques, donc avec codes semestres"""
|
"""Reportlab bug turnaround (could be removed in a future version).
|
||||||
if decision["prev_decision_sem"]:
|
p is a string with Reportlab intra-paragraph XML tags.
|
||||||
params["prev_code_descr"] = decision["prev_code_descr"]
|
Replaces <br/> (currently ignored by Reportlab) by </para><para>
|
||||||
params[
|
|
||||||
"prev_decision_sem_txt"
|
|
||||||
] = f"""<b>Décision du semestre antérieur S{params['prev_semestre_id']} :</b> {params['prev_code_descr']}"""
|
|
||||||
# Décision semestre courant:
|
|
||||||
if formsemestre.semestre_id >= 0:
|
|
||||||
params["decision_orig"] = f"du semestre S{formsemestre.semestre_id}"
|
|
||||||
else:
|
|
||||||
params["decision_orig"] = ""
|
|
||||||
|
|
||||||
|
|
||||||
def add_apc_infos(formsemestre: FormSemestre, params: dict, decision: dict):
|
|
||||||
"""Ajoute les champs pour les formations APC (BUT), donc avec codes RCUE et année"""
|
|
||||||
annee_but = (formsemestre.semestre_id + 1) // 2
|
|
||||||
params["decision_orig"] = f"année BUT{annee_but}"
|
|
||||||
params["decision_sem_descr"] = decision.get("decision_annee", {}).get("code", "")
|
|
||||||
params[
|
|
||||||
"decision_ue_txt"
|
|
||||||
] = f"""{params["decision_ue_txt"]}<br/>
|
|
||||||
<b>Niveaux de compétences:</b><br/> {decision.get("descr_decisions_rcue", "")}
|
|
||||||
"""
|
"""
|
||||||
|
l = re.split(r"<.*?br.*?/>", p)
|
||||||
|
return ("</para>" + para).join(l)
|
||||||
|
|
||||||
|
|
||||||
|
def _make_signature_image(signature, leftindent, formsemestre_id):
|
||||||
|
"cree un paragraphe avec l'image signature"
|
||||||
|
# cree une image PIL pour avoir la taille (W,H)
|
||||||
|
from PIL import Image as PILImage
|
||||||
|
|
||||||
|
f = io.BytesIO(signature)
|
||||||
|
im = PILImage.open(f)
|
||||||
|
width, height = im.size
|
||||||
|
pdfheight = (
|
||||||
|
1.0
|
||||||
|
* sco_preferences.get_preference("pv_sig_image_height", formsemestre_id)
|
||||||
|
* mm
|
||||||
|
)
|
||||||
|
f.seek(0, 0)
|
||||||
|
|
||||||
|
style = styles.ParagraphStyle({})
|
||||||
|
style.leading = 1.0 * sco_preferences.get_preference(
|
||||||
|
"SCOLAR_FONT_SIZE", formsemestre_id
|
||||||
|
) # vertical space
|
||||||
|
style.leftIndent = leftindent
|
||||||
|
return Table(
|
||||||
|
[("", Image(f, width=width * pdfheight / float(height), height=pdfheight))],
|
||||||
|
colWidths=(9 * cm, 7 * cm),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------
|
# ----------------------------------------------
|
||||||
@ -736,8 +699,7 @@ def _pvjury_pdf_type(
|
|||||||
|
|
||||||
sem = dpv["formsemestre"]
|
sem = dpv["formsemestre"]
|
||||||
formsemestre_id = sem["formsemestre_id"]
|
formsemestre_id = sem["formsemestre_id"]
|
||||||
formsemestre: FormSemestre = FormSemestre.query.get(formsemestre_id)
|
titre_jury, _ = _descr_jury(sem, diplome)
|
||||||
titre_jury, _ = _descr_jury(formsemestre, diplome)
|
|
||||||
titre_diplome = pv_title or dpv["formation"]["titre_officiel"]
|
titre_diplome = pv_title or dpv["formation"]["titre_officiel"]
|
||||||
objects = []
|
objects = []
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ import pydot
|
|||||||
|
|
||||||
from app.comp import res_sem
|
from app.comp import res_sem
|
||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.models import FormSemestre, ScolarAutorisationInscription
|
from app.models import FormSemestre
|
||||||
|
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app.models import FormationModalite
|
from app.models import FormationModalite
|
||||||
@ -51,6 +51,7 @@ from app.scodoc import sco_codes_parcours
|
|||||||
from app.scodoc import sco_etud
|
from app.scodoc import sco_etud
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
from app.scodoc import sco_formsemestre_inscriptions
|
from app.scodoc import sco_formsemestre_inscriptions
|
||||||
|
from app.scodoc import sco_parcours_dut
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
import sco_version
|
import sco_version
|
||||||
from app.scodoc.gen_tables import GenTable
|
from app.scodoc.gen_tables import GenTable
|
||||||
@ -80,10 +81,10 @@ def formsemestre_etuds_stats(sem, only_primo=False):
|
|||||||
if "codedecision" not in etud:
|
if "codedecision" not in etud:
|
||||||
etud["codedecision"] = "(nd)" # pas de decision jury
|
etud["codedecision"] = "(nd)" # pas de decision jury
|
||||||
# Ajout devenir (autorisations inscriptions), utile pour stats passage
|
# Ajout devenir (autorisations inscriptions), utile pour stats passage
|
||||||
aut_list = ScolarAutorisationInscription.query.filter_by(
|
aut_list = sco_parcours_dut.formsemestre_get_autorisation_inscription(
|
||||||
etudid=etudid, origin_formsemestre_id=sem["formsemestre_id"]
|
etudid, sem["formsemestre_id"]
|
||||||
).all()
|
)
|
||||||
autorisations = [f"S{a.semestre_id}" for a in aut_list]
|
autorisations = ["S%s" % x["semestre_id"] for x in aut_list]
|
||||||
autorisations.sort()
|
autorisations.sort()
|
||||||
autorisations_str = ", ".join(autorisations)
|
autorisations_str = ", ".join(autorisations)
|
||||||
etud["devenir"] = autorisations_str
|
etud["devenir"] = autorisations_str
|
||||||
|
@ -664,15 +664,6 @@ def flash_errors(form):
|
|||||||
# see https://getbootstrap.com/docs/4.0/components/alerts/
|
# see https://getbootstrap.com/docs/4.0/components/alerts/
|
||||||
|
|
||||||
|
|
||||||
def flash_once(message: str):
|
|
||||||
"""Flash the message, but only once per request"""
|
|
||||||
if not hasattr(g, "sco_flashed_once"):
|
|
||||||
g.sco_flashed_once = set()
|
|
||||||
if not message in g.sco_flashed_once:
|
|
||||||
flash(message)
|
|
||||||
g.sco_flashed_once.add(message)
|
|
||||||
|
|
||||||
|
|
||||||
def sendCSVFile(data, filename): # DEPRECATED utiliser send_file
|
def sendCSVFile(data, filename): # DEPRECATED utiliser send_file
|
||||||
"""publication fichier CSV."""
|
"""publication fichier CSV."""
|
||||||
return send_file(data, filename=filename, mime=CSV_MIMETYPE, attached=True)
|
return send_file(data, filename=filename, mime=CSV_MIMETYPE, attached=True)
|
||||||
|
@ -169,7 +169,7 @@ section>div:nth-child(1){
|
|||||||
border: none;
|
border: none;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
.rang, .competence{
|
.rang{
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
.ue .rang{
|
.ue .rang{
|
||||||
|
@ -2210,7 +2210,6 @@ ul.notes_module_list {
|
|||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Choix niveau dans form edit UE */
|
|
||||||
div.ue_choix_niveau {
|
div.ue_choix_niveau {
|
||||||
background-color: rgb(191, 242, 255);
|
background-color: rgb(191, 242, 255);
|
||||||
border: 1px solid blue;
|
border: 1px solid blue;
|
||||||
@ -2220,19 +2219,6 @@ div.ue_choix_niveau {
|
|||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Choix niveau dans edition programme (ue_table) */
|
|
||||||
div.formation_list_ues div.ue_choix_niveau {
|
|
||||||
margin-left: 64px;
|
|
||||||
margin-right: 64px;
|
|
||||||
margin-top: 2px;
|
|
||||||
padding: 4px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.formation_list_ues div.ue_choix_niveau b {
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
div#ue_list_modules {
|
div#ue_list_modules {
|
||||||
background-color: rgb(251, 225, 165);
|
background-color: rgb(251, 225, 165);
|
||||||
border: 1px solid blue;
|
border: 1px solid blue;
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
// Affiche et met a jour la liste des UE partageant le meme code
|
// Affiche et met a jour la liste des UE partageant le meme code
|
||||||
|
|
||||||
$().ready(function () {
|
$().ready(function () {
|
||||||
if (document.querySelector("#tf_ue_id")) {
|
update_ue_list();
|
||||||
/* fonctions spécifiques pour edition UE */
|
$("#tf_ue_code").bind("keyup", update_ue_list);
|
||||||
update_ue_list();
|
|
||||||
$("#tf_ue_code").bind("keyup", update_ue_list);
|
|
||||||
|
|
||||||
$("select#tf_type").change(function () {
|
$("select#tf_type").change(function () {
|
||||||
update_bonus_description();
|
|
||||||
});
|
|
||||||
update_bonus_description();
|
update_bonus_description();
|
||||||
}
|
});
|
||||||
|
update_bonus_description();
|
||||||
});
|
});
|
||||||
|
|
||||||
function update_bonus_description() {
|
function update_bonus_description() {
|
||||||
@ -36,10 +33,11 @@ function update_ue_list() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function set_ue_niveau_competence(elem) {
|
function set_ue_niveau_competence() {
|
||||||
let ue_id = elem.dataset.ue_id;
|
let ue_id = document.querySelector("#tf_ue_id").value;
|
||||||
let niveau_id = elem.value;
|
let select = document.querySelector("#form_ue_choix_niveau select");
|
||||||
let set_ue_niveau_competence_url = elem.dataset.setter;
|
let niveau_id = select.value;
|
||||||
|
let set_ue_niveau_competence_url = select.dataset.setter;
|
||||||
$.post(set_ue_niveau_competence_url,
|
$.post(set_ue_niveau_competence_url,
|
||||||
{
|
{
|
||||||
ue_id: ue_id,
|
ue_id: ue_id,
|
||||||
|
@ -232,7 +232,7 @@ class releveBUT extends HTMLElement {
|
|||||||
${(()=>{
|
${(()=>{
|
||||||
let output = "";
|
let output = "";
|
||||||
data.semestre.decision_rcue.forEach(competence=>{
|
data.semestre.decision_rcue.forEach(competence=>{
|
||||||
output += `<div class=competence>${competence.niveau.competence.titre}</div><div>${competence.code}</div>`;
|
output += `<div class=rang>${competence.niveau.competence.titre}</div><div>${competence.code}</div>`;
|
||||||
})
|
})
|
||||||
return output;
|
return output;
|
||||||
})()}
|
})()}
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
<span class="ue_type_{{ue.type}}">
|
<span class="ue_type_{{ue.type}}">
|
||||||
<span class="ue_color_indicator" style="background:{{
|
<span class="ue_color_indicator" style="background:{{
|
||||||
ue.color if ue.color is not none else 'blue'}}"></span>
|
ue.color if ue.color is not none else 'blue'}}"></span>
|
||||||
<b>{{ue.acronyme}} <a class="discretelink" href="{{
|
<b>{{ue.acronyme}}</b> <a class="discretelink" href="{{
|
||||||
url_for('notes.ue_infos', scodoc_dept=g.scodoc_dept, ue_id=ue.id)}}"
|
url_for('notes.ue_infos', scodoc_dept=g.scodoc_dept, ue_id=ue.id)}}"
|
||||||
title="{{ue.acronyme}}: {{
|
title="{{ue.acronyme}}: {{
|
||||||
('pas de compétence associée'
|
('pas de compétence associée'
|
||||||
@ -40,7 +40,6 @@
|
|||||||
else ''
|
else ''
|
||||||
}}"
|
}}"
|
||||||
>{{ue.titre}}</a>
|
>{{ue.titre}}</a>
|
||||||
</b>
|
|
||||||
{% set virg = joiner(", ") %}
|
{% set virg = joiner(", ") %}
|
||||||
<span class="ue_code">(
|
<span class="ue_code">(
|
||||||
{%- if ue.ue_code -%}{{ virg() }}code {{ue.ue_code}} {%- endif -%}
|
{%- if ue.ue_code -%}{{ virg() }}code {{ue.ue_code}} {%- endif -%}
|
||||||
@ -54,6 +53,9 @@
|
|||||||
)
|
)
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
{% if (ue.niveau_competence is none) and ue.type == 0 %}
|
||||||
|
<span class="fontred">pas de compétence associée</span>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if editable and not ue.is_locked() %}
|
{% if editable and not ue.is_locked() %}
|
||||||
<a class="stdlink" href="{{ url_for('notes.ue_edit',
|
<a class="stdlink" href="{{ url_for('notes.ue_edit',
|
||||||
@ -61,9 +63,6 @@
|
|||||||
}}">modifier</a>
|
}}">modifier</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{{ form_ue_choix_niveau(formation, ue)|safe }}
|
|
||||||
|
|
||||||
|
|
||||||
{% if ue.type == 1 and ue.modules.count() == 0 %}
|
{% if ue.type == 1 and ue.modules.count() == 0 %}
|
||||||
<span class="warning" title="pas de module, donc pas de bonus calculé">aucun module rattaché !</span>
|
<span class="warning" title="pas de module, donc pas de bonus calculé">aucun module rattaché !</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -296,9 +296,7 @@ def formsemestre_bulletinetud(
|
|||||||
format = format or "html"
|
format = format or "html"
|
||||||
|
|
||||||
if not isinstance(formsemestre_id, int):
|
if not isinstance(formsemestre_id, int):
|
||||||
raise ScoInvalidIdType(
|
raise ScoInvalidIdType("formsemestre_id must be an integer !")
|
||||||
"formsemestre_bulletinetud: formsemestre_id must be an integer !"
|
|
||||||
)
|
|
||||||
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
if etudid:
|
if etudid:
|
||||||
etud = models.Identite.query.get_or_404(etudid)
|
etud = models.Identite.query.get_or_404(etudid)
|
||||||
@ -828,9 +826,7 @@ def XMLgetFormsemestres(etape_apo=None, formsemestre_id=None):
|
|||||||
if not formsemestre_id:
|
if not formsemestre_id:
|
||||||
return flask.abort(404, "argument manquant: formsemestre_id")
|
return flask.abort(404, "argument manquant: formsemestre_id")
|
||||||
if not isinstance(formsemestre_id, int):
|
if not isinstance(formsemestre_id, int):
|
||||||
return flask.abort(
|
return flask.abort(404, "formsemestre_id must be an integer !")
|
||||||
404, "XMLgetFormsemestres: formsemestre_id must be an integer !"
|
|
||||||
)
|
|
||||||
args = {}
|
args = {}
|
||||||
if etape_apo:
|
if etape_apo:
|
||||||
args["etape_apo"] = etape_apo
|
args["etape_apo"] = etape_apo
|
||||||
@ -2552,8 +2548,9 @@ def formsemestre_validation_suppress_etud(
|
|||||||
)
|
)
|
||||||
if not dialog_confirmed:
|
if not dialog_confirmed:
|
||||||
d = sco_bulletins_json.dict_decision_jury(
|
d = sco_bulletins_json.dict_decision_jury(
|
||||||
etud, formsemestre, with_decisions=True
|
etudid, formsemestre_id, with_decisions=True
|
||||||
)
|
)
|
||||||
|
d.update(but_validations.dict_decision_jury(etud, formsemestre))
|
||||||
|
|
||||||
descr_ues = [f"{u['acronyme']}: {u['code']}" for u in d.get("decision_ue", [])]
|
descr_ues = [f"{u['acronyme']}: {u['code']}" for u in d.get("decision_ue", [])]
|
||||||
dec_annee = d.get("decision_annee")
|
dec_annee = d.get("decision_annee")
|
||||||
|
@ -14,17 +14,17 @@ config = context.config
|
|||||||
# Interpret the config file for Python logging.
|
# Interpret the config file for Python logging.
|
||||||
# This line sets up loggers basically.
|
# This line sets up loggers basically.
|
||||||
fileConfig(config.config_file_name)
|
fileConfig(config.config_file_name)
|
||||||
logger = logging.getLogger('alembic.env')
|
logger = logging.getLogger("alembic.env")
|
||||||
|
|
||||||
# add your model's MetaData object here
|
# add your model's MetaData object here
|
||||||
# for 'autogenerate' support
|
# for 'autogenerate' support
|
||||||
# from myapp import mymodel
|
# from myapp import mymodel
|
||||||
# target_metadata = mymodel.Base.metadata
|
# target_metadata = mymodel.Base.metadata
|
||||||
config.set_main_option(
|
config.set_main_option(
|
||||||
'sqlalchemy.url',
|
"sqlalchemy.url",
|
||||||
str(current_app.extensions['migrate'].db.get_engine().url).replace(
|
str(current_app.extensions["migrate"].db.get_engine().url).replace("%", "%%"),
|
||||||
'%', '%%'))
|
)
|
||||||
target_metadata = current_app.extensions['migrate'].db.metadata
|
target_metadata = current_app.extensions["migrate"].db.metadata
|
||||||
|
|
||||||
# other values from the config, defined by the needs of env.py,
|
# other values from the config, defined by the needs of env.py,
|
||||||
# can be acquired:
|
# can be acquired:
|
||||||
@ -45,9 +45,7 @@ def run_migrations_offline():
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
url = config.get_main_option("sqlalchemy.url")
|
url = config.get_main_option("sqlalchemy.url")
|
||||||
context.configure(
|
context.configure(url=url, target_metadata=target_metadata, literal_binds=True)
|
||||||
url=url, target_metadata=target_metadata, literal_binds=True
|
|
||||||
)
|
|
||||||
|
|
||||||
with context.begin_transaction():
|
with context.begin_transaction():
|
||||||
context.run_migrations()
|
context.run_migrations()
|
||||||
@ -65,20 +63,20 @@ def run_migrations_online():
|
|||||||
# when there are no changes to the schema
|
# when there are no changes to the schema
|
||||||
# reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
|
# reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
|
||||||
def process_revision_directives(context, revision, directives):
|
def process_revision_directives(context, revision, directives):
|
||||||
if getattr(config.cmd_opts, 'autogenerate', False):
|
if getattr(config.cmd_opts, "autogenerate", False):
|
||||||
script = directives[0]
|
script = directives[0]
|
||||||
if script.upgrade_ops.is_empty():
|
if script.upgrade_ops.is_empty():
|
||||||
directives[:] = []
|
directives[:] = []
|
||||||
logger.info('No changes in schema detected.')
|
logger.info("No changes in schema detected.")
|
||||||
|
|
||||||
connectable = current_app.extensions['migrate'].db.get_engine()
|
connectable = current_app.extensions["migrate"].db.get_engine()
|
||||||
|
|
||||||
with connectable.connect() as connection:
|
with connectable.connect() as connection:
|
||||||
context.configure(
|
context.configure(
|
||||||
connection=connection,
|
connection=connection,
|
||||||
target_metadata=target_metadata,
|
target_metadata=target_metadata,
|
||||||
process_revision_directives=process_revision_directives,
|
process_revision_directives=process_revision_directives,
|
||||||
**current_app.extensions['migrate'].configure_args
|
**current_app.extensions["migrate"].configure_args
|
||||||
)
|
)
|
||||||
|
|
||||||
with context.begin_transaction():
|
with context.begin_transaction():
|
||||||
|
@ -10,21 +10,23 @@ import sqlalchemy as sa
|
|||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision = '017e32eb4773'
|
revision = "017e32eb4773"
|
||||||
down_revision = '6b071b7947e5'
|
down_revision = "6b071b7947e5"
|
||||||
branch_labels = None
|
branch_labels = None
|
||||||
depends_on = None
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.add_column('identite', sa.Column('scodoc7_id', sa.Text(), nullable=True))
|
op.add_column("identite", sa.Column("scodoc7_id", sa.Text(), nullable=True))
|
||||||
op.add_column('notes_formsemestre', sa.Column('scodoc7_id', sa.Text(), nullable=True))
|
op.add_column(
|
||||||
|
"notes_formsemestre", sa.Column("scodoc7_id", sa.Text(), nullable=True)
|
||||||
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_column('notes_formsemestre', 'scodoc7_id')
|
op.drop_column("notes_formsemestre", "scodoc7_id")
|
||||||
op.drop_column('identite', 'scodoc7_id')
|
op.drop_column("identite", "scodoc7_id")
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
@ -10,21 +10,38 @@ import sqlalchemy as sa
|
|||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision = '1efe07413835'
|
revision = "1efe07413835"
|
||||||
down_revision = '75cf18659984'
|
down_revision = "75cf18659984"
|
||||||
branch_labels = None
|
branch_labels = None
|
||||||
depends_on = None
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_constraint('absences_notifications_formsemestre_id_fkey', 'absences_notifications', type_='foreignkey')
|
op.drop_constraint(
|
||||||
op.create_foreign_key(None, 'absences_notifications', 'notes_formsemestre', ['formsemestre_id'], ['id'], ondelete='CASCADE')
|
"absences_notifications_formsemestre_id_fkey",
|
||||||
|
"absences_notifications",
|
||||||
|
type_="foreignkey",
|
||||||
|
)
|
||||||
|
op.create_foreign_key(
|
||||||
|
None,
|
||||||
|
"absences_notifications",
|
||||||
|
"notes_formsemestre",
|
||||||
|
["formsemestre_id"],
|
||||||
|
["id"],
|
||||||
|
ondelete="CASCADE",
|
||||||
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_constraint(None, 'absences_notifications', type_='foreignkey')
|
op.drop_constraint(None, "absences_notifications", type_="foreignkey")
|
||||||
op.create_foreign_key('absences_notifications_formsemestre_id_fkey', 'absences_notifications', 'notes_formsemestre', ['formsemestre_id'], ['id'])
|
op.create_foreign_key(
|
||||||
|
"absences_notifications_formsemestre_id_fkey",
|
||||||
|
"absences_notifications",
|
||||||
|
"notes_formsemestre",
|
||||||
|
["formsemestre_id"],
|
||||||
|
["id"],
|
||||||
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
@ -10,25 +10,57 @@ import sqlalchemy as sa
|
|||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision = '39818df276aa'
|
revision = "39818df276aa"
|
||||||
down_revision = '1efe07413835'
|
down_revision = "1efe07413835"
|
||||||
branch_labels = None
|
branch_labels = None
|
||||||
depends_on = None
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_constraint('itemsuivi_tags_assoc_tag_id_fkey', 'itemsuivi_tags_assoc', type_='foreignkey')
|
op.drop_constraint(
|
||||||
op.drop_constraint('itemsuivi_tags_assoc_itemsuivi_id_fkey', 'itemsuivi_tags_assoc', type_='foreignkey')
|
"itemsuivi_tags_assoc_tag_id_fkey", "itemsuivi_tags_assoc", type_="foreignkey"
|
||||||
op.create_foreign_key(None, 'itemsuivi_tags_assoc', 'itemsuivi', ['itemsuivi_id'], ['id'], ondelete='CASCADE')
|
)
|
||||||
op.create_foreign_key(None, 'itemsuivi_tags_assoc', 'itemsuivi_tags', ['tag_id'], ['id'], ondelete='CASCADE')
|
op.drop_constraint(
|
||||||
|
"itemsuivi_tags_assoc_itemsuivi_id_fkey",
|
||||||
|
"itemsuivi_tags_assoc",
|
||||||
|
type_="foreignkey",
|
||||||
|
)
|
||||||
|
op.create_foreign_key(
|
||||||
|
None,
|
||||||
|
"itemsuivi_tags_assoc",
|
||||||
|
"itemsuivi",
|
||||||
|
["itemsuivi_id"],
|
||||||
|
["id"],
|
||||||
|
ondelete="CASCADE",
|
||||||
|
)
|
||||||
|
op.create_foreign_key(
|
||||||
|
None,
|
||||||
|
"itemsuivi_tags_assoc",
|
||||||
|
"itemsuivi_tags",
|
||||||
|
["tag_id"],
|
||||||
|
["id"],
|
||||||
|
ondelete="CASCADE",
|
||||||
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_constraint(None, 'itemsuivi_tags_assoc', type_='foreignkey')
|
op.drop_constraint(None, "itemsuivi_tags_assoc", type_="foreignkey")
|
||||||
op.drop_constraint(None, 'itemsuivi_tags_assoc', type_='foreignkey')
|
op.drop_constraint(None, "itemsuivi_tags_assoc", type_="foreignkey")
|
||||||
op.create_foreign_key('itemsuivi_tags_assoc_itemsuivi_id_fkey', 'itemsuivi_tags_assoc', 'itemsuivi', ['itemsuivi_id'], ['id'])
|
op.create_foreign_key(
|
||||||
op.create_foreign_key('itemsuivi_tags_assoc_tag_id_fkey', 'itemsuivi_tags_assoc', 'itemsuivi_tags', ['tag_id'], ['id'])
|
"itemsuivi_tags_assoc_itemsuivi_id_fkey",
|
||||||
|
"itemsuivi_tags_assoc",
|
||||||
|
"itemsuivi",
|
||||||
|
["itemsuivi_id"],
|
||||||
|
["id"],
|
||||||
|
)
|
||||||
|
op.create_foreign_key(
|
||||||
|
"itemsuivi_tags_assoc_tag_id_fkey",
|
||||||
|
"itemsuivi_tags_assoc",
|
||||||
|
"itemsuivi_tags",
|
||||||
|
["tag_id"],
|
||||||
|
["id"],
|
||||||
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
@ -10,19 +10,24 @@ import sqlalchemy as sa
|
|||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision = '669065fb2d20'
|
revision = "669065fb2d20"
|
||||||
down_revision = 'a217bf588f4c'
|
down_revision = "a217bf588f4c"
|
||||||
branch_labels = None
|
branch_labels = None
|
||||||
depends_on = None
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.add_column('notes_formsemestre', sa.Column('block_moyennes', sa.Boolean(), server_default='false', nullable=False))
|
op.add_column(
|
||||||
|
"notes_formsemestre",
|
||||||
|
sa.Column(
|
||||||
|
"block_moyennes", sa.Boolean(), server_default="false", nullable=False
|
||||||
|
),
|
||||||
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_column('notes_formsemestre', 'block_moyennes')
|
op.drop_column("notes_formsemestre", "block_moyennes")
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
@ -10,25 +10,31 @@ import sqlalchemy as sa
|
|||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision = '6b071b7947e5'
|
revision = "6b071b7947e5"
|
||||||
down_revision = '993ce4a01d57'
|
down_revision = "993ce4a01d57"
|
||||||
branch_labels = None
|
branch_labels = None
|
||||||
depends_on = None
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.alter_column('notes_modules', 'code',
|
op.alter_column(
|
||||||
existing_type=sa.VARCHAR(length=32),
|
"notes_modules",
|
||||||
type_=sa.Text(),
|
"code",
|
||||||
existing_nullable=False)
|
existing_type=sa.VARCHAR(length=32),
|
||||||
|
type_=sa.Text(),
|
||||||
|
existing_nullable=False,
|
||||||
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.alter_column('notes_modules', 'code',
|
op.alter_column(
|
||||||
existing_type=sa.Text(),
|
"notes_modules",
|
||||||
type_=sa.VARCHAR(length=32),
|
"code",
|
||||||
existing_nullable=False)
|
existing_type=sa.Text(),
|
||||||
|
type_=sa.VARCHAR(length=32),
|
||||||
|
existing_nullable=False,
|
||||||
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
@ -10,26 +10,33 @@ import sqlalchemy as sa
|
|||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision = '6cfc21a7ae1b'
|
revision = "6cfc21a7ae1b"
|
||||||
down_revision = 'ada0d1f3d84f'
|
down_revision = "ada0d1f3d84f"
|
||||||
branch_labels = None
|
branch_labels = None
|
||||||
depends_on = None
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.create_table('module_ue_coef',
|
op.create_table(
|
||||||
sa.Column('module_id', sa.Integer(), nullable=False),
|
"module_ue_coef",
|
||||||
sa.Column('ue_id', sa.Integer(), nullable=False),
|
sa.Column("module_id", sa.Integer(), nullable=False),
|
||||||
sa.Column('coef', sa.Float(), nullable=False),
|
sa.Column("ue_id", sa.Integer(), nullable=False),
|
||||||
sa.ForeignKeyConstraint(['module_id'], ['notes_modules.id'], ),
|
sa.Column("coef", sa.Float(), nullable=False),
|
||||||
sa.ForeignKeyConstraint(['ue_id'], ['notes_ue.id'], ),
|
sa.ForeignKeyConstraint(
|
||||||
sa.PrimaryKeyConstraint('module_id', 'ue_id')
|
["module_id"],
|
||||||
|
["notes_modules.id"],
|
||||||
|
),
|
||||||
|
sa.ForeignKeyConstraint(
|
||||||
|
["ue_id"],
|
||||||
|
["notes_ue.id"],
|
||||||
|
),
|
||||||
|
sa.PrimaryKeyConstraint("module_id", "ue_id"),
|
||||||
)
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_table('module_ue_coef')
|
op.drop_table("module_ue_coef")
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
@ -10,25 +10,50 @@ import sqlalchemy as sa
|
|||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision = '75cf18659984'
|
revision = "75cf18659984"
|
||||||
down_revision = 'd74b4e16fb3c'
|
down_revision = "d74b4e16fb3c"
|
||||||
branch_labels = None
|
branch_labels = None
|
||||||
depends_on = None
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_constraint('notes_modules_tags_tag_id_fkey', 'notes_modules_tags', type_='foreignkey')
|
op.drop_constraint(
|
||||||
op.drop_constraint('notes_modules_tags_module_id_fkey', 'notes_modules_tags', type_='foreignkey')
|
"notes_modules_tags_tag_id_fkey", "notes_modules_tags", type_="foreignkey"
|
||||||
op.create_foreign_key(None, 'notes_modules_tags', 'notes_tags', ['tag_id'], ['id'], ondelete='CASCADE')
|
)
|
||||||
op.create_foreign_key(None, 'notes_modules_tags', 'notes_modules', ['module_id'], ['id'], ondelete='CASCADE')
|
op.drop_constraint(
|
||||||
|
"notes_modules_tags_module_id_fkey", "notes_modules_tags", type_="foreignkey"
|
||||||
|
)
|
||||||
|
op.create_foreign_key(
|
||||||
|
None, "notes_modules_tags", "notes_tags", ["tag_id"], ["id"], ondelete="CASCADE"
|
||||||
|
)
|
||||||
|
op.create_foreign_key(
|
||||||
|
None,
|
||||||
|
"notes_modules_tags",
|
||||||
|
"notes_modules",
|
||||||
|
["module_id"],
|
||||||
|
["id"],
|
||||||
|
ondelete="CASCADE",
|
||||||
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_constraint(None, 'notes_modules_tags', type_='foreignkey')
|
op.drop_constraint(None, "notes_modules_tags", type_="foreignkey")
|
||||||
op.drop_constraint(None, 'notes_modules_tags', type_='foreignkey')
|
op.drop_constraint(None, "notes_modules_tags", type_="foreignkey")
|
||||||
op.create_foreign_key('notes_modules_tags_module_id_fkey', 'notes_modules_tags', 'notes_modules', ['module_id'], ['id'])
|
op.create_foreign_key(
|
||||||
op.create_foreign_key('notes_modules_tags_tag_id_fkey', 'notes_modules_tags', 'notes_tags', ['tag_id'], ['id'])
|
"notes_modules_tags_module_id_fkey",
|
||||||
|
"notes_modules_tags",
|
||||||
|
"notes_modules",
|
||||||
|
["module_id"],
|
||||||
|
["id"],
|
||||||
|
)
|
||||||
|
op.create_foreign_key(
|
||||||
|
"notes_modules_tags_tag_id_fkey",
|
||||||
|
"notes_modules_tags",
|
||||||
|
"notes_tags",
|
||||||
|
["tag_id"],
|
||||||
|
["id"],
|
||||||
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
@ -10,46 +10,77 @@ import sqlalchemy as sa
|
|||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision = '92789d50f6b6'
|
revision = "92789d50f6b6"
|
||||||
down_revision = '00ad500fb118'
|
down_revision = "00ad500fb118"
|
||||||
branch_labels = None
|
branch_labels = None
|
||||||
depends_on = None
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_table('modules_acs')
|
op.drop_table("modules_acs")
|
||||||
op.drop_table('app_crit')
|
op.drop_table("app_crit")
|
||||||
op.add_column('apc_annee_parcours', sa.Column('ordre', sa.Integer(), nullable=True))
|
op.add_column("apc_annee_parcours", sa.Column("ordre", sa.Integer(), nullable=True))
|
||||||
op.drop_column('apc_annee_parcours', 'numero')
|
op.drop_column("apc_annee_parcours", "numero")
|
||||||
op.create_index(op.f('ix_apc_app_critique_code'), 'apc_app_critique', ['code'], unique=False)
|
op.create_index(
|
||||||
op.create_unique_constraint('apc_competence_referentiel_id_titre_key', 'apc_competence', ['referentiel_id', 'titre'])
|
op.f("ix_apc_app_critique_code"), "apc_app_critique", ["code"], unique=False
|
||||||
op.create_index(op.f('ix_apc_competence_titre'), 'apc_competence', ['titre'], unique=False)
|
)
|
||||||
op.add_column('apc_referentiel_competences', sa.Column('scodoc_date_loaded', sa.DateTime(), nullable=True))
|
op.create_unique_constraint(
|
||||||
op.add_column('apc_referentiel_competences', sa.Column('scodoc_orig_filename', sa.Text(), nullable=True))
|
"apc_competence_referentiel_id_titre_key",
|
||||||
|
"apc_competence",
|
||||||
|
["referentiel_id", "titre"],
|
||||||
|
)
|
||||||
|
op.create_index(
|
||||||
|
op.f("ix_apc_competence_titre"), "apc_competence", ["titre"], unique=False
|
||||||
|
)
|
||||||
|
op.add_column(
|
||||||
|
"apc_referentiel_competences",
|
||||||
|
sa.Column("scodoc_date_loaded", sa.DateTime(), nullable=True),
|
||||||
|
)
|
||||||
|
op.add_column(
|
||||||
|
"apc_referentiel_competences",
|
||||||
|
sa.Column("scodoc_orig_filename", sa.Text(), nullable=True),
|
||||||
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_column('apc_referentiel_competences', 'scodoc_orig_filename')
|
op.drop_column("apc_referentiel_competences", "scodoc_orig_filename")
|
||||||
op.drop_column('apc_referentiel_competences', 'scodoc_date_loaded')
|
op.drop_column("apc_referentiel_competences", "scodoc_date_loaded")
|
||||||
op.drop_index(op.f('ix_apc_competence_titre'), table_name='apc_competence')
|
op.drop_index(op.f("ix_apc_competence_titre"), table_name="apc_competence")
|
||||||
op.drop_constraint('apc_competence_referentiel_id_titre_key', 'apc_competence', type_='unique')
|
op.drop_constraint(
|
||||||
op.drop_index(op.f('ix_apc_app_critique_code'), table_name='apc_app_critique')
|
"apc_competence_referentiel_id_titre_key", "apc_competence", type_="unique"
|
||||||
op.add_column('apc_annee_parcours', sa.Column('numero', sa.INTEGER(), autoincrement=False, nullable=True))
|
|
||||||
op.drop_column('apc_annee_parcours', 'ordre')
|
|
||||||
op.create_table('app_crit',
|
|
||||||
sa.Column('id', sa.INTEGER(), server_default=sa.text("nextval('app_crit_id_seq'::regclass)"), autoincrement=True, nullable=False),
|
|
||||||
sa.Column('code', sa.TEXT(), autoincrement=False, nullable=False),
|
|
||||||
sa.Column('titre', sa.TEXT(), autoincrement=False, nullable=True),
|
|
||||||
sa.PrimaryKeyConstraint('id', name='app_crit_pkey'),
|
|
||||||
postgresql_ignore_search_path=False
|
|
||||||
)
|
)
|
||||||
op.create_table('modules_acs',
|
op.drop_index(op.f("ix_apc_app_critique_code"), table_name="apc_app_critique")
|
||||||
sa.Column('module_id', sa.INTEGER(), autoincrement=False, nullable=True),
|
op.add_column(
|
||||||
sa.Column('ac_id', sa.INTEGER(), autoincrement=False, nullable=True),
|
"apc_annee_parcours",
|
||||||
sa.ForeignKeyConstraint(['ac_id'], ['app_crit.id'], name='modules_acs_ac_id_fkey'),
|
sa.Column("numero", sa.INTEGER(), autoincrement=False, nullable=True),
|
||||||
sa.ForeignKeyConstraint(['module_id'], ['notes_modules.id'], name='modules_acs_module_id_fkey')
|
)
|
||||||
|
op.drop_column("apc_annee_parcours", "ordre")
|
||||||
|
op.create_table(
|
||||||
|
"app_crit",
|
||||||
|
sa.Column(
|
||||||
|
"id",
|
||||||
|
sa.INTEGER(),
|
||||||
|
server_default=sa.text("nextval('app_crit_id_seq'::regclass)"),
|
||||||
|
autoincrement=True,
|
||||||
|
nullable=False,
|
||||||
|
),
|
||||||
|
sa.Column("code", sa.TEXT(), autoincrement=False, nullable=False),
|
||||||
|
sa.Column("titre", sa.TEXT(), autoincrement=False, nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint("id", name="app_crit_pkey"),
|
||||||
|
postgresql_ignore_search_path=False,
|
||||||
|
)
|
||||||
|
op.create_table(
|
||||||
|
"modules_acs",
|
||||||
|
sa.Column("module_id", sa.INTEGER(), autoincrement=False, nullable=True),
|
||||||
|
sa.Column("ac_id", sa.INTEGER(), autoincrement=False, nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(
|
||||||
|
["ac_id"], ["app_crit.id"], name="modules_acs_ac_id_fkey"
|
||||||
|
),
|
||||||
|
sa.ForeignKeyConstraint(
|
||||||
|
["module_id"], ["notes_modules.id"], name="modules_acs_module_id_fkey"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
@ -10,27 +10,50 @@ import sqlalchemy as sa
|
|||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision = 'a217bf588f4c'
|
revision = "a217bf588f4c"
|
||||||
down_revision = 'f73251d1d825'
|
down_revision = "f73251d1d825"
|
||||||
branch_labels = None
|
branch_labels = None
|
||||||
depends_on = None
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.alter_column('notes_semset_formsemestre', 'semset_id',
|
op.alter_column(
|
||||||
existing_type=sa.INTEGER(),
|
"notes_semset_formsemestre",
|
||||||
nullable=False)
|
"semset_id",
|
||||||
op.drop_constraint('notes_semset_formsemestre_semset_id_fkey', 'notes_semset_formsemestre', type_='foreignkey')
|
existing_type=sa.INTEGER(),
|
||||||
op.create_foreign_key(None, 'notes_semset_formsemestre', 'notes_semset', ['semset_id'], ['id'], ondelete='CASCADE')
|
nullable=False,
|
||||||
|
)
|
||||||
|
op.drop_constraint(
|
||||||
|
"notes_semset_formsemestre_semset_id_fkey",
|
||||||
|
"notes_semset_formsemestre",
|
||||||
|
type_="foreignkey",
|
||||||
|
)
|
||||||
|
op.create_foreign_key(
|
||||||
|
None,
|
||||||
|
"notes_semset_formsemestre",
|
||||||
|
"notes_semset",
|
||||||
|
["semset_id"],
|
||||||
|
["id"],
|
||||||
|
ondelete="CASCADE",
|
||||||
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_constraint(None, 'notes_semset_formsemestre', type_='foreignkey')
|
op.drop_constraint(None, "notes_semset_formsemestre", type_="foreignkey")
|
||||||
op.create_foreign_key('notes_semset_formsemestre_semset_id_fkey', 'notes_semset_formsemestre', 'notes_semset', ['semset_id'], ['id'])
|
op.create_foreign_key(
|
||||||
op.alter_column('notes_semset_formsemestre', 'semset_id',
|
"notes_semset_formsemestre_semset_id_fkey",
|
||||||
existing_type=sa.INTEGER(),
|
"notes_semset_formsemestre",
|
||||||
nullable=True)
|
"notes_semset",
|
||||||
|
["semset_id"],
|
||||||
|
["id"],
|
||||||
|
)
|
||||||
|
op.alter_column(
|
||||||
|
"notes_semset_formsemestre",
|
||||||
|
"semset_id",
|
||||||
|
existing_type=sa.INTEGER(),
|
||||||
|
nullable=True,
|
||||||
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
@ -10,21 +10,23 @@ import sqlalchemy as sa
|
|||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision = 'c8efc54586d8'
|
revision = "c8efc54586d8"
|
||||||
down_revision = '6cfc21a7ae1b'
|
down_revision = "6cfc21a7ae1b"
|
||||||
branch_labels = None
|
branch_labels = None
|
||||||
depends_on = None
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.add_column('notes_ue', sa.Column('semestre_idx', sa.Integer(), nullable=True))
|
op.add_column("notes_ue", sa.Column("semestre_idx", sa.Integer(), nullable=True))
|
||||||
op.create_index(op.f('ix_notes_ue_semestre_idx'), 'notes_ue', ['semestre_idx'], unique=False)
|
op.create_index(
|
||||||
|
op.f("ix_notes_ue_semestre_idx"), "notes_ue", ["semestre_idx"], unique=False
|
||||||
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_index(op.f('ix_notes_ue_semestre_idx'), table_name='notes_ue')
|
op.drop_index(op.f("ix_notes_ue_semestre_idx"), table_name="notes_ue")
|
||||||
op.drop_column('notes_ue', 'semestre_idx')
|
op.drop_column("notes_ue", "semestre_idx")
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
@ -10,23 +10,25 @@ import sqlalchemy as sa
|
|||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision = 'd3d92b2d0092'
|
revision = "d3d92b2d0092"
|
||||||
down_revision = '017e32eb4773'
|
down_revision = "017e32eb4773"
|
||||||
branch_labels = None
|
branch_labels = None
|
||||||
depends_on = None
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.add_column('itemsuivi_tags', sa.Column('dept_id', sa.Integer(), nullable=True))
|
op.add_column("itemsuivi_tags", sa.Column("dept_id", sa.Integer(), nullable=True))
|
||||||
op.create_index(op.f('ix_itemsuivi_tags_dept_id'), 'itemsuivi_tags', ['dept_id'], unique=False)
|
op.create_index(
|
||||||
op.create_foreign_key(None, 'itemsuivi_tags', 'departement', ['dept_id'], ['id'])
|
op.f("ix_itemsuivi_tags_dept_id"), "itemsuivi_tags", ["dept_id"], unique=False
|
||||||
|
)
|
||||||
|
op.create_foreign_key(None, "itemsuivi_tags", "departement", ["dept_id"], ["id"])
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_constraint(None, 'itemsuivi_tags', type_='foreignkey')
|
op.drop_constraint(None, "itemsuivi_tags", type_="foreignkey")
|
||||||
op.drop_index(op.f('ix_itemsuivi_tags_dept_id'), table_name='itemsuivi_tags')
|
op.drop_index(op.f("ix_itemsuivi_tags_dept_id"), table_name="itemsuivi_tags")
|
||||||
op.drop_column('itemsuivi_tags', 'dept_id')
|
op.drop_column("itemsuivi_tags", "dept_id")
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
@ -10,49 +10,73 @@ import sqlalchemy as sa
|
|||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision = 'f6e7d2e01be1'
|
revision = "f6e7d2e01be1"
|
||||||
down_revision = 'd3d92b2d0092'
|
down_revision = "d3d92b2d0092"
|
||||||
branch_labels = None
|
branch_labels = None
|
||||||
depends_on = None
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.alter_column('notes_formsemestre_etapes', 'etape_apo',
|
op.alter_column(
|
||||||
existing_type=sa.VARCHAR(length=16),
|
"notes_formsemestre_etapes",
|
||||||
type_=sa.String(length=24),
|
"etape_apo",
|
||||||
existing_nullable=True)
|
existing_type=sa.VARCHAR(length=16),
|
||||||
op.alter_column('notes_formsemestre_inscription', 'etape',
|
type_=sa.String(length=24),
|
||||||
existing_type=sa.VARCHAR(length=16),
|
existing_nullable=True,
|
||||||
type_=sa.String(length=24),
|
)
|
||||||
existing_nullable=True)
|
op.alter_column(
|
||||||
op.alter_column('notes_modules', 'code_apogee',
|
"notes_formsemestre_inscription",
|
||||||
existing_type=sa.VARCHAR(length=16),
|
"etape",
|
||||||
type_=sa.String(length=24),
|
existing_type=sa.VARCHAR(length=16),
|
||||||
existing_nullable=True)
|
type_=sa.String(length=24),
|
||||||
op.alter_column('notes_ue', 'code_apogee',
|
existing_nullable=True,
|
||||||
existing_type=sa.VARCHAR(length=16),
|
)
|
||||||
type_=sa.String(length=24),
|
op.alter_column(
|
||||||
existing_nullable=True)
|
"notes_modules",
|
||||||
|
"code_apogee",
|
||||||
|
existing_type=sa.VARCHAR(length=16),
|
||||||
|
type_=sa.String(length=24),
|
||||||
|
existing_nullable=True,
|
||||||
|
)
|
||||||
|
op.alter_column(
|
||||||
|
"notes_ue",
|
||||||
|
"code_apogee",
|
||||||
|
existing_type=sa.VARCHAR(length=16),
|
||||||
|
type_=sa.String(length=24),
|
||||||
|
existing_nullable=True,
|
||||||
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.alter_column('notes_ue', 'code_apogee',
|
op.alter_column(
|
||||||
existing_type=sa.String(length=24),
|
"notes_ue",
|
||||||
type_=sa.VARCHAR(length=16),
|
"code_apogee",
|
||||||
existing_nullable=True)
|
existing_type=sa.String(length=24),
|
||||||
op.alter_column('notes_modules', 'code_apogee',
|
type_=sa.VARCHAR(length=16),
|
||||||
existing_type=sa.String(length=24),
|
existing_nullable=True,
|
||||||
type_=sa.VARCHAR(length=16),
|
)
|
||||||
existing_nullable=True)
|
op.alter_column(
|
||||||
op.alter_column('notes_formsemestre_inscription', 'etape',
|
"notes_modules",
|
||||||
existing_type=sa.String(length=24),
|
"code_apogee",
|
||||||
type_=sa.VARCHAR(length=16),
|
existing_type=sa.String(length=24),
|
||||||
existing_nullable=True)
|
type_=sa.VARCHAR(length=16),
|
||||||
op.alter_column('notes_formsemestre_etapes', 'etape_apo',
|
existing_nullable=True,
|
||||||
existing_type=sa.String(length=24),
|
)
|
||||||
type_=sa.VARCHAR(length=16),
|
op.alter_column(
|
||||||
existing_nullable=True)
|
"notes_formsemestre_inscription",
|
||||||
|
"etape",
|
||||||
|
existing_type=sa.String(length=24),
|
||||||
|
type_=sa.VARCHAR(length=16),
|
||||||
|
existing_nullable=True,
|
||||||
|
)
|
||||||
|
op.alter_column(
|
||||||
|
"notes_formsemestre_etapes",
|
||||||
|
"etape_apo",
|
||||||
|
existing_type=sa.String(length=24),
|
||||||
|
type_=sa.VARCHAR(length=16),
|
||||||
|
existing_nullable=True,
|
||||||
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
@ -10,26 +10,29 @@ import sqlalchemy as sa
|
|||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision = 'f73251d1d825'
|
revision = "f73251d1d825"
|
||||||
down_revision = 'f6e7d2e01be1'
|
down_revision = "f6e7d2e01be1"
|
||||||
branch_labels = None
|
branch_labels = None
|
||||||
depends_on = None
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.create_table('scodoc_site_config',
|
op.create_table(
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
"scodoc_site_config",
|
||||||
sa.Column('name', sa.String(length=128), nullable=False),
|
sa.Column("id", sa.Integer(), nullable=False),
|
||||||
sa.Column('value', sa.Text(), nullable=True),
|
sa.Column("name", sa.String(length=128), nullable=False),
|
||||||
sa.PrimaryKeyConstraint('id')
|
sa.Column("value", sa.Text(), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint("id"),
|
||||||
|
)
|
||||||
|
op.create_index(
|
||||||
|
op.f("ix_scodoc_site_config_name"), "scodoc_site_config", ["name"], unique=False
|
||||||
)
|
)
|
||||||
op.create_index(op.f('ix_scodoc_site_config_name'), 'scodoc_site_config', ['name'], unique=False)
|
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_index(op.f('ix_scodoc_site_config_name'), table_name='scodoc_site_config')
|
op.drop_index(op.f("ix_scodoc_site_config_name"), table_name="scodoc_site_config")
|
||||||
op.drop_table('scodoc_site_config')
|
op.drop_table("scodoc_site_config")
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
@ -10,21 +10,31 @@ import sqlalchemy as sa
|
|||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision = 'f86c013c9fbd'
|
revision = "f86c013c9fbd"
|
||||||
down_revision = '669065fb2d20'
|
down_revision = "669065fb2d20"
|
||||||
branch_labels = None
|
branch_labels = None
|
||||||
depends_on = None
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_constraint('notes_formations_acronyme_titre_version_key', 'notes_formations', type_='unique')
|
op.drop_constraint(
|
||||||
op.create_unique_constraint(None, 'notes_formations', ['dept_id', 'acronyme', 'titre', 'version'])
|
"notes_formations_acronyme_titre_version_key",
|
||||||
|
"notes_formations",
|
||||||
|
type_="unique",
|
||||||
|
)
|
||||||
|
op.create_unique_constraint(
|
||||||
|
None, "notes_formations", ["dept_id", "acronyme", "titre", "version"]
|
||||||
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_constraint(None, 'notes_formations', type_='unique')
|
op.drop_constraint(None, "notes_formations", type_="unique")
|
||||||
op.create_unique_constraint('notes_formations_acronyme_titre_version_key', 'notes_formations', ['acronyme', 'titre', 'version'])
|
op.create_unique_constraint(
|
||||||
|
"notes_formations_acronyme_titre_version_key",
|
||||||
|
"notes_formations",
|
||||||
|
["acronyme", "titre", "version"],
|
||||||
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
@ -7,65 +7,84 @@ Source: http://wikipython.flibuste.net/moin.py/JouerAvecUnicode#head-1213938516c
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
_reptable = {}
|
_reptable = {}
|
||||||
|
|
||||||
|
|
||||||
def _fill_reptable():
|
def _fill_reptable():
|
||||||
_corresp = [
|
_corresp = [
|
||||||
(u"A", [0x00C0,0x00C1,0x00C2,0x00C3,0x00C4,0x00C5,0x0100,0x0102,0x0104]),
|
("A", [0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x0100, 0x0102, 0x0104]),
|
||||||
(u"AE", [0x00C6]),
|
("AE", [0x00C6]),
|
||||||
(u"a", [0x00E0,0x00E1,0x00E2,0x00E3,0x00E4,0x00E5,0x0101,0x0103,0x0105]),
|
("a", [0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x0101, 0x0103, 0x0105]),
|
||||||
(u"ae", [0x00E6]),
|
("ae", [0x00E6]),
|
||||||
(u"C", [0x00C7,0x0106,0x0108,0x010A,0x010C]),
|
("C", [0x00C7, 0x0106, 0x0108, 0x010A, 0x010C]),
|
||||||
(u"c", [0x00E7,0x0107,0x0109,0x010B,0x010D]),
|
("c", [0x00E7, 0x0107, 0x0109, 0x010B, 0x010D]),
|
||||||
(u"D", [0x00D0,0x010E,0x0110]),
|
("D", [0x00D0, 0x010E, 0x0110]),
|
||||||
(u"d", [0x00F0,0x010F,0x0111]),
|
("d", [0x00F0, 0x010F, 0x0111]),
|
||||||
(u"E", [0x00C8,0x00C9,0x00CA,0x00CB,0x0112,0x0114,0x0116,0x0118,0x011A]),
|
("E", [0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0112, 0x0114, 0x0116, 0x0118, 0x011A]),
|
||||||
(u"e", [0x00E8,0x00E9,0x00EA,0x00EB,0x0113,0x0115,0x0117,0x0119,0x011B]),
|
("e", [0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0113, 0x0115, 0x0117, 0x0119, 0x011B]),
|
||||||
(u"G", [0x011C,0x011E,0x0120,0x0122]),
|
("G", [0x011C, 0x011E, 0x0120, 0x0122]),
|
||||||
(u"g", [0x011D,0x011F,0x0121,0x0123]),
|
("g", [0x011D, 0x011F, 0x0121, 0x0123]),
|
||||||
(u"H", [0x0124,0x0126]),
|
("H", [0x0124, 0x0126]),
|
||||||
(u"h", [0x0125,0x0127]),
|
("h", [0x0125, 0x0127]),
|
||||||
(u"I", [0x00CC,0x00CD,0x00CE,0x00CF,0x0128,0x012A,0x012C,0x012E,0x0130]),
|
("I", [0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x0128, 0x012A, 0x012C, 0x012E, 0x0130]),
|
||||||
(u"i", [0x00EC,0x00ED,0x00EE,0x00EF,0x0129,0x012B,0x012D,0x012F,0x0131]),
|
("i", [0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x0129, 0x012B, 0x012D, 0x012F, 0x0131]),
|
||||||
(u"IJ", [0x0132]),
|
("IJ", [0x0132]),
|
||||||
(u"ij", [0x0133]),
|
("ij", [0x0133]),
|
||||||
(u"J", [0x0134]),
|
("J", [0x0134]),
|
||||||
(u"j", [0x0135]),
|
("j", [0x0135]),
|
||||||
(u"K", [0x0136]),
|
("K", [0x0136]),
|
||||||
(u"k", [0x0137,0x0138]),
|
("k", [0x0137, 0x0138]),
|
||||||
(u"L", [0x0139,0x013B,0x013D,0x013F,0x0141]),
|
("L", [0x0139, 0x013B, 0x013D, 0x013F, 0x0141]),
|
||||||
(u"l", [0x013A,0x013C,0x013E,0x0140,0x0142]),
|
("l", [0x013A, 0x013C, 0x013E, 0x0140, 0x0142]),
|
||||||
(u"N", [0x00D1,0x0143,0x0145,0x0147,0x014A]),
|
("N", [0x00D1, 0x0143, 0x0145, 0x0147, 0x014A]),
|
||||||
(u"n", [0x00F1,0x0144,0x0146,0x0148,0x0149,0x014B]),
|
("n", [0x00F1, 0x0144, 0x0146, 0x0148, 0x0149, 0x014B]),
|
||||||
(u"O", [0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D8,0x014C,0x014E,0x0150]),
|
("O", [0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D8, 0x014C, 0x014E, 0x0150]),
|
||||||
(u"o", [0x00F2,0x00F3,0x00F4,0x00F5,0x00F6,0x00F8,0x014D,0x014F,0x0151]),
|
("o", [0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F8, 0x014D, 0x014F, 0x0151]),
|
||||||
(u"OE", [0x0152]),
|
("OE", [0x0152]),
|
||||||
(u"oe", [0x0153]),
|
("oe", [0x0153]),
|
||||||
(u"R", [0x0154,0x0156,0x0158]),
|
("R", [0x0154, 0x0156, 0x0158]),
|
||||||
(u"r", [0x0155,0x0157,0x0159]),
|
("r", [0x0155, 0x0157, 0x0159]),
|
||||||
(u"S", [0x015A,0x015C,0x015E,0x0160]),
|
("S", [0x015A, 0x015C, 0x015E, 0x0160]),
|
||||||
(u"s", [0x015B,0x015D,0x015F,0x01610,0x017F]),
|
("s", [0x015B, 0x015D, 0x015F, 0x01610, 0x017F]),
|
||||||
(u"T", [0x0162,0x0164,0x0166]),
|
("T", [0x0162, 0x0164, 0x0166]),
|
||||||
(u"t", [0x0163,0x0165,0x0167]),
|
("t", [0x0163, 0x0165, 0x0167]),
|
||||||
(u"U", [0x00D9,0x00DA,0x00DB,0x00DC,0x0168,0x016A,0x016C,0x016E,0x0170,0x172]),
|
(
|
||||||
(u"u", [0x00F9,0x00FA,0x00FB,0x00FC,0x0169,0x016B,0x016D,0x016F,0x0171]),
|
"U",
|
||||||
(u"W", [0x0174]),
|
[
|
||||||
(u"w", [0x0175]),
|
0x00D9,
|
||||||
(u"Y", [0x00DD,0x0176,0x0178]),
|
0x00DA,
|
||||||
(u"y", [0x00FD,0x00FF,0x0177]),
|
0x00DB,
|
||||||
(u"Z", [0x0179,0x017B,0x017D]),
|
0x00DC,
|
||||||
(u"z", [0x017A,0x017C,0x017E]),
|
0x0168,
|
||||||
(u"2", [0x00B2]), # deux exposant
|
0x016A,
|
||||||
(u" ", [0x00A0]), #  
|
0x016C,
|
||||||
(u"", [0xB0]), # degre
|
0x016E,
|
||||||
(u"", [0xA9]), # copyright
|
0x0170,
|
||||||
(u"1/2", [0xBD]), # 1/2
|
0x172,
|
||||||
]
|
],
|
||||||
|
),
|
||||||
|
("u", [0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x016D, 0x016F, 0x0171]),
|
||||||
|
("W", [0x0174]),
|
||||||
|
("w", [0x0175]),
|
||||||
|
("Y", [0x00DD, 0x0176, 0x0178]),
|
||||||
|
("y", [0x00FD, 0x00FF, 0x0177]),
|
||||||
|
("Z", [0x0179, 0x017B, 0x017D]),
|
||||||
|
("z", [0x017A, 0x017C, 0x017E]),
|
||||||
|
("2", [0x00B2]), # deux exposant
|
||||||
|
(" ", [0x00A0]), #  
|
||||||
|
("", [0xB0]), # degre
|
||||||
|
("", [0xA9]), # copyright
|
||||||
|
("1/2", [0xBD]), # 1/2
|
||||||
|
]
|
||||||
global _reptable
|
global _reptable
|
||||||
for repchar,codes in _corresp :
|
for repchar, codes in _corresp:
|
||||||
for code in codes :
|
for code in codes:
|
||||||
_reptable[code] = repchar
|
_reptable[code] = repchar
|
||||||
|
|
||||||
|
|
||||||
_fill_reptable()
|
_fill_reptable()
|
||||||
def suppression_diacritics(s) :
|
|
||||||
|
|
||||||
|
def suppression_diacritics(s):
|
||||||
"""Suppression des accents et autres marques.
|
"""Suppression des accents et autres marques.
|
||||||
|
|
||||||
@param s: le texte à nettoyer.
|
@param s: le texte à nettoyer.
|
||||||
@ -73,6 +92,6 @@ def suppression_diacritics(s) :
|
|||||||
@return: le texte nettoyé de ses marques diacritiques.
|
@return: le texte nettoyé de ses marques diacritiques.
|
||||||
@rtype: unicode
|
@rtype: unicode
|
||||||
"""
|
"""
|
||||||
if isinstance(s,str) :
|
if isinstance(s, str):
|
||||||
s = unicode(s,"utf8","replace")
|
s = unicode(s, "utf8", "replace")
|
||||||
return s.translate(_reptable)
|
return s.translate(_reptable)
|
||||||
|
2
sco_version.py
Normal file → Executable file
2
sco_version.py
Normal file → Executable file
@ -1,7 +1,7 @@
|
|||||||
# -*- mode: python -*-
|
# -*- mode: python -*-
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
SCOVERSION = "9.3.19"
|
SCOVERSION = "9.3.16"
|
||||||
|
|
||||||
SCONAME = "ScoDoc"
|
SCONAME = "ScoDoc"
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ def test_abs_groupe_etat(api_headers):
|
|||||||
# XXX TODO
|
# XXX TODO
|
||||||
# def reset_etud_abs(api_headers):
|
# def reset_etud_abs(api_headers):
|
||||||
# """
|
# """
|
||||||
# Test 'reset_etud_abs'
|
# Test 'abs_groupe_etat'
|
||||||
#
|
#
|
||||||
# Routes :
|
# Routes :
|
||||||
# - /absences/etudid/<int:etudid>/list_abs/<string:list_abs>/reset_etud_abs
|
# - /absences/etudid/<int:etudid>/list_abs/<string:list_abs>/reset_etud_abs
|
||||||
|
@ -70,7 +70,7 @@ def test_evaluations(api_headers):
|
|||||||
assert eval["moduleimpl_id"] == moduleimpl_id
|
assert eval["moduleimpl_id"] == moduleimpl_id
|
||||||
|
|
||||||
|
|
||||||
def test_evaluation_notes(api_headers): # XXX TODO changer la boucle pour parcourir le dict sans les indices
|
def test_evaluation_notes(api_headers):
|
||||||
"""
|
"""
|
||||||
Test 'evaluation_notes'
|
Test 'evaluation_notes'
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ from config import TestConfig
|
|||||||
from tests.unit import sco_fake_gen
|
from tests.unit import sco_fake_gen
|
||||||
|
|
||||||
import app
|
import app
|
||||||
from app import db
|
|
||||||
from app.comp import res_sem
|
from app.comp import res_sem
|
||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.models import FormSemestre
|
from app.models import FormSemestre
|
||||||
@ -32,7 +31,8 @@ from app.scodoc import sco_codes_parcours
|
|||||||
from app.scodoc import sco_evaluations
|
from app.scodoc import sco_evaluations
|
||||||
from app.scodoc import sco_evaluation_db
|
from app.scodoc import sco_evaluation_db
|
||||||
from app.scodoc import sco_formsemestre_validation
|
from app.scodoc import sco_formsemestre_validation
|
||||||
from app.scodoc import sco_cursus_dut
|
from app.scodoc import sco_parcours_dut
|
||||||
|
from app.scodoc import sco_cache
|
||||||
from app.scodoc import sco_saisie_notes
|
from app.scodoc import sco_saisie_notes
|
||||||
from app.scodoc import sco_utils as scu
|
from app.scodoc import sco_utils as scu
|
||||||
|
|
||||||
@ -194,20 +194,20 @@ def run_sco_basic(verbose=False):
|
|||||||
|
|
||||||
# --- Permission saisie notes et décisions de jury, avec ou sans démission ou défaillance
|
# --- Permission saisie notes et décisions de jury, avec ou sans démission ou défaillance
|
||||||
# on n'a pas encore saisi de décisions
|
# on n'a pas encore saisi de décisions
|
||||||
assert not sco_cursus_dut.formsemestre_has_decisions(formsemestre_id)
|
assert not sco_parcours_dut.formsemestre_has_decisions(formsemestre_id)
|
||||||
# Saisie d'un décision AJ, non assidu
|
# Saisie d'un décision AJ, non assidu
|
||||||
etudid = etuds[-1]["etudid"]
|
etudid = etuds[-1]["etudid"]
|
||||||
sco_cursus_dut.formsemestre_validate_ues(
|
sco_parcours_dut.formsemestre_validate_ues(
|
||||||
formsemestre_id, etudid, sco_codes_parcours.AJ, False
|
formsemestre_id, etudid, sco_codes_parcours.AJ, False
|
||||||
)
|
)
|
||||||
assert sco_cursus_dut.formsemestre_has_decisions(
|
assert sco_parcours_dut.formsemestre_has_decisions(
|
||||||
formsemestre_id
|
formsemestre_id
|
||||||
), "décisions manquantes"
|
), "décisions manquantes"
|
||||||
# Suppression de la décision
|
# Suppression de la décision
|
||||||
sco_formsemestre_validation.formsemestre_validation_suppress_etud(
|
sco_formsemestre_validation.formsemestre_validation_suppress_etud(
|
||||||
formsemestre_id, etudid
|
formsemestre_id, etudid
|
||||||
)
|
)
|
||||||
assert not sco_cursus_dut.formsemestre_has_decisions(
|
assert not sco_parcours_dut.formsemestre_has_decisions(
|
||||||
formsemestre_id
|
formsemestre_id
|
||||||
), "décisions non effacées"
|
), "décisions non effacées"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user