forked from ScoDoc/ScoDoc
Page accueil dept: sélection de plusieurs formsemestres et menu associé.
This commit is contained in:
parent
aae5068b7e
commit
867575ac78
@ -646,17 +646,18 @@ class FormSemestre(models.ScoDocModel):
|
||||
)
|
||||
return [db.session.get(ModuleImpl, modimpl_id) for modimpl_id in cursor]
|
||||
|
||||
def can_be_edited_by(self, user: User):
|
||||
"""Vrai si user peut modifier ce semestre (est chef ou l'un des responsables)"""
|
||||
def can_be_edited_by(self, user: User | None = None, allow_locked=False) -> bool:
|
||||
"""Vrai si user (par def. current) peut modifier ce semestre
|
||||
(est chef ou l'un des responsables).
|
||||
Si le semestre est verrouillé, faux sauf si allow_locked.
|
||||
"""
|
||||
user = user or current_user
|
||||
if user.passwd_must_be_changed or not user.has_permission(
|
||||
Permission.EditFormSemestre
|
||||
): # pas chef
|
||||
if not self.resp_can_edit or user.id not in [
|
||||
resp.id for resp in self.responsables
|
||||
]:
|
||||
): # pas chef de dept.
|
||||
if not self.resp_can_edit or not self.est_responsable(user):
|
||||
return False
|
||||
|
||||
return True
|
||||
return allow_locked or not self.etat
|
||||
|
||||
def est_courant(self) -> bool:
|
||||
"""Vrai si la date actuelle (now) est dans le semestre
|
||||
@ -902,13 +903,6 @@ class FormSemestre(models.ScoDocModel):
|
||||
"True si l'user est l'un des responsables du semestre"
|
||||
return user.id in [u.id for u in self.responsables]
|
||||
|
||||
def est_chef_or_diretud(self, user: User | None = None) -> bool:
|
||||
"Vrai si utilisateur (par def. current) est admin, chef dept ou responsable du semestre"
|
||||
user = user or current_user
|
||||
return user.has_permission(Permission.EditFormSemestre) or self.est_responsable(
|
||||
user
|
||||
)
|
||||
|
||||
def can_change_groups(self, user: User = None) -> bool:
|
||||
"""Vrai si l'utilisateur (par def. current) peut changer les groupes dans
|
||||
ce semestre: vérifie permission et verrouillage (mais pas si la partition est éditable).
|
||||
@ -926,10 +920,7 @@ class FormSemestre(models.ScoDocModel):
|
||||
"""Vrai si utilisateur (par def. current) peut saisir decision de jury
|
||||
dans ce semestre: vérifie permission et verrouillage.
|
||||
"""
|
||||
user = user or current_user
|
||||
if user.passwd_must_be_changed:
|
||||
return False
|
||||
return self.etat and self.est_chef_or_diretud(user)
|
||||
return self.can_be_edited_by(user)
|
||||
|
||||
def can_edit_pv(self, user: User = None):
|
||||
"Vrai si utilisateur (par def. current) peut editer un PV de jury de ce semestre"
|
||||
@ -937,7 +928,7 @@ class FormSemestre(models.ScoDocModel):
|
||||
if user.passwd_must_be_changed:
|
||||
return False
|
||||
# Autorise les secrétariats, repérés via la permission EtudChangeAdr
|
||||
return self.est_chef_or_diretud(user) or user.has_permission(
|
||||
return self.can_be_edited_by(user, allow_locked=True) or user.has_permission(
|
||||
Permission.EtudChangeAdr
|
||||
)
|
||||
|
||||
|
@ -100,15 +100,11 @@ def make_menu(title, items, css_class="", alone=False) -> str:
|
||||
def gen_menu_items(items):
|
||||
H.append("<ul>")
|
||||
for item in items:
|
||||
if not item.get("enabled", True):
|
||||
cls = ' class="ui-state-disabled"'
|
||||
else:
|
||||
cls = ""
|
||||
cls = f''' class="sco_menu_item {
|
||||
'' if item.get("enabled", True) else 'ui-state-disabled'
|
||||
}"'''
|
||||
the_id = item.get("id", "")
|
||||
if the_id:
|
||||
li_id = 'id="%s" ' % the_id
|
||||
else:
|
||||
li_id = ""
|
||||
li_id = f'id="{the_id}" ' if the_id else ""
|
||||
if "endpoint" in item:
|
||||
args = item.get("args", {})
|
||||
item["urlq"] = url_for(
|
||||
@ -134,7 +130,7 @@ def make_menu(title, items, css_class="", alone=False) -> str:
|
||||
H = []
|
||||
if alone:
|
||||
H.append('<ul class="sco_dropdown_menu %s">' % css_class)
|
||||
H.append("""<li><a href="#">%s</a>""" % title)
|
||||
H.append("""<li class="sco_menu_title"><a href="#">%s</a>""" % title)
|
||||
gen_menu_items(items)
|
||||
H.append("</li>")
|
||||
if alone:
|
||||
@ -142,12 +138,8 @@ def make_menu(title, items, css_class="", alone=False) -> str:
|
||||
return "".join(H)
|
||||
|
||||
|
||||
"""
|
||||
HTML <-> text conversions.
|
||||
http://stackoverflow.com/questions/328356/extracting-text-from-html-file-using-python
|
||||
"""
|
||||
|
||||
|
||||
# HTML <-> text conversions.
|
||||
# http://stackoverflow.com/questions/328356/extracting-text-from-html-file-using-python
|
||||
class _HTMLToText(HTMLParser):
|
||||
def __init__(self):
|
||||
HTMLParser.__init__(self)
|
||||
|
@ -36,6 +36,7 @@ from flask_sqlalchemy.query import Query
|
||||
import app
|
||||
from app import log
|
||||
from app.models import FormSemestre, ScolarNews, ScoDocSiteConfig
|
||||
from app.scodoc import htmlutils
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc.gen_tables import GenTable
|
||||
from app.scodoc.sco_permissions import Permission
|
||||
@ -83,6 +84,42 @@ def index_html(showcodes=0, showsemtable=0, export_table_formsemestres=False):
|
||||
sco_modalites.group_formsemestres_by_modalite(current_formsemestres)
|
||||
)
|
||||
passerelle_disabled = ScoDocSiteConfig.is_passerelle_disabled()
|
||||
|
||||
menu_items = [
|
||||
{
|
||||
"title": "Verrouiller les semestres sélectionnés",
|
||||
"endpoint": "notes.formsemestres_lock",
|
||||
"args": {
|
||||
"unlock": False,
|
||||
},
|
||||
},
|
||||
{
|
||||
"title": "Déverrouiller les semestres sélectionnés",
|
||||
"endpoint": "notes.formsemestres_lock",
|
||||
"args": {
|
||||
"unlock": True,
|
||||
},
|
||||
},
|
||||
{
|
||||
"title": "Publier les semestres sélectionnés sur la passerelle",
|
||||
"endpoint": "notes.formsemestres_enable_publish",
|
||||
"args": {
|
||||
"enable": True,
|
||||
},
|
||||
},
|
||||
{
|
||||
"title": "Ne pas publier les semestres sélectionnés sur la passerell ",
|
||||
"endpoint": "notes.formsemestres_enable_publish",
|
||||
"args": {
|
||||
"enable": False,
|
||||
},
|
||||
},
|
||||
]
|
||||
menu_formsemestres_action = (
|
||||
htmlutils.make_menu("_", menu_items, alone=True)
|
||||
if current_user.has_permission(Permission.EditFormSemestre)
|
||||
else ""
|
||||
)
|
||||
return render_template(
|
||||
"scolar/index.j2",
|
||||
current_user=current_user,
|
||||
@ -98,6 +135,7 @@ def index_html(showcodes=0, showsemtable=0, export_table_formsemestres=False):
|
||||
icon_hidden="" if passerelle_disabled else scu.ICON_HIDDEN,
|
||||
icon_published="" if passerelle_disabled else scu.ICON_PUBLISHED,
|
||||
locked_formsemestres=locked_formsemestres,
|
||||
menu_formsemestres_action=menu_formsemestres_action,
|
||||
modalites=modalites,
|
||||
nb_locked=locked_formsemestres.count(),
|
||||
nb_user_accounts=sco_users.get_users_count(dept=g.scodoc_dept),
|
||||
@ -107,6 +145,7 @@ def index_html(showcodes=0, showsemtable=0, export_table_formsemestres=False):
|
||||
showcodes=showcodes,
|
||||
showsemtable=showsemtable,
|
||||
sco=ScoData(),
|
||||
title=f"ScoDoc {g.scodoc_dept}",
|
||||
)
|
||||
|
||||
|
||||
|
@ -1706,42 +1706,6 @@ def formsemestre_edit_options(formsemestre_id):
|
||||
)
|
||||
|
||||
|
||||
def formsemestre_change_publication_bul(formsemestre_id, dialog_confirmed=False):
|
||||
"""Change état publication bulletins sur portail"""
|
||||
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
||||
ok, err = sco_permissions_check.check_access_diretud(formsemestre)
|
||||
if not ok:
|
||||
return err
|
||||
etat = not formsemestre.bul_hide_xml
|
||||
|
||||
status_url = url_for(
|
||||
"notes.formsemestre_status",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=formsemestre.id,
|
||||
)
|
||||
if not dialog_confirmed:
|
||||
msg = "non" if etat else ""
|
||||
return scu.confirm_dialog(
|
||||
f"<h2>Confirmer la {msg} publication des bulletins ?</h2>",
|
||||
help_msg="""Il est parfois utile de désactiver la diffusion des bulletins,
|
||||
par exemple pendant la tenue d'un jury ou avant harmonisation des notes.
|
||||
<br>
|
||||
Ce réglage n'a d'effet que si votre établissement a interfacé ScoDoc avec
|
||||
une passerelle étudiant.
|
||||
""",
|
||||
dest_url="",
|
||||
cancel_url=status_url,
|
||||
parameters={"bul_hide_xml": etat, "formsemestre_id": formsemestre_id},
|
||||
)
|
||||
|
||||
formsemestre.bul_hide_xml = etat
|
||||
db.session.add(formsemestre)
|
||||
db.session.commit()
|
||||
log(f"formsemestre_change_publication_bul: {formsemestre} -> {etat}")
|
||||
|
||||
return flask.redirect(status_url)
|
||||
|
||||
|
||||
def formsemestre_edit_uecoefs(formsemestre_id, err_ue_id=None):
|
||||
"""Changement manuel des coefficients des UE capitalisées."""
|
||||
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
||||
|
@ -417,7 +417,7 @@ def formsemestre_status_menubar(formsemestre: FormSemestre | None) -> str:
|
||||
"title": "Importer les notes",
|
||||
"endpoint": "notes.formsemestre_import_notes",
|
||||
"args": {"formsemestre_id": formsemestre_id},
|
||||
"enabled": formsemestre.est_chef_or_diretud(),
|
||||
"enabled": formsemestre.can_be_edited_by(),
|
||||
},
|
||||
]
|
||||
menu_jury = [
|
||||
|
@ -1648,6 +1648,9 @@ def confirm_dialog(
|
||||
template="sco_page.j2",
|
||||
):
|
||||
"""HTML confirmation dialog: submit (POST) to same page or dest_url if given."""
|
||||
from app.models import FormSemestre, Identite
|
||||
from app.views import ScoData
|
||||
|
||||
parameters = parameters or {}
|
||||
# dialog de confirmation simple
|
||||
parameters[target_variable] = 1
|
||||
@ -1687,9 +1690,21 @@ def confirm_dialog(
|
||||
)
|
||||
H.append("</form>")
|
||||
if help_msg:
|
||||
H.append('<p class="help">' + help_msg + "</p>")
|
||||
H.append('<div class="scobox help explanation">' + help_msg + "</div>")
|
||||
if add_headers:
|
||||
return render_template(template, content="\n".join(H))
|
||||
formsemestre = (
|
||||
FormSemestre.get_formsemestre(parameters["formsemestre_id"])
|
||||
if "formsemestre_id" in parameters
|
||||
else None
|
||||
)
|
||||
etud = (
|
||||
Identite.get_etud(parameters["etudid"]) if "etudid" in parameters else None
|
||||
)
|
||||
return render_template(
|
||||
template,
|
||||
content="\n".join(H),
|
||||
sco=ScoData(formsemestre=formsemestre, etud=etud),
|
||||
)
|
||||
return "\n".join(H)
|
||||
|
||||
|
||||
|
@ -1732,18 +1732,16 @@ h2.formsemestre,
|
||||
color: black;
|
||||
}
|
||||
|
||||
.formsemestre_page_title .eye,
|
||||
formsemestre_page_title .eye img {
|
||||
display: inline-block;
|
||||
margin-left: 12px;
|
||||
.formsemestre_page_title .infos span {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.formsemestre_page_title .infos span.lock,
|
||||
formsemestre_page_title .lock img {
|
||||
div.formsemestre_page_title .infos span.lock,
|
||||
div.formsemestre_page_title .infos span.eye,
|
||||
span.lock img,
|
||||
span.eye img {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
#formnotes .tf-explanation {
|
||||
@ -1854,10 +1852,6 @@ div.inscr_addremove_menu {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.formsemestre_page_title .infos span {
|
||||
padding-right: 25px;
|
||||
}
|
||||
|
||||
.formsemestre_page_title span.semtitle {
|
||||
font-size: 12pt;
|
||||
}
|
||||
|
@ -16,7 +16,55 @@ $(document).ready(function () {
|
||||
orderCellsTop: true, // cellules ligne 1 pour tri
|
||||
aaSorting: [], // Prevent initial sorting
|
||||
};
|
||||
$("table.semlist").DataTable(table_options);
|
||||
const table = new DataTable("table.semlist", table_options);
|
||||
// Sélection de semestres et mise à jour du menu associé
|
||||
table.on('click', 'tbody tr', function (e) {
|
||||
e.currentTarget.classList.toggle('selected');
|
||||
var nbSelectedRows = table.rows('.selected').count();
|
||||
if (nbSelectedRows == 0) {
|
||||
document.getElementById("formsemestres-select-infos").style.display = 'none';
|
||||
}
|
||||
else {
|
||||
document.getElementById("formsemestres-select-infos").style.display = 'inline';
|
||||
if (nbSelectedRows > 1) {
|
||||
document.querySelector("#formsemestres-select-menu li.sco_menu_title a").childNodes[1].nodeValue = nbSelectedRows + " semestres sélectionnés";
|
||||
} else {
|
||||
document.querySelector("#formsemestres-select-menu li.sco_menu_title a").childNodes[1].nodeValue = nbSelectedRows + " semestre sélectionné";
|
||||
}
|
||||
}
|
||||
});
|
||||
// Lien déselectionner
|
||||
document.getElementById("formsemestres-deselect").addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
table.rows('.selected').nodes().to$().removeClass('selected');
|
||||
document.getElementById("formsemestres-select-infos").style.display = 'none';
|
||||
});
|
||||
// Modification des liens de la section formsemestres-actions: ajout des formsemestres selectionnés:
|
||||
const links = document.querySelectorAll('#formsemestres-select-menu li.sco_menu_item a');
|
||||
links.forEach(link => {
|
||||
link.addEventListener('click', function(event) {
|
||||
// Prevent the default action (navigation)
|
||||
event.preventDefault();
|
||||
|
||||
// Build the query string with formsemestre_id parameters
|
||||
const selectedRows = document.querySelectorAll('tr.selected');
|
||||
const selectedFormsemestreIds = Array.from(selectedRows).map(row => row.dataset.formsemestre_id);
|
||||
const queryString = selectedFormsemestreIds
|
||||
.map(id => `formsemestre_ids=${encodeURIComponent(id)}`)
|
||||
.join('&');
|
||||
|
||||
// Construct the new URL
|
||||
const originalHref = link.getAttribute('href');
|
||||
const newHref = originalHref.includes('?')
|
||||
? `${originalHref}&${queryString}` // If there's already a query string
|
||||
: `${originalHref}?${queryString}`; // If no query string exists
|
||||
|
||||
// Navigate to the new URL
|
||||
window.location.href = newHref;
|
||||
});
|
||||
});
|
||||
|
||||
// Edition des codes Apo
|
||||
let table_editable = document.querySelector("table#semlist.apo_editable");
|
||||
if (table_editable) {
|
||||
let save_url = document.querySelector("table#semlist.apo_editable").dataset
|
||||
|
@ -8,7 +8,7 @@
|
||||
scodoc_dept=g.scodoc_dept, formsemestre_id=sco.formsemestre.id)
|
||||
}}">{{sco.formsemestre.titre}}</a>
|
||||
<a title="{{sco.formsemestre.etapes_apo_str()}}">
|
||||
{% if sco.formsemestre.semestre_id != -1 %}, {{sco.formsemestre.formation.get_cursus().SESSION_NAME}}
|
||||
{% if sco.formsemestre.semestre_id != -1 %} {{sco.formsemestre.formation.get_cursus().SESSION_NAME}}
|
||||
{{sco.formsemestre.semestre_id}}
|
||||
{% endif %}</a>
|
||||
{% if sco.formsemestre.modalite %} en {{sco.formsemestre.modalite}}{% endif %}
|
||||
@ -35,12 +35,16 @@
|
||||
</span>
|
||||
<span class="eye">
|
||||
{% if not scu.is_passerelle_disabled() %}
|
||||
<a href="{{url_for('notes.formsemestre_change_publication_bul', scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=sco.formsemestre.id)}}">
|
||||
{% if sco.formsemestre.bul_hide_xml %}
|
||||
<a href="{{url_for('notes.formsemestres_enable_publish', scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=sco.formsemestre.id, enable=True)}}">
|
||||
{{ scu.ICON_HIDDEN|safe}}
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{{url_for('notes.formsemestres_enable_publish', scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=sco.formsemestre.id, enable=False)}}">
|
||||
{{ scu.ICON_PUBLISHED|safe }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</a>
|
||||
{% endif %}
|
||||
|
@ -30,11 +30,15 @@ a.disabled-link {
|
||||
margin-left: 16px;
|
||||
color: purple;
|
||||
font-weight: normal;
|
||||
display: none;
|
||||
}
|
||||
#formsemestres-select-infos a {
|
||||
a#formsemestres-deselect {
|
||||
margin-left: 8px;
|
||||
text-decoration: underline;
|
||||
}
|
||||
#formsemestres-select-menu ul {
|
||||
display: inline-block;
|
||||
}
|
||||
div.semlist {
|
||||
padding-right: 8px;
|
||||
}
|
||||
@ -253,6 +257,12 @@ div.effectif {
|
||||
<a href="{{
|
||||
url_for('scolar.export_table_dept_formsemestres', scodoc_dept=g.scodoc_dept)
|
||||
}}">{{scu.ICON_XLS|safe}}</a>
|
||||
{% if menu_formsemestres_action %}
|
||||
<span id="formsemestres-select-infos">
|
||||
<span id="formsemestres-select-menu">{{menu_formsemestres_action|safe}}</span>
|
||||
<a id="formsemestres-deselect" href="#">tout désélectionner</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
</summary>
|
||||
<div class="semlist">
|
||||
{{ html_table_formsemestres|safe }}
|
||||
|
@ -904,48 +904,6 @@ sco_publish(
|
||||
methods=["GET", "POST"],
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/formsemestre_flip_lock", methods=["GET", "POST"])
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoView) # acces vérifié dans la vue
|
||||
@scodoc7func
|
||||
def formsemestre_flip_lock(formsemestre_id, dialog_confirmed=False):
|
||||
"Changement de l'état de verrouillage du semestre"
|
||||
formsemestre: FormSemestre = FormSemestre.get_or_404(formsemestre_id)
|
||||
dest_url = url_for(
|
||||
"notes.formsemestre_status",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=formsemestre.id,
|
||||
)
|
||||
if not formsemestre.est_chef_or_diretud():
|
||||
raise ScoPermissionDenied("opération non autorisée", dest_url=dest_url)
|
||||
if not dialog_confirmed:
|
||||
msg = "verrouillage" if formsemestre.etat else "déverrouillage"
|
||||
return scu.confirm_dialog(
|
||||
f"<h2>Confirmer le {msg} du semestre ?</h2>",
|
||||
help_msg="""Les notes d'un semestre verrouillé ne peuvent plus être modifiées.
|
||||
Un semestre verrouillé peut cependant être déverrouillé facilement à tout moment
|
||||
(par son responsable ou un administrateur).
|
||||
<br>
|
||||
Le programme d'une formation qui a un semestre verrouillé ne peut plus être modifié.
|
||||
""",
|
||||
dest_url="",
|
||||
cancel_url=dest_url,
|
||||
parameters={"formsemestre_id": formsemestre_id},
|
||||
)
|
||||
|
||||
formsemestre.flip_lock()
|
||||
db.session.commit()
|
||||
|
||||
return flask.redirect(dest_url)
|
||||
|
||||
|
||||
sco_publish(
|
||||
"/formsemestre_change_publication_bul",
|
||||
sco_formsemestre_edit.formsemestre_change_publication_bul,
|
||||
Permission.ScoView,
|
||||
methods=["GET", "POST"],
|
||||
)
|
||||
sco_publish(
|
||||
"/view_formsemestre_by_etape",
|
||||
sco_formsemestre.view_formsemestre_by_etape,
|
||||
@ -1942,7 +1900,7 @@ def _formsemestre_or_modimpl_import_notes(
|
||||
formsemestre_id=formsemestre.id,
|
||||
)
|
||||
)
|
||||
if formsemestre and not formsemestre.est_chef_or_diretud():
|
||||
if formsemestre and not formsemestre.can_be_edited_by():
|
||||
raise ScoPermissionDenied("opération non autorisée", dest_url=dest_url)
|
||||
if modimpl and not modimpl.can_edit_notes(current_user):
|
||||
raise ScoPermissionDenied("opération non autorisée", dest_url=dest_url)
|
||||
|
@ -33,6 +33,7 @@ import datetime
|
||||
import io
|
||||
import zipfile
|
||||
|
||||
import flask
|
||||
from flask import flash, redirect, render_template, url_for
|
||||
from flask import current_app, g, request
|
||||
import PIL
|
||||
@ -56,11 +57,8 @@ from app.models import (
|
||||
FORMSEMESTRE_DISPOSITIFS,
|
||||
ScoDocSiteConfig,
|
||||
)
|
||||
from app.scodoc import (
|
||||
sco_edt_cal,
|
||||
sco_groups_view,
|
||||
)
|
||||
from app.scodoc.sco_exceptions import ScoValueError
|
||||
from app.scodoc import sco_edt_cal, sco_groups_view
|
||||
from app.scodoc.sco_exceptions import ScoPermissionDenied, ScoValueError
|
||||
from app.scodoc.sco_permissions import Permission
|
||||
from app.scodoc import sco_utils as scu
|
||||
from app.views import notes_bp as bp
|
||||
@ -475,3 +473,163 @@ def formsemestres_import_from_description_sample():
|
||||
return scu.send_file(
|
||||
xls, "ImportSemestres", scu.XLSX_SUFFIX, mime=scu.XLSX_MIMETYPE
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/formsemestre_flip_lock/<int:formsemestre_id>", methods=["GET", "POST"])
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoView) # acces vérifié dans la vue
|
||||
def formsemestre_flip_lock(formsemestre_id: int):
|
||||
"Changement de l'état de verrouillage du semestre. Si GET, dialogue de confirmation."
|
||||
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
||||
dest_url = url_for(
|
||||
"notes.formsemestre_status",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=formsemestre.id,
|
||||
)
|
||||
if not formsemestre.can_be_edited_by(allow_locked=True):
|
||||
raise ScoPermissionDenied("opération non autorisée", dest_url=dest_url)
|
||||
if request.method == "GET":
|
||||
msg = "verrouillage" if formsemestre.etat else "déverrouillage"
|
||||
return scu.confirm_dialog(
|
||||
f"<h2>Confirmer le {msg} du semestre ?</h2>",
|
||||
help_msg="""Les notes d'un semestre verrouillé ne peuvent plus être modifiées.
|
||||
Un semestre verrouillé peut cependant être déverrouillé facilement à tout moment
|
||||
(par son responsable ou un administrateur).
|
||||
<br>
|
||||
Le programme d'une formation qui a un semestre verrouillé ne peut plus être modifié.
|
||||
""",
|
||||
dest_url="",
|
||||
cancel_url=dest_url,
|
||||
parameters={"formsemestre_id": formsemestre_id},
|
||||
)
|
||||
|
||||
formsemestre.flip_lock()
|
||||
db.session.commit()
|
||||
|
||||
return flask.redirect(dest_url)
|
||||
|
||||
|
||||
@bp.route("/formsemestres_unlock", defaults={"unlock": True}, methods=["GET", "POST"])
|
||||
@bp.route("/formsemestres_lock", defaults={"unlock": False}, methods=["GET", "POST"])
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoView) # acces vérifié dans la vue
|
||||
def formsemestres_lock(unlock: bool = False):
|
||||
"Lock formsemestres (or unlock if unlock is True). If GET, asks for confirmation."
|
||||
dest_url = url_for("scolar.index_html", scodoc_dept=g.scodoc_dept, showsemtable=1)
|
||||
try:
|
||||
formsemestre_ids = request.args.getlist("formsemestre_ids", type=int)
|
||||
except ValueError as exc:
|
||||
raise ScoValueError("argument formsemestre_ids invalide") from exc
|
||||
if not formsemestre_ids:
|
||||
raise ScoValueError("aucun semestre sélectionné")
|
||||
formsemestres = [
|
||||
FormSemestre.get_formsemestre(formsemestre_id)
|
||||
for formsemestre_id in formsemestre_ids
|
||||
]
|
||||
for formsemestre in formsemestres:
|
||||
if not formsemestre.can_be_edited_by(allow_locked=True):
|
||||
raise ScoPermissionDenied("opération non autorisée", dest_url=dest_url)
|
||||
if request.method == "GET":
|
||||
return scu.confirm_dialog(
|
||||
f"<h2>Confirmer le {'dé' if unlock else ''}verrouillage des semestres ?</h2>",
|
||||
help_msg=f"""
|
||||
<div>
|
||||
Les semestres suivants seront modifiés:
|
||||
<ul>
|
||||
<li>{'</li><li>'.join([ s.html_link_status() for s in formsemestres ])}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
Les notes d'un semestre verrouillé ne peuvent plus être modifiées.
|
||||
Un semestre verrouillé peut cependant être déverrouillé facilement à tout moment
|
||||
(par son responsable ou un administrateur).
|
||||
<br>
|
||||
Le programme d'une formation qui a un semestre verrouillé ne peut plus être modifié.
|
||||
</div>
|
||||
""",
|
||||
dest_url="",
|
||||
cancel_url=dest_url,
|
||||
parameters={"formsemestre_ids": formsemestre_ids},
|
||||
)
|
||||
|
||||
for formsemestre in formsemestres:
|
||||
formsemestre.etat = unlock
|
||||
db.session.add(formsemestre)
|
||||
db.session.commit()
|
||||
if unlock:
|
||||
flash(f"{len(formsemestres)} semestres déverrouillés")
|
||||
else:
|
||||
flash(f"{len(formsemestres)} semestres verrouillés")
|
||||
return redirect(dest_url)
|
||||
|
||||
|
||||
@bp.route(
|
||||
"/formsemestres_enable_publish", defaults={"enable": True}, methods=["GET", "POST"]
|
||||
)
|
||||
@bp.route(
|
||||
"/formsemestres_disable_publish",
|
||||
defaults={"enable": False},
|
||||
methods=["GET", "POST"],
|
||||
)
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoView) # acces vérifié dans la vue
|
||||
def formsemestres_enable_publish(enable: bool = False):
|
||||
"""Change état publication bulletins sur portail.
|
||||
Peut affecter un (formsemestre_id) ou plusieurs (formsemestre_ids) semestres.
|
||||
"""
|
||||
arg_name = (
|
||||
"formsemestre_ids" if "formsemestre_ids" in request.args else "formsemestre_id"
|
||||
)
|
||||
try:
|
||||
formsemestre_ids = request.args.getlist(arg_name, type=int)
|
||||
except ValueError as exc:
|
||||
raise ScoValueError("argument formsemestre_ids invalide") from exc
|
||||
if not formsemestre_ids:
|
||||
raise ScoValueError("aucun semestre sélectionné")
|
||||
formsemestres = [
|
||||
FormSemestre.get_formsemestre(formsemestre_id)
|
||||
for formsemestre_id in formsemestre_ids
|
||||
]
|
||||
dest_url = (
|
||||
url_for("scolar.index_html", scodoc_dept=g.scodoc_dept, showsemtable=1)
|
||||
if "formsemestre_ids" in request.args
|
||||
else url_for(
|
||||
"notes.formsemestre_status",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=formsemestres[0].id,
|
||||
)
|
||||
)
|
||||
for formsemestre in formsemestres:
|
||||
if not formsemestre.can_be_edited_by(allow_locked=True):
|
||||
raise ScoPermissionDenied("opération non autorisée", dest_url=dest_url)
|
||||
|
||||
if request.method == "GET":
|
||||
return scu.confirm_dialog(
|
||||
f"<h2>Confirmer la {'' if enable else 'non'} publication des bulletins ?</h2>",
|
||||
help_msg="""Il est parfois utile de désactiver la diffusion des bulletins sur
|
||||
la passerelle, par exemple pendant la tenue d'un jury ou avant harmonisation
|
||||
des notes.
|
||||
<br>
|
||||
Ce réglage n'a d'effet que si votre établissement a interfacé ScoDoc avec
|
||||
une passerelle étudiant.
|
||||
""",
|
||||
dest_url="",
|
||||
cancel_url=dest_url,
|
||||
parameters={"formsemestre_ids": formsemestre_ids},
|
||||
)
|
||||
|
||||
for formsemestre in formsemestres:
|
||||
formsemestre.bul_hide_xml = not enable
|
||||
db.session.add(formsemestre)
|
||||
log(
|
||||
f"formsemestres_enable_publish: {formsemestre} -> {formsemestre.bul_hide_xml}"
|
||||
)
|
||||
|
||||
db.session.commit()
|
||||
s = "s" if len(formsemestres) > 1 else ""
|
||||
if enable:
|
||||
flash(f"{len(formsemestres)} semestre{s} publié{s}")
|
||||
else:
|
||||
flash(f"{len(formsemestres)} semestre{s} non publié{s}")
|
||||
|
||||
return flask.redirect(dest_url)
|
||||
|
Loading…
x
Reference in New Issue
Block a user