forked from ScoDoc/ScoDoc
Apo: modif semset pour BUT. Interdit changement période.
This commit is contained in:
parent
339d70edd2
commit
54bcbff179
@ -7,33 +7,34 @@
|
|||||||
"""
|
"""
|
||||||
ScoDoc 9 API : accès aux formsemestres
|
ScoDoc 9 API : accès aux formsemestres
|
||||||
"""
|
"""
|
||||||
from flask import g, jsonify, request
|
# from flask import g, jsonify, request
|
||||||
from flask_login import login_required
|
# from flask_login import login_required
|
||||||
|
|
||||||
import app
|
# import app
|
||||||
from app.api import api_bp as bp, api_web_bp, API_CLIENT_ERROR
|
# from app.api import api_bp as bp, api_web_bp, API_CLIENT_ERROR
|
||||||
from app.decorators import scodoc, permission_required
|
# from app.decorators import scodoc, permission_required
|
||||||
from app.scodoc.sco_utils import json_error
|
# from app.scodoc.sco_utils import json_error
|
||||||
from app.models.formsemestre import NotesSemSet
|
# from app.models.formsemestre import NotesSemSet
|
||||||
from app.scodoc.sco_permissions import Permission
|
# from app.scodoc.sco_permissions import Permission
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/semset/set_periode/<int:semset_id>", methods=["POST"])
|
# Impossible de changer la période à cause des archives
|
||||||
@api_web_bp.route("/semset/set_periode/<int:semset_id>", methods=["POST"])
|
# @bp.route("/semset/set_periode/<int:semset_id>", methods=["POST"])
|
||||||
@login_required
|
# @api_web_bp.route("/semset/set_periode/<int:semset_id>", methods=["POST"])
|
||||||
@scodoc
|
# @login_required
|
||||||
@permission_required(Permission.ScoEditApo)
|
# @scodoc
|
||||||
# TODO à modifier pour utiliser @as_json
|
# @permission_required(Permission.ScoEditApo)
|
||||||
def semset_set_periode(semset_id: int):
|
# # TODO à modifier pour utiliser @as_json
|
||||||
"Change la période d'un semset"
|
# def semset_set_periode(semset_id: int):
|
||||||
query = NotesSemSet.query.filter_by(semset_id=semset_id)
|
# "Change la période d'un semset"
|
||||||
if g.scodoc_dept:
|
# query = NotesSemSet.query.filter_by(semset_id=semset_id)
|
||||||
query = query.filter_by(dept_id=g.scodoc_dept_id)
|
# if g.scodoc_dept:
|
||||||
semset: NotesSemSet = query.first_or_404()
|
# query = query.filter_by(dept_id=g.scodoc_dept_id)
|
||||||
data = request.get_json(force=True) # may raise 400 Bad Request
|
# semset: NotesSemSet = query.first_or_404()
|
||||||
try:
|
# data = request.get_json(force=True) # may raise 400 Bad Request
|
||||||
periode = int(data)
|
# try:
|
||||||
semset.set_periode(periode)
|
# periode = int(data)
|
||||||
except ValueError:
|
# semset.set_periode(periode)
|
||||||
return json_error(API_CLIENT_ERROR, "invalid periode value")
|
# except ValueError:
|
||||||
return jsonify({"OK": True})
|
# return json_error(API_CLIENT_ERROR, "invalid periode value")
|
||||||
|
# return jsonify({"OK": True})
|
||||||
|
@ -19,6 +19,7 @@ from app.models import Identite, FormSemestre, ModuleImpl, ScolarAutorisationIns
|
|||||||
from app.scodoc.codes_cursus import UE_SPORT, DEF
|
from app.scodoc.codes_cursus import UE_SPORT, DEF
|
||||||
from app.scodoc import sco_utils as scu
|
from app.scodoc import sco_utils as scu
|
||||||
|
|
||||||
|
|
||||||
# Pour raccorder le code des anciens codes qui attendent une NoteTable
|
# Pour raccorder le code des anciens codes qui attendent une NoteTable
|
||||||
class NotesTableCompat(ResultatsSemestre):
|
class NotesTableCompat(ResultatsSemestre):
|
||||||
"""Implementation partielle de NotesTable
|
"""Implementation partielle de NotesTable
|
||||||
@ -266,16 +267,21 @@ class NotesTableCompat(ResultatsSemestre):
|
|||||||
ue_status_list.append(ue_status)
|
ue_status_list.append(ue_status)
|
||||||
return self.parcours.check_barre_ues(ue_status_list)
|
return self.parcours.check_barre_ues(ue_status_list)
|
||||||
|
|
||||||
def all_etuds_have_sem_decisions(self):
|
def etudids_without_decisions(self) -> list[int]:
|
||||||
"""True si tous les étudiants du semestre ont une décision de jury.
|
"""Liste des id d'étudiants du semestre non démissionnaires
|
||||||
Ne regarde pas les décisions d'UE.
|
n'ayant pas de décision de jury.
|
||||||
|
- En classic: ne regarde pas que la décision de semestre (pas les décisions d'UE).
|
||||||
|
- en BUT: utilise etud_has_decision
|
||||||
"""
|
"""
|
||||||
for ins in self.formsemestre.inscriptions:
|
check_func = (
|
||||||
if ins.etat != scu.INSCRIT:
|
self.etud_has_decision if self.is_apc else self.get_etud_decision_sem
|
||||||
continue # skip démissionnaires
|
)
|
||||||
if self.get_etud_decision_sem(ins.etudid) is None:
|
etudids = [
|
||||||
return False
|
ins.etudid
|
||||||
return True
|
for ins in self.formsemestre.inscriptions
|
||||||
|
if (ins.etat == scu.INSCRIT) and (not check_func(ins.etudid))
|
||||||
|
]
|
||||||
|
return etudids
|
||||||
|
|
||||||
def etud_has_decision(self, etudid):
|
def etud_has_decision(self, etudid):
|
||||||
"""True s'il y a une décision de jury pour cet étudiant émanant de ce formsemestre.
|
"""True s'il y a une décision de jury pour cet étudiant émanant de ce formsemestre.
|
||||||
|
@ -143,10 +143,9 @@ def apo_csv_list_stored_archives(annee_scolaire=None, sem_id=None, etapes=None):
|
|||||||
if annee_scolaire:
|
if annee_scolaire:
|
||||||
e = re.compile(str(annee_scolaire) + "-.+")
|
e = re.compile(str(annee_scolaire) + "-.+")
|
||||||
oids = [x for x in oids if e.match(x)]
|
oids = [x for x in oids if e.match(x)]
|
||||||
# Note: ne filtre plus sur la période, afin que l'on puisse chnager le semset de période.
|
if sem_id:
|
||||||
# if sem_id:
|
e = re.compile(r"[0-9]{4}-" + str(sem_id))
|
||||||
# e = re.compile(r"[0-9]{4}-" + str(sem_id))
|
oids = [x for x in oids if e.match(x)]
|
||||||
# oids = [x for x in oids if e.match(x)]
|
|
||||||
|
|
||||||
infos = [] # liste d'infos
|
infos = [] # liste d'infos
|
||||||
for oid in oids:
|
for oid in oids:
|
||||||
|
@ -240,7 +240,11 @@ def apo_semset_maq_status(
|
|||||||
if semset["jury_ok"]:
|
if semset["jury_ok"]:
|
||||||
H.append("""<li>Décisions de jury saisies</li>""")
|
H.append("""<li>Décisions de jury saisies</li>""")
|
||||||
else:
|
else:
|
||||||
H.append("""<li>Il manque des décisions de jury !</li>""")
|
H.append(
|
||||||
|
f"""<li>Il manque de {semset["jury_nb_missing"]}
|
||||||
|
décision{"s" if semset["jury_nb_missing"] > 1 else ""}
|
||||||
|
de jury !</li>"""
|
||||||
|
)
|
||||||
|
|
||||||
if ok_for_export:
|
if ok_for_export:
|
||||||
H.append("""<li>%d étudiants, prêt pour l'export.</li>""" % len(nips_ok))
|
H.append("""<li>%d étudiants, prêt pour l'export.</li>""" % len(nips_ok))
|
||||||
|
@ -156,6 +156,8 @@ class SemSet(dict):
|
|||||||
|
|
||||||
def add(self, formsemestre_id):
|
def add(self, formsemestre_id):
|
||||||
"Ajoute ce semestre à l'ensemble"
|
"Ajoute ce semestre à l'ensemble"
|
||||||
|
# check for valid formsemestre_id
|
||||||
|
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
# check
|
# check
|
||||||
if formsemestre_id in self.formsemestre_ids:
|
if formsemestre_id in self.formsemestre_ids:
|
||||||
return # already there
|
return # already there
|
||||||
@ -166,6 +168,19 @@ class SemSet(dict):
|
|||||||
f"can't add {formsemestre_id} to set {self.semset_id}: incompatible sem_id"
|
f"can't add {formsemestre_id} to set {self.semset_id}: incompatible sem_id"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if self.formsemestre_ids:
|
||||||
|
formsemestre_1 = formsemestre.query.get(self.formsemestre_ids[0])
|
||||||
|
if formsemestre.formation.is_apc() != formsemestre_1.formation.is_apc():
|
||||||
|
raise ScoValueError(
|
||||||
|
"""On ne peut pas mélanger des semestres BUT/APC
|
||||||
|
avec des semestres ordinaires dans le même export.""",
|
||||||
|
dest_url=url_for(
|
||||||
|
"notes.apo_semset_maq_status",
|
||||||
|
scodoc_dept=g.scodoc_dept,
|
||||||
|
semset_id=self.semset_id,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
ndb.SimpleQuery(
|
ndb.SimpleQuery(
|
||||||
"""INSERT INTO notes_semset_formsemestre
|
"""INSERT INTO notes_semset_formsemestre
|
||||||
(formsemestre_id, semset_id)
|
(formsemestre_id, semset_id)
|
||||||
@ -249,17 +264,28 @@ class SemSet(dict):
|
|||||||
def load_etuds(self):
|
def load_etuds(self):
|
||||||
self["etuds_without_nip"] = set() # etudids
|
self["etuds_without_nip"] = set() # etudids
|
||||||
self["jury_ok"] = True
|
self["jury_ok"] = True
|
||||||
|
self["jury_nb_missing"] = 0
|
||||||
|
is_apc = None
|
||||||
for sem in self.sems:
|
for sem in self.sems:
|
||||||
formsemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"])
|
formsemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"])
|
||||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||||
|
if is_apc is not None and is_apc != nt.is_apc:
|
||||||
|
raise ScoValueError(
|
||||||
|
"Incohérence: semestre APC (BUT) et ordinaires mélangés !"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
is_apc = nt.is_apc
|
||||||
sem["etuds"] = list(nt.identdict.values())
|
sem["etuds"] = list(nt.identdict.values())
|
||||||
sem["nips"] = {e["code_nip"] for e in sem["etuds"] if e["code_nip"]}
|
sem["nips"] = {e["code_nip"] for e in sem["etuds"] if e["code_nip"]}
|
||||||
sem["etuds_without_nip"] = {
|
sem["etuds_without_nip"] = {
|
||||||
e["etudid"] for e in sem["etuds"] if not e["code_nip"]
|
e["etudid"] for e in sem["etuds"] if not e["code_nip"]
|
||||||
}
|
}
|
||||||
self["etuds_without_nip"] |= sem["etuds_without_nip"]
|
self["etuds_without_nip"] |= sem["etuds_without_nip"]
|
||||||
sem["jury_ok"] = nt.all_etuds_have_sem_decisions()
|
sem["etudids_no_jury"] = nt.etudids_without_decisions()
|
||||||
|
sem["jury_ok"] = not sem["etudids_no_jury"]
|
||||||
self["jury_ok"] &= sem["jury_ok"]
|
self["jury_ok"] &= sem["jury_ok"]
|
||||||
|
self["jury_nb_missing"] += len(sem["etudids_no_jury"])
|
||||||
|
self["is_apc"] = bool(is_apc)
|
||||||
|
|
||||||
def html_descr(self):
|
def html_descr(self):
|
||||||
"""Short HTML description"""
|
"""Short HTML description"""
|
||||||
@ -279,36 +305,21 @@ class SemSet(dict):
|
|||||||
)
|
)
|
||||||
H.append("</p>")
|
H.append("</p>")
|
||||||
|
|
||||||
H.append(
|
if self["sem_id"] == 1:
|
||||||
f"""<p>Période: <select name="periode" onchange="set_periode(this);">
|
periode = "1re période (S1, S3)"
|
||||||
<option value="1" {"selected" if self["sem_id"] == 1 else ""}>1re période (S1, S3)</option>
|
elif self["sem_id"] == 1:
|
||||||
<option value="2" {"selected" if self["sem_id"] == 2 else ""}>2de période (S2, S4)</option>
|
periode = "2de période (S2, S4)"
|
||||||
<option value="0" {"selected" if self["sem_id"] == 0 else ""}>non semestrialisée (LP, ...)</option>
|
else:
|
||||||
</select>
|
periode = "non semestrialisée (LP, ...). Incompatible avec BUT."
|
||||||
</p>
|
|
||||||
<script>
|
|
||||||
function set_periode(elt) {{
|
|
||||||
fetch(
|
|
||||||
"{ url_for("apiweb.semset_set_periode", scodoc_dept=g.scodoc_dept,
|
|
||||||
semset_id=self.semset_id )
|
|
||||||
}",
|
|
||||||
{{
|
|
||||||
method: "POST",
|
|
||||||
headers: {{
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
}},
|
|
||||||
body: JSON.stringify( elt.value )
|
|
||||||
}},
|
|
||||||
).then(sco_message("période modifiée"));
|
|
||||||
}};
|
|
||||||
</script>
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
H.append(
|
H.append(
|
||||||
f"<p>Etapes: <tt>{sco_formsemestre.etapes_apo_str(self.list_etapes())}</tt></p>"
|
f"""
|
||||||
|
<p>Période: <b>{periode}</b></p>
|
||||||
|
<p>Etapes: <tt>{sco_formsemestre.etapes_apo_str(self.list_etapes())}</tt></p>
|
||||||
|
|
||||||
|
<h4>Semestres de l'ensemble:</h4><ul class="semset_listsems">
|
||||||
|
"""
|
||||||
)
|
)
|
||||||
H.append("""<h4>Semestres de l'ensemble:</h4><ul class="semset_listsems">""")
|
|
||||||
|
|
||||||
for sem in self.sems:
|
for sem in self.sems:
|
||||||
H.append(
|
H.append(
|
||||||
@ -429,12 +440,8 @@ def do_semset_add_sem(semset_id, formsemestre_id):
|
|||||||
raise ScoValueError("empty semset_id")
|
raise ScoValueError("empty semset_id")
|
||||||
if formsemestre_id == "":
|
if formsemestre_id == "":
|
||||||
raise ScoValueError("pas de semestre choisi !")
|
raise ScoValueError("pas de semestre choisi !")
|
||||||
s = SemSet(semset_id=semset_id)
|
semset = SemSet(semset_id=semset_id)
|
||||||
# check for valid formsemestre_id
|
semset.add(formsemestre.id)
|
||||||
_ = sco_formsemestre.get_formsemestre(formsemestre_id) # raise exc
|
|
||||||
|
|
||||||
s.add(formsemestre_id)
|
|
||||||
|
|
||||||
return flask.redirect("apo_semset_maq_status?semset_id=%s" % semset_id)
|
return flask.redirect("apo_semset_maq_status?semset_id=%s" % semset_id)
|
||||||
|
|
||||||
|
|
||||||
@ -541,7 +548,7 @@ def semset_page(format="html"):
|
|||||||
<select name="sem_id">
|
<select name="sem_id">
|
||||||
<option value="1">1re période (S1, S3)</option>
|
<option value="1">1re période (S1, S3)</option>
|
||||||
<option value="2">2de période (S2, S4)</option>
|
<option value="2">2de période (S2, S4)</option>
|
||||||
<option value="0">non semestrialisée (LP, ...)</option>
|
<option value="0">non semestrialisée (LP, ... mais pas pour le BUT !)</option>
|
||||||
</select>
|
</select>
|
||||||
<input type="text" name="title" size="32"/>
|
<input type="text" name="title" size="32"/>
|
||||||
<input type="submit" value="Créer"/>
|
<input type="submit" value="Créer"/>
|
||||||
|
Loading…
Reference in New Issue
Block a user