From b5138d3dfe39486f8aa5150d3c52409ebd97ad1f Mon Sep 17 00:00:00 2001
From: Emmanuel Viennet <emmanuel.viennet@gmail.com>
Date: Sat, 25 Jun 2022 14:18:34 +0200
Subject: [PATCH] =?UTF-8?q?Suppression=20d=C3=A9cisions=20de=20jury=20BUT?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 app/but/jury_but.py               | 44 +++++++++++++++++++++++++++++++
 app/scodoc/sco_pvjury.py          |  4 +--
 app/templates/confirm_dialog.html | 22 ++++++++++++++++
 app/views/notes.py                | 43 ++++++++++++++++++++++++++++++
 4 files changed, 110 insertions(+), 3 deletions(-)
 create mode 100644 app/templates/confirm_dialog.html

diff --git a/app/but/jury_but.py b/app/but/jury_but.py
index fb255f0d2..840933c08 100644
--- a/app/but/jury_but.py
+++ b/app/but/jury_but.py
@@ -571,6 +571,32 @@ class DecisionsProposeesAnnee(DecisionsProposees):
                 # s'il n'y a pas de codee, efface
                 dec.record(dec.codes[0])
 
+    def erase(self):
+        """Efface les décisions de jury de cet étudiant
+        pour cette année: décisions d'UE, de RCUE, d'année,
+        et autorisations d'inscription émises.
+        """
+        for dec_ue in self.decisions_ues.values():
+            dec_ue.erase()
+        for dec_rcue in self.decisions_rcue_by_niveau.values():
+            dec_rcue.erase()
+        if self.formsemestre_impair:
+            ScolarAutorisationInscription.delete_autorisation_etud(
+                self.etud.id, self.formsemestre_impair.id
+            )
+        if self.formsemestre_pair:
+            ScolarAutorisationInscription.delete_autorisation_etud(
+                self.etud.id, self.formsemestre_pair.id
+            )
+        validations = ApcValidationAnnee.query.filter_by(
+            etudid=self.etud.id,
+            formsemestre_id=self.formsemestre_impair.id,
+            ordre=self.annee_but,
+        )
+        for validation in validations:
+            db.session.delete(validation)
+        db.session.flush()
+
 
 class DecisionsProposeesRCUE(DecisionsProposees):
     """Liste des codes de décisions que l'on peut proposer pour
@@ -637,6 +663,14 @@ class DecisionsProposeesRCUE(DecisionsProposees):
             db.session.add(self.validation)
         self.recorded = True
 
+    def erase(self):
+        """Efface la décision de jury de cet étudiant pour cet RCUE"""
+        # par prudence, on requete toutes les validations, en cas de doublons
+        validations = self.rcue.query_validations()
+        for validation in validations:
+            db.session.delete(validation)
+        db.session.flush()
+
 
 class DecisionsProposeesUE(DecisionsProposees):
     """Décisions de jury sur une UE du BUT
@@ -743,6 +777,16 @@ class DecisionsProposeesUE(DecisionsProposees):
             db.session.add(self.validation)
         self.recorded = True
 
+    def erase(self):
+        """Efface la décision de jury de cet étudiant pour cette UE"""
+        # par prudence, on requete toutes les validations, en cas de doublons
+        validations = ScolarFormSemestreValidation.query.filter_by(
+            etudid=self.etud.id, formsemestre_id=self.formsemestre.id, ue_id=self.ue.id
+        )
+        for validation in validations:
+            db.session.delete(validation)
+        db.session.flush()
+
 
 class BUTCursusEtud:  # WIP TODO
     """Validation du cursus d'un étudiant"""
