diff --git a/__manifest__.py b/__manifest__.py index eb51915aa96469343c266e9deb43f88f2dbe1d76..7fcc52ee63a6be8d80473efa1279ca24192455ac 100755 --- a/__manifest__.py +++ b/__manifest__.py @@ -11,12 +11,14 @@ "l10n_fr", "lefilament_export_journal_tool", "cgscop_cotisation", + "queue_job_batch", ], "data": [ # Security "security/security_rules.xml", "security/ir.model.access.csv", "datas/mail_data.xml", + "datas/queue_job_data.xml", "datas/ir_sequence_data.xml", # Reports "report/report_scop_bordereau.xml", diff --git a/datas/queue_job_data.xml b/datas/queue_job_data.xml new file mode 100644 index 0000000000000000000000000000000000000000..01f22859e7e811dfc5d607083dc3a157edc9db19 --- /dev/null +++ b/datas/queue_job_data.xml @@ -0,0 +1,24 @@ +<?xml version="1.0"?> +<!-- Copyright 2021 Le Filament (<https://www.le-filament.com>) + License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). --> +<odoo> + <data noupdate="1"> + + <record id="job_function_cotisation_cg_create_bordereau" model="queue.job.function"> + <field name="model_id" ref="cgscop_cotisation_cg.model_scop_cotisation_cg" /> + <field name="method">create_bordereau</field> + <field name="channel_id" ref="queue_job.channel_root" /> + <field name="related_action" eval='{"func_name": "related_action_custom", "kwargs": {"model": "scop.bordereau", "record": "result"}}' /> + <field name="retry_pattern" eval="{1: 10, 5: 30, 10: 300}" /> + </record> + + <record id="job_function_cotisation_cg_validate_bordereau" model="queue.job.function"> + <field name="model_id" ref="cgscop_cotisation_cg.model_scop_bordereau" /> + <field name="method">validate_bordereau</field> + <field name="channel_id" ref="queue_job.channel_root" /> + <field name="related_action" eval='{"func_name": "related_action_custom", "kwargs": {"record": "result"}}' /> + <field name="retry_pattern" eval="{1: 10, 5: 30, 10: 300}" /> + </record> + + </data> +</odoo> \ No newline at end of file diff --git a/models/scop_bordereau_cg.py b/models/scop_bordereau_cg.py index cd0960f3dca21fce41cce7c3b4330ebc2133c407..ec3728614fc2b2b3cb6992dabfd8ab8675a531d7 100644 --- a/models/scop_bordereau_cg.py +++ b/models/scop_bordereau_cg.py @@ -382,16 +382,28 @@ class Bordereau(models.Model): inv.action_invoice_open() def validate_bordereau(self): + """ + Affecte le nom du bordereau avec la séquence et valide les invoices + """ self.ensure_one() if self.name == 'Brouillon': self.name = self.env['ir.sequence'].next_by_code('scop.bordereau') self.validate_cotiz_cg() + return self.id @api.multi def validate_bordereau_multi(self): - threaded_validate_bordereau = threading.Thread( - target=self.process_bordereau_validate) - threaded_validate_bordereau.start() + """ + Utilise job queue pour valider les bordereaux + """ + batch_name = (fields.Datetime.to_string(fields.Datetime.now()) + + " Validation bordereaux ") + batch = self.env['queue.job.batch'].get_new_batch(batch_name) + for bordereau in self: + bordereau.with_context( + job_batch=batch + ).with_delay().validate_bordereau() + batch.enqueue() @api.multi def print_bordereau(self): @@ -472,6 +484,9 @@ class Bordereau(models.Model): return action def action_show_cotiz(self): + """ + :return: Ouvre la vue des cotisations liées au bordereau + """ tree_view_id = self.env.ref( 'cgscop_cotisation.invoice_tree_scop_inherited').id form_view_id = self.env.ref( @@ -490,6 +505,9 @@ class Bordereau(models.Model): } def action_change_liasse(self): + """ + :return: Ouvre le wizard pour changer la liasse + """ wizard = self.env['scop.bordereau.change.liasse.wizard']. \ create({ 'bordereau_id': self.id, @@ -505,10 +523,13 @@ class Bordereau(models.Model): } def action_change_payment_mode(self): + """ + :return: Ouvre le wizard pour changer le mode de paiement + """ wizard = self.env['scop.bordereau.change.payment.mode.wizard']. \ create({ - 'bordereau_id': self.id, - }) + 'bordereau_id': self.id, + }) return { 'type': 'ir.actions.act_window', 'name': 'Changer le mode de paiement', @@ -520,6 +541,11 @@ class Bordereau(models.Model): } def validate_ongoing_bordereau(self): + """ + - Valide les invoices en brouillon + - Met à jour le numéro de version du bordereau + - Valide le versionnage en cours + """ self.ensure_one() ongoing_version = self.check_ongoing_version() self.validate_bordereau() @@ -532,6 +558,11 @@ class Bordereau(models.Model): }) def cancel_ongoing_bordereau(self): + """ + - Supprime les invoice en brouillon + - Réaffecte la dernière liasse fiscale (enregistrée dans la version) + - Supprime le versionnage en cours + """ self.ensure_one() self.invoice_ids.filtered( lambda i: i.state == 'draft' @@ -564,6 +595,9 @@ class Bordereau(models.Model): # Global Functions # ------------------------------------------------------ def check_ongoing_version(self): + """ + :return: le versionnage en cours + """ ongoing_version = self.bordereau_version_ids.filtered( lambda v: v.version == self.version and v.state == 'new' ) @@ -672,20 +706,3 @@ class Bordereau(models.Model): def get_recipients(self): recipients = ','.join(map(lambda x: str(x), self.recipient_ids.ids)) return recipients - - # ------------------------------------------------------ - # Threading task - # ------------------------------------------------------ - def process_bordereau_validate(self): - 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 - ) - for bordereau in self.with_env(new_env): - try: - bordereau.validate_bordereau() - bordereau.env.cr.commit() - except Exception as e: - _logger.exception(str(e)) diff --git a/models/scop_cotisation_cg.py b/models/scop_cotisation_cg.py index 6f6960597cbda30b89f92aa85b5351489cf0183c..6ec2f6e2eb69ddb4f319b890de3687138e141682 100644 --- a/models/scop_cotisation_cg.py +++ b/models/scop_cotisation_cg.py @@ -4,12 +4,11 @@ import base64 import json import logging -import threading import xlsxwriter from io import BytesIO from datetime import datetime -from odoo import models, fields, api, exceptions, registry +from odoo import models, fields, api, exceptions _logger = logging.getLogger(__name__) @@ -242,19 +241,18 @@ class ScopCotisation(models.Model): """ members_to_invoice = self.env['res.partner'].browse(*ids) - # Création de la task - cotiz_cg_task = self.env['scop.cotisation.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() + # Job queue + batch_name = (fields.Datetime.to_string(fields.Datetime.now()) + + " Génération des bordereaux " + str(self.year)) + batch = self.env['queue.job.batch'].get_new_batch(batch_name) + for member in members_to_invoice: + liasse_id = self.get_liasse(member) + self.with_context( + job_batch=batch + ).with_delay().create_bordereau( + member=member, liasse=liasse_id, + nb_quarter=4, date=False) + batch.enqueue() def cotiz_generate_wizard(self): if not self.trimester_1 or not self.trimester_2 or not self.trimester_3 or not self.trimester_4: @@ -332,11 +330,11 @@ class ScopCotisation(models.Model): :param date: :return bordereau_id: """ - existing_bordereau = self.env['scop.bordereau'].search([ + bordereau = self.env['scop.bordereau'].search([ ('partner_id', '=', member.id), ('year', '=', self.year), ]) - if not existing_bordereau or is_regul: + if not bordereau or is_regul: # Variables to calculate cotiz staff_id = self.get_last_staff_id(member) if staff_id: @@ -361,9 +359,8 @@ class ScopCotisation(models.Model): 'staff_shareholder_count': staff_shareholder_count, 'staff_average': staff_average, }) - return bordereau - else: - return existing_bordereau + self.create_cotiz_and_lines(bordereau) + return bordereau.id def bordereau_validate(self): bordereau_to_validate = self.bordereau_ids.filtered( @@ -873,62 +870,3 @@ class ScopCotisation(models.Model): else: type_cotiz = 'ca' return type_cotiz - - # ------------------------------------------------------ - # Threading task - # ------------------------------------------------------ - def process_cotiz_generate(self, partner_ids, cotiz_cg_task, - nb_quarter=4, date=False): - """ - 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) - - # Creation of cotiz invoice for each member - for member_id in partner_ids: - member = member_id.with_env(new_env) - liasse_id = new_self.get_liasse(member) - try: - # Bordereau - bordereau = new_self.create_bordereau( - member=member, liasse=liasse_id, - nb_quarter=nb_quarter, date=date) - bordereau.env.cr.commit() - - # Cotisations - new_self.create_cotiz_and_lines(bordereau) - - cotiz_created += 1 - task.write({ - 'cotiz_created': cotiz_created, - 'message': "%d / %d ont été créés" % ( - cotiz_created, cotiz_to_create), - }) - if cotiz_created == cotiz_to_create: - task.write({ - 'message': "Tous les bordereaux ont été créés", - 'status': "done" - }) - 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/wizard/scop_cotisation_cg_wizard.py b/wizard/scop_cotisation_cg_wizard.py index a81e48473456e85387c2ce5c1f7a27ca4b6eba88..6d95f817006e42734621f7ecaea64a64b7538949 100644 --- a/wizard/scop_cotisation_cg_wizard.py +++ b/wizard/scop_cotisation_cg_wizard.py @@ -2,7 +2,6 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). import logging -import threading from odoo import api, fields, models, exceptions @@ -87,20 +86,20 @@ class ScopCotisationWizard(models.TransientModel): message_id = self.env['message.wizard'].create( {'message': message}) - # Création de la task - cotiz_cg_task = self.env['scop.cotisation.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.cotisation_cg_id.process_cotiz_generate, - args=(members_to_invoice, cotiz_cg_task, - self.nb_quarter, self.date)) - threaded_cotiz.start() + # Job queue + batch_name = (fields.Datetime.to_string(fields.Datetime.now()) + + " Génération des bordereaux " + + str(self.cotisation_cg_id.year)) + batch = self.env['queue.job.batch'].get_new_batch(batch_name) + for member in members_to_invoice: + liasse_id = self.cotisation_cg_id.get_liasse(member) + self.cotisation_cg_id.with_context( + job_batch=batch + ).with_delay().create_bordereau( + member=member, liasse=liasse_id, + nb_quarter=self.nb_quarter, date=self.date) + batch.enqueue() + else: message = ("<p class='text-center'>Tous les bordereaux pour les " "coops qui ont adhéré cette année avant le %s ont "