Cascades sur Identite. Inscription aux parcours BUT.

This commit is contained in:
Emmanuel Viennet 2022-05-26 03:55:03 +02:00
commit 3c9cc3121f
18 changed files with 430 additions and 40 deletions

View File

@ -4,7 +4,6 @@
# See LICENSE
##############################################################################
from xml.etree import ElementTree
from typing import TextIO
import sqlalchemy

View File

@ -70,6 +70,7 @@ class ResultatsSemestre(ResultatsCache):
self.etud_moy_gen: pd.Series = None
self.etud_moy_gen_ranks = {}
self.etud_moy_gen_ranks_int = {}
self.moy_gen_rangs_by_group = None # virtual
self.modimpl_inscr_df: pd.DataFrame = None
"Inscriptions: row etudid, col modimlpl_id"
self.modimpls_results: ModuleImplResults = None
@ -824,17 +825,25 @@ class ResultatsSemestre(ResultatsCache):
self.formsemestre.id
)
first_partition = True
col_order = 10
for partition in partitions:
cid = f"part_{partition['partition_id']}"
rg_cid = cid + "_rg" # rang dans la partition
titles[cid] = partition["partition_name"]
if first_partition:
klass = "partition"
else:
klass = "partition partition_aux"
titles[f"_{cid}_class"] = klass
titles[f"_{cid}_col_order"] = 10
titles[f"_{cid}_col_order"] = col_order
titles[f"_{rg_cid}_col_order"] = col_order + 1
col_order += 2
if partition["bul_show_rank"]:
titles[rg_cid] = f"Rg {partition['partition_name']}"
titles[f"_{rg_cid}_class"] = "partition_rangs"
partition_etud_groups = partitions_etud_groups[partition["partition_id"]]
for row in rows:
group = None # group (dict) de l'étudiant dans cette partition
# dans NotesTableCompat, à revoir
etud_etat = self.get_etud_etat(row["etudid"])
if etud_etat == "D":
@ -847,8 +856,17 @@ class ResultatsSemestre(ResultatsCache):
group = partition_etud_groups.get(row["etudid"])
gr_name = group["group_name"] if group else ""
if gr_name:
row[f"{cid}"] = gr_name
row[cid] = gr_name
row[f"_{cid}_class"] = klass
# Rangs dans groupe
if (
partition["bul_show_rank"]
and (group is not None)
and (group["id"] in self.moy_gen_rangs_by_group)
):
rang = self.moy_gen_rangs_by_group[group["id"]][0]
row[rg_cid] = rang.get(row["etudid"], "")
first_partition = False
def _recap_add_evaluations(

View File

@ -11,7 +11,9 @@ class Absence(db.Model):
__tablename__ = "absences"
id = db.Column(db.Integer, primary_key=True)
etudid = db.Column(db.Integer, db.ForeignKey("identite.id"), index=True)
etudid = db.Column(
db.Integer, db.ForeignKey("identite.id", ondelete="CASCADE"), index=True
)
jour = db.Column(db.Date)
estabs = db.Column(db.Boolean())
estjust = db.Column(db.Boolean())
@ -50,7 +52,7 @@ class AbsenceNotification(db.Model):
id = db.Column(db.Integer, primary_key=True)
etudid = db.Column(
db.Integer,
db.ForeignKey("identite.id"),
db.ForeignKey("identite.id", ondelete="CASCADE"),
)
notification_date = db.Column(
db.DateTime(timezone=True), server_default=db.func.now()

View File

@ -436,7 +436,7 @@ class Adresse(db.Model):
adresse_id = db.synonym("id")
etudid = db.Column(
db.Integer,
db.ForeignKey("identite.id"),
db.ForeignKey("identite.id", ondelete="CASCADE"),
)
email = db.Column(db.Text()) # mail institutionnel
emailperso = db.Column(db.Text) # email personnel (exterieur)
@ -470,7 +470,7 @@ class Admission(db.Model):
adm_id = db.synonym("id")
etudid = db.Column(
db.Integer,
db.ForeignKey("identite.id"),
db.ForeignKey("identite.id", ondelete="CASCADE"),
)
# Anciens champs de ScoDoc7, à revoir pour être plus générique et souple
# notamment dans le cadre du bac 2021
@ -540,7 +540,7 @@ class ItemSuivi(db.Model):
itemsuivi_id = db.synonym("id")
etudid = db.Column(
db.Integer,
db.ForeignKey("identite.id"),
db.ForeignKey("identite.id", ondelete="CASCADE"),
)
item_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
situation = db.Column(db.Text)

View File

@ -323,6 +323,25 @@ class FormSemestre(db.Model):
return ""
return ", ".join(sorted([etape.etape_apo for etape in self.etapes if etape]))
def regroupements_coherents_etud(self) -> list[tuple[UniteEns, UniteEns]]:
"""Calcule la liste des regroupements cohérents d'UE impliquant ce
formsemestre.
Pour une année donnée: l'étudiant est inscrit dans ScoDoc soit dans le semestre
impair, soit pair, soit les deux (il est rare mais pas impossible d'avoir une
inscription seulement en semestre pair, par exemple suite à un transfert ou un
arrêt temporaire du cursus).
1. Déterminer l'*autre* formsemestre: semestre précédent ou suivant de la même
année, formation compatible (même référentiel de compétence) dans lequel
l'étudiant est inscrit.
2. Construire les couples d'UE (regroupements cohérents): apparier les UE qui
ont le même `ApcParcoursNiveauCompetence`.
"""
if not self.formation.is_apc():
return []
raise NotImplementedError() # XXX
def responsables_str(self, abbrev_prenom=True) -> str:
"""chaîne "J. Dupond, X. Martin"
ou "Jacques Dupond, Xavier Martin"
@ -614,7 +633,9 @@ class FormSemestreInscription(db.Model):
id = db.Column(db.Integer, primary_key=True)
formsemestre_inscription_id = db.synonym("id")
etudid = db.Column(db.Integer, db.ForeignKey("identite.id"), index=True)
etudid = db.Column(
db.Integer, db.ForeignKey("identite.id", ondelete="CASCADE"), index=True
)
formsemestre_id = db.Column(
db.Integer,
db.ForeignKey("notes_formsemestre.id"),
@ -634,11 +655,16 @@ class FormSemestreInscription(db.Model):
)
# I inscrit, D demission en cours de semestre, DEF si "defaillant"
etat = db.Column(db.String(CODE_STR_LEN), index=True)
# etape apogee d'inscription (experimental 2020)
# Etape Apogée d'inscription (ajout 2020)
etape = db.Column(db.String(APO_CODE_STR_LEN))
# Parcours (pour les BUT)
parcour_id = db.Column(db.Integer, db.ForeignKey("apc_parcours.id"), index=True)
parcour = db.relationship(ApcParcours)
def __repr__(self):
return f"<{self.__class__.__name__} {self.id} etudid={self.etudid} sem={self.formsemestre_id} etat={self.etat}>"
return f"""<{self.__class__.__name__} {self.id} etudid={self.etudid} sem={
self.formsemestre_id} etat={self.etat} {
('parcours='+str(self.parcour)) if self.parcour else ''}>"""
class NotesSemSet(db.Model):

View File

@ -106,7 +106,7 @@ class GroupDescr(db.Model):
group_membership = db.Table(
"group_membership",
db.Column("etudid", db.Integer, db.ForeignKey("identite.id")),
db.Column("etudid", db.Integer, db.ForeignKey("identite.id", ondelete="CASCADE")),
db.Column("group_id", db.Integer, db.ForeignKey("group_descr.id")),
db.UniqueConstraint("etudid", "group_id"),
)
@ -116,5 +116,5 @@ group_membership = db.Table(
# __tablename__ = "group_membership"
# __table_args__ = (db.UniqueConstraint("etudid", "group_id"),)
# id = db.Column(db.Integer, primary_key=True)
# etudid = db.Column(db.Integer, db.ForeignKey("identite.id"))
# etudid = db.Column(db.Integer, db.ForeignKey("identite.id", ondelete="CASCADE"))
# group_id = db.Column(db.Integer, db.ForeignKey("group_descr.id"))

View File

@ -17,7 +17,7 @@ class BulAppreciations(db.Model):
date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
etudid = db.Column(
db.Integer,
db.ForeignKey("identite.id"),
db.ForeignKey("identite.id", ondelete="CASCADE"),
index=True,
)
formsemestre_id = db.Column(
@ -36,7 +36,7 @@ class NotesNotes(db.Model):
id = db.Column(db.Integer, primary_key=True)
etudid = db.Column(
db.Integer,
db.ForeignKey("identite.id"),
db.ForeignKey("identite.id", ondelete="CASCADE"),
)
evaluation_id = db.Column(
db.Integer, db.ForeignKey("notes_evaluation.id"), index=True
@ -56,7 +56,7 @@ class NotesNotesLog(db.Model):
etudid = db.Column(
db.Integer,
db.ForeignKey("identite.id"),
db.ForeignKey("identite.id", ondelete="CASCADE"),
)
evaluation_id = db.Column(
db.Integer,

View File

@ -19,7 +19,7 @@ class ScolarFormSemestreValidation(db.Model):
formsemestre_validation_id = db.synonym("id")
etudid = db.Column(
db.Integer,
db.ForeignKey("identite.id"),
db.ForeignKey("identite.id", ondelete="CASCADE"),
index=True,
)
formsemestre_id = db.Column(
@ -66,7 +66,7 @@ class ScolarAutorisationInscription(db.Model):
etudid = db.Column(
db.Integer,
db.ForeignKey("identite.id"),
db.ForeignKey("identite.id", ondelete="CASCADE"),
)
formation_code = db.Column(db.String(SHORT_STR_LEN), nullable=False)
# semestre ou on peut s'inscrire:
@ -86,7 +86,7 @@ class ScolarEvent(db.Model):
event_id = db.synonym("id")
etudid = db.Column(
db.Integer,
db.ForeignKey("identite.id"),
db.ForeignKey("identite.id", ondelete="CASCADE"),
)
event_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
formsemestre_id = db.Column(

View File

@ -244,7 +244,11 @@ def formation_edit(formation_id=None, create=False):
return (
"\n".join(H)
+ tf_error_message(
"Valeurs incorrectes: il existe déjà une formation avec même titre, acronyme et version."
f"""Valeurs incorrectes: il existe déjà <a href="{
url_for('notes.ue_table', scodoc_dept=g.scodoc_dept, formation_id=others[0]["id"])
}">une formation</a> avec même titre,
acronyme et version.
"""
)
+ tf[1]
+ html_sco_header.sco_footer()

View File

@ -352,7 +352,7 @@ def module_edit(
title = f"""Création {object_name} dans la formation
{formation.acronyme}"""
else:
page_title = "Modification du module {module.code or module.titre or ''}"
page_title = f"Modification du module {module.code or module.titre or ''}"
title = f"""Modification du module {module.code or ''} {module.titre or ''}
(formation {formation.acronyme}, version {formation.version})
"""

View File

@ -1009,7 +1009,7 @@ def edit_partition_form(formsemestre_id=None):
<input type="submit" name="ok" disabled="1" value="Nouvelle partition"/>
"""
)
if formsemestre.formation.is_apc() and "Parcours" not in (
if formsemestre.formation.is_apc() and scu.PARTITION_PARCOURS not in (
p["partition_name"] for p in partitions
):
# propose création partition "Parcours"
@ -1068,9 +1068,7 @@ def partition_set_attr(partition_id, attr, value):
partition[attr] = value
partitionEditor.edit(cnx, partition)
# invalid bulletin cache
sco_cache.invalidate_formsemestre(
pdfonly=True, formsemestre_id=partition["formsemestre_id"]
)
sco_cache.invalidate_formsemestre(formsemestre_id=partition["formsemestre_id"])
return "enregistré"

View File

@ -111,6 +111,8 @@ MODULE_TYPE_NAMES = {
None: "Module",
}
PARTITION_PARCOURS = "Parcours"
MALUS_MAX = 20.0
MALUS_MIN = -20.0

View File

@ -15,13 +15,23 @@ $(function () {
},
{
name: "toggle_partitions",
text: "Toutes les partitions",
text: "Montrer groupes",
action: function (e, dt, node, config) {
let visible = dt.columns(".partition_aux").visible()[0];
dt.columns(".partition_aux").visible(!visible);
dt.buttons('toggle_partitions:name').text(visible ? "Toutes les partitions" : "Cacher les partitions");
dt.buttons('toggle_partitions:name').text(visible ? "Montrer groupes" : "Cacher les groupes");
}
}];
},
{
name: "toggle_partitions_rangs",
text: "Rangs groupes",
action: function (e, dt, node, config) {
let rangs_visible = dt.columns(".partition_rangs").visible()[0];
dt.columns(".partition_rangs").visible(!rangs_visible);
dt.buttons('toggle_partitions_rangs:name').text(rangs_visible ? "Rangs groupes" : "Cacher rangs groupes");
}
},
];
if (!$('table.table_recap').hasClass("jury")) {
buttons.push(
$('table.table_recap').hasClass("apc") ?
@ -95,7 +105,7 @@ $(function () {
"columnDefs": [
{
// cache les codes, le détail de l'identité, les groupes, les colonnes admission et les vides
targets: ["codes", "identite_detail", "partition_aux", "admission", "col_empty"],
targets: ["codes", "identite_detail", "partition_aux", "partition_rangs", "admission", "col_empty"],
visible: false,
},
{

View File

@ -6,12 +6,12 @@
<div class="help">
<p>Ces codes (ADM, AJ, ...) sont utilisés pour représenter les décisions de jury
et les validations de semestres ou d'UE. les valeurs indiquées ici sont utilisées
dans les exports Apogée.
<p>
<p>Ne les modifier que si vous savez ce que vous faites !
</p>
<p>Ces codes (ADM, AJ, ...) sont utilisés pour représenter les décisions de jury
et les validations de semestres ou d'UE.
Les valeurs indiquées ici sont utilisées dans les exports Apogée.
<p>
<p>Ne les modifier que si vous savez ce que vous faites !
</p>
</div>
<div class="row">
<div class="col-md-4">

View File

@ -15,7 +15,7 @@
<li>Code: <tt>{{ue.ue_code}}</tt></li>
<li>Type: {{ue.type}}</li>
<li>Externe: {{ "oui" if ue.is_external else "non" }}</li>
<li>Code Apogée: {{ue.code_apogee}}</li>
<li>Code Apogée: {{ue.code_apogee or "aucun"}}</li>
</ul>
</li>
<li>Formation:

View File

@ -915,13 +915,14 @@ sco_publish(
@permission_required(Permission.ScoView)
@scodoc7func
def create_partition_parcours(formsemestre_id):
"""Création d'une partitions nommée "Parcours" avec un groupe par parcours."""
"""Création d'une partitions nommée "Parcours" (PARTITION_PARCOURS)
avec un groupe par parcours."""
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
if "Parcours" in (p.partition_name for p in formsemestre.partitions):
flash("""Partition "Parcours" déjà existante""")
if scu.PARTITION_PARCOURS in (p.partition_name for p in formsemestre.partitions):
flash(f"""Partition "{scu.PARTITION_PARCOURS}" déjà existante""")
else:
partition_id = sco_groups.partition_create(
formsemestre_id, partition_name="Parcours", redirect=False
formsemestre_id, partition_name=scu.PARTITION_PARCOURS, redirect=False
)
n = 0
for parcour in formsemestre.parcours:

View File

@ -0,0 +1,308 @@
"""Formsemestre / parcours, Inscriptions aux parcours + cascades sur Identite
Revision ID: a2771105c21c
Revises: 6002d7d366e5
Create Date: 2022-05-25 20:32:06.868296
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = "a2771105c21c"
down_revision = "6002d7d366e5"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"parcours_formsemestre",
sa.Column("parcours_id", sa.Integer(), nullable=False),
sa.Column("formsemestre_id", sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(
["formsemestre_id"], ["notes_formsemestre.id"], ondelete="CASCADE"
),
sa.ForeignKeyConstraint(
["parcours_id"],
["apc_parcours.id"],
),
sa.PrimaryKeyConstraint("parcours_id", "formsemestre_id"),
)
op.drop_constraint("absences_etudid_fkey", "absences", type_="foreignkey")
op.create_foreign_key(
"absences_etudid_fkey",
"absences",
"identite",
["etudid"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint(
"absences_notifications_etudid_fkey",
"absences_notifications",
type_="foreignkey",
)
op.create_foreign_key(
"absences_notifications_etudid_fkey",
"absences_notifications",
"identite",
["etudid"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint("admissions_etudid_fkey", "admissions", type_="foreignkey")
op.create_foreign_key(
"admissions_etudid_fkey",
"admissions",
"identite",
["etudid"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint("adresse_etudid_fkey", "adresse", type_="foreignkey")
op.create_foreign_key(
"adresse_etudid_fkey",
"adresse",
"identite",
["etudid"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint(
"group_membership_etudid_fkey", "group_membership", type_="foreignkey"
)
op.create_foreign_key(
"group_membership_etudid_fkey",
"group_membership",
"identite",
["etudid"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint("itemsuivi_etudid_fkey", "itemsuivi", type_="foreignkey")
op.create_foreign_key(
"itemsuivi_etudid_fkey",
"itemsuivi",
"identite",
["etudid"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint(
"notes_appreciations_etudid_fkey", "notes_appreciations", type_="foreignkey"
)
op.create_foreign_key(
"notes_appreciations_etudid_fkey",
"notes_appreciations",
"identite",
["etudid"],
["id"],
ondelete="CASCADE",
)
# INSCRIPTIONS
op.drop_constraint(
"notes_formsemestre_inscription_etudid_fkey",
"notes_formsemestre_inscription",
type_="foreignkey",
)
op.create_foreign_key(
"notes_formsemestre_inscription_etudid_fkey",
"notes_formsemestre_inscription",
"identite",
["etudid"],
["id"],
ondelete="CASCADE",
)
op.add_column(
"notes_formsemestre_inscription",
sa.Column("parcour_id", sa.Integer(), nullable=True),
)
op.create_index(
op.f("ix_notes_formsemestre_inscription_parcour_id"),
"notes_formsemestre_inscription",
["parcour_id"],
unique=False,
)
op.create_foreign_key(
"notes_formsemestre_inscription_parcour_id_fkey",
"notes_formsemestre_inscription",
"apc_parcours",
["parcour_id"],
["id"],
)
# ---
op.drop_constraint("notes_notes_etudid_fkey", "notes_notes", type_="foreignkey")
op.create_foreign_key(
"notes_notes_etudid_fkey",
"notes_notes",
"identite",
["etudid"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint(
"notes_notes_log_etudid_fkey", "notes_notes_log", type_="foreignkey"
)
op.create_foreign_key(
"notes_notes_log_etudid_fkey",
"notes_notes_log",
"identite",
["etudid"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint(
"scolar_autorisation_inscription_etudid_fkey",
"scolar_autorisation_inscription",
type_="foreignkey",
)
op.create_foreign_key(
"scolar_autorisation_inscription_etudid_fkey",
"scolar_autorisation_inscription",
"identite",
["etudid"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint("scolar_events_etudid_fkey", "scolar_events", type_="foreignkey")
op.create_foreign_key(
"scolar_events_etudid_fkey",
"scolar_events",
"identite",
["etudid"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint(
"scolar_formsemestre_validation_etudid_fkey",
"scolar_formsemestre_validation",
type_="foreignkey",
)
op.create_foreign_key(
"scolar_formsemestre_validation_etudid_fkey",
"scolar_formsemestre_validation",
"identite",
["etudid"],
["id"],
ondelete="CASCADE",
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(
"scolar_formsemestre_validation_etudid_fkey",
"scolar_formsemestre_validation",
type_="foreignkey",
)
op.create_foreign_key(
"scolar_formsemestre_validation_etudid_fkey",
"scolar_formsemestre_validation",
"identite",
["etudid"],
["id"],
)
op.drop_constraint("scolar_events_etudid_fkey", "scolar_events", type_="foreignkey")
op.create_foreign_key(
"scolar_events_etudid_fkey", "scolar_events", "identite", ["etudid"], ["id"]
)
op.drop_constraint(
"scolar_autorisation_inscription_etudid_fkey",
"scolar_autorisation_inscription",
type_="foreignkey",
)
op.create_foreign_key(
"scolar_autorisation_inscription_etudid_fkey",
"scolar_autorisation_inscription",
"identite",
["etudid"],
["id"],
)
op.drop_constraint(
"notes_notes_log_etudid_fkey", "notes_notes_log", type_="foreignkey"
)
op.create_foreign_key(
"notes_notes_log_etudid_fkey", "notes_notes_log", "identite", ["etudid"], ["id"]
)
op.drop_constraint("notes_notes_etudid_fkey", "notes_notes", type_="foreignkey")
op.create_foreign_key(
"notes_notes_etudid_fkey", "notes_notes", "identite", ["etudid"], ["id"]
)
# INSCRIPTIONS
op.drop_constraint(
"notes_formsemestre_inscription_etudid_fkey",
"notes_formsemestre_inscription",
type_="foreignkey",
)
op.create_foreign_key(
"notes_formsemestre_inscription_etudid_fkey",
"notes_formsemestre_inscription",
"identite",
["etudid"],
["id"],
)
op.drop_constraint(
"notes_formsemestre_inscription_parcour_id_fkey",
"notes_formsemestre_inscription",
type_="foreignkey",
)
op.drop_index(
op.f("ix_notes_formsemestre_inscription_parcour_id"),
table_name="notes_formsemestre_inscription",
)
op.drop_column("notes_formsemestre_inscription", "parcour_id")
# --
op.drop_constraint(
"notes_appreciations_etudid_fkey", "notes_appreciations", type_="foreignkey"
)
op.create_foreign_key(
"notes_appreciations_etudid_fkey",
"notes_appreciations",
"identite",
["etudid"],
["id"],
)
op.drop_constraint("itemsuivi_etudid_fkey", "itemsuivi", type_="foreignkey")
op.create_foreign_key(
"itemsuivi_etudid_fkey", "itemsuivi", "identite", ["etudid"], ["id"]
)
op.drop_constraint(
"group_membership_etudid_fkey", "group_membership", type_="foreignkey"
)
op.create_foreign_key(
"group_membership_etudid_fkey",
"group_membership",
"identite",
["etudid"],
["id"],
)
op.drop_constraint("adresse_etudid_fkey", "adresse", type_="foreignkey")
op.create_foreign_key(
"adresse_etudid_fkey", "adresse", "identite", ["etudid"], ["id"]
)
op.drop_constraint("admissions_etudid_fkey", "admissions", type_="foreignkey")
op.create_foreign_key(
"admissions_etudid_fkey", "admissions", "identite", ["etudid"], ["id"]
)
op.drop_constraint(
"absences_notifications_etudid_fkey",
"absences_notifications",
type_="foreignkey",
)
op.create_foreign_key(
"absences_notifications_etudid_fkey",
"absences_notifications",
"identite",
["etudid"],
["id"],
)
op.drop_constraint("absences_etudid_fkey", "absences", type_="foreignkey")
op.create_foreign_key(
"absences_etudid_fkey", "absences", "identite", ["etudid"], ["id"]
)
op.drop_table("parcours_formsemestre")
# ### end Alembic commands ###

View File

@ -14,6 +14,7 @@ Au besoin, créer un base de test neuve:
import random
from flask import g
from app.models.formsemestre import FormSemestreInscription
from config import TestConfig
from tests.unit import sco_fake_gen
@ -85,6 +86,15 @@ def run_sco_basic(verbose=False):
# --- Inscription des étudiants
for etud in etuds:
G.inscrit_etudiant(formsemestre_id, etud)
# Vérification incription semestre:
q = FormSemestreInscription.query.filter_by(
etudid=etuds[0].id, formsemestre_id=formsemestre_id
)
assert q.count() == 1
ins = q.first()
assert ins.etape == None
assert ins.etat == "I"
assert ins.parcour == None
# --- Creation évaluation
e = G.create_evaluation(
@ -217,3 +227,15 @@ def run_sco_basic(verbose=False):
dec_ues = nt.get_etud_decision_ues(etud["etudid"])
for ue_id in dec_ues:
assert dec_ues[ue_id]["code"] in {"ADM", "CMP"}
# ---- Suppression étudiant, vérification inscription
# (permet de tester les cascades)
etud = etuds[0]
etudid = etud.id
db.session.delete(etud)
db.session.commit()
# Vérification incription semestre:
q = FormSemestreInscription.query.filter_by(
etudid=etudid, formsemestre_id=formsemestre_id
)
assert q.count() == 0