From f39d8223c51902abb5aa2057e4d0c71bbb30a253 Mon Sep 17 00:00:00 2001
From: benjamin <benjamin@le-filament.com>
Date: Thu, 6 Feb 2025 18:57:05 +0100
Subject: [PATCH] [UPD] add satisfaction survey configuration & update report
 xls & add checks for survey subscription

---
 __init__.py                   |   2 +-
 __manifest__.py               |   2 +
 controllers/survey.py         |  28 +++++++
 data/message_type.xml         |   8 ++
 models/res_company.py         |   7 ++
 models/res_config_settings.py |   4 +
 models/survey_user_input.py   |   4 +
 models/training.py            |  11 ++-
 report/__init__.py            |   1 +
 report/report_survey_xlsx.py  |  14 ++++
 security/survey_security.xml  |  12 ++-
 templates/survey_message.xml  |  23 ++++++
 views/res_company.xml         |   3 +
 views/res_config_settings.xml |   9 +++
 views/survey_user_input.xml   |   3 +-
 views/training.xml            | 146 +++++++++++++++++++---------------
 16 files changed, 202 insertions(+), 75 deletions(-)
 create mode 100644 data/message_type.xml
 create mode 100644 report/__init__.py
 create mode 100644 report/report_survey_xlsx.py
 create mode 100644 templates/survey_message.xml

diff --git a/__init__.py b/__init__.py
index 72d3ea6..c0771f7 100644
--- a/__init__.py
+++ b/__init__.py
@@ -1 +1 @@
-from . import controllers, models
+from . import controllers, models, report
diff --git a/__manifest__.py b/__manifest__.py
index 1894c9c..27cd6d3 100644
--- a/__manifest__.py
+++ b/__manifest__.py
@@ -18,10 +18,12 @@
         "data/mail_end_training.xml",
         "data/mail_subscription.xml",
         "data/mail_training_confirmation.xml",
+        "data/message_type.xml",
         # templates
         "templates/survey_closed.xml",
         "templates/survey_duplicated_answer.xml",
         "templates/survey_max_student.xml",
+        "templates/survey_message.xml",
         "templates/survey_template_management.xml",
         # views
         "views/res_company.xml",
diff --git a/controllers/survey.py b/controllers/survey.py
index 5214036..691ea2a 100644
--- a/controllers/survey.py
+++ b/controllers/survey.py
@@ -42,8 +42,36 @@ class TrainingSurvey(Survey):
         )
 
         training_id = post.get("training_id")
+        if (
+            survey_sudo.survey_type == "training"
+            and survey_sudo.training_survey_type == "subscribe"
+            and not training_id
+        ):
+            return request.env["ir.qweb"]._render(
+                "training_survey.survey_message",
+                {
+                    "title": survey_sudo.title,
+                    "message": "Inscription impossible, il semble que l'URL ne soit pas correcte.",
+                    "main_object": survey_sudo,
+                },
+            )
+
         if training_id:
             training = request.env["training.training"].sudo().browse(int(training_id))
