WIP: Partitions non editables (pour groupes de parcours)

This commit is contained in:
Emmanuel Viennet 2022-05-26 23:45:57 +02:00
parent 3c9cc3121f
commit 5af4b5bed6
7 changed files with 90 additions and 34 deletions

View File

@ -23,7 +23,7 @@ class Partition(db.Model):
) )
# "TD", "TP", ... (NULL for 'all') # "TD", "TP", ... (NULL for 'all')
partition_name = db.Column(db.String(SHORT_STR_LEN)) partition_name = db.Column(db.String(SHORT_STR_LEN))
# numero = ordre de presentation) # Numero = ordre de presentation)
numero = db.Column(db.Integer) numero = db.Column(db.Integer)
# Calculer le rang ? # Calculer le rang ?
bul_show_rank = db.Column( bul_show_rank = db.Column(
@ -33,6 +33,10 @@ class Partition(db.Model):
show_in_lists = db.Column( show_in_lists = db.Column(
db.Boolean(), nullable=False, default=True, server_default="true" db.Boolean(), nullable=False, default=True, server_default="true"
) )
# Editable ? (faux pour les groupes de parcours)
groups_editable = db.Column(
db.Boolean(), nullable=False, default=True, server_default="true"
)
groups = db.relationship( groups = db.relationship(
"GroupDescr", "GroupDescr",
backref=db.backref("partition", lazy=True), backref=db.backref("partition", lazy=True),

View File

@ -35,6 +35,7 @@ from flask import url_for, g, request
from app.comp import res_sem from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat from app.comp.res_compat import NotesTableCompat
from app.models import FormSemestre from app.models import FormSemestre
from app.models.groups import GroupDescr, Partition
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app import log from app import log
from app.scodoc.scolog import logdb from app.scodoc.scolog import logdb
@ -263,8 +264,7 @@ def do_formsemestre_inscription_with_modules(
args["etat"] = etat args["etat"] = etat
do_formsemestre_inscription_create(args, method=method) do_formsemestre_inscription_create(args, method=method)
log( log(
"do_formsemestre_inscription_with_modules: etudid=%s formsemestre_id=%s" f"do_formsemestre_inscription_with_modules: etudid={etudid} formsemestre_id={formsemestre_id}"
% (etudid, formsemestre_id)
) )
# inscriptions aux groupes # inscriptions aux groupes
# 1- inscrit au groupe 'tous' # 1- inscrit au groupe 'tous'
@ -275,8 +275,14 @@ def do_formsemestre_inscription_with_modules(
# 2- inscrit aux groupes # 2- inscrit aux groupes
for group_id in group_ids: for group_id in group_ids:
if group_id and not group_id in gdone: if group_id and not group_id in gdone:
group = GroupDescr.query.get_or_404(group_id)
if group.partition.groups_editable:
sco_groups.set_group(etudid, group_id) sco_groups.set_group(etudid, group_id)
gdone[group_id] = 1 gdone[group_id] = 1
else:
log(
f"do_formsemestre_inscription_with_modules: group {group:r} belongs to non editable partition"
)
# inscription a tous les modules de ce semestre # inscription a tous les modules de ce semestre
modimpls = sco_moduleimpl.moduleimpl_withmodule_list( modimpls = sco_moduleimpl.moduleimpl_withmodule_list(
@ -534,12 +540,15 @@ def formsemestre_inscription_option(etudid, formsemestre_id):
ue_status = nt.get_etud_ue_status(etudid, ue_id) ue_status = nt.get_etud_ue_status(etudid, ue_id)
if ue_status and ue_status["is_capitalized"]: if ue_status and ue_status["is_capitalized"]:
sem_origin = sco_formsemestre.get_formsemestre(ue_status["formsemestre_id"]) sem_origin = sco_formsemestre.get_formsemestre(ue_status["formsemestre_id"])
ue_descr += ' <a class="discretelink" href="formsemestre_bulletinetud?formsemestre_id=%s&etudid=%s" title="%s">(capitalisée le %s)' % ( ue_descr += (
' <a class="discretelink" href="formsemestre_bulletinetud?formsemestre_id=%s&etudid=%s" title="%s">(capitalisée le %s)'
% (
sem_origin["formsemestre_id"], sem_origin["formsemestre_id"],
etudid, etudid,
sem_origin["titreannee"], sem_origin["titreannee"],
ndb.DateISOtoDMY(ue_status["event_date"]), ndb.DateISOtoDMY(ue_status["event_date"]),
) )
)
descr.append( descr.append(
( (
"sec_%s" % ue_id, "sec_%s" % ue_id,

View File

@ -346,7 +346,7 @@ def formsemestre_status_menubar(sem):
"title": "%s" % partition["partition_name"], "title": "%s" % partition["partition_name"],
"endpoint": "scolar.affect_groups", "endpoint": "scolar.affect_groups",
"args": {"partition_id": partition["partition_id"]}, "args": {"partition_id": partition["partition_id"]},
"enabled": enabled, "enabled": enabled and partition["groups_editable"],
} }
) )
menuGroupes.append( menuGroupes.append(

View File

@ -76,10 +76,12 @@ partitionEditor = ndb.EditableTable(
"numero", "numero",
"bul_show_rank", "bul_show_rank",
"show_in_lists", "show_in_lists",
"editable",
), ),
input_formators={ input_formators={
"bul_show_rank": bool, "bul_show_rank": bool,
"show_in_lists": bool, "show_in_lists": bool,
"editable": bool,
}, },
) )
@ -621,10 +623,12 @@ def comp_origin(etud, cur_sem):
return "" # parcours normal, ne le signale pas return "" # parcours normal, ne le signale pas
def set_group(etudid, group_id): def set_group(etudid: int, group_id: int) -> bool:
"""Inscrit l'étudiant au groupe. """Inscrit l'étudiant au groupe.
Return True if ok, False si deja inscrit. Return True if ok, False si deja inscrit.
Warning: don't check if group_id exists (the caller should check). Warning:
- don't check if group_id exists (the caller should check).
- don't check if group's partition is editable
""" """
cnx = ndb.GetDBConnexion() cnx = ndb.GetDBConnexion()
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
@ -698,14 +702,28 @@ def setGroups(
groupsToCreate="", # name and members of new groups groupsToCreate="", # name and members of new groups
groupsToDelete="", # groups to delete groupsToDelete="", # groups to delete
): ):
"""Affect groups (Ajax request) """Affect groups (Ajax request): renvoie du XML
groupsLists: lignes de la forme "group_id;etudid;...\n" groupsLists: lignes de la forme "group_id;etudid;...\n"
groupsToCreate: lignes "group_name;etudid;...\n" groupsToCreate: lignes "group_name;etudid;...\n"
groupsToDelete: group_id;group_id;... groupsToDelete: group_id;group_id;...
Ne peux pas modifier les groupes des partitions non éditables.
""" """
from app.scodoc import sco_formsemestre from app.scodoc import sco_formsemestre
def xml_error(msg, code=404):
data = (
f'<?xml version="1.0" encoding="utf-8"?><response>Error: {msg}</response>'
)
response = make_response(data, code)
response.headers["Content-Type"] = scu.XML_MIMETYPE
return response
partition = get_partition(partition_id) partition = get_partition(partition_id)
if not partition["group_editable"]:
msg = "setGroups: partition non editable"
log(msg)
return xml_error(msg, code=403)
formsemestre_id = partition["formsemestre_id"] formsemestre_id = partition["formsemestre_id"]
if not sco_permissions_check.can_change_groups(formsemestre_id): if not sco_permissions_check.can_change_groups(formsemestre_id):
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !") raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
@ -727,8 +745,8 @@ def setGroups(
continue continue
try: try:
group_id = int(group_id) group_id = int(group_id)
except ValueError as exc: except ValueError:
log("setGroups: ignoring invalid group_id={group_id}") log(f"setGroups: ignoring invalid group_id={group_id}")
continue continue
group = get_group(group_id) group = get_group(group_id)
# Anciens membres du groupe: # Anciens membres du groupe:
@ -967,14 +985,19 @@ def edit_partition_form(formsemestre_id=None):
for group in get_partition_groups(p) for group in get_partition_groups(p)
] ]
H.append(", ".join(lg)) H.append(", ".join(lg))
H.append("""</td><td>""")
if p["groups_editable"]:
H.append( H.append(
f"""</td><td><a class="stdlink" href="{ f"""<a class="stdlink" href="{
url_for("scolar.affect_groups", url_for("scolar.affect_groups",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
partition_id=p["partition_id"]) partition_id=p["partition_id"])
}">répartir</a></td> }">répartir</a></td>
""" """
) )
else:
H.append("""non éditable""")
H.append("""</td>""")
H.append( H.append(
'<td><a class="stdlink" href="partition_rename?partition_id=%s">renommer</a></td>' '<td><a class="stdlink" href="partition_rename?partition_id=%s">renommer</a></td>'
% p["partition_id"] % p["partition_id"]
@ -1334,6 +1357,8 @@ def groups_auto_repartition(partition_id=None):
from app.scodoc import sco_formsemestre from app.scodoc import sco_formsemestre
partition = get_partition(partition_id) partition = get_partition(partition_id)
if not partition["groups_editable"]:
raise AccessDenied("Partition non éditable")
formsemestre_id = partition["formsemestre_id"] formsemestre_id = partition["formsemestre_id"]
formsemestre = FormSemestre.query.get(formsemestre_id) formsemestre = FormSemestre.query.get(formsemestre_id)
# renvoie sur page édition groupes # renvoie sur page édition groupes

View File

@ -33,14 +33,13 @@ import io
import os import os
import re import re
import time import time
from datetime import date
from flask import g, url_for from flask import g, url_for
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
from app import log from app import log
from app.models import ScolarNews from app.models import ScolarNews, GroupDescr
from app.scodoc.sco_excel import COLORS from app.scodoc.sco_excel import COLORS
from app.scodoc.sco_formsemestre_inscriptions import ( from app.scodoc.sco_formsemestre_inscriptions import (
@ -718,9 +717,17 @@ def scolars_import_admission(datafile, formsemestre_id=None, type_admission=None
) )
for group_id in group_ids: for group_id in group_ids:
group = GroupDescr.query.get(group_id)
if group.partition.groups_editable:
sco_groups.change_etud_group_in_partition( sco_groups.change_etud_group_in_partition(
args["etudid"], group_id args["etudid"], group_id
) )
else:
log("scolars_import_admission: partition non editable")
diag.append(
f"Attention: partition {group.partition} non editable (ignorée)"
)
# #
diag.append("import de %s" % (etud["nomprenom"])) diag.append("import de %s" % (etud["nomprenom"]))
n_import += 1 n_import += 1

View File

@ -219,6 +219,7 @@ def do_inscrit(sem, etudids, inscrit_groupes=False):
# inscrit aux groupes # inscrit aux groupes
for partition_group in partition_groups: for partition_group in partition_groups:
if partition_group["groups_editable"]:
sco_groups.change_etud_group_in_partition( sco_groups.change_etud_group_in_partition(
etudid, etudid,
partition_group["group_id"], partition_group["group_id"],

View File

@ -102,6 +102,13 @@ def upgrade():
["id"], ["id"],
ondelete="CASCADE", ondelete="CASCADE",
) )
# GROUPES
op.add_column(
"partition",
sa.Column(
"groups_editable", sa.Boolean(), server_default="true", nullable=False
),
)
# INSCRIPTIONS # INSCRIPTIONS
op.drop_constraint( op.drop_constraint(
"notes_formsemestre_inscription_etudid_fkey", "notes_formsemestre_inscription_etudid_fkey",
@ -192,6 +199,7 @@ def upgrade():
# ### end Alembic commands ### # ### end Alembic commands ###
# --------------------------------------------------------------
def downgrade(): def downgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint( op.drop_constraint(
@ -232,6 +240,8 @@ def downgrade():
op.create_foreign_key( op.create_foreign_key(
"notes_notes_etudid_fkey", "notes_notes", "identite", ["etudid"], ["id"] "notes_notes_etudid_fkey", "notes_notes", "identite", ["etudid"], ["id"]
) )
# GROUPES
op.drop_column("partition", "groups_editable")
# INSCRIPTIONS # INSCRIPTIONS
op.drop_constraint( op.drop_constraint(
"notes_formsemestre_inscription_etudid_fkey", "notes_formsemestre_inscription_etudid_fkey",