forked from ScoDoc/ScoDoc
Apo: modif semset pour BUT. Interdit changement période.
This commit is contained in:
parent
36f75ab0c4
commit
6ae31c3e9f
@ -7,33 +7,34 @@
|
||||
"""
|
||||
ScoDoc 9 API : accès aux formsemestres
|
||||
"""
|
||||
from flask import g, jsonify, request
|
||||
from flask_login import login_required
|
||||
# from flask import g, jsonify, request
|
||||
# from flask_login import login_required
|
||||
|
||||
import app
|
||||
from app.api import api_bp as bp, api_web_bp, API_CLIENT_ERROR
|
||||
from app.decorators import scodoc, permission_required
|
||||
from app.scodoc.sco_utils import json_error
|
||||
from app.models.formsemestre import NotesSemSet
|
||||
from app.scodoc.sco_permissions import Permission
|
||||
# import app
|
||||
# from app.api import api_bp as bp, api_web_bp, API_CLIENT_ERROR
|
||||
# from app.decorators import scodoc, permission_required
|
||||
# from app.scodoc.sco_utils import json_error
|
||||
# from app.models.formsemestre import NotesSemSet
|
||||
# from app.scodoc.sco_permissions import Permission
|
||||
|
||||
|
||||
@bp.route("/semset/set_periode/<int:semset_id>", methods=["POST"])
|
||||
@api_web_bp.route("/semset/set_periode/<int:semset_id>", methods=["POST"])
|
||||
@login_required
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoEditApo)
|
||||
# TODO à modifier pour utiliser @as_json
|
||||
def semset_set_periode(semset_id: int):
|
||||
"Change la période d'un semset"
|
||||
query = NotesSemSet.query.filter_by(semset_id=semset_id)
|
||||
if g.scodoc_dept:
|
||||
query = query.filter_by(dept_id=g.scodoc_dept_id)
|
||||
semset: NotesSemSet = query.first_or_404()
|
||||
data = request.get_json(force=True) # may raise 400 Bad Request
|
||||
try:
|
||||
periode = int(data)
|
||||
semset.set_periode(periode)
|
||||
except ValueError:
|
||||
return json_error(API_CLIENT_ERROR, "invalid periode value")
|
||||
return jsonify({"OK": True})
|
||||
# Impossible de changer la période à cause des archives
|
||||
# @bp.route("/semset/set_periode/<int:semset_id>", methods=["POST"])
|
||||
# @api_web_bp.route("/semset/set_periode/<int:semset_id>", methods=["POST"])
|
||||
# @login_required
|
||||
# @scodoc
|
||||
# @permission_required(Permission.ScoEditApo)
|
||||
# # TODO à modifier pour utiliser @as_json
|
||||
# def semset_set_periode(semset_id: int):
|
||||
# "Change la période d'un semset"
|
||||
# query = NotesSemSet.query.filter_by(semset_id=semset_id)
|
||||
# if g.scodoc_dept:
|
||||
# query = query.filter_by(dept_id=g.scodoc_dept_id)
|
||||
# semset: NotesSemSet = query.first_or_404()
|
||||
# data = request.get_json(force=True) # may raise 400 Bad Request
|
||||
# try:
|
||||
# periode = int(data)
|
||||
# semset.set_periode(periode)
|
||||
# except ValueError:
|
||||
# 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 import sco_utils as scu
|
||||
|
||||
|
||||
# Pour raccorder le code des anciens codes qui attendent une NoteTable
|
||||
class NotesTableCompat(ResultatsSemestre):
|
||||
"""Implementation partielle de NotesTable
|
||||
@ -266,16 +267,21 @@ class NotesTableCompat(ResultatsSemestre):
|
||||
ue_status_list.append(ue_status)
|
||||
return self.parcours.check_barre_ues(ue_status_list)
|
||||
|
||||
def all_etuds_have_sem_decisions(self):
|
||||
"""True si tous les étudiants du semestre ont une décision de jury.
|
||||
Ne regarde pas les décisions d'UE.
|
||||
def etudids_without_decisions(self) -> list[int]:
|
||||
"""Liste des id d'étudiants du semestre non démissionnaires
|
||||
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:
|
||||
if ins.etat != scu.INSCRIT:
|
||||
continue # skip démissionnaires
|
||||
if self.get_etud_decision_sem(ins.etudid) is None:
|
||||
return False
|
||||
return True
|
||||
check_func = (
|
||||
self.etud_has_decision if self.is_apc else self.get_etud_decision_sem
|
||||
)
|
||||
etudids = [
|
||||
ins.etudid
|
||||
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):
|
||||
"""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:
|
||||
e = re.compile(str(annee_scolaire) + "-.+")
|
||||
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:
|
||||
# e = re.compile(r"[0-9]{4}-" + str(sem_id))
|
||||
# oids = [x for x in oids if e.match(x)]
|
||||
if sem_id:
|
||||
e = re.compile(r"[0-9]{4}-" + str(sem_id))
|
||||
oids = [x for x in oids if e.match(x)]
|
||||
|
||||
infos = [] # liste d'infos
|
||||
for oid in oids:
|
||||
|
@ -240,7 +240,11 @@ def apo_semset_maq_status(
|
||||
if semset["jury_ok"]:
|
||||
H.append("""<li>Décisions de jury saisies</li>""")
|
||||
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:
|
||||
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):
|
||||
"Ajoute ce semestre à l'ensemble"
|
||||
# check for valid formsemestre_id
|
||||
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||
# check
|
||||
if formsemestre_id in self.formsemestre_ids:
|
||||
return # already there
|
||||
@ -166,6 +168,19 @@ class SemSet(dict):
|
||||
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(
|
||||
"""INSERT INTO notes_semset_formsemestre
|
||||
(formsemestre_id, semset_id)
|
||||
@ -249,17 +264,28 @@ class SemSet(dict):
|
||||
def load_etuds(self):
|
||||
self["etuds_without_nip"] = set() # etudids
|
||||
self["jury_ok"] = True
|
||||
self["jury_nb_missing"] = 0
|
||||
is_apc = None
|
||||
for sem in self.sems:
|
||||
formsemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"])
|
||||
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["nips"] = {e["code_nip"] for e in sem["etuds"] if e["code_nip"]}
|
||||
sem["etuds_without_nip"] = {
|
||||
e["etudid"] for e in sem["etuds"] if not e["code_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_nb_missing"] += len(sem["etudids_no_jury"])
|
||||
self["is_apc"] = bool(is_apc)
|
||||
|
||||
def html_descr(self):
|
||||
"""Short HTML description"""
|
||||
@ -279,36 +305,21 @@ class SemSet(dict):
|
||||
)
|
||||
H.append("</p>")
|
||||
|
||||
H.append(
|
||||
f"""<p>Période: <select name="periode" onchange="set_periode(this);">
|
||||
<option value="1" {"selected" if self["sem_id"] == 1 else ""}>1re période (S1, S3)</option>
|
||||
<option value="2" {"selected" if self["sem_id"] == 2 else ""}>2de période (S2, S4)</option>
|
||||
<option value="0" {"selected" if self["sem_id"] == 0 else ""}>non semestrialisée (LP, ...)</option>
|
||||
</select>
|
||||
</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>
|
||||
"""
|
||||
)
|
||||
if self["sem_id"] == 1:
|
||||
periode = "1re période (S1, S3)"
|
||||
elif self["sem_id"] == 1:
|
||||
periode = "2de période (S2, S4)"
|
||||
else:
|
||||
periode = "non semestrialisée (LP, ...). Incompatible avec BUT."
|
||||
|
||||
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:
|
||||
H.append(
|
||||
@ -429,12 +440,8 @@ def do_semset_add_sem(semset_id, formsemestre_id):
|
||||
raise ScoValueError("empty semset_id")
|
||||
if formsemestre_id == "":
|
||||
raise ScoValueError("pas de semestre choisi !")
|
||||
s = SemSet(semset_id=semset_id)
|
||||
# check for valid formsemestre_id
|
||||
_ = sco_formsemestre.get_formsemestre(formsemestre_id) # raise exc
|
||||
|
||||
s.add(formsemestre_id)
|
||||
|
||||
semset = SemSet(semset_id=semset_id)
|
||||
semset.add(formsemestre.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">
|
||||
<option value="1">1re période (S1, S3)</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>
|
||||
<input type="text" name="title" size="32"/>
|
||||
<input type="submit" value="Créer"/>
|
||||
|
Loading…
Reference in New Issue
Block a user