+            if not training.active or (
+                training not in survey_sudo.training_ids
+                and training.program_id not in survey_sudo.program_ids
+            ):
+                return request.env["ir.qweb"]._render(
+                    "training_survey.survey_message",
+                    {
+                        "title": survey_sudo.title,
+                        "training": training,
+                        "message": "La page que vous recherchez n'est pas ou plus accessible.",
+                        "main_object": training,
+                    },
+                )
+
             if training.date_limit and date.today() > training.date_limit:
                 return request.env["ir.qweb"]._render(
                     "training_survey.survey_closed",
diff --git a/data/message_type.xml b/data/message_type.xml
new file mode 100644
index 0000000..e9f4878
--- /dev/null
+++ b/data/message_type.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+    <record id="mt_new_student" model="mail.message.subtype">
+        <field name="name">Nouveau stagiaire</field>
+        <field name="res_model">training.training</field>
+        <field name="default" eval="True" />
+    </record>
+</odoo>
diff --git a/models/res_company.py b/models/res_company.py
index ba05ca2..c4b4993 100644
--- a/models/res_company.py
+++ b/models/res_company.py
@@ -7,6 +7,13 @@ from odoo import fields, models
 class ResCompany(models.Model):
     _inherit = "res.company"
 
+    # Questionnaire
+    is_satisfaction_mandatory = fields.Boolean(
+        string="Questionnaire de satisfaction obligatoire",
+        default=True,
+        help="Cette option permet de configurer si une formation peut être diffusée sans "
+        "questionnaire de satisfaction",
+    )
     # Emails
     subscribe_mail_template_id = fields.Many2one(
         comodel_name="mail.template", string="Modèle d'email de pré-inscrition"
diff --git a/models/res_config_settings.py b/models/res_config_settings.py
index 06dd8af..f8a22db 100644
--- a/models/res_config_settings.py
+++ b/models/res_config_settings.py
@@ -7,6 +7,10 @@ from odoo import fields, models
 class ResConfigSettings(models.TransientModel):
     _inherit = "res.config.settings"
 
+    # Questionnaire
+    is_satisfaction_mandatory = fields.Boolean(
+        related="company_id.is_satisfaction_mandatory", readonly=False
+    )
     # Emails
     subscribe_mail_template_id = fields.Many2one(
         related="company_id.subscribe_mail_template_id", readonly=False
diff --git a/models/survey_user_input.py b/models/survey_user_input.py
index 674d9d5..14df35d 100644
--- a/models/survey_user_input.py
+++ b/models/survey_user_input.py
@@ -93,6 +93,10 @@ class SurveyUserInput(models.Model):
         # Pré-inscription du stagiaire
         student_id = self._create_student()
         if student_id:
+            self.training_id.message_post(
+                body=f"Nouvelle inscription : {student_id.display_name}",
+                subtype_xmlid="training_survey.mt_new_student",
+            )
             template_id = student_id.training_id.company_id._get_subscription_email()
             if template_id:
                 template_id.send_mail(
diff --git a/models/training.py b/models/training.py
index cc9c4e5..c10d259 100644
--- a/models/training.py
+++ b/models/training.py
@@ -157,7 +157,10 @@ class Training(models.Model):
     # Inherit parent
     # ------------------------------------------------------
     def action_valid(self):
-        if not self.satisfaction_survey_id:
+        if (
+            not self.satisfaction_survey_id
+            and self.env.company.is_satisfaction_mandatory
+        ):
             raise UserError(_("Le questionnaire de satisfaction doit être configuré."))
         return super().action_valid()
 
@@ -165,7 +168,11 @@ class Training(models.Model):
     # Business function
     # ------------------------------------------------------
     def _get_survey_xlsx(self, survey_id):
-        return self.env.ref("survey_xlsx.report_survey_xlsx").report_action(survey_id)
+        return (
+            self.env.ref("survey_xlsx.report_survey_xlsx")
+            .with_context(training_id=self.id)
+            .report_action(docids=survey_id, data={"training_id": self.id})
+        )
 
     def get_registration_survey_start_url(self):
         url = self.registration_survey_id.get_start_url()
diff --git a/report/__init__.py b/report/__init__.py
new file mode 100644
index 0000000..2a41f6f
--- /dev/null
+++ b/report/__init__.py
@@ -0,0 +1 @@
+from . import report_survey_xlsx
diff --git a/report/report_survey_xlsx.py b/report/report_survey_xlsx.py
new file mode 100644
index 0000000..21acef0
--- /dev/null
+++ b/report/report_survey_xlsx.py
@@ -0,0 +1,14 @@
+# © 2024 Le Filament (<http://www.le-filament.com>)
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+
+from odoo import models
+
+
+class ReportSurveyXlsx(models.AbstractModel):
+    _inherit = "report.survey.xlsx"
+
+    def _get_input_domain(self, results):
+        domain = super()._get_input_domain(results)
+        if self.env.context.get("training_id"):
+            domain.append(("training_id", "=", self.env.context.get("training_id")))
+        return domain
diff --git a/security/survey_security.xml b/security/survey_security.xml
index 641a52a..d7ba7c2 100644
--- a/security/survey_security.xml
+++ b/security/survey_security.xml
@@ -3,12 +3,10 @@
     <record id="survey_server_rule" model="ir.rule">
         <field name="name">survey multi-company</field>
         <field name="model_id" ref="survey.model_survey_survey" />
-        <field name="perm_read" eval="True"/>
-        <field name="perm_write" eval="False"/>
-        <field name="perm_create" eval="False"/>
-        <field name="perm_unlink" eval="False"/>
-        <field
-            name="domain_force"
-        >[('company_id', 'in', company_ids + [False])]</field>
+        <field name="perm_read" eval="True" />
+        <field name="perm_write" eval="False" />
+        <field name="perm_create" eval="False" />
+        <field name="perm_unlink" eval="False" />
+        <field name="domain_force">[('company_id', 'in', company_ids + [False])]</field>
     </record>
 </odoo>
diff --git a/templates/survey_message.xml b/templates/survey_message.xml
new file mode 100644
index 0000000..c765ae1
--- /dev/null
+++ b/templates/survey_message.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+    <template id="survey_message" name="Survey: Website message">
+        <t t-call="web.frontend_layout">
+            <t t-set="html_data" t-value="{'style': 'height: 100%;'}"/>
+            <t t-set="no_header" t-value="True"/>
+            <t t-set="no_footer" t-value="True"/>
+
+            <div class="wrap d-flex align-items-center h-100">
+                <div class="container">
+                    <div class="fs-3 fw-light">
+                        <span t-out="message" />
+                    </div>
+                    <div class="mt-4" t-if="not hide_back_training_list">
+                        <a class="btn btn-primary" href="/formations/liste">
+                            Retour à la liste des formations
+                        </a>
+                    </div>
+                </div>
+            </div>
+        </t>
+    </template>
+</odoo>
diff --git a/views/res_company.xml b/views/res_company.xml
index 7483679..286a72b 100644
--- a/views/res_company.xml
+++ b/views/res_company.xml
@@ -9,6 +9,9 @@
         <field name="model">res.company</field>
         <field name="inherit_id" ref="training.res_company_training_form_view" />
         <field name="arch" type="xml">
+            <xpath expr="//field[@name='agreement_special_condition']" position="after">
+                <field name="is_satisfaction_mandatory" widget="boolean_toggle" />
+            </xpath>
             <xpath expr="//page[@name='training']/group" position="after">
                 <group string="Emails">
                     <group>
diff --git a/views/res_config_settings.xml b/views/res_config_settings.xml
index b854f6a..2f4e008 100644
--- a/views/res_config_settings.xml
+++ b/views/res_config_settings.xml
@@ -6,6 +6,15 @@
         <field name="priority" eval="40" />
         <field name="inherit_id" ref="training.res_config_settings_view_form" />
         <field name="arch" type="xml">
+            <xpath expr="//div[@name='training_internal_regulation']" position="after">
+                <div class="row mt16" name="is_satisfaction_mandatory">
+                    <label
+                        for="is_satisfaction_mandatory"
+                        class="col-lg-6 o_light_label"
+                    />
+                    <field name="is_satisfaction_mandatory" widget="boolean_toggle" />
+                </div>
+            </xpath>
             <xpath expr="//div[@name='training_settings']" position="after">
                 <h2>Configuration des emails</h2>
                 <div
diff --git a/views/survey_user_input.xml b/views/survey_user_input.xml
index 3140619..4c4421b 100644
--- a/views/survey_user_input.xml
+++ b/views/survey_user_input.xml
@@ -36,8 +36,7 @@
             >
                 <field
                     name="training_id"
-                    readonly="1"
-                    attrs="{'invisible': [('training_id', '=', False)]}"
+                    attrs="{'invisible': [('training_survey_type', '=', False)]}"
                 />
                 <field
                     name="training_survey_type"
diff --git a/views/training.xml b/views/training.xml
index bab001f..aa42995 100644
--- a/views/training.xml
+++ b/views/training.xml
@@ -40,76 +40,96 @@
 
             <xpath expr="//notebook" position="inside">
                 <page string="Questionnaires" name="survey">
-                    <p class="o_horizontal_separator">
+                    <!-- Pré-inscription/Positionnement-->
+                    <div class="o_horizontal_separator mb-3">
                         Pré-inscription/Positionnement
-                    </p>
-                    <p>
-                        <field name="registration_survey_id" class="me-4" />
-                        <button
-                            name="action_export_registration"
-                            type="object"
-                            icon="fa-file-o"
-                            class="btn-outline-primary"
-                            title="Exporter réponses positionnement"
-                            attrs="{'invisible': [('registration_survey_id', '=', False)]}"
-                        />
-                    </p>
+                    </div>
+                    <div class="row">
+                        <div class="col-8">
+                            <field name="registration_survey_id" />
+                        </div>
+                        <div class="col-4 text-end">
+                            <button
+                                name="action_export_registration"
+                                type="object"
+                                class="btn-outline-primary btn-sm"
+                                title="Exporter les réponses"
+                                attrs="{'invisible': [('registration_survey_id', '=', False)]}"
+                            >
+                                Exporter les réponses
+                            </button>
+                        </div>
+                    </div>
 
-                    <p class="o_horizontal_separator">
+                    <!-- AECI -->
+                    <div class="o_horizontal_separator mt-5 mb-3">
                         AECI
-                    </p>
-                    <p>
-                        <field name="aeci_survey_id" class="me-4" />
-                        <button
-                            name="action_export_aeci"
-                            type="object"
-                            icon="fa-file-o"
-                            class="btn-outline-primary"
-                            title="Export réponses AECI"
-                            attrs="{'invisible': [('aeci_survey_id', '=', False)]}"
-                        />
-                    </p>
+                    </div>
+                    <div class="row">
+                        <div class="col-8">
+                            <field name="aeci_survey_id" />
+                        </div>
+                        <div class="col-4 text-end">
+                            <button
+                                name="action_export_aeci"
+                                type="object"
+                                class="btn-outline-primary btn-sm"
+                                title="Exporter les réponses AECI"
+                                attrs="{'invisible': [('aeci_survey_id', '=', False)]}"
+                            >
+                                Exporter les réponses
+                            </button>
+                        </div>
+                    </div>
 
-                    <p class="o_horizontal_separator">
+
+                    <!-- AECT -->
+                    <div class="o_horizontal_separator mt-5 mb-3">
                         AECT
-                    </p>
-                    <p>
-                        <field name="aect_survey_id" class="me-4" />
-                        <button
-                            name="action_export_aect"
-                            type="object"
-                            icon="fa-file-o"
-                            class="btn-outline-primary"
-                            title="Export réponses AECT"
-                            attrs="{'invisible': [('aect_survey_id', '=', False)]}"
-                        />
-                    </p>
+                    </div>
+                    <div class="row">
+                        <div class="col-8">
+                            <field name="aect_survey_id" />
+                        </div>
+                        <div class="col-4 text-end">
+                            <button
+                                name="action_export_aect"
+                                type="object"
+                                class="btn-outline-primary btn-sm"
+                                title="Exporter les réponses AECT"
+                                attrs="{'invisible': [('aect_survey_id', '=', False)]}"
+                            >
+                                Exporter les réponses
+                            </button>
+                        </div>
+                    </div>
 
-                    <p class="o_horizontal_separator">
+                    <!-- Satisfaction -->
+                    <div class="o_horizontal_separator mt-5 mb-3">
                         Satisfaction
-                    </p>
-                    <p>
-                        <field
-                            name="satisfaction_survey_id"
-                            class="me-4 col-12 col-md-6"
-                            options="{'no_create': 1}"
-                        />
-                        <button
-                            name="action_create_satisfaction_survey"
-                            type="object"
-                            class="btn-outline-primary"
-                            string="Créer un nouveau questionnaire de satisfaction"
-                            attrs="{'invisible': [('satisfaction_survey_id', '!=', False)]}"
-                        />
-                        <button
-                            name="action_export_satisfaction"
-                            type="object"
-                            icon="fa-file-o"
-                            class="btn-outline-primary"
-                            title="Export réponses satisfaction"
-                            attrs="{'invisible': [('satisfaction_survey_id', '=', False)]}"
-                        />
-                    </p>
+                    </div>
+                    <div class="row">
+                        <div class="col-8">
+                            <field name="satisfaction_survey_id" />
+                        </div>
+                        <div class="col-4 text-end">
+                            <button
+                                name="action_create_satisfaction_survey"
+                                type="object"
+                                class="btn-outline-primary btn-sm"
+                                string="Créer un nouveau questionnaire de satisfaction"
+                                attrs="{'invisible': [('satisfaction_survey_id', '!=', False)]}"
+                            />
+                            <button
+                                name="action_export_satisfaction"
+                                type="object"
+                                class="btn-outline-primary btn-sm"
+                                string="Export réponses satisfaction"
+                                attrs="{'invisible': [('satisfaction_survey_id', '=', False)]}"
+                            />
+                        </div>
+                    </div>
+
                 </page>
             </xpath>
         </field>
-- 
GitLab