diff --git a/app/but/forms/refcomp_forms.py b/app/but/forms/refcomp_forms.py index dd7d557d4..5727454b1 100644 --- a/app/but/forms/refcomp_forms.py +++ b/app/but/forms/refcomp_forms.py @@ -27,8 +27,22 @@ class RefCompLoadForm(FlaskForm): referentiel_standard = SelectField( "Choisir un référentiel de compétences officiel BUT" ) + submit = SubmitField("Valider") + cancel = SubmitField("Annuler") + + def validate(self, extra_validators=None) -> bool: + if not super().validate(extra_validators): + return False + if self.referentiel_standard.data == "0": + self.referentiel_standard.errors.append("Choisir soit un référentiel") + return False + return True + + +class RefCompUploadForm(FlaskForm): + "Upload d'un référentiel" upload = FileField( - label="... ou bien sélectionner un fichier XML au format Orébut (réservé aux développeurs !)", + label="Sélectionner un fichier XML au format Orébut", validators=[ FileAllowed( [ @@ -41,13 +55,11 @@ class RefCompLoadForm(FlaskForm): submit = SubmitField("Valider") cancel = SubmitField("Annuler") - def validate(self, extra_validators=None): + def validate(self, extra_validators=None) -> bool: if not super().validate(extra_validators): return False - if (self.referentiel_standard.data == "0") == (not self.upload.data): - self.referentiel_standard.errors.append( - "Choisir soit un référentiel, soit un fichier xml" - ) + if not self.upload.data: + self.upload.errors.append("Choisir un fichier XML") return False return True diff --git a/app/templates/but/refcomp_load.j2 b/app/templates/but/refcomp_load.j2 index b1e2ea567..9a9faf115 100644 --- a/app/templates/but/refcomp_load.j2 +++ b/app/templates/but/refcomp_load.j2 @@ -3,7 +3,19 @@ {% import 'wtf.j2' as wtf %} {% block app_content %} -

Charger un référentiel de compétences

+

Charger un référentiel de compétences de BUT (officiel)

+ +
+ +

Les référentiels de compétence de BUT font partie du Programme National (PN) +de BUT et ne sont pas modifiables. ScoDoc est livré avec une copie des +référentiels officiels issus de l'application Orébut.

+ +

Il est aussi possible de définir un référentiel de compétences ad-hoc pour +des formations par compétences non BUT (mais ayant le même principe de +fonctionnement, avec une architecture en blocs de compétences et RCUEs).

+ +
@@ -13,14 +25,21 @@
-
diff --git a/app/templates/but/refcomp_upload_new.j2 b/app/templates/but/refcomp_upload_new.j2 new file mode 100644 index 000000000..7404f8338 --- /dev/null +++ b/app/templates/but/refcomp_upload_new.j2 @@ -0,0 +1,59 @@ +{# -*- mode: jinja-html -*- #} +{% extends "sco_page_dept.j2" %} +{% import 'wtf.j2' as wtf %} + +{% block app_content %} +

Charger un référentiel de compétences externe (non BUT)

+ +
+ +

Cette page permet de charger votre propre référentiel de compétence. +Le fichier doit être au format XML, et doit respecter le schéma de référentiel +de compétences "Orébut", qui n'est pas documenté dans ScoDoc (voir le logiciel Orébut). +

+ +

Cette approche ne fonctionne que si votre formation suit les principes architecturaux +du BUT (blocs de compétences, RCUEs, ressources, SAÉs, etc.). +

+ + +
Attention : ne pas utiliser cette page pour les référentiels de BUT. +Pour le BUT utiliser impérativement les référentiels officiels, qui sont +distribués avec ScoDoc : + Voir cette page. +
+ +
+ +
+
+ {{ wtf.quick_form(form) }} +
+
+ + + +{% endblock %} diff --git a/app/views/refcomp.py b/app/views/refcomp.py index bf4bd9f4a..e263afba7 100644 --- a/app/views/refcomp.py +++ b/app/views/refcomp.py @@ -26,6 +26,7 @@ from app.but.forms.refcomp_forms import ( FormationChangeRefCompForm, FormationRefCompForm, RefCompLoadForm, + RefCompUploadForm, ) from app.scodoc.gen_tables import GenTable from app.scodoc import sco_utils as scu @@ -207,10 +208,9 @@ def refcomp_desassoc_formation(formation_id: int): @permission_required(Permission.EditFormation) def refcomp_load(formation_id=None): """Formulaire association ref. compétence""" - if formation_id is not None: - formation = Formation.query.get_or_404(formation_id) - else: - formation = None + formation = ( + Formation.get_formation(formation_id) if formation_id is not None else None + ) refs_distrib_files = sorted( list( ( @@ -253,34 +253,17 @@ def refcomp_load(formation_id=None): for r in refs_distrib_dict ] if form.validate_on_submit(): - if form.upload.data: - f = form.upload.data - filename = secure_filename(f.filename) - elif form.referentiel_standard.data: + if form.referentiel_standard.data: try: filename = refs_distrib_dict[int(form.referentiel_standard.data)][ "filename" ] except (ValueError, IndexError) as exc: raise ScoValueError("choix invalide") from exc - f = open(filename, encoding="utf-8") else: raise ScoValueError("choix invalide") - try: - xml_data = f.read() - _ = orebut_import_refcomp( - xml_data, dept_id=g.scodoc_dept_id, orig_filename=Path(filename).name - ) - except TypeError as exc: - raise ScoFormatError( - f"fichier XML Orébut invalide (1): {exc.args}" - ) from exc - # peut aussi lever ScoFormatError - - flash( - Markup(f"Référentiel {Path(filename).name} chargé."), - category="info", - ) + with open(filename, encoding="utf-8") as stream: + _upload_ref_xml(filename, stream) return redirect( url_for( @@ -297,6 +280,65 @@ def refcomp_load(formation_id=None): ) +def _upload_ref_xml(filename: str, stream): + """ + peut lever ScoFormatError. + """ + try: + xml_data = stream.read() + _ = orebut_import_refcomp( + xml_data, dept_id=g.scodoc_dept_id, orig_filename=Path(filename).name + ) + except TypeError as exc: + raise ScoFormatError(f"fichier XML Orébut invalide (1): {exc.args}") from exc + # + flash( + Markup(f"Référentiel {Path(filename).name} chargé."), + category="info", + ) + + +@bp.route( + "/referentiel/comp/upload_new", + defaults={"formation_id": None}, + methods=["GET", "POST"], +) +@bp.route("/referentiel/comp/upload_new/", methods=["GET", "POST"]) +@scodoc +@permission_required(Permission.EditFormation) +def refcomp_upload_new(formation_id=None): + """Formulaire chargement fichier externe ref. compétence""" + formation = ( + Formation.get_formation(formation_id) if formation_id is not None else None + ) + form = RefCompUploadForm() + if form.validate_on_submit(): + if form.upload.data: + f = form.upload.data + filename = secure_filename(f.filename) + _upload_ref_xml(filename, f) + return redirect( + url_for( + "notes.refcomp_table", + scodoc_dept=g.scodoc_dept, + ) + ) + if form.cancel.data: # cancel button + return redirect( + url_for( + "notes.refcomp_load", + scodoc_dept=g.scodoc_dept, + ) + ) + + return render_template( + "but/refcomp_upload_new.j2", + form=form, + formation=formation, + title="Chargement réf. compétences externe", + ) + + @bp.route("/formation//change_refcomp", methods=["GET", "POST"]) @scodoc @permission_required(Permission.EditFormation)