diff --git a/__manifest__.py b/__manifest__.py index 6473c94ae0f68e13e81e26b86567ba6e46273d6c..c20d0d86f8080d0f2ca9378d82a709c4e4b13954 100755 --- a/__manifest__.py +++ b/__manifest__.py @@ -18,6 +18,7 @@ "views/res_config_settings.xml", "views/scop_bordereau_cg.xml", "views/scop_cotisation_cg.xml", + "views/scop_cotisation_cg_task.xml", "views/union_regionale.xml", ] } diff --git a/models/__init__.py b/models/__init__.py index acfb330ac3a306fb874954cfd949a61a302c7f06..121d01a45839e3a7dee484624b8fb208d5dac7b4 100755 --- a/models/__init__.py +++ b/models/__init__.py @@ -6,4 +6,5 @@ from . import res_company from . import res_config_settings from . import scop_bordereau_cg from . import scop_cotisation_cg +from . import scop_cotisation_cg_task from . import union_regionale diff --git a/models/res_config_settings.py b/models/res_config_settings.py index 67ae9b3062021af2b59a12f65bb7ada9bbfa8970..ba2374e6c2b6b70ae1a57740f62d20bbe096c9e2 100644 --- a/models/res_config_settings.py +++ b/models/res_config_settings.py @@ -58,9 +58,12 @@ class CotisationsConfigSettings(models.TransientModel): 'cgscop_cotisation_cg.menu_scop_cotisation_cg_calcul') menu_bordereaux_cg = self.env.ref( 'cgscop_cotisation_cg.scop_bordereau_menu') + menu_cotiz_cg_task = self.env.ref( + 'cgscop_cotisation_cg.menu_scop_cotisation_cg_list_task') bool_condition = self.is_contribution_cg self.add_company_to_menu(menu_appels_cotiz_cg, bool_condition) self.add_company_to_menu(menu_cotiz_cg, bool_condition) self.add_company_to_menu(menu_bordereaux_cg, bool_condition) + self.add_company_to_menu(menu_cotiz_cg_task, bool_condition) return res diff --git a/models/scop_cotisation_cg.py b/models/scop_cotisation_cg.py index 243cc1bff6d046e6cae38e9fcd2a1844e94604fa..4bff2088f97544246d95c86c8124dc08439e237e 100644 --- a/models/scop_cotisation_cg.py +++ b/models/scop_cotisation_cg.py @@ -2,9 +2,14 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). import json -from odoo import models, fields, api, exceptions +import logging +import threading from datetime import date +from odoo import models, fields, api, exceptions, registry + +_logger = logging.getLogger(__name__) + class ScopCotisation(models.Model): _inherit = "scop.cotisation" @@ -231,22 +236,6 @@ class ScopCotisation(models.Model): raise exceptions.UserError( "La cotisation CG Scop n'est pas configurée.") - # Definition of specific params - # CG - product_cg = self.company_id.contribution_cg_id - type_cotisation_cg = self.env.ref('cgscop_partner.riga_14397') - # Fede - product_fede = self.company_id.contribution_fede_id - type_cotisation_fede = self.env.ref('cgscop_partner.riga_14398') - # UR HDF - product_hdf = self.company_id.contribution_hdf_id - ur_hdf = self.env.ref('cgscop_partner.riga_14232') - # UR Med - product_med = self.company_id.contribution_med_id - ur_med = self.env.ref('cgscop_partner.riga_14238') - # - type_cotisation_ur = self.env.ref('cgscop_partner.riga_14399') - # List of members already invoiced member_invoiced = self.invoice_ids.mapped('partner_id') @@ -257,55 +246,51 @@ class ScopCotisation(models.Model): # TODO: enlever limit members_to_invoice = (members - member_invoiced)[:10] - # Creation of cotiz invoice for each member - for member in members_to_invoice: - liasse_id = self._get_liasse(member) - - # Bordereau - bordereau_id = self.create_bordereau(member) - - # Invoice cotiz CG - amount_cg = self.get_cotiz_cg(member, liasse_id) - invoice_cotiz_cg = self.create_contribution( - product_cg, member, liasse_id, amount_cg) - invoice_cotiz_cg.write({ - 'type_contribution_id': type_cotisation_cg.id, - 'cotisation_cg_id': self.id, - 'bordereau_id': bordereau_id.id + if len(members_to_invoice) > 0: + message = ( + "<h3>Appels de cotisation " + str(self.year) + + "</h3> <hr/>" + + "Nombre d'adhérents renouvelés : " + + str(self.member_count) + + # "<br/>Nombre de nouveaux adhérents : " + + # str(self.new_member_count) + + "<br/>Bordereaux déjà générées : " + + str(self.invoiced_member_count) + + "<br/>Bordereaux à générer : " + + str(len(members_to_invoice)) + + "<p>Les appels de cotisation sont en cours de " + "création...</p> " + ) + message_id = self.env['message.wizard'].create( + {'message': message}) + + # Création de la task + cotiz_cg_task = self.env['scop.cotisation.cg.task'].create({ + 'year': self.year, + 'cotiz_to_create': len(members_to_invoice), + 'message': "En cours de création", + 'status': 'in_process' }) + cotiz_cg_task.env.cr.commit() + # Lancement du calcul en arrière plan + threaded_cotiz = threading.Thread( + target=self._process_cotiz_generate, + args=(members_to_invoice, cotiz_cg_task)) + threaded_cotiz.start() + else: + message = ("<p class='text-center'>Tous les appels de " + + "cotisations annuels ont déjà été créés !</p>") + message_id = self.env['message.wizard'].create( + {'message': message}) - # Invoice cotiz Fede - if member.is_federation_com: - amount_fede = self.get_cotiz_fede(member, liasse_id) - invoice_cotiz_fede = self.create_contribution( - product_fede, member, liasse_id, amount_fede) - invoice_cotiz_fede.write({ - 'type_contribution_id': type_cotisation_fede.id, - 'cotisation_cg_id': self.id, - 'bordereau_id': bordereau_id.id - }) - - # Invoice cotiz UR HDF - if member.ur_id.id == ur_hdf.id: - amount_hdf = self.get_cotiz_hdf(member, liasse_id) - invoice_cotiz_hdf = self.create_contribution( - product_hdf, member, liasse_id, amount_hdf) - invoice_cotiz_hdf.write({ - 'type_contribution_id': type_cotisation_ur.id, - 'cotisation_cg_id': self.id, - 'bordereau_id': bordereau_id.id - }) - - # Invoice cotiz UR Med - if member.ur_id.id == ur_med.id: - amount_med = self.get_cotiz_med(member, liasse_id) - invoice_cotiz_med = self.create_contribution( - product_med, member, liasse_id, amount_med) - invoice_cotiz_med.write({ - 'type_contribution_id': type_cotisation_ur.id, - 'cotisation_cg_id': self.id, - 'bordereau_id': bordereau_id.id - }) + return { + 'name': 'Génération des appels de cotisation annuels', + 'type': 'ir.actions.act_window', + 'view_mode': 'form', + 'res_model': 'message.wizard', + 'res_id': message_id.id, + 'target': 'new' + } def cotiz_view(self): tree_id = self.env.ref( @@ -383,7 +368,7 @@ class ScopCotisation(models.Model): return members @api.multi - def _get_liasse(self, member): + def get_liasse(self, member): self.ensure_one() liasse_id = self.env['scop.liasse.fiscale'].search([ ('partner_id', '=', member.id) @@ -584,3 +569,120 @@ class ScopCotisation(models.Model): cotiz = [(assiette * rate) + (net_results * 0.01)] * abatt_rate return cotiz + + # ------------------------------------------------------ + # Threading task + # ------------------------------------------------------ + def _process_cotiz_generate(self, partner_ids, cotiz_cg_task): + """ + Process de génération des cotiz CG en background + """ + cotiz_created = 0 + cotiz_to_create = len(partner_ids) + + # Creation of cotiz invoice for each member + with api.Environment.manage(): + with registry(self.env.cr.dbname).cursor() as new_cr: + # Def new env + new_env = api.Environment( + new_cr, self.env.uid, self.env.context + ) + # Def new var in new env + task = cotiz_cg_task.with_env(new_env) + new_self = self.with_env(new_env) + # Definition of specific params + # CG + product_cg_id = new_self.company_id.contribution_cg_id + type_cotisation_cg = new_self.env.ref( + 'cgscop_partner.riga_14397').id + # Fede + product_fede_id = new_self.company_id.contribution_fede_id + type_cotisation_fede = new_self.env.ref( + 'cgscop_partner.riga_14398').id + # UR HDF + product_hdf_id = new_self.company_id.contribution_hdf_id + ur_hdf = new_self.env.ref('cgscop_partner.riga_14232').id + # UR Med + product_med_id = new_self.company_id.contribution_med_id + ur_med = new_self.env.ref('cgscop_partner.riga_14238').id + # + type_cotisation_ur = new_self.env.ref( + 'cgscop_partner.riga_14399').id + + for member_id in partner_ids: + member = member_id.with_env(new_env) + try: + liasse_id = new_self.get_liasse(member) + + # Bordereau + bordereau_id = new_self.create_bordereau(member) + + # Invoice cotiz CG + amount_cg = new_self.get_cotiz_cg(member, liasse_id) + invoice_cotiz_cg = new_self.create_contribution( + product_cg_id, member, liasse_id, amount_cg) + invoice_cotiz_cg.write({ + 'type_contribution_id': type_cotisation_cg, + 'cotisation_cg_id': new_self.id, + 'bordereau_id': bordereau_id.id + }) + + # Invoice cotiz Fede + if member.is_federation_com: + amount_fede = new_self.get_cotiz_fede( + member, liasse_id) + invoice_cotiz_fede = new_self.create_contribution( + product_fede_id, member, liasse_id, + amount_fede) + invoice_cotiz_fede.write({ + 'type_contribution_id': type_cotisation_fede, + 'cotisation_cg_id': new_self.id, + 'bordereau_id': bordereau_id.id + }) + + # Invoice cotiz UR HDF + if member.ur_id.id == ur_hdf: + amount_hdf = new_self.get_cotiz_hdf( + member, liasse_id) + invoice_cotiz_hdf = new_self.create_contribution( + product_hdf_id, member, liasse_id, amount_hdf) + invoice_cotiz_hdf.write({ + 'type_contribution_id': type_cotisation_ur, + 'cotisation_cg_id': new_self.id, + 'bordereau_id': bordereau_id.id + }) + + # Invoice cotiz UR Med + if member.ur_id.id == ur_med: + amount_med = new_self.get_cotiz_med( + member, liasse_id) + invoice_cotiz_med = new_self.create_contribution( + product_med_id, member, liasse_id, amount_med) + invoice_cotiz_med.write({ + 'type_contribution_id': type_cotisation_ur, + 'cotisation_cg_id': new_self.id, + 'bordereau_id': bordereau_id.id + }) + + cotiz_created += 1 + task.write({ + 'cotiz_created': cotiz_created, + }) + if cotiz_created == cotiz_to_create: + task.write({ + 'message': "Tous les appels de cotisaions ont" + " été créés", + 'status': "done" + }) + invoice_cotiz_cg.env.cr.commit() + task.env.cr.commit() + except Exception as e: + _logger.exception(str(e)) + task.write({ + 'cotiz_created': cotiz_created, + 'message': "%d / %d ont été créés" % ( + cotiz_created, cotiz_to_create), + 'is_error': True, + 'status': "done" + }) + task.env.cr.commit() diff --git a/models/scop_cotisation_cg_task.py b/models/scop_cotisation_cg_task.py new file mode 100644 index 0000000000000000000000000000000000000000..d0b4b4dd2e4296a9797350ac6129c6013c71f4c2 --- /dev/null +++ b/models/scop_cotisation_cg_task.py @@ -0,0 +1,19 @@ +# © 2021 Le Filament (<http://www.le-filament.com>) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class CotisationCGTask(models.Model): + _name = 'scop.cotisation.cg.task' + _description = 'Gestion des créations des cotisations CG' + + year = fields.Integer('Année') + message = fields.Char("Message") + cotiz_created = fields.Integer("Appels de cotisation créés") + cotiz_to_create = fields.Integer("Appels de cotisation à créer") + is_error = fields.Boolean('En erreur', default=False) + status = fields.Selection([ + ('in_process', 'En cours'), + ('done', 'Terminé') + ], string='Statut') diff --git a/security/ir.model.access.csv b/security/ir.model.access.csv index 36996cc0cf79a2e5a9767ea4adc01eaee08221b6..47ea0c32b19bfe124174dc152b7c6a7c7bc7930e 100755 --- a/security/ir.model.access.csv +++ b/security/ir.model.access.csv @@ -1,5 +1,7 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_scop_cotisation_cg,access_scop_cotisation_cg,model_scop_cotisation_cg,account.group_account_manager,1,1,1,0 admin_access_scop_cotisation_cg,admin_access_scop_cotisation_cg,model_scop_cotisation_cg,cgscop_partner.group_cg_administrator,1,1,1,1 +access_scop_cotisation_cg_task,access_scop_cotisation_cg_task,model_scop_cotisation_cg_task,account.group_account_manager,1,1,1,0 +admin_access_scop_cotisation_cg_task,admin_access_scop_cotisation_cg_task,model_scop_cotisation_cg_task,cgscop_partner.group_cg_administrator,1,1,1,1 access_scop_bordereau,access_scop_bordereau,model_scop_bordereau,account.group_account_manager,1,1,1,0 admin_access_scop_bordereau,admin_access_scop_bordereau,model_scop_bordereau,cgscop_partner.group_cg_administrator,1,1,1,1 diff --git a/views/scop_cotisation_cg_task.xml b/views/scop_cotisation_cg_task.xml new file mode 100644 index 0000000000000000000000000000000000000000..013cece1dfad36e80ffd5b0f0460a8f821846ec0 --- /dev/null +++ b/views/scop_cotisation_cg_task.xml @@ -0,0 +1,40 @@ +<?xml version="1.0"?> +<!-- Copyright 2021 Le Filament + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> + +<odoo> + <data> + + <!-- TREE VIEW --> + <record model="ir.ui.view" id="view_scop_cotisation_aura_task_tree"> + <field name="name">scop.cotisation.cg.task.tree</field> + <field name="model">scop.cotisation.cg.task</field> + <field name="arch" type="xml"> + <tree create="false" string="Taches création cotisations CG"> + <field name="create_date"/> + <field name="year"/> + <field name='status'/> + <field name='cotiz_created'/> + <field name='cotiz_to_create'/> + <field name='is_error'/> + <field name="message"/> + </tree> + </field> + </record> + + <!-- ACTIONS VIEWS--> + <record model="ir.actions.act_window" id="action_scop_cotisation_cg_task"> + <field name="name">Taches cotisation CG</field> + <field name="res_model">scop.cotisation.cg.task</field> + <field name="view_mode">tree,form</field> + </record> + + <!-- MENU --> + <menuitem id="menu_scop_cotisation_cg_list_task" + parent="account.menu_finance_configuration" + name="Taches création cotisations CG" + sequence="50" + action="action_scop_cotisation_cg_task"/> + + </data> +</odoo> \ No newline at end of file