2021-11-12 22:17:46 +01:00
|
|
|
# -*- mode: python -*-
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
##############################################################################
|
|
|
|
#
|
|
|
|
# ScoDoc
|
|
|
|
#
|
2023-12-31 23:04:06 +01:00
|
|
|
# Copyright (c) 1999 - 2024 Emmanuel Viennet. All rights reserved.
|
2021-11-12 22:17:46 +01:00
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program; if not, write to the Free Software
|
|
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
#
|
|
|
|
# Emmanuel Viennet emmanuel.viennet@viennet.net
|
|
|
|
#
|
|
|
|
##############################################################################
|
|
|
|
|
|
|
|
"""
|
|
|
|
PN / Edition des coefs
|
|
|
|
|
|
|
|
Emmanuel Viennet, 2021
|
|
|
|
"""
|
|
|
|
|
|
|
|
from flask import url_for
|
2023-03-26 10:08:50 +02:00
|
|
|
from flask import g, request
|
2023-04-06 16:10:32 +02:00
|
|
|
from flask_json import as_json
|
2021-11-12 22:17:46 +01:00
|
|
|
from flask_login import current_user
|
2023-04-06 16:10:32 +02:00
|
|
|
from flask.templating import render_template
|
2023-02-12 13:36:47 +01:00
|
|
|
from app.scodoc.codes_cursus import UE_SPORT
|
2021-11-12 22:17:46 +01:00
|
|
|
|
|
|
|
|
2023-03-26 10:08:50 +02:00
|
|
|
from app import db, models
|
2021-11-12 22:17:46 +01:00
|
|
|
|
|
|
|
from app.comp import moy_ue
|
|
|
|
from app.decorators import scodoc, permission_required
|
2023-03-26 10:08:50 +02:00
|
|
|
from app.models import ApcParcours, Formation, Module
|
2021-11-12 22:17:46 +01:00
|
|
|
from app.views import notes_bp as bp
|
|
|
|
|
|
|
|
from app.scodoc import html_sco_header
|
2023-03-26 10:08:50 +02:00
|
|
|
from app.scodoc import sco_utils as scu
|
2021-11-12 22:17:46 +01:00
|
|
|
from app.scodoc.sco_permissions import Permission
|
|
|
|
|
|
|
|
|
2021-11-18 22:46:18 +01:00
|
|
|
@bp.route("/table_modules_ue_coefs/<int:formation_id>")
|
2022-02-15 13:15:56 +01:00
|
|
|
@bp.route("/table_modules_ue_coefs/<int:formation_id>/<int:semestre_idx>")
|
2022-10-31 09:38:39 +01:00
|
|
|
@bp.route(
|
|
|
|
"/table_modules_ue_coefs/<int:formation_id>/<int:semestre_idx>/<int:parcours_id>"
|
|
|
|
)
|
2021-11-12 22:17:46 +01:00
|
|
|
@scodoc
|
|
|
|
@permission_required(Permission.ScoView)
|
2023-04-06 16:10:32 +02:00
|
|
|
@as_json
|
2022-10-31 09:38:39 +01:00
|
|
|
def table_modules_ue_coefs(formation_id, semestre_idx=None, parcours_id: int = None):
|
|
|
|
"""Description JSON de la table des coefs modules/UE dans une formation
|
|
|
|
|
|
|
|
Si le parcours est indiqué et que la formation a un référentiel de compétence,
|
|
|
|
restreint l'affichage aux UE et modules de ce parcours.
|
|
|
|
"""
|
|
|
|
formation: Formation = models.Formation.query.get_or_404(formation_id) # check
|
2021-11-18 22:46:18 +01:00
|
|
|
if semestre_idx == "":
|
|
|
|
semestre_idx = None
|
2022-10-31 09:38:39 +01:00
|
|
|
if parcours_id == "":
|
|
|
|
parcours_id = None
|
|
|
|
if parcours_id is not None and formation.referentiel_competence is not None:
|
|
|
|
parcour: ApcParcours = ApcParcours.query.get_or_404(parcours_id)
|
|
|
|
else:
|
|
|
|
parcour = None
|
2021-11-28 16:31:33 +01:00
|
|
|
df, ues, modules = moy_ue.df_load_module_coefs(formation_id, semestre_idx)
|
2022-10-31 09:38:39 +01:00
|
|
|
# Filtrage par parcours
|
|
|
|
if parcour is not None:
|
2022-10-31 09:46:30 +01:00
|
|
|
ues = [
|
|
|
|
ue
|
|
|
|
for ue in ues
|
2023-04-03 17:46:31 +02:00
|
|
|
if (parcours_id in (p.id for p in ue.parcours)) or (not ue.parcours)
|
2022-10-31 09:46:30 +01:00
|
|
|
]
|
2022-10-31 09:38:39 +01:00
|
|
|
modules = [
|
2022-10-31 09:46:30 +01:00
|
|
|
mod
|
|
|
|
for mod in modules
|
2023-05-14 15:00:39 +02:00
|
|
|
if ((parcours_id in (p.id for p in mod.parcours)) or (mod.parcours is None))
|
|
|
|
and mod.module_type in (scu.ModuleType.RESSOURCE, scu.ModuleType.SAE)
|
|
|
|
]
|
|
|
|
else: # ne montre que les ressources et SAE (pas le bonus...)
|
|
|
|
modules = [
|
|
|
|
mod
|
|
|
|
for mod in modules
|
|
|
|
if mod.module_type in (scu.ModuleType.RESSOURCE, scu.ModuleType.SAE)
|
2022-10-31 09:38:39 +01:00
|
|
|
]
|
2021-11-12 22:17:46 +01:00
|
|
|
# Titre des modules, en ligne
|
|
|
|
col_titres_mods = [
|
|
|
|
{
|
|
|
|
"x": 1, # 1ere colonne
|
|
|
|
"y": row,
|
|
|
|
# "nbX": 1,
|
|
|
|
# "nbY": 1,
|
2021-11-18 22:46:18 +01:00
|
|
|
"style": "title_mod title_" + scu.ModuleType(mod.module_type).name,
|
2021-11-12 22:17:46 +01:00
|
|
|
"data": mod.code,
|
|
|
|
"title": mod.titre,
|
|
|
|
}
|
|
|
|
for (row, mod) in enumerate(modules, start=2)
|
|
|
|
]
|
|
|
|
row_titres_ue = [
|
|
|
|
{
|
|
|
|
"x": col,
|
|
|
|
"y": 1, # 1ere ligne
|
|
|
|
"style": "title_ue",
|
|
|
|
"data": ue.acronyme,
|
|
|
|
"title": ue.titre,
|
|
|
|
}
|
|
|
|
for (col, ue) in enumerate(ues, start=2)
|
|
|
|
]
|
|
|
|
# Les champs de saisie
|
|
|
|
cells = []
|
2023-04-06 16:10:32 +02:00
|
|
|
for row, mod in enumerate(modules, start=2):
|
2021-11-18 22:46:18 +01:00
|
|
|
style = "champs champs_" + scu.ModuleType(mod.module_type).name
|
2023-04-03 17:46:31 +02:00
|
|
|
mod_parcours_ids = {p.id for p in mod.parcours}
|
2023-04-06 16:10:32 +02:00
|
|
|
for col, ue in enumerate(ues, start=2):
|
2022-10-31 10:22:25 +01:00
|
|
|
# met en gris les coefs qui devraient être nuls
|
|
|
|
# car le module n'est pas dans le parcours de l'UE:
|
|
|
|
if (
|
2023-05-14 15:00:39 +02:00
|
|
|
mod.parcours
|
|
|
|
and ue.parcours
|
2023-04-03 17:46:31 +02:00
|
|
|
and not {p.id for p in ue.parcours}.intersection(mod_parcours_ids)
|
2022-10-31 10:22:25 +01:00
|
|
|
):
|
2022-10-31 23:06:56 +01:00
|
|
|
cell_style = style + " champs_coef_hors_parcours"
|
2022-10-31 10:22:25 +01:00
|
|
|
else:
|
|
|
|
cell_style = style
|
2021-11-12 22:17:46 +01:00
|
|
|
cells.append(
|
|
|
|
{
|
|
|
|
"x": col,
|
|
|
|
"y": row,
|
2022-10-31 10:22:25 +01:00
|
|
|
"style": cell_style,
|
2021-11-17 10:28:51 +01:00
|
|
|
"data": df[mod.id][ue.id] or "",
|
2022-03-19 14:22:52 +01:00
|
|
|
"editable": mod.ue.type != UE_SPORT,
|
2021-11-12 22:17:46 +01:00
|
|
|
"module_id": mod.id,
|
|
|
|
"ue_id": ue.id,
|
|
|
|
}
|
|
|
|
)
|
2023-04-06 16:10:32 +02:00
|
|
|
return col_titres_mods + row_titres_ue + cells
|
2021-11-12 22:17:46 +01:00
|
|
|
|
|
|
|
|
|
|
|
@bp.route("/set_module_ue_coef", methods=["POST"])
|
|
|
|
@scodoc
|
2023-09-29 21:17:31 +02:00
|
|
|
@permission_required(Permission.EditFormation)
|
2021-11-12 22:17:46 +01:00
|
|
|
def set_module_ue_coef():
|
|
|
|
"""Set coef from module to UE"""
|
|
|
|
try:
|
|
|
|
module_id = int(request.form["module_id"])
|
|
|
|
except ValueError:
|
2022-08-07 19:56:25 +02:00
|
|
|
return scu.json_error(404, "invalid module_id")
|
2021-11-12 22:17:46 +01:00
|
|
|
try:
|
|
|
|
ue_id = int(request.form["ue_id"])
|
|
|
|
except ValueError:
|
2022-08-07 19:56:25 +02:00
|
|
|
return scu.json_error(404, "invalid ue_id")
|
2021-11-12 22:17:46 +01:00
|
|
|
try:
|
|
|
|
coef = float(request.form["coef"].replace(",", "."))
|
|
|
|
except ValueError:
|
2022-08-07 19:56:25 +02:00
|
|
|
return scu.json_error(404, "invalid coef")
|
2023-07-11 06:57:38 +02:00
|
|
|
module: Module = db.session.get(Module, module_id)
|
2021-11-12 22:17:46 +01:00
|
|
|
if module is None:
|
2022-08-07 19:56:25 +02:00
|
|
|
return scu.json_error(404, f"module not found ({module_id})")
|
2023-07-11 06:57:38 +02:00
|
|
|
ue = db.session.get(models.UniteEns, ue_id)
|
2021-11-12 22:17:46 +01:00
|
|
|
if not ue:
|
2022-08-07 19:56:25 +02:00
|
|
|
return scu.json_error(404, f"UE not found ({ue_id})")
|
2021-11-12 22:17:46 +01:00
|
|
|
module.set_ue_coef(ue, coef)
|
|
|
|
db.session.commit()
|
2021-12-16 16:27:35 +01:00
|
|
|
module.formation.invalidate_cached_sems()
|
|
|
|
|
2022-08-07 19:56:25 +02:00
|
|
|
return scu.json_ok_response(201)
|
2021-11-12 22:17:46 +01:00
|
|
|
|
|
|
|
|
2021-11-18 11:29:38 +01:00
|
|
|
@bp.route("/edit_modules_ue_coefs")
|
2021-11-12 22:17:46 +01:00
|
|
|
@scodoc
|
2022-03-15 23:09:41 +01:00
|
|
|
@permission_required(Permission.ScoView)
|
2021-11-18 22:46:18 +01:00
|
|
|
def edit_modules_ue_coefs():
|
2021-11-12 22:17:46 +01:00
|
|
|
"""Formulaire édition grille coefs EU/modules"""
|
2021-11-18 11:29:38 +01:00
|
|
|
formation_id = int(request.args["formation_id"])
|
2021-11-18 22:46:18 +01:00
|
|
|
semestre_idx = request.args.get("semestre_idx", "")
|
2022-10-31 09:38:39 +01:00
|
|
|
parcours_id = request.args.get("parcours_id")
|
|
|
|
if parcours_id == "":
|
|
|
|
parcours_id = None
|
|
|
|
if parcours_id is not None:
|
|
|
|
parcours_id = int(parcours_id)
|
2021-11-18 22:46:18 +01:00
|
|
|
if len(semestre_idx.strip()) > 0:
|
|
|
|
semestre_idx = int(semestre_idx)
|
|
|
|
else:
|
|
|
|
semestre_idx = None
|
2021-11-12 22:17:46 +01:00
|
|
|
formation = models.Formation.query.filter_by(
|
|
|
|
formation_id=formation_id
|
|
|
|
).first_or_404()
|
2023-02-17 22:07:03 +01:00
|
|
|
locked = formation.has_locked_sems(semestre_idx)
|
2021-11-18 00:24:56 +01:00
|
|
|
if locked:
|
|
|
|
lockicon = scu.icontag("lock32_img", title="verrouillé")
|
|
|
|
else:
|
|
|
|
lockicon = ""
|
|
|
|
H = [
|
|
|
|
html_sco_header.sco_header(
|
|
|
|
cssstyles=["css/table_editor.css"],
|
|
|
|
javascripts=[
|
|
|
|
"js/table_editor.js",
|
|
|
|
],
|
|
|
|
page_title=f"Coefs programme {formation.acronyme}",
|
2021-11-12 22:17:46 +01:00
|
|
|
),
|
2021-12-10 15:51:43 +01:00
|
|
|
f"""<h2>Formation {formation.titre} ({formation.acronyme})
|
2021-11-18 00:24:56 +01:00
|
|
|
[version {formation.version}] code {formation.formation_code}
|
|
|
|
{lockicon}
|
|
|
|
</h2>
|
|
|
|
""",
|
2023-12-31 23:04:06 +01:00
|
|
|
"""<span class="warning">Formation verrouilée car un ou plusieurs
|
2023-02-22 22:54:33 +01:00
|
|
|
semestres verrouillés l'utilisent.
|
|
|
|
</span>"""
|
|
|
|
if locked
|
|
|
|
else "",
|
2021-11-18 00:24:56 +01:00
|
|
|
render_template(
|
2023-01-25 15:17:52 +01:00
|
|
|
"pn/form_modules_ue_coefs.j2",
|
2021-11-18 00:24:56 +01:00
|
|
|
formation=formation,
|
|
|
|
data_source=url_for(
|
|
|
|
"notes.table_modules_ue_coefs",
|
|
|
|
scodoc_dept=g.scodoc_dept,
|
|
|
|
formation_id=formation_id,
|
2021-11-18 11:29:38 +01:00
|
|
|
semestre_idx=semestre_idx,
|
2022-10-31 09:38:39 +01:00
|
|
|
parcours_id=parcours_id,
|
2021-11-18 00:24:56 +01:00
|
|
|
),
|
|
|
|
data_save=url_for(
|
|
|
|
"notes.set_module_ue_coef",
|
|
|
|
scodoc_dept=g.scodoc_dept,
|
|
|
|
),
|
2023-02-06 10:13:01 +01:00
|
|
|
read_only=locked
|
2023-09-29 21:17:31 +02:00
|
|
|
or not current_user.has_permission(Permission.EditFormation),
|
2021-11-18 11:29:38 +01:00
|
|
|
semestre_idx=semestre_idx,
|
2023-02-12 13:36:47 +01:00
|
|
|
semestre_ids=range(1, formation.get_cursus().NB_SEM + 1),
|
2022-10-31 09:38:39 +01:00
|
|
|
parcours_id=parcours_id,
|
2021-11-12 22:17:46 +01:00
|
|
|
),
|
2021-11-18 00:24:56 +01:00
|
|
|
html_sco_header.sco_footer(),
|
|
|
|
]
|
|
|
|
|
|
|
|
return "\n".join(H)
|