forked from ScoDoc/ScoDoc
Compare commits
6 Commits
f2574c2d49
...
2f05e081ee
Author | SHA1 | Date | |
---|---|---|---|
2f05e081ee | |||
fb5cdc2624 | |||
9bdeda7559 | |||
cb0b890f1f | |||
cde5960899 | |||
0573081711 |
@ -269,13 +269,7 @@ def validation_rcue_record(etudid: int):
|
|||||||
validation.parcours_id = parcours_id
|
validation.parcours_id = parcours_id
|
||||||
validation.ue1_id = ue1_id
|
validation.ue1_id = ue1_id
|
||||||
validation.ue2_id = ue2_id
|
validation.ue2_id = ue2_id
|
||||||
log(f"updating {validation}")
|
operation = "update"
|
||||||
Scolog.logdb(
|
|
||||||
method="validation_rcue_record",
|
|
||||||
etudid=etudid,
|
|
||||||
msg=f"Mise à jour {validation}",
|
|
||||||
commit=False,
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
validation = ApcValidationRCUE(
|
validation = ApcValidationRCUE(
|
||||||
code=code,
|
code=code,
|
||||||
@ -286,15 +280,16 @@ def validation_rcue_record(etudid: int):
|
|||||||
ue1_id=ue1_id,
|
ue1_id=ue1_id,
|
||||||
ue2_id=ue2_id,
|
ue2_id=ue2_id,
|
||||||
)
|
)
|
||||||
log(f"recording {validation}")
|
operation = "record"
|
||||||
Scolog.logdb(
|
|
||||||
method="validation_rcue_record",
|
|
||||||
etudid=etudid,
|
|
||||||
msg=f"Enregistrement {validation}",
|
|
||||||
commit=False,
|
|
||||||
)
|
|
||||||
db.session.add(validation)
|
db.session.add(validation)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
Scolog.logdb(
|
||||||
|
method="validation_rcue_record",
|
||||||
|
etudid=etudid,
|
||||||
|
msg=f"Enregistrement {validation}",
|
||||||
|
commit=True,
|
||||||
|
)
|
||||||
|
log(f"{operation} {validation}")
|
||||||
return validation.to_dict()
|
return validation.to_dict()
|
||||||
|
|
||||||
|
|
||||||
|
@ -212,6 +212,34 @@ class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
|
|||||||
else:
|
else:
|
||||||
self.ue_std_rows(rows, ue, title_bg)
|
self.ue_std_rows(rows, ue, title_bg)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def affichage_bonus_malus(ue: dict) -> list:
|
||||||
|
fields_bmr = []
|
||||||
|
# lecture des bonus sport culture et malus (ou bonus autre) (0 si valeur non numérique)
|
||||||
|
try:
|
||||||
|
bonus_sc = float(ue.get("bonus", 0.0)) or 0
|
||||||
|
except ValueError:
|
||||||
|
bonus_sc = 0
|
||||||
|
try:
|
||||||
|
malus = float(ue.get("malus", 0.0)) or 0
|
||||||
|
except ValueError:
|
||||||
|
malus = 0
|
||||||
|
# Calcul de l affichage
|
||||||
|
if malus < 0:
|
||||||
|
if bonus_sc > 0:
|
||||||
|
fields_bmr.append(f"Bonus sport/culture: {bonus_sc}")
|
||||||
|
fields_bmr.append(f"Bonus autres: {-malus}")
|
||||||
|
else:
|
||||||
|
fields_bmr.append(f"Bonus: {-malus}")
|
||||||
|
elif malus > 0:
|
||||||
|
if bonus_sc > 0:
|
||||||
|
fields_bmr.append(f"Bonus: {bonus_sc}")
|
||||||
|
fields_bmr.append(f"Malus: {malus}")
|
||||||
|
else:
|
||||||
|
if bonus_sc > 0:
|
||||||
|
fields_bmr.append(f"Bonus: {bonus_sc}")
|
||||||
|
return fields_bmr
|
||||||
|
|
||||||
def ue_std_rows(self, rows: list, ue: dict, title_bg: tuple):
|
def ue_std_rows(self, rows: list, ue: dict, title_bg: tuple):
|
||||||
"Lignes décrivant une UE standard dans la table de synthèse"
|
"Lignes décrivant une UE standard dans la table de synthèse"
|
||||||
# 2eme ligne titre UE (bonus/malus/ects)
|
# 2eme ligne titre UE (bonus/malus/ects)
|
||||||
@ -220,20 +248,7 @@ class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
|
|||||||
else:
|
else:
|
||||||
ects_txt = ""
|
ects_txt = ""
|
||||||
# case Bonus/Malus/Rang "bmr"
|
# case Bonus/Malus/Rang "bmr"
|
||||||
fields_bmr = []
|
fields_bmr = BulletinGeneratorStandardBUT.affichage_bonus_malus(ue)
|
||||||
try:
|
|
||||||
value = float(ue.get("bonus", 0.0))
|
|
||||||
if value != 0:
|
|
||||||
fields_bmr.append(f"Bonus: {ue['bonus']}")
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
value = float(ue.get("malus", 0.0))
|
|
||||||
if value != 0:
|
|
||||||
fields_bmr.append(f"Malus: {ue['malus']}")
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
moy_ue = ue.get("moyenne", "-")
|
moy_ue = ue.get("moyenne", "-")
|
||||||
if isinstance(moy_ue, dict): # UE non capitalisées
|
if isinstance(moy_ue, dict): # UE non capitalisées
|
||||||
if self.preferences["bul_show_ue_rangs"]:
|
if self.preferences["bul_show_ue_rangs"]:
|
||||||
|
@ -82,6 +82,10 @@ class ApcValidationRCUE(db.Model):
|
|||||||
"as a dict"
|
"as a dict"
|
||||||
d = dict(self.__dict__)
|
d = dict(self.__dict__)
|
||||||
d.pop("_sa_instance_state", None)
|
d.pop("_sa_instance_state", None)
|
||||||
|
d["etud"] = self.etud.to_dict_short()
|
||||||
|
d["ue1"] = self.ue1.to_dict()
|
||||||
|
d["ue2"] = self.ue2.to_dict()
|
||||||
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def to_dict_bul(self) -> dict:
|
def to_dict_bul(self) -> dict:
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
|
|
||||||
import collections
|
import collections
|
||||||
import datetime
|
import datetime
|
||||||
import operator
|
|
||||||
import urllib
|
import urllib
|
||||||
from urllib.parse import parse_qs
|
from urllib.parse import parse_qs
|
||||||
import time
|
import time
|
||||||
@ -42,6 +41,8 @@ import time
|
|||||||
from flask import url_for, g, request
|
from flask import url_for, g, request
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
|
|
||||||
|
from app import db
|
||||||
|
from app.models import FormSemestre
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app.scodoc import html_sco_header
|
from app.scodoc import html_sco_header
|
||||||
from app.scodoc import sco_abs
|
from app.scodoc import sco_abs
|
||||||
@ -65,6 +66,7 @@ JAVASCRIPTS = html_sco_header.BOOTSTRAP_MULTISELECT_JS + [
|
|||||||
|
|
||||||
CSSSTYLES = html_sco_header.BOOTSTRAP_MULTISELECT_CSS
|
CSSSTYLES = html_sco_header.BOOTSTRAP_MULTISELECT_CSS
|
||||||
|
|
||||||
|
|
||||||
# view:
|
# view:
|
||||||
def groups_view(
|
def groups_view(
|
||||||
group_ids=(),
|
group_ids=(),
|
||||||
@ -422,6 +424,13 @@ class DisplayedGroupsInfos(object):
|
|||||||
H.append(f'<input type="hidden" name="group_ids" value="{group_id}"/>')
|
H.append(f'<input type="hidden" name="group_ids" value="{group_id}"/>')
|
||||||
return "\n".join(H)
|
return "\n".join(H)
|
||||||
|
|
||||||
|
def get_formsemestre(self) -> FormSemestre:
|
||||||
|
return (
|
||||||
|
db.session.get(FormSemestre, self.formsemestre_id)
|
||||||
|
if self.formsemestre_id
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Ancien ZScolar.group_list renommé ici en group_table
|
# Ancien ZScolar.group_list renommé ici en group_table
|
||||||
def groups_table(
|
def groups_table(
|
||||||
|
@ -517,7 +517,7 @@ def ficheEtud(etudid=None):
|
|||||||
cursus=but_cursus,
|
cursus=but_cursus,
|
||||||
scu=scu,
|
scu=scu,
|
||||||
)}
|
)}
|
||||||
<div>
|
<div class="link_validation_rcues">
|
||||||
<a href="{url_for("notes.validation_rcues",
|
<a href="{url_for("notes.validation_rcues",
|
||||||
scodoc_dept=g.scodoc_dept, etudid=etudid,
|
scodoc_dept=g.scodoc_dept, etudid=etudid,
|
||||||
formsemestre_id=last_formsemestre.id)}"
|
formsemestre_id=last_formsemestre.id)}"
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from flask import g, url_for
|
from flask import g, url_for
|
||||||
from app.models import Identite, Assiduite, Justificatif
|
from app.models import Identite, Justificatif
|
||||||
from app.tables import table_builder as tb
|
from app.tables import table_builder as tb
|
||||||
import app.scodoc.sco_assiduites as scass
|
import app.scodoc.sco_assiduites as scass
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
@ -65,31 +65,35 @@ class RowAssi(tb.Row):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
bilan_etud = f"{url_for('assiduites.bilan_etud', scodoc_dept=g.scodoc_dept)}?etudid={etud.id}"
|
bilan_etud = url_for(
|
||||||
|
"assiduites.bilan_etud", scodoc_dept=g.scodoc_dept, etudid=etud.id
|
||||||
|
)
|
||||||
self.add_cell(
|
self.add_cell(
|
||||||
"nom_disp",
|
"nom_disp",
|
||||||
"Nom",
|
"Nom",
|
||||||
etud.nom_disp(),
|
etud.nom_disp(),
|
||||||
"identite_detail",
|
"etudinfo",
|
||||||
|
attrs={"id": str(etud.id)},
|
||||||
data={"order": etud.sort_key},
|
data={"order": etud.sort_key},
|
||||||
target=bilan_etud,
|
target=bilan_etud,
|
||||||
target_attrs={"class": "discretelink", "id": str(etud.id)},
|
target_attrs={"class": "discretelink"},
|
||||||
)
|
)
|
||||||
self.add_cell(
|
self.add_cell(
|
||||||
"prenom",
|
"prenom",
|
||||||
"Prénom",
|
"Prénom",
|
||||||
etud.prenom,
|
etud.prenom_str,
|
||||||
"identite_detail",
|
"etudinfo",
|
||||||
|
attrs={"id": str(etud.id)},
|
||||||
data={"order": etud.sort_key},
|
data={"order": etud.sort_key},
|
||||||
target=bilan_etud,
|
target=bilan_etud,
|
||||||
target_attrs={"class": "discretelink", "id": str(etud.id)},
|
target_attrs={"class": "discretelink"},
|
||||||
)
|
)
|
||||||
stats = self._get_etud_stats(etud)
|
stats = self._get_etud_stats(etud)
|
||||||
for key, value in stats.items():
|
for key, value in stats.items():
|
||||||
self.add_cell(key, value[0], f"{value[1] - value[2]}", "assi_stats")
|
self.add_cell(key, value[0], f"{value[1] - value[2]}", "assi_stats")
|
||||||
self.add_cell(
|
self.add_cell(
|
||||||
key + "_justi",
|
key + "_justi",
|
||||||
value[0] + " Justifiée(s)",
|
value[0] + " Justifiées",
|
||||||
f"{value[2]}",
|
f"{value[2]}",
|
||||||
"assi_stats",
|
"assi_stats",
|
||||||
)
|
)
|
||||||
@ -102,9 +106,9 @@ class RowAssi(tb.Row):
|
|||||||
|
|
||||||
def _get_etud_stats(self, etud: Identite) -> dict[str, list[str, float, float]]:
|
def _get_etud_stats(self, etud: Identite) -> dict[str, list[str, float, float]]:
|
||||||
retour: dict[str, tuple[str, float, float]] = {
|
retour: dict[str, tuple[str, float, float]] = {
|
||||||
"present": ["Présence(s)", 0.0, 0.0],
|
"present": ["Présences", 0.0, 0.0],
|
||||||
"retard": ["Retard(s)", 0.0, 0.0],
|
"retard": ["Retards", 0.0, 0.0],
|
||||||
"absent": ["Absence(s)", 0.0, 0.0],
|
"absent": ["Absences", 0.0, 0.0],
|
||||||
}
|
}
|
||||||
|
|
||||||
assi_metric = {
|
assi_metric = {
|
||||||
|
@ -1,11 +1,22 @@
|
|||||||
|
{% extends "sco_page.j2" %}
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
{{ super() }}
|
||||||
|
<script src="{{scu.STATIC_DIR}}/js/etud_info.js"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
|
||||||
<h2>Visualisation de l'assiduité {{gr_tit|safe}}</h2>
|
<h2>Visualisation de l'assiduité {{gr_tit|safe}}</h2>
|
||||||
|
|
||||||
<div class="stats-inputs">
|
<div class="stats-inputs">
|
||||||
<label class="stats-label"> Date de début<input type="date" name="stats_date_debut" id="stats_date_debut"
|
<label class="stats-label"> Date de début <input type="date" name="stats_date_debut" id="stats_date_debut"
|
||||||
value="{{date_debut}}"></label>
|
value="{{date_debut}}"></label>
|
||||||
<label class="stats-label"> Date de fin<input type="date" name="stats_date_fin" id="stats_date_fin"
|
<label class="stats-label"> Date de fin <input type="date" name="stats_date_fin" id="stats_date_fin"
|
||||||
value="{{date_fin}}"></label>
|
value="{{date_fin}}"></label>
|
||||||
<button onclick="stats()">Changer la période</button>
|
<button onclick="stats()">Changer</button>
|
||||||
|
|
||||||
|
<a style="margin-left:32px;" href="{{request.url}}&format=xlsx">{{scu.ICON_XLS|safe}}</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{tableau | safe}}
|
{{tableau | safe}}
|
||||||
@ -26,4 +37,6 @@
|
|||||||
document.querySelector('#stats_date_fin').value = date_fin;
|
document.querySelector('#stats_date_fin').value = date_fin;
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
@ -100,6 +100,7 @@
|
|||||||
data-ue2_id="{{niv['ue_pair'].id}}"
|
data-ue2_id="{{niv['ue_pair'].id}}"
|
||||||
data-code="{{validation.code if validation else ''}}"
|
data-code="{{validation.code if validation else ''}}"
|
||||||
>
|
>
|
||||||
|
<option value="" disabled {{"selected" if not validation else ""}}>-</option>
|
||||||
{% for code in rcue_codes %}
|
{% for code in rcue_codes %}
|
||||||
<option value="{{code}}"
|
<option value="{{code}}"
|
||||||
{% if validation and validation.code == code -%}
|
{% if validation and validation.code == code -%}
|
||||||
|
@ -649,6 +649,7 @@ def visu_assi_group():
|
|||||||
"debut": request.args.get("date_debut"),
|
"debut": request.args.get("date_debut"),
|
||||||
"fin": request.args.get("date_fin"),
|
"fin": request.args.get("date_fin"),
|
||||||
}
|
}
|
||||||
|
fmt = request.args.get("format", "html")
|
||||||
|
|
||||||
group_ids: list[int] = request.args.get("group_ids", None)
|
group_ids: list[int] = request.args.get("group_ids", None)
|
||||||
etudiants: list[dict] = []
|
etudiants: list[dict] = []
|
||||||
@ -662,14 +663,16 @@ def visu_assi_group():
|
|||||||
groups_infos = sco_groups_view.DisplayedGroupsInfos(group_ids)
|
groups_infos = sco_groups_view.DisplayedGroupsInfos(group_ids)
|
||||||
|
|
||||||
etuds = etuds_sorted_from_ids([m["etudid"] for m in groups_infos.members])
|
etuds = etuds_sorted_from_ids([m["etudid"] for m in groups_infos.members])
|
||||||
|
|
||||||
header: str = html_sco_header.sco_header(
|
|
||||||
page_title="Visualisation des assiduités",
|
|
||||||
init_qtip=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
table: TableAssi = TableAssi(etuds=etuds, dates=list(dates.values()))
|
table: TableAssi = TableAssi(etuds=etuds, dates=list(dates.values()))
|
||||||
|
|
||||||
|
if fmt.startswith("xls"):
|
||||||
|
return scu.send_file(
|
||||||
|
table.excel(),
|
||||||
|
filename=f"assiduite-{groups_infos.groups_filename}",
|
||||||
|
mime=scu.XLSX_MIMETYPE,
|
||||||
|
suffix=scu.XLSX_SUFFIX,
|
||||||
|
)
|
||||||
|
|
||||||
if groups_infos.tous_les_etuds_du_sem:
|
if groups_infos.tous_les_etuds_du_sem:
|
||||||
gr_tit = "en"
|
gr_tit = "en"
|
||||||
else:
|
else:
|
||||||
@ -681,18 +684,16 @@ def visu_assi_group():
|
|||||||
grp + ' <span class="fontred">' + groups_infos.groups_titles + "</span>"
|
grp + ' <span class="fontred">' + groups_infos.groups_titles + "</span>"
|
||||||
)
|
)
|
||||||
|
|
||||||
return HTMLBuilder(
|
return render_template(
|
||||||
header,
|
"assiduites/pages/visu_assi.j2",
|
||||||
render_template(
|
tableau=table.html(),
|
||||||
"assiduites/pages/visu_assi.j2",
|
gr_tit=gr_tit,
|
||||||
tableau=table.html(),
|
date_debut=dates["debut"],
|
||||||
gr_tit=gr_tit,
|
date_fin=dates["fin"],
|
||||||
date_debut=dates["debut"],
|
group_ids=request.args.get("group_ids", None),
|
||||||
date_fin=dates["fin"],
|
sco=ScoData(formsemestre=groups_infos.get_formsemestre()),
|
||||||
group_ids=request.args.get("group_ids", None),
|
title=f"Assiduité {grp} {groups_infos.groups_titles}",
|
||||||
),
|
)
|
||||||
html_sco_header.sco_footer(),
|
|
||||||
).build()
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/SignalAssiduiteDifferee")
|
@bp.route("/SignalAssiduiteDifferee")
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- mode: python -*-
|
# -*- mode: python -*-
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
SCOVERSION = "9.6.0"
|
SCOVERSION = "9.6.3"
|
||||||
|
|
||||||
SCONAME = "ScoDoc"
|
SCONAME = "ScoDoc"
|
||||||
|
|
||||||
|
82
tests/unit/test_bulletin_bonus.py
Normal file
82
tests/unit/test_bulletin_bonus.py
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
"""Tests unitaires : bulletins de notes
|
||||||
|
|
||||||
|
Utiliser comme:
|
||||||
|
pytest tests/unit/test_bulletin_bonus.py
|
||||||
|
|
||||||
|
"""
|
||||||
|
from app.but.bulletin_but_pdf import BulletinGeneratorStandardBUT
|
||||||
|
|
||||||
|
|
||||||
|
def test_nobonus():
|
||||||
|
assert BulletinGeneratorStandardBUT.affichage_bonus_malus({}) == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_bonus_sport_nul():
|
||||||
|
assert BulletinGeneratorStandardBUT.affichage_bonus_malus({"bonus": 0}) == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_malus_nul():
|
||||||
|
assert BulletinGeneratorStandardBUT.affichage_bonus_malus({"malus": 0}) == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_bonus_et_malus_nuls():
|
||||||
|
assert (
|
||||||
|
BulletinGeneratorStandardBUT.affichage_bonus_malus({"bonus": 0, "malus": 0})
|
||||||
|
== []
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_vrai_malus():
|
||||||
|
assert BulletinGeneratorStandardBUT.affichage_bonus_malus({"malus": 0.1}) == [
|
||||||
|
"Malus: 0.1"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_bonus_sport_et_vrai_malus():
|
||||||
|
assert BulletinGeneratorStandardBUT.affichage_bonus_malus(
|
||||||
|
{"malus": 0.12, "bonus": 0.23}
|
||||||
|
) == [
|
||||||
|
"Bonus: 0.23",
|
||||||
|
"Malus: 0.12",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_bonus_sport_seul():
|
||||||
|
assert BulletinGeneratorStandardBUT.affichage_bonus_malus({"bonus": 0.5}) == [
|
||||||
|
"Bonus: 0.5"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_bonus_sport_nul_et_vrai_malus():
|
||||||
|
assert BulletinGeneratorStandardBUT.affichage_bonus_malus(
|
||||||
|
{"bonus": 0, "malus": 0.5}
|
||||||
|
) == ["Malus: 0.5"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_bonus_sport_et_malus_nul():
|
||||||
|
assert BulletinGeneratorStandardBUT.affichage_bonus_malus(
|
||||||
|
{"bonus": 0.5, "malus": 0}
|
||||||
|
) == [
|
||||||
|
"Bonus: 0.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_faux_malus():
|
||||||
|
assert BulletinGeneratorStandardBUT.affichage_bonus_malus({"malus": -0.6}) == [
|
||||||
|
"Bonus: 0.6"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_sport_nul_faux_malus():
|
||||||
|
assert BulletinGeneratorStandardBUT.affichage_bonus_malus(
|
||||||
|
{"bonus": 0, "malus": -0.6}
|
||||||
|
) == ["Bonus: 0.6"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_bonus_sport_et_faux_malus():
|
||||||
|
assert BulletinGeneratorStandardBUT.affichage_bonus_malus(
|
||||||
|
{"bonus": 0.3, "malus": -0.6}
|
||||||
|
) == [
|
||||||
|
"Bonus sport/culture: 0.3",
|
||||||
|
"Bonus autres: 0.6",
|
||||||
|
]
|
@ -75,9 +75,9 @@ fi
|
|||||||
#echo "Creating python3 virtualenv..."
|
#echo "Creating python3 virtualenv..."
|
||||||
su -c "(cd $SCODOC_DIR && python3 -m venv venv)" "$SCODOC_USER" || die "Error creating Python 3 virtualenv"
|
su -c "(cd $SCODOC_DIR && python3 -m venv venv)" "$SCODOC_USER" || die "Error creating Python 3 virtualenv"
|
||||||
|
|
||||||
# ------------ INSTALL DES PAQUETS PYTHON (3.9)
|
# ------------ INSTALL DES PAQUETS PYTHON (3.11)
|
||||||
# pip in our env, as user "scodoc"
|
# pip in our env, as user "scodoc"
|
||||||
su -c "(cd $SCODOC_DIR && source venv/bin/activate && pip install wheel && pip install -r requirements-3.9.txt)" "$SCODOC_USER" || die "Error installing python packages"
|
su -c "(cd $SCODOC_DIR && source venv/bin/activate && pip install wheel && pip install -r requirements-3.11.txt)" "$SCODOC_USER" || die "Error installing python packages"
|
||||||
|
|
||||||
# --- NGINX
|
# --- NGINX
|
||||||
# Evite d'écraser: il faudrait ici présenter un dialogue "fichier local modifié, ..."
|
# Evite d'écraser: il faudrait ici présenter un dialogue "fichier local modifié, ..."
|
||||||
|
@ -7,6 +7,8 @@ from datetime import date, datetime, time, timedelta
|
|||||||
from json import dump, dumps
|
from json import dump, dumps
|
||||||
from sqlalchemy import not_
|
from sqlalchemy import not_
|
||||||
|
|
||||||
|
from flask import g
|
||||||
|
|
||||||
from app import db
|
from app import db
|
||||||
from app.models import (
|
from app.models import (
|
||||||
Absence,
|
Absence,
|
||||||
@ -30,6 +32,7 @@ from app.scodoc.sco_utils import (
|
|||||||
localize_datetime,
|
localize_datetime,
|
||||||
print_progress_bar,
|
print_progress_bar,
|
||||||
)
|
)
|
||||||
|
from app.scodoc import notesdb as ndb
|
||||||
|
|
||||||
|
|
||||||
class _glob:
|
class _glob:
|
||||||
@ -38,7 +41,6 @@ class _glob:
|
|||||||
DEBUG: bool = False
|
DEBUG: bool = False
|
||||||
PROBLEMS: dict[int, list[str]] = {}
|
PROBLEMS: dict[int, list[str]] = {}
|
||||||
DEPT_ETUDIDS: dict[int, Identite] = {}
|
DEPT_ETUDIDS: dict[int, Identite] = {}
|
||||||
MODULES: dict[tuple[int, int]] = {}
|
|
||||||
COMPTE: list[int, int] = []
|
COMPTE: list[int, int] = []
|
||||||
ERR_ETU: list[int] = []
|
ERR_ETU: list[int] = []
|
||||||
MERGER_ASSI: "_Merger" = None
|
MERGER_ASSI: "_Merger" = None
|
||||||
@ -97,42 +99,70 @@ class _Merger:
|
|||||||
date_deb = _Merger._tuple_to_date(self.deb)
|
date_deb = _Merger._tuple_to_date(self.deb)
|
||||||
date_fin = _Merger._tuple_to_date(self.fin, end=True)
|
date_fin = _Merger._tuple_to_date(self.fin, end=True)
|
||||||
|
|
||||||
retour = Justificatif.fast_create_justificatif(
|
_glob.cursor.execute(
|
||||||
etudid=self.etudid,
|
"""INSERT INTO justificatifs
|
||||||
date_debut=date_deb,
|
(etudid,date_debut,date_fin,etat,raison,entry_date)
|
||||||
date_fin=date_fin,
|
VALUES (%(etudid)s,%(date_debut)s,%(date_fin)s,%(etat)s,%(raison)s,%(entry_date)s)
|
||||||
etat=EtatJustificatif.VALIDE,
|
""",
|
||||||
raison=self.raison,
|
{
|
||||||
entry_date=self.entry_date,
|
"etudid": self.etudid,
|
||||||
|
"date_debut": date_deb,
|
||||||
|
"date_fin": date_fin,
|
||||||
|
"etat": EtatJustificatif.VALIDE,
|
||||||
|
"raison": self.raison,
|
||||||
|
"entry_date": self.entry_date,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
return retour
|
# retour = Justificatif.fast_create_justificatif(
|
||||||
|
# etudid=self.etudid,
|
||||||
|
# date_debut=date_deb,
|
||||||
|
# date_fin=date_fin,
|
||||||
|
# etat=EtatJustificatif.VALIDE,
|
||||||
|
# raison=self.raison,
|
||||||
|
# entry_date=self.entry_date,
|
||||||
|
# )
|
||||||
|
# return retour
|
||||||
|
|
||||||
def _to_assi(self):
|
def _to_assi(self):
|
||||||
date_deb = _Merger._tuple_to_date(self.deb)
|
date_deb = _Merger._tuple_to_date(self.deb)
|
||||||
date_fin = _Merger._tuple_to_date(self.fin, end=True)
|
date_fin = _Merger._tuple_to_date(self.fin, end=True)
|
||||||
|
|
||||||
retour = Assiduite.fast_create_assiduite(
|
_glob.cursor.execute(
|
||||||
etudid=self.etudid,
|
"""INSERT INTO assiduites
|
||||||
date_debut=date_deb,
|
(etudid,date_debut,date_fin,etat,moduleimpl_id,"desc",entry_date)
|
||||||
date_fin=date_fin,
|
VALUES (%(etudid)s,%(date_debut)s,%(date_fin)s,%(etat)s,%(moduleimpl_id)s,%(desc)s,%(entry_date)s)
|
||||||
etat=EtatAssiduite.ABSENT,
|
""",
|
||||||
moduleimpl_id=self.moduleimpl,
|
{
|
||||||
description=self.raison,
|
"etudid": self.etudid,
|
||||||
entry_date=self.entry_date,
|
"date_debut": date_deb,
|
||||||
|
"date_fin": date_fin,
|
||||||
|
"etat": EtatAssiduite.ABSENT,
|
||||||
|
"moduleimpl_id": self.moduleimpl,
|
||||||
|
"desc": self.raison,
|
||||||
|
"entry_date": self.entry_date,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
return retour
|
|
||||||
|
# retour = Assiduite.fast_create_assiduite(
|
||||||
|
# etudid=self.etudid,
|
||||||
|
# date_debut=date_deb,
|
||||||
|
# date_fin=date_fin,
|
||||||
|
# etat=EtatAssiduite.ABSENT,
|
||||||
|
# moduleimpl_id=self.moduleimpl,
|
||||||
|
# description=self.raison,
|
||||||
|
# entry_date=self.entry_date,
|
||||||
|
# )
|
||||||
|
# return retour
|
||||||
|
|
||||||
def export(self):
|
def export(self):
|
||||||
"""Génère un nouvel objet Assiduité ou Justificatif"""
|
"""Génère un nouvel objet Assiduité ou Justificatif"""
|
||||||
obj: Assiduite or Justificatif = None
|
obj: Assiduite or Justificatif = None
|
||||||
if self.est_abs:
|
if self.est_abs:
|
||||||
_glob.COMPTE[0] += 1
|
_glob.COMPTE[0] += 1
|
||||||
obj = self._to_assi()
|
self._to_assi()
|
||||||
else:
|
else:
|
||||||
_glob.COMPTE[1] += 1
|
_glob.COMPTE[1] += 1
|
||||||
obj = self._to_justif()
|
self._to_justif()
|
||||||
|
|
||||||
db.session.add(obj)
|
|
||||||
|
|
||||||
|
|
||||||
class _Statistics:
|
class _Statistics:
|
||||||
@ -243,6 +273,10 @@ def migrate_abs_to_assiduites(
|
|||||||
evening: list[str] = str(evening).split(":")
|
evening: list[str] = str(evening).split(":")
|
||||||
_glob.EVENING = time(int(evening[0]), int(evening[1]))
|
_glob.EVENING = time(int(evening[0]), int(evening[1]))
|
||||||
|
|
||||||
|
ndb.open_db_connection()
|
||||||
|
_glob.cnx = g.db_conn
|
||||||
|
_glob.cursor = _glob.cnx.cursor()
|
||||||
|
|
||||||
if dept is None:
|
if dept is None:
|
||||||
prof_total = Profiler("MigrationTotal")
|
prof_total = Profiler("MigrationTotal")
|
||||||
prof_total.start()
|
prof_total.start()
|
||||||
@ -287,7 +321,6 @@ def migrate_dept(dept_name: str, stats: _Statistics, time_elapsed: Profiler):
|
|||||||
return
|
return
|
||||||
|
|
||||||
_glob.DEPT_ETUDIDS = {e.id for e in Identite.query.filter_by(dept_id=dept.id)}
|
_glob.DEPT_ETUDIDS = {e.id for e in Identite.query.filter_by(dept_id=dept.id)}
|
||||||
_glob.MODULES = {}
|
|
||||||
_glob.COMPTE = [0, 0]
|
_glob.COMPTE = [0, 0]
|
||||||
_glob.ERR_ETU = []
|
_glob.ERR_ETU = []
|
||||||
_glob.MERGER_ASSI = None
|
_glob.MERGER_ASSI = None
|
||||||
@ -299,9 +332,17 @@ def migrate_dept(dept_name: str, stats: _Statistics, time_elapsed: Profiler):
|
|||||||
|
|
||||||
print_progress_bar(0, absences_len, "Progression", "effectué", autosize=True)
|
print_progress_bar(0, absences_len, "Progression", "effectué", autosize=True)
|
||||||
|
|
||||||
|
etuds_modimpl_ids = {}
|
||||||
for i, abs_ in enumerate(absences):
|
for i, abs_ in enumerate(absences):
|
||||||
|
etud_modimpl_ids = etuds_modimpl_ids.get(abs_.etudid)
|
||||||
|
if etud_modimpl_ids is None:
|
||||||
|
etud_modimpl_ids = {
|
||||||
|
ins.moduleimpl_id
|
||||||
|
for ins in ModuleImplInscription.query.filter_by(etudid=abs_.etudid)
|
||||||
|
}
|
||||||
|
etuds_modimpl_ids[abs_.etudid] = etud_modimpl_ids
|
||||||
try:
|
try:
|
||||||
_from_abs_to_assiduite_justificatif(abs_)
|
_from_abs_to_assiduite_justificatif(abs_, etud_modimpl_ids)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
stats.add_problem(abs_, e.args[0])
|
stats.add_problem(abs_, e.args[0])
|
||||||
|
|
||||||
@ -322,14 +363,14 @@ def migrate_dept(dept_name: str, stats: _Statistics, time_elapsed: Profiler):
|
|||||||
"effectué",
|
"effectué",
|
||||||
autosize=True,
|
autosize=True,
|
||||||
)
|
)
|
||||||
db.session.commit()
|
_glob.cnx.commit()
|
||||||
|
|
||||||
if _glob.MERGER_ASSI is not None:
|
if _glob.MERGER_ASSI is not None:
|
||||||
_glob.MERGER_ASSI.export()
|
_glob.MERGER_ASSI.export()
|
||||||
if _glob.MERGER_JUST is not None:
|
if _glob.MERGER_JUST is not None:
|
||||||
_glob.MERGER_JUST.export()
|
_glob.MERGER_JUST.export()
|
||||||
|
|
||||||
db.session.commit()
|
_glob.cnx.commit()
|
||||||
|
|
||||||
print_progress_bar(
|
print_progress_bar(
|
||||||
absences_len,
|
absences_len,
|
||||||
@ -379,24 +420,15 @@ def migrate_dept(dept_name: str, stats: _Statistics, time_elapsed: Profiler):
|
|||||||
print(dumps(statistiques, indent=2))
|
print(dumps(statistiques, indent=2))
|
||||||
|
|
||||||
|
|
||||||
def _from_abs_to_assiduite_justificatif(_abs: Absence):
|
def _from_abs_to_assiduite_justificatif(_abs: Absence, etud_modimpl_ids: set[int]):
|
||||||
if _abs.etudid not in _glob.DEPT_ETUDIDS:
|
if _abs.etudid not in _glob.DEPT_ETUDIDS:
|
||||||
raise ValueError("Etudiant inexistant")
|
raise ValueError("Etudiant inexistant")
|
||||||
|
|
||||||
if _abs.estabs:
|
if _abs.estabs:
|
||||||
moduleimpl_id: int = _abs.moduleimpl_id
|
if (_abs.moduleimpl_id is not None) and (
|
||||||
if (
|
_abs.moduleimpl_id not in etud_modimpl_ids
|
||||||
moduleimpl_id is not None
|
|
||||||
and (_abs.etudid, _abs.moduleimpl_id) not in _glob.MODULES
|
|
||||||
):
|
):
|
||||||
moduleimpl_inscription: ModuleImplInscription = (
|
raise ValueError("Moduleimpl_id incorrect ou étudiant non inscrit")
|
||||||
ModuleImplInscription.query.filter_by(
|
|
||||||
moduleimpl_id=_abs.moduleimpl_id, etudid=_abs.etudid
|
|
||||||
).first()
|
|
||||||
)
|
|
||||||
if moduleimpl_inscription is None:
|
|
||||||
raise ValueError("Moduleimpl_id incorrect ou étudiant non inscrit")
|
|
||||||
_glob.MODULES[(_abs.etudid, _abs.moduleimpl_id)] = True
|
|
||||||
|
|
||||||
if _glob.MERGER_ASSI is None:
|
if _glob.MERGER_ASSI is None:
|
||||||
_glob.MERGER_ASSI = _Merger(_abs, True)
|
_glob.MERGER_ASSI = _Merger(_abs, True)
|
||||||
|
Loading…
Reference in New Issue
Block a user