From b88e9a42068ad5a0b9af6c8a50a8db77fb8ca172 Mon Sep 17 00:00:00 2001
From: jordan <jordan@le-filament.com>
Date: Thu, 25 Nov 2021 17:59:03 +0100
Subject: [PATCH] [update] enable to change liasse fiscale from bordereau +
 clean code

---
 __manifest__.py                               |   1 +
 models/scop_bordereau_cg.py                   |  22 +-
 models/scop_cotisation_cg.py                  | 244 +-----------------
 models/scop_liasse_fiscale.py                 | 127 +++++----
 views/scop_bordereau_cg.xml                   |  17 +-
 wizard/__init__.py                            |   1 +
 ...scop_cotisation_cg_change_liasse_wizard.py | 172 ++++++++++++
 ...cop_cotisation_cg_change_liasse_wizard.xml |  75 ++++++
 8 files changed, 356 insertions(+), 303 deletions(-)
 create mode 100644 wizard/scop_cotisation_cg_change_liasse_wizard.py
 create mode 100644 wizard/scop_cotisation_cg_change_liasse_wizard.xml

diff --git a/__manifest__.py b/__manifest__.py
index 5a7ef5b..f6ba730 100755
--- a/__manifest__.py
+++ b/__manifest__.py
@@ -25,6 +25,7 @@
         "report/report_scop_bordereau_refund.xml",
         "views/account_invoice.xml",
         "views/res_config_settings.xml",
+        "wizard/scop_cotisation_cg_change_liasse_wizard.xml",
         "views/scop_bordereau_cg.xml",
         "views/scop_cotisation_cg.xml",
         "views/scop_cotisation_simulation.xml",
diff --git a/models/scop_bordereau_cg.py b/models/scop_bordereau_cg.py
index fcd4f62..5a3ce42 100644
--- a/models/scop_bordereau_cg.py
+++ b/models/scop_bordereau_cg.py
@@ -137,11 +137,11 @@ class Bordereau(models.Model):
         compute='_compute_montant_assiette')
     ca = fields.Float(
         string='CA',
-        readonly=True,
+        compute='_compute_values_calculation', store=True,
         track_visibility='onchange')
     va = fields.Float(
         string='VA',
-        readonly=True,
+        compute='_compute_values_calculation', store=True,
         track_visibility='onchange')
     staff_count = fields.Integer(
         string='Effectif de la coop',
@@ -154,10 +154,10 @@ class Bordereau(models.Model):
         readonly=True)
     net_results = fields.Float(
         string='Résultat net',
-        readonly=True)
+        compute='_compute_values_calculation', store=True,)
     wage_cg = fields.Float(
         string='Montant masse salariale',
-        readonly=True)
+        compute='_compute_values_calculation', store=True,)
     is_sdd = fields.Boolean(
         'Au prélèvement',
         compute='compute_is_sdd',
@@ -191,6 +191,20 @@ class Bordereau(models.Model):
     # ------------------------------------------------------
     # Compute
     # ------------------------------------------------------
+    @api.depends('liasse_fiscale_id')
+    @api.multi
+    def _compute_values_calculation(self):
+        for r in self:
+            if r.liasse_fiscale_id:
+                liasse = r.liasse_fiscale_id
+                r.ca = liasse.revenue_cgsubv
+                r.va = r.base_cotisation_cg.get_va(liasse)
+                r.net_results = liasse.L2053_HN \
+                    if liasse.L2053_HN > 0 else liasse.L2051_DI
+                r.wage_cg = liasse.wage_cg
+            else:
+                r.ca = r.va = r.net_results = r.wage_cg = 0
+
     @api.multi
     def _compute_name(self):
         for bordereau in self:
diff --git a/models/scop_cotisation_cg.py b/models/scop_cotisation_cg.py
index 19809a0..03a80c0 100644
--- a/models/scop_cotisation_cg.py
+++ b/models/scop_cotisation_cg.py
@@ -338,14 +338,6 @@ class ScopCotisation(models.Model):
         ])
         if not existing_bordereau or is_regul:
             # Variables to calculate cotiz
-            if liasse:
-                ca = liasse.revenue_cgsubv
-                va = self.get_va(liasse)
-                net_results = liasse.L2053_HN \
-                    if liasse.L2053_HN > 0 else liasse.L2051_DI
-                wage_cg = liasse.wage_cg
-            else:
-                ca = va = net_results = wage_cg = 0
             staff_id = self.get_last_staff_id(member)
             if staff_id:
                 staff_shareholder_count = staff_id.staff_shareholder_count
