This commit is contained in:
Emmanuel Viennet 2022-04-21 16:40:04 +02:00
commit eb5b8d69da
12 changed files with 173 additions and 55 deletions

View File

@ -302,22 +302,46 @@ class Identite(db.Model):
else:
date_ins = events[0].event_date
situation += date_ins.strftime(" le %d/%m/%Y")
elif inscr.etat == scu.DEF:
situation = f"défaillant en {inscr.formsemestre.titre_mois()}"
event = (
models.ScolarEvent.query.filter_by(
etudid=self.id,
formsemestre_id=inscr.formsemestre.id,
event_type="DEFAILLANCE",
)
.order_by(models.ScolarEvent.event_date)
.first()
)
if not event:
log(
f"*** situation inconsistante pour {self} (def mais pas d'event)"
)
situation += "???" # ???
else:
date_def = event.event_date
situation += date_def.strftime(" le %d/%m/%Y")
else:
situation = f"démission de {inscr.formsemestre.titre_mois()}"
# Cherche la date de demission dans scolar_events:
events = models.ScolarEvent.query.filter_by(
etudid=self.id,
formsemestre_id=inscr.formsemestre.id,
event_type="DEMISSION",
).all()
if not events:
event = (
models.ScolarEvent.query.filter_by(
etudid=self.id,
formsemestre_id=inscr.formsemestre.id,
event_type="DEMISSION",
)
.order_by(models.ScolarEvent.event_date)
.first()
)
if not event:
log(
f"*** situation inconsistante pour {self} (demission mais pas d'event)"
)
date_dem = "???" # ???
situation += "???" # ???
else:
date_dem = events[0].event_date
situation += date_dem.strftime(" le %d/%m/%Y")
date_dem = event.event_date
situation += date_dem.strftime(" le %d/%m/%Y")
else:
situation = "non inscrit" + self.e

View File

@ -237,6 +237,8 @@ def _sem_table_gt(sems, showcodes=False):
"titre_resp",
"nb_inscrits",
"etapes_apo_str",
"elt_annee_apo",
"elt_sem_apo",
)
if showcodes:
columns_ids = ("formsemestre_id",) + columns_ids
@ -253,6 +255,9 @@ def _sem_table_gt(sems, showcodes=False):
"dash_mois_fin": "Année",
"titre_resp": "Semestre",
"nb_inscrits": "N",
"etapes_apo_str": "Étape Apo.",
"elt_annee_apo": "Elt. année Apo.",
"elt_sem_apo": "Elt. sem. Apo.",
},
columns_ids=columns_ids,
rows=sems,
@ -260,7 +265,11 @@ def _sem_table_gt(sems, showcodes=False):
html_class_ignore_default=True,
html_class=html_class,
html_sortable=True,
html_table_attrs=f"""data-apo_save_url="{url_for('notes.formsemestre_set_apo_etapes', scodoc_dept=g.scodoc_dept)}" """,
html_table_attrs=f"""
data-apo_save_url="{url_for('notes.formsemestre_set_apo_etapes', scodoc_dept=g.scodoc_dept)}"
data-elt_annee_apo_save_url="{url_for('notes.formsemestre_set_elt_annee_apo', scodoc_dept=g.scodoc_dept)}"
data-elt_sem_apo_save_url="{url_for('notes.formsemestre_set_elt_sem_apo', scodoc_dept=g.scodoc_dept)}"
""",
html_with_td_classes=True,
preferences=sco_preferences.SemPreferences(),
)
@ -298,6 +307,12 @@ def _style_sems(sems):
sem[
"_etapes_apo_str_td_attrs"
] = f""" data-oid="{sem['formsemestre_id']}" data-value="{sem['etapes_apo_str']}" """
sem[
"_elt_annee_apo_td_attrs"
] = f""" data-oid="{sem['formsemestre_id']}" data-value="{sem['elt_annee_apo']}" """
sem[
"_elt_sem_apo_td_attrs"
] = f""" data-oid="{sem['formsemestre_id']}" data-value="{sem['elt_sem_apo']}" """
def delete_dept(dept_id: int):

View File

@ -30,6 +30,7 @@
import io
from zipfile import ZipFile, BadZipfile
from flask import Response
from flask import send_file, url_for
from flask import g, request
from flask_login import current_user
@ -44,7 +45,7 @@ import app.scodoc.sco_utils as scu
# ---- Table recap formation
def formation_table_recap(formation_id, format="html"):
def formation_table_recap(formation_id, format="html") -> Response:
"""Table recapitulant formation."""
T = []
formation = Formation.query.get_or_404(formation_id)
@ -70,7 +71,7 @@ def formation_table_recap(formation_id, format="html"):
"_apo_td_attrs": f""" data-oid="{ue.id}" data-value="{ue.code_apogee or ''}" """,
"coef": ue.coefficient or "",
"ects": ue.ects,
"_css_row_class": f"ue ue_",
"_css_row_class": "ue",
}
)
li += 1

View File

@ -95,9 +95,12 @@ _formsemestreEditor = ndb.EditableTable(
def get_formsemestre(formsemestre_id, raise_soft_exc=False):
"list ONE formsemestre"
if formsemestre_id is None:
raise ValueError(f"get_formsemestre: id manquant")
if formsemestre_id in g.stored_get_formsemestre:
return g.stored_get_formsemestre[formsemestre_id]
if not isinstance(formsemestre_id, int):
log(f"get_formsemestre: invalid id '{formsemestre_id}'")
raise ScoInvalidIdType("formsemestre_id must be an integer !")
sems = do_formsemestre_list(args={"formsemestre_id": formsemestre_id})
if not sems:

View File

@ -966,6 +966,7 @@ Il y a des notes en attente ! Le classement des étudiants n'a qu'une valeur ind
def formsemestre_status(formsemestre_id=None):
"""Tableau de bord semestre HTML"""
# porté du DTML
sem = sco_formsemestre.get_formsemestre(formsemestre_id, raise_soft_exc=True)
modimpls = sco_moduleimpl.moduleimpl_withmodule_list(
formsemestre_id=formsemestre_id
@ -987,7 +988,9 @@ def formsemestre_status(formsemestre_id=None):
use_ue_coefs = sco_preferences.get_preference("use_ue_coefs", formsemestre_id)
H = [
html_sco_header.sco_header(page_title="Semestre %s" % sem["titreannee"]),
html_sco_header.sco_header(
page_title=f"{formsemestre.sem_modalite()} {formsemestre.titre_annee()}"
),
'<div class="formsemestre_status">',
formsemestre_status_head(
formsemestre_id=formsemestre_id, page_title="Tableau de bord"

View File

@ -103,7 +103,7 @@ def formsemestre_recapcomplet(
return data
H = [
html_sco_header.sco_header(
page_title="Récapitulatif",
page_title=f"{formsemestre.sem_modalite()}: moyennes",
no_side_bar=True,
init_qtip=True,
javascripts=["js/etud_info.js", "js/table_recap.js"],

View File

@ -704,6 +704,7 @@ def do_import_etuds_from_portal(sem, a_importer, etudsapo_ident):
typ=ScolarNews.NEWS_INSCR,
text="Import Apogée de %d étudiants en " % len(created_etudids),
obj=sem["formsemestre_id"],
max_frequency=10 * 60, # 10'
)

View File

@ -1,5 +1,7 @@
/* Page accueil département */
var apo_editor = null;
var elt_annee_apo_editor = null;
var elt_sem_apo_editor = null;
$(document).ready(function () {
var table_options = {
@ -17,8 +19,14 @@ $(document).ready(function () {
$('table.semlist').DataTable(table_options);
let table_editable = document.querySelector("table#semlist.apo_editable");
if (table_editable) {
let apo_save_url = document.querySelector("table#semlist.apo_editable").dataset.apo_save_url;
apo_editor = new ScoFieldEditor(".etapes_apo_str", apo_save_url, false);
let save_url = document.querySelector("table#semlist.apo_editable").dataset.apo_save_url;
apo_editor = new ScoFieldEditor(".etapes_apo_str", save_url, false);
save_url = document.querySelector("table#semlist.apo_editable").dataset.elt_annee_apo_save_url;
elt_annee_apo_editor = new ScoFieldEditor(".elt_annee_apo", save_url, false);
save_url = document.querySelector("table#semlist.apo_editable").dataset.elt_sem_apo_save_url;
elt_sem_apo_editor = new ScoFieldEditor(".elt_sem_apo", save_url, false);
}
});

View File

@ -1,6 +1,5 @@
{# -*- mode: jinja-html -*- #}
{% extends 'base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}

View File

@ -290,10 +290,9 @@ def formsemestre_bulletinetud(
code_ine=None,
):
format = format or "html"
if not formsemestre_id:
flask.abort(404, "argument manquant: formsemestre_id")
if not isinstance(formsemestre_id, int):
raise ScoInvalidIdType("formsemestre_id must be an integer !")
raise ValueError("formsemestre_id must be an integer !")
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
if etudid:
etud = models.Identite.query.get_or_404(etudid)
@ -481,11 +480,16 @@ sco_publish(
Permission.ScoView,
methods=["GET", "POST"],
)
sco_publish(
"/formation_table_recap",
sco_formation_recap.formation_table_recap,
Permission.ScoView,
)
@bp.route("/formation_table_recap")
@scodoc
@permission_required(Permission.ScoView)
@scodoc7func
def formation_table_recap(formation_id, format="html"):
return sco_formation_recap.formation_table_recap(formation_id, format="html")
sco_publish(
"/export_recap_formations_annee_scolaire",
sco_formation_recap.export_recap_formations_annee_scolaire,
@ -2459,6 +2463,51 @@ def formsemestre_set_apo_etapes():
ScolarNews.add(
typ=ScolarNews.NEWS_APO,
text=f"Modification code Apogée du semestre {formsemestre.titre_annee()})",
max_frequency=10 * 60,
)
return ("", 204)
@bp.route("/formsemestre_set_elt_annee_apo", methods=["POST"])
@scodoc
@permission_required(Permission.ScoEditApo)
def formsemestre_set_elt_annee_apo():
"""Change les codes étapes du semestre indiqué.
Args: oid=formsemestre_id, value=chaine "V3ONM, V3ONM1, V3ONM2", codes séparés par des virgules
"""
oid = int(request.form.get("oid"))
value = (request.form.get("value") or "").strip()
formsemestre: FormSemestre = FormSemestre.query.get_or_404(oid)
if value != formsemestre.elt_annee_apo:
formsemestre.elt_annee_apo = value
db.session.add(formsemestre)
db.session.commit()
ScolarNews.add(
typ=ScolarNews.NEWS_APO,
text=f"Modification code Apogée du semestre {formsemestre.titre_annee()})",
max_frequency=10 * 60,
)
return ("", 204)
@bp.route("/formsemestre_set_elt_sem_apo", methods=["POST"])
@scodoc
@permission_required(Permission.ScoEditApo)
def formsemestre_set_elt_sem_apo():
"""Change les codes étapes du semestre indiqué.
Args: oid=formsemestre_id, value=chaine "V3ONM, V3ONM1, V3ONM2", codes séparés par des virgules
"""
oid = int(request.form.get("oid"))
value = (request.form.get("value") or "").strip()
formsemestre: FormSemestre = FormSemestre.query.get_or_404(oid)
if value != formsemestre.elt_sem_apo:
formsemestre.elt_sem_apo = value
db.session.add(formsemestre)
db.session.commit()
ScolarNews.add(
typ=ScolarNews.NEWS_APO,
text=f"Modification code Apogée du semestre {formsemestre.titre_annee()})",
max_frequency=10 * 60,
)
return ("", 204)
@ -2480,6 +2529,7 @@ def ue_set_apo():
ScolarNews.add(
typ=ScolarNews.NEWS_FORM,
text=f"Modification code Apogée d'UE dans la formation {ue.formation.titre} ({ue.formation.acronyme})",
max_frequency=10 * 60,
)
return ("", 204)
@ -2501,6 +2551,7 @@ def module_set_apo():
ScolarNews.add(
typ=ScolarNews.NEWS_FORM,
text=f"Modification code Apogée d'UE dans la formation {mod.formation.titre} ({mod.formation.acronyme})",
max_frequency=10 * 60,
)
return ("", 204)

View File

@ -1,74 +1,87 @@
alembic==1.7.5
alembic==1.7.7
astroid==2.11.2
async-timeout==4.0.2
attrs==21.4.0
Babel==2.9.1
black==22.3.0
blinker==1.4
certifi==2021.10.8
cffi==1.15.0
chardet==4.0.0
charset-normalizer==2.0.9
click==8.0.3
charset-normalizer==2.0.12
click==8.1.2
cracklib==2.9.3
cryptography==36.0.1
cryptography==36.0.2
Deprecated==1.2.13
dnspython==2.1.0
dill==0.3.4
dominate==2.6.0
email-validator==1.1.3
et-xmlfile==1.1.0
Flask==2.0.2
Flask==2.1.1
Flask-Babel==2.0.0
Flask-Bootstrap==3.3.7.1
Flask-Caching==1.10.1
Flask-HTTPAuth==4.5.0
Flask-Login==0.5.0
Flask-Login==0.6.0
Flask-Mail==0.9.1
Flask-Migrate==3.1.0
Flask-Moment==1.0.2
Flask-SQLAlchemy==2.5.1
Flask-WTF==1.0.0
Flask-WTF==1.0.1
greenlet==1.1.2
gunicorn==20.1.0
icalendar==4.0.9
idna==3.3
importlib-metadata==4.11.3
iniconfig==1.1.1
isort==5.10.1
itsdangerous==2.0.1
Jinja2==3.0.3
itsdangerous==2.1.2
Jinja2==3.1.1
lazy-object-proxy==1.7.1
lxml==4.8.0
Mako==1.1.6
MarkupSafe==2.0.1
mccabe==0.6.1
numpy==1.22.0
Mako==1.2.0
MarkupSafe==2.1.1
mccabe==0.7.0
mypy==0.942
mypy-extensions==0.4.3
numpy==1.22.3
openpyxl==3.0.9
packaging==21.3
pandas==1.3.5
Pillow==8.4.0
pandas==1.4.2
pathspec==0.9.0
Pillow==9.1.0
pkg_resources==0.0.0
platformdirs==2.5.1
pluggy==1.0.0
psycopg2==2.9.3
py==1.11.0
pycparser==2.21
pydot==1.4.2
PyJWT==2.3.0
pyOpenSSL==21.0.0
pyparsing==3.0.6
pytest==6.2.5
pylint==2.13.5
pylint-flask==0.6
pylint-flask-sqlalchemy==0.2.0
pylint-plugin-utils==0.7
pyOpenSSL==22.0.0
pyparsing==3.0.8
pytest==7.1.1
python-dateutil==2.8.2
python-docx==0.8.11
python-dotenv==0.19.2
python-dotenv==0.20.0
python-editor==1.0.4
pytz==2021.3
redis==4.1.0
reportlab==3.6.5
requests==2.26.0
pytz==2022.1
redis==4.2.2
reportlab==3.6.9
requests==2.27.1
rq==1.10.1
six==1.16.0
SQLAlchemy==1.4.29
SQLAlchemy==1.4.35
toml==0.10.2
tornado==6.1
typing-extensions==4.0.1
urllib3==1.26.7
typing_extensions==4.1.1
urllib3==1.26.9
visitor==0.1.3
Werkzeug==2.0.2
wrapt==1.13.3
Werkzeug==2.1.1
wrapt==1.14.0
WTForms==3.0.1
zipp==3.8.0

View File

@ -1,7 +1,7 @@
# -*- mode: python -*-
# -*- coding: utf-8 -*-
SCOVERSION = "9.2.6"
SCOVERSION = "9.2.7"
SCONAME = "ScoDoc"