diff --git a/app/scodoc/sco_pvjury.py b/app/scodoc/sco_pvjury.py
index cfa7bae61..7ddc0aa1d 100644
--- a/app/scodoc/sco_pvjury.py
+++ b/app/scodoc/sco_pvjury.py
@@ -492,9 +492,7 @@ def pvjury_table(
 
 
 def formsemestre_pvjury(formsemestre_id, format="html", publish=True):
-    """Page récapitulant les décisions de jury
-    dpv: result of dict_pvjury
-    """
+    """Page récapitulant les décisions de jury"""
     footer = html_sco_header.sco_footer()
 
     dpv = dict_pvjury(formsemestre_id, with_prev=True)
diff --git a/app/templates/confirm_dialog.html b/app/templates/confirm_dialog.html
new file mode 100644
index 000000000..8067f6c74
--- /dev/null
+++ b/app/templates/confirm_dialog.html
@@ -0,0 +1,22 @@
+{# -*- mode: jinja-html -*- #}
+{% extends 'base.html' %}
+{% import 'bootstrap/wtf.html' as wtf %}
+
+{% block app_content %}
+
+<h2>{{ title }}</h2>
+
+<div style="margin-top: 16px;">
+    {{ explanation }}
+</div>
+<div style="margin-top: 16px;">
+    <form method="post">
+        <input type="submit" value="OK" />
+        {% if cancel_url %}
+        <input type="button" value="Annuler" style="margin-left: 16px;"
+            onClick="document.location='{{ cancel_url }}';" />
+        {% endif %}
+    </form>
+</div>
+
+{% endblock %}
\ No newline at end of file
diff --git a/app/views/notes.py b/app/views/notes.py
index 97aa43baf..005e7963a 100644
--- a/app/views/notes.py
+++ b/app/views/notes.py
@@ -2262,6 +2262,13 @@ def formsemestre_validation_but(formsemestre_id: int, etudid: int):
                 etudid=etudid,
             )
         )
+    if deca.code_valide:
+        erase_span = f"""<a href="{
+            url_for("notes.formsemestre_jury_but_erase", 
+            scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, 
+            etudid=etudid)}" class="stdlink">effacer décisions</a>"""
+    else:
+        erase_span = ""
     H.append(
         f"""
     <div>
@@ -2279,6 +2286,7 @@ def formsemestre_validation_but(formsemestre_id: int, etudid: int):
                 disabled=True, klass="manual")
         }
         <span>({'non ' if deca.code_valide is None else ''}enregistrée)</span>
+        <span>{erase_span}</span>
         </div>
         <span class="but_explanation">{deca.explanation}</span>
     </div>
@@ -2630,6 +2638,41 @@ def formsemestre_jury_but_recap(formsemestre_id: int, selected_etudid: int = Non
     )
 
 
+@bp.route(
+    "/formsemestre_jury_but_erase/<int:formsemestre_id>/<int:etudid>",
+    methods=["GET", "POST"],
+)
+@scodoc
+@permission_required(Permission.ScoView)
+def formsemestre_jury_but_erase(formsemestre_id: int, etudid: int = None):
+    """Supprime la décision de jury BUT pour cette année"""
+    formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
+    if not formsemestre.formation.is_apc():
+        raise ScoValueError("semestre non BUT")
+    etud: Identite = Identite.query.get_or_404(etudid)
+    if not sco_permissions_check.can_validate_sem(formsemestre_id):
+        raise ScoValueError("opération non autorisée")
+    dest_url = url_for(
+        "notes.formsemestre_validation_but",
+        scodoc_dept=g.scodoc_dept,
+        formsemestre_id=formsemestre_id,
+        etudid=etudid,
+    )
+    if request.method == "POST":
+        deca = jury_but.DecisionsProposeesAnnee(etud, formsemestre)
+        deca.erase()
+        db.session.commit()
+        flash("décisions de jury effacées")
+        return redirect(dest_url)
+
+    return render_template(
+        "confirm_dialog.html",
+        title=f"Effacer les validations de jury de {etud.nomprenom} ?",
+        explanation="""Les validations de toutes les UE, RCUE (compétences) et année seront effacées.""",
+        cancel_url=dest_url,
+    )
+
+
 sco_publish(
     "/formsemestre_lettres_individuelles",
     sco_pvjury.formsemestre_lettres_individuelles,
-- 
GitLab