@@ -365,13 +357,9 @@ class ScopCotisation(models.Model):
                 'year_liasse': liasse.year if liasse else 0,
                 'date_cotisation': date_invoice,
                 'nb_quarter': nb_quarter,
-                'ca': ca,
-                'va': va,
                 'staff_count': staff_count,
                 'staff_shareholder_count': staff_shareholder_count,
                 'staff_average': staff_average,
-                'net_results': net_results,
-                'wage_cg': wage_cg,
             })
             return bordereau
         else:
@@ -790,8 +778,12 @@ class ScopCotisation(models.Model):
             type_cotisation_fede_cae = self.env.ref(
                 'cgscop_partner.cotiz_fede_cae').id
 
-            amount_fede_cae = self.round_to_closest_multiple(
-                self.get_cotiz_fede_cae(), 4)
+            if liasse:
+                amount_fede_cae = self.round_to_closest_multiple(
+                    liasse.contribution_cae, 4)
+            else:
+                amount_fede_cae = self.env['scop.liasse.fiscale'].\
+                    get_plancher_cotiz['fede_cae']
             self.create_contribution(
                 product_fede_cae_id, partner, type_cotisation_fede_cae,
                 bordereau, liasse, amount_fede_cae,
@@ -842,183 +834,6 @@ class ScopCotisation(models.Model):
     # ------------------------------------------------------
     # Calcul des cotisations
     # ------------------------------------------------------
-    # TODO: A voir si on conserve ces fonctions.
-    #       --
-    #       Le montant des cotisations est calculé depuis la liasse, à vois si il est nécessaire
-    #       de conserver ces fonctions :
-    #        - si il y a une liasse, on applique les montants de la liasse
-    #        - si il n'y en a pas, on applique la valeur plancher (auquel cas, on supprime ces fonctions)
-    #       A checker également pour les ajustements, les modifications et les exonérations
-    #       --
-    #       Hypothèse :
-    #        - soit on a la liasse fiscale et on ajuste via les données de la liasse
-    #        - soit on ajuste manuelement le calcul
-    #       => A valider par Hervé + Christophe (et faire une revue du code de recalcul des cotisations)
-
-    # def get_cotiz_cg(self, partner, bordereau):
-    #     """
-    #         Appelle la fonction de calcul de la cotisation CG Scop
-    #         à partir des variables du bordereau
-    #     """
-    #
-    #     type_assiette = bordereau.type_assiette_retenu
-    #     ca = self.check_dureeExercice(
-    #         bordereau.ca_retenu, bordereau.dureeExercice)
-    #     va = self.check_dureeExercice(
-    #         bordereau.va_cg_retenu, bordereau.dureeExercice)
-    #     return self.calc_cotiz_cg(partner, ca, va, type_assiette)
-    #
-    # def calc_cotiz_cg(self, partner, ca, va, type_assiette):
-    #     """
-    #         Calcule la cotisation de la CG Scop :
-    #         - VA = VA saisie ou VA au sens CGSCOP si pas de VA renseignée
-    #         - 0,3% du CA ou 0,7% de la VA
-    #         - 300 € pour CA compris entre 0 et 100 K€
-    #         - 600 € pour CA compris entre 100 et 200 K€
-    #         - Max = 375 K€
-    #
-    #         Utilisation de hack_check_exercice pour avoir la valeur non
-    #         proratisée de la cotisation pour le calcul de la cotisation UR med
-    #
-    #         @return float : cotisation
-    #     """
-    #     values = self.get_values_for_cotiz_cg(partner)
-    #     if type_assiette == 'ca':
-    #         rate = self.get_rate_ca(partner)
-    #         cotiz = ca * rate
-    #     else:
-    #         rate = self.get_rate_va(partner)
-    #         cotiz = va * rate
-    #
-    #     if cotiz < values['plancher1']:
-    #         return values['plancher1']
-    #     elif cotiz < values['plancher2']:
-    #         return values['plancher2']
-    #     elif cotiz >= values['plancher3']:
-    #         if type_assiette == 'ca':
-    #             cotiz = (25000000 * rate) + (ca - 25000000) * (rate / 2)
-    #         else:
-    #             cotiz = (10714286 * rate) + (va - 10714286) * (rate / 2)
-    #         if cotiz <= values['plafond']:
-    #             return cotiz
-    #         else:
-    #             return values['plafond']
-    #     else:
-    #         return cotiz
-    #
-    # def get_cotiz_fede_com(self, bordereau):
-    #     """
-    #         Calcule la cotisation de la fédération de la com pour 1 partenaire
-    #         - Assiette annuelle : VA saisie ou VA au sens CGSCOP
-    #         - Taux : 0.0032
-    #         - Calcul : Valeur Ajoutée * 0.0032
-    #         - Pour les nouvelles coopératives (pas de comptes annuels) :
-    #             108 € par salarié (effectif moyen s’il est saisi, à défaut
-    #             effectif), soit 27 € par salarié et par trimestre.
-    #         - Plancher annuel : 108 €
-    #         - Plafond annuel : 18 428 €
-    #
-    #         @return float : cotisation
-    #     """
-    #     plancher = 108
-    #     plafond = 18428
-    #     rate = 0.0032
-    #     va = self.check_dureeExercice(
-    #         bordereau.va_fede_com_retenu, bordereau.dureeExercice)
-    #     staff_average = bordereau.staff_average_retenu
-    #     staff_count = bordereau.staff_fede_com_count_retenu
-    #     if va != 0:
-    #         cotiz = va * rate
-    #     else:
-    #         if staff_average > 0:
-    #             cotiz = staff_average * plancher
-    #         else:
-    #             cotiz = staff_count * plancher
-    #     if plancher <= cotiz <= plafond:
-    #         return cotiz
-    #     elif cotiz < plancher:
-    #         return plancher
-    #     else:
-    #         return plafond
-    #
-    # def get_cotiz_hdf(self, bordereau):
-    #     """
-    #         Calcule la cotisation de l'UR HDF pour 1 partenaire :
-    #         - 0,1 % de la masse salariale annuelle brute prévisionnelle
-    #         ou figurant sur la liasse fiscale.
-    #
-    #         @return float : cotisation
-    #     """
-    #     rate = 0.001
-    #     plancher = 40
-    #     wage_cg = self.check_dureeExercice(
-    #         bordereau.wage_cg_retenu, bordereau.dureeExercice)
-    #     if wage_cg > 0:
-    #         cotiz = wage_cg * rate
-    #     else:
-    #         cotiz = 0
-    #
-    #     if cotiz > plancher:
-    #         return cotiz
-    #     else:
-    #         return plancher
-    #
-    # def get_cotiz_med(self, cotiz_cg, bordereau):
-    #     """
-    #         Calcule la cotisation de l'UR Med pour 1 partenaire :
-    #         - Assiette : Assiette de la cotisation CGSCOP
-    #         - Taux d’appel : 1/3 du taux
-    #         - Calcul intermédiaire : Assiette * taux
-    #             (soit 1/3 de la cotisation CGSCOP sans plancher)
-    #         - Complément de cotisation : 1% du résultat net si positif
-    #         - Abattement pour sociétariat :
-    #             Taux de sociétariat =   nombre de salariés sociétaires /
-    #                                     nombre de salariés
-    #             Abattement 20 % si >= 50 %
-    #             Abattement 30 % si >= 80 %
-    #         - Calcul cotisations :
-    #             [(Assiette*taux) + (résultat net *0.01)]* (1 ou 0.8 ou 0.7)
-    #
-    #         @return float : cotisation
-    #     """
-    #     # Assiette CG
-    #     assiette_rate = 1 / 3
-    #     assiette = cotiz_cg
-    #
-    #     # Résultat net
-    #     net_results_rate = 0.01
-    #
-    #     net_results = self.check_dureeExercice(
-    #         bordereau.net_results_retenu, bordereau.dureeExercice)
-    #     staff_count = bordereau.staff_shareholder_count_retenu
-    #     staff_shareholder_count = bordereau.staff_ur_med_count_retenu
-    #
-    #     # Taux d'abattement pour sociétariat
-    #     if staff_count > 0:
-    #         societariat_rate = staff_shareholder_count / staff_count
-    #     else:
-    #         societariat_rate = 0
-    #
-    #     if 0.5 <= societariat_rate < 0.8:
-    #         abatt_rate = 1 - 0.2
-    #     elif societariat_rate >= 0.8:
-    #         abatt_rate = 1 - 0.3
-    #     else:
-    #         abatt_rate = 1 - 0
-    #
-    #     # Cotiz
-    #     cotiz = ((assiette * assiette_rate) +
-    #              (net_results * net_results_rate)) * abatt_rate
-    #     final_cotiz = cotiz if cotiz >= 0 else 0
-    #     return final_cotiz
-
-    def get_cotiz_fede_cae(self):
-        """
-            100€ if partner is CAE
-        """
-        cotiz = 100
-        return cotiz
-
     def get_va(self, liasse):
         """
         VA saisie ou VA au sens CGSCOP
@@ -1057,53 +872,6 @@ class ScopCotisation(models.Model):
                 type_cotiz = 'ca'
         return type_cotiz
 
-    # def get_rate_ca(self, partner):
-    #     # Calcul des Taux SCOP en fonction du type
-    #     if partner.cooperative_form_id in (
-    #             self.env.ref('cgscop_partner.form_coop47'),
-    #             self.env.ref('cgscop_partner.form_lamaneur')):
-    #         rate_ca = 0.002
-    #     else:
-    #         rate_ca = 0.003
-    #     return rate_ca
-
-    # def get_rate_va(self, partner):
-    #     # Calcul des Taux SCOP en fonction du type
-    #     if partner.cooperative_form_id in (
-    #             self.env.ref('cgscop_partner.form_coop47'),
-    #             self.env.ref('cgscop_partner.form_lamaneur')):
-    #         rate_va = 0.0047
-    #     else:
-    #         rate_va = 0.007
-    #     return rate_va
-    #
-    # def get_values_for_cotiz_cg(self, partner):
-    #     # Calcul des Taux SCOP en fonction du type
-    #     plancher1 = 300
-    #     plancher2 = 600
-    #     plancher3 = 75000
-    #     plafond = 375000
-    #     if partner.cooperative_form_id in (
-    #             self.env.ref('cgscop_partner.form_coop47'),
-    #             self.env.ref('cgscop_partner.form_lamaneur')):
-    #         plancher1 = 1 / 3 * plancher1
-    #         plancher2 = 1 / 3 * plancher2
-    #         plancher3 = 1 / 3 * plancher3
-    #         plafond = 1 / 3 * plafond
-    #
-    #     return {
-    #         'plancher1': plancher1,
-    #         'plancher2': plancher2,
-    #         'plancher3': plancher3,
-    #         'plafond': plafond,
-    #     }
-
-    # def check_dureeExercice(self, amount, duree_exercice):
-    #     if duree_exercice and duree_exercice not in (0, 12):
-    #         return amount * (12 / duree_exercice)
-    #     else:
-    #         return amount
-
     # ------------------------------------------------------
     # Threading task
     # ------------------------------------------------------
diff --git a/models/scop_liasse_fiscale.py b/models/scop_liasse_fiscale.py
index cdfb6e3..7836d68 100644
--- a/models/scop_liasse_fiscale.py
+++ b/models/scop_liasse_fiscale.py
@@ -33,6 +33,10 @@ class ScopLiasseFiscale(models.Model):
         string='Cotisation Fédération Com',
         compute='_compute_contribution_com',
         store=True)
+    contribution_cae = fields.Float(
+        string='Cotisation Fédération CAE',
+        compute='_compute_contribution_cae',
+        store=True)
 
     # ------------------------------------------------------
     # Compute fields
@@ -115,7 +119,7 @@ class ScopLiasseFiscale(models.Model):
             @return float : cotisation
         """
         ur_hdf = self.env.ref('cgscop_partner.riga_14232')
-        plancher = self.get_plancher_cotiz['ur_hdf']
+        plancher = self.get_plancher_cotiz()['ur_hdf']
         for liasse in self:
             if liasse.partner_id.ur_id == ur_hdf:
                 rate = 0.001
@@ -133,60 +137,6 @@ class ScopLiasseFiscale(models.Model):
                 else:
                     liasse.contribution_hdf = plancher
 
-    @api.depends('av_lf', 'av_cg')
-    @api.multi
-    def _compute_contribution_com(self):
-        """
-            Calcule la cotisation de la fédération de la com pour 1 partenaire
-            - Assiette annuelle : VA saisie ou VA au sens CGSCOP
-            - Taux : 0.0032
-            - Calcul : Valeur Ajoutée * 0.0032
-            - Pour les nouvelles coopératives (pas de comptes annuels) :
-                108 € par salarié (effectif moyen s’il est saisi, à défaut
-                effectif), soit 27 € par salarié et par trimestre.
-            - Plancher annuel : 108 €
-            - Plafond annuel : 18 428 €
-
-            @return float : cotisation
-        """
-        plancher = self.get_plancher_cotiz['fede_com']
-        plafond = 18428
-        rate = 0.0032
-        for liasse in self:
-            if liasse.partner_id.is_federation_com:
-                # Calcul VA
-                va = liasse.av_lf if liasse.av_lf > 0 else liasse.av_cg
-
-                # Calcul VA proratisée
-                if liasse.dureeExercice and liasse.dureeExercice not in (0, 12):
-                    va = va * (12 / liasse.dureeExercice)
-                else:
-                    va = va
-
-                # Calcul effectifs
-                staff_id = self.get_last_staff_id(liasse.partner_id)
-                if staff_id:
-                    staff_average = staff_id.staff_average
-                    staff_count = staff_id.staff_count
-                else:
-                    staff_average = 0
-                    staff_count = 0
-
-                # Calcul cotisation
-                if va != 0:
-                    contribution_com = va * rate
-                else:
-                    if staff_average > 0:
-                        contribution_com = staff_average * plancher
-                    else:
-                        contribution_com = staff_count * plancher
-                if plancher <= contribution_com <= plafond:
-                    liasse.contribution_com = contribution_com
-                elif contribution_com < plancher:
-                    liasse.contribution_com = plancher
-                else:
-                    liasse.contribution_com = plafond
-
     @api.depends('contribution_cg', 'L2053_HN')
     @api.multi
     def _compute_contribution_med(self):
@@ -208,7 +158,7 @@ class ScopLiasseFiscale(models.Model):
             @return float : cotisation
         """
         ur_med = self.env.ref('cgscop_partner.riga_14243')
-        plancher = self.get_plancher_cotiz['ur_med']
+        plancher = self.get_plancher_cotiz()['ur_med']
         for liasse in self:
             if liasse.partner_id.ur_id == ur_med:
                 # Assiette CG
@@ -248,12 +198,77 @@ class ScopLiasseFiscale(models.Model):
                 final_contribution_med = contribution_med if contribution_med >= 0 else plancher
                 liasse.contribution_med = final_contribution_med
 
+    @api.depends('av_lf', 'av_cg')
+    @api.multi
+    def _compute_contribution_com(self):
+        """
+            Calcule la cotisation de la fédération de la com pour 1 partenaire
+            - Assiette annuelle : VA saisie ou VA au sens CGSCOP
+            - Taux : 0.0032
+            - Calcul : Valeur Ajoutée * 0.0032
+            - Pour les nouvelles coopératives (pas de comptes annuels) :
+                108 € par salarié (effectif moyen s’il est saisi, à défaut
+                effectif), soit 27 € par salarié et par trimestre.
+            - Plancher annuel : 108 €
+            - Plafond annuel : 18 428 €
+
+            @return float : cotisation
+        """
+        plancher = self.get_plancher_cotiz()['fede_com']
+        plafond = 18428
+        rate = 0.0032
+        for liasse in self:
+            if liasse.partner_id.is_federation_com:
+                # Calcul VA
+                va = liasse.av_lf if liasse.av_lf > 0 else liasse.av_cg
+
+                # Calcul VA proratisée
+                if liasse.dureeExercice and liasse.dureeExercice not in (0, 12):
+                    va = va * (12 / liasse.dureeExercice)
+                else:
+                    va = va
+
+                # Calcul effectifs
+                staff_id = self.get_last_staff_id(liasse.partner_id)
+                if staff_id:
+                    staff_average = staff_id.staff_average
+                    staff_count = staff_id.staff_count
+                else:
+                    staff_average = 0
+                    staff_count = 0
+
+                # Calcul cotisation
+                if va != 0:
+                    contribution_com = va * rate
+                else:
+                    if staff_average > 0:
+                        contribution_com = staff_average * plancher
+                    else:
+                        contribution_com = staff_count * plancher
+                if plancher <= contribution_com <= plafond:
+                    liasse.contribution_com = contribution_com
+                elif contribution_com < plancher:
+                    liasse.contribution_com = plancher
+                else:
+                    liasse.contribution_com = plafond
+
+    @api.multi
+    def _compute_contribution_cae(self):
+        """
+           100€ if partner is CAE
+       """
+        for liasse in self:
+            if liasse.partner_id.cae:
+                cotiz = plancher = self.get_plancher_cotiz()['fede_cae']
+                return cotiz
+
     # ------------------------------------------------------
     # Business Function
     # ------------------------------------------------------
     def get_plancher_cotiz(self):
         return {
             'fede_com': 108,
+            'cae': 100,
             'ur_med': 0,
             'ur_hdf': 40,
         }
diff --git a/views/scop_bordereau_cg.xml b/views/scop_bordereau_cg.xml
index 4bcbbbc..0f06de4 100644
--- a/views/scop_bordereau_cg.xml
+++ b/views/scop_bordereau_cg.xml
@@ -12,7 +12,8 @@
                 <form create="false" string="Bordereaux">
                     <header>
                         <field name="state" widget="statusbar" clickable="False" readonly="True"/>
-                        <button name="validate_bordereau" class="oe_highlight" string="Valider le bordereau" type="object" states="new" confirm="Confirmer la validation du bordereau ?"/>
+                        <button name="validate_bordereau" class="oe_highlight" string="Valider le bordereau" type="object"
+                                states="new" confirm="Confirmer la validation du bordereau ?"/>
                         <button name="print_bordereau" string="Imprimer" type="object" states="validated,paid"/>
                         <button name="action_send_email" string="Envoyer par mail" type="object" states="validated"/>
                         <button name="%(cgscop_cotisation_cg.scop_cotisation_regul_wizard_act_window)d"
@@ -100,10 +101,16 @@
                         </group>
                         <notebook>
                             <page string="Valeurs pour le calcul">
-                                <header>
-                                    <button name="update_liasse_fiscale" class="btn-info"
-                                            string="Changer de liasse fiscale" type="object" states="new"/>
-                                </header>
+                                <div class="o_row">
+                                    <span class="oe_grey" attrs="{'invisible': [('liasse_fiscale_id', '=', False)]}">Liasse fiscale utilisée :</span>
+                                    <span class="oe_grey" attrs="{'invisible': [('liasse_fiscale_id', '!=', False)]}">Pas de liasse fiscale utilisée</span>
+                                    <field name="liasse_fiscale_id" class="oe_grey" options="{'no_open': True, 'no_create': True}"/>
+                                     <button name="%(cgscop_cotisation_cg.scop_cotisation_change_liasse_wizard_act_window)d"
+                                             class="btn-info"
+                                             string="Changer de liasse fiscale"
+                                             type="action"
+                                             states="new"/>
+                                </div>
                                 <group col="2">
                                     <group string="Cotisation CG">
                                         <field name="ca"/>
diff --git a/wizard/__init__.py b/wizard/__init__.py
index 909809b..1a32a8c 100644
--- a/wizard/__init__.py
+++ b/wizard/__init__.py
@@ -7,3 +7,4 @@ from . import scop_bordereau_update_confirm
 from . import scop_bordereau_validate_confirm
 from . import scop_cotisation_cg_regul
 from . import scop_cotisation_cg_wizard
+from . import scop_cotisation_cg_change_liasse_wizard
diff --git a/wizard/scop_cotisation_cg_change_liasse_wizard.py b/wizard/scop_cotisation_cg_change_liasse_wizard.py
new file mode 100644
index 0000000..24bd8c0
--- /dev/null
+++ b/wizard/scop_cotisation_cg_change_liasse_wizard.py
@@ -0,0 +1,172 @@
+# Copyright 2021 Le Filament
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from odoo import fields, models, api
+
+
+class ScopCotisationChangeLiasse(models.TransientModel):
+    _name = 'scop.cotisation.change.liasse.wizard'
+    _description = 'Changement de liasse sur le bordereau'
+
+    bordereau_id = fields.Many2one(
+        comodel_name='scop.bordereau',
+        string='Bordereau',
+        readonly=True,
+    )
+    company_currency_id = fields.Many2one(
+        related='bordereau_id.company_currency_id')
+
+    # Ancienne liasse
+    liasse_fiscale_id = fields.Many2one(
+        related='bordereau_id.liasse_fiscale_id')
+    amount_total_cotiz = fields.Monetary(
+        string='Montant total de(s) cotisation(s)',
+        currency_field='company_currency_id', readonly=True)
+    amount_cg = fields.Float(
+        'Cotisation CG Scop actuelle', readonly=True)
+    amount_ur_med = fields.Float(
+        'Cotisation UR Med actuelle', readonly=True)
+    amount_ur_hdf = fields.Float(
+        'Cotisation UR HDF actuelle', readonly=True)
+    amount_fede_com = fields.Float(
+        'Cotisation Fede Com actuelle', readonly=True)
+    amount_fede_cae = fields.Float(
+        'Cotisation Fede CAE actuelle', readonly=True)
+    type_assiette = fields.Selection(
+        string='Type d\'assiette actuel',
+        selection=[('ca', 'CA'),
+                   ('va', 'VA'), ],
+        readonly=True)
+    montant_assiette = fields.Float(
+        'Montant assiette actuel', readonly=True)
+    ca = fields.Float(
+        'CA actuel', readonly=True)
+    va = fields.Float(
+        'VA actuelle', readonly=True)
+    net_results = fields.Float(
+        'Résultat net actuel', readonly=True)
+    wage_cg = fields.Float(
+        'Masse salariale actuelle', readonly=True)
+
+    # Nouvelle liasse
+    liasse_fiscale_new_id = fields.Many2one(
+        comodel_name='scop.liasse.fiscale',
+        string='Nouvelle liasse Fiscale',
+        domain=lambda self: self._get_liasse_fiscale_new_id_domain()
+    )
+    amount_total_cotiz_new = fields.Monetary(
+        string='Montant total de(s) cotisation(s)',
+        currency_field='company_currency_id',
+        readonly=1)
+    amount_cg_new = fields.Float(
+        'Cotisation CG Scop',
+        related='liasse_fiscale_new_id.contribution_cg')
+    amount_ur_med_new = fields.Float(
+        'Cotisation UR Méditerranée',
+        related='liasse_fiscale_new_id.contribution_med')
+    amount_ur_hdf_new = fields.Float(
+        'Cotisation UR HDF',
+        related='liasse_fiscale_new_id.contribution_hdf')
+    amount_fede_com_new = fields.Float(
+        'Cotisation Fédé Communication',
+        related='liasse_fiscale_new_id.contribution_com')
+    amount_fede_cae_new = fields.Float(
+        'Cotisation Fédé CAE',
+        related='liasse_fiscale_new_id.contribution_cae')
+    type_assiette_new = fields.Selection(
+        string='Type d\'assiette de cotisation',
+        selection=[('ca', 'CA'),
+                   ('va', 'VA'), ],
+        readonly=1)
+    montant_assiette_new = fields.Float(
+        string='Montant assiette de cotisation liasse actuelle',
+        readonly=1)
+    ca_new = fields.Float(
+        string='CA', readonly=1)
+    va_new = fields.Float(
+        string='VA', readonly=1)
+    net_results_new = fields.Float(
+        string='Résultat net', readonly=1)
+    wage_cg_new = fields.Float(
+        string='Montant masse salariale', readonly=1)
+
+    # ------------------------------------------------------
+    # Override ORM
+    # ------------------------------------------------------
+    @api.model
+    def default_get(self, fields):
+        res = super(ScopCotisationChangeLiasse, self).default_get(fields)
+        bordereau_id = self.env['scop.bordereau'].browse(
+            self.env.context.get('active_id')
+        )
+
+        def round(x):
+            return self.env['scop.cotisation.cg'].round_to_closest_multiple(x, 4)
+
+        res.update({
+            'bordereau_id': bordereau_id.id,
+            'amount_total_cotiz': bordereau_id.amount_total_cotiz,
+            'amount_cg': round(bordereau_id.liasse_fiscale_id.contribution_cg),
+            'amount_ur_med': round(bordereau_id.liasse_fiscale_id.contribution_med),
+            'amount_ur_hdf': round(bordereau_id.liasse_fiscale_id.contribution_hdf),
+            'amount_fede_com': round(bordereau_id.liasse_fiscale_id.contribution_com),
+            'amount_fede_cae': round(bordereau_id.liasse_fiscale_id.contribution_cae),
+            'type_assiette': bordereau_id.type_assiette,
+            'montant_assiette': bordereau_id.montant_assiette,
+            'ca': bordereau_id.ca,
+            'va': bordereau_id.va,
+            'net_results': bordereau_id.net_results,
+            'wage_cg': bordereau_id.wage_cg,
+        })
+        return res
+
+    @api.model
+    def _get_liasse_fiscale_new_id_domain(self):
+        bordereau_id = self.env['scop.bordereau'].browse(
+            self.env.context.get('active_id')
+        )
+        res = [('partner_id', '=', bordereau_id.partner_id.id),
+               ('is_qualified', '=', True),
+               ('id', '!=', bordereau_id.liasse_fiscale_id.id)]
+        return res
+
+    # ------------------------------------------------------
+    # Onchange
+    # ------------------------------------------------------
+    @api.onchange('liasse_fiscale_new_id')
+    def _onchange_liasse_new_values(self):
+        if self.liasse_fiscale_new_id:
+            liasse = self.liasse_fiscale_new_id
+            self.ca_new = liasse.revenue_cgsubv
+            self.va_new = self.env['scop.cotisation.cg'].get_va(liasse)
+            self.net_results_new = liasse.L2053_HN \
+                if liasse.L2053_HN > 0 else liasse.L2051_DI
+            self.wage_cg_new = liasse.wage_cg
+            self.type_assiette_new = self.env['scop.cotisation.cg'].\
+                get_type_assiette(self.ca_new, self.va_new)
+            if self.type_assiette_new == 'ca':
+                self.montant_assiette_new = self.ca_new
+            else:  # type_assiette == 'va'
+                self.montant_assiette_new = self.va_new
+            self.amount_total_cotiz_new = \
+                self.amount_cg_new + self.amount_ur_hdf_new + \
+                self.amount_ur_med_new + self.amount_fede_com
+
+    # ------------------------------------------------------
+    # Action Button
+    # ------------------------------------------------------
+    def update_liasse_fiscale(self):
+        bordereau_id = self.bordereau_id
+        # Link new liasse fiscale to bordereau
+        bordereau_id.update({
+            'liasse_fiscale_id': self.liasse_fiscale_new_id,
+        })
+        bordereau_id.update_cotiz_and_lines()
+        # Return Action
+        action = {
+            'type': 'ir.actions.act_window',
+            'res_model': 'scop.bordereau',
+            'view_mode': 'form',
+            'res_id': bordereau_id.id,
+        }
+        return action
diff --git a/wizard/scop_cotisation_cg_change_liasse_wizard.xml b/wizard/scop_cotisation_cg_change_liasse_wizard.xml
new file mode 100644
index 0000000..82bd9de
--- /dev/null
+++ b/wizard/scop_cotisation_cg_change_liasse_wizard.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+    <!--  Copyright 2021 Le Filament
+          License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).  -->
+    <data>
+
+        <record id="scop_cotisation_change_liasse_wizard_form_view" model="ir.ui.view">
+            <field name="name">scop.cotisation.change.liasse.wizard.form</field>
+            <field name="model">scop.cotisation.change.liasse.wizard</field>
+            <field name="arch" type="xml">
+                <form string="Changement de liasse">
+                    <sheet>
+                        <div class="row">
+                            <div class="col-6">
+                                <group string="Données initiales" class="text-muted">
+                                    <field name="liasse_fiscale_id" options='{"no_open": True}'/>
+                                    <hr/>
+                                    <field name="amount_total_cotiz"/>
+                                    <field name="amount_cg"/>
+                                    <field name="amount_ur_med" attrs="{'invisible':[('amount_ur_med','=',0)]}"/>
+                                    <field name="amount_ur_hdf" attrs="{'invisible':[('amount_ur_hdf','=',0)]}"/>
+                                    <field name="amount_fede_com" attrs="{'invisible':[('amount_fede_com','=',0)]}"/>
+                                    <field name="amount_fede_cae" attrs="{'invisible':[('amount_fede_cae','=',0)]}"/>
+                                    <hr/>
+                                    <field name="type_assiette"/>
+                                    <field name="montant_assiette"/>
+                                    <hr/>
+                                    <field name="ca"/>
+                                    <field name="va"/>
+                                    <field name="net_results"/>
+                                    <field name="wage_cg"/>
+                                </group>
+                            </div>
+                            <div class="col-6">
+                                <group>
+                                    <field name="liasse_fiscale_new_id" options='{"no_open": True, "no_create":True}'/>
+                                </group>
+                                <group string="Nouveaux calculs (Sans arrondi)" attrs="{'invisible':[('liasse_fiscale_new_id','=',False)]}">
+                                    <field name="amount_total_cotiz_new"/>
+                                    <field name="amount_cg_new"/>
+                                    <field name="amount_ur_med_new" attrs="{'invisible':[('amount_ur_med_new','=',0)]}"/>
+                                    <field name="amount_ur_hdf_new" attrs="{'invisible':[('amount_ur_hdf_new','=',0)]}"/>
+                                    <field name="amount_fede_com_new" attrs="{'invisible':[('amount_fede_com_new','=',0)]}"/>
+                                    <field name="amount_fede_cae_new" attrs="{'invisible':[('amount_fede_cae_new','=',0)]}"/>
+                                    <hr/>
+                                    <field name="type_assiette_new"/>
+                                    <field name="montant_assiette_new"/>
+                                    <hr/>
+                                    <field name="ca_new"/>
+                                    <field name="va_new"/>
+                                    <field name="net_results_new"/>
+                                    <field name="wage_cg_new"/>
+                                </group>
+                            </div>
+                        </div>
+                    </sheet>
+                    <footer>
+                        <button name="update_liasse_fiscale" type="object"  string="Modifier la liasse" class="oe_highlight" confirm="Confirmer le changement de liasse"/>
+                        <button string="Annuler" special="cancel" class="oe_link"/>
+                    </footer>
+                </form>
+            </field>
+        </record>
+
+        <record id="scop_cotisation_change_liasse_wizard_act_window" model="ir.actions.act_window">
+            <field name="name">Changement liasse bordereau</field>
+            <field name="type">ir.actions.act_window</field>
+            <field name="res_model">scop.cotisation.change.liasse.wizard</field>
+            <field name="view_type">form</field>
+            <field name="view_mode">form</field>
+            <field name="target">new</field>
+        </record>
+
+    </data>
+</odoo>
\ No newline at end of file
-- 
GitLab