From 5765df18a8047174bd086bca3d1f996026033ff0 Mon Sep 17 00:00:00 2001 From: benjamin <benjamin@le-filament.com> Date: Mon, 13 Dec 2021 18:34:01 +0100 Subject: [PATCH] [add] review all module to add calculation process, exo lines, template, scop_bordereau inheritance --- __init__.py | 5 +- __manifest__.py | 15 +- datas/ir_sequence_data.xml | 9 +- datas/mail_data.xml | 63 ---- models/__init__.py | 4 + models/res_partner.py | 15 + models/scop_bordereau.py | 57 +++ models/scop_cotisation_cg.py | 34 ++ models/scop_cotisation_cg_exo.py | 328 +++++++++++++++++- models/scop_cotisation_cg_exo_line.py | 38 ++ security/ir.model.access.csv | 7 +- security/security_rules.xml | 29 +- templates/report_scop_exo.xml | 55 ++- views/res_partner.xml | 55 +++ views/scop_bordereau_cg.xml | 224 +----------- views/scop_cotisation_cg_exo.xml | 81 ++++- wizard/__init__.py | 4 + wizard/scop_bordereau_update_liasse_wizard.py | 18 + 18 files changed, 694 insertions(+), 347 deletions(-) delete mode 100644 datas/mail_data.xml create mode 100644 models/res_partner.py create mode 100644 models/scop_bordereau.py create mode 100644 models/scop_cotisation_cg.py create mode 100644 models/scop_cotisation_cg_exo_line.py create mode 100644 views/res_partner.xml create mode 100755 wizard/__init__.py create mode 100644 wizard/scop_bordereau_update_liasse_wizard.py diff --git a/__init__.py b/__init__.py index dc5e6b6..f8a7089 100755 --- a/__init__.py +++ b/__init__.py @@ -1,4 +1,5 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. +# © 2021 Le Filament (<http://www.le-filament.com>) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from . import models +from . import wizard diff --git a/__manifest__.py b/__manifest__.py index f4f578d..fa07e41 100755 --- a/__manifest__.py +++ b/__manifest__.py @@ -11,17 +11,18 @@ "cgscop_instance", ], "data": [ - # SECURITY - # "security/security_rules.xml", + # security + "security/security_rules.xml", "security/ir.model.access.csv", - # DATAS + # datas "datas/exo_ur_notice_data.xml", - # "datas/mail_data.xml", - # "datas/ir_sequence_data.xml", - # VIEWS + "datas/ir_sequence_data.xml", + # views + "views/res_partner.xml", + "views/scop_bordereau_cg.xml", "views/scop_cotisation_cg_exo.xml", "views/scop_cotisation_cg_exo_ur_notice.xml", - # TEMPLATES + # templates "templates/report_scop_exo.xml" ] } diff --git a/datas/ir_sequence_data.xml b/datas/ir_sequence_data.xml index b4fc35a..3a5abd7 100644 --- a/datas/ir_sequence_data.xml +++ b/datas/ir_sequence_data.xml @@ -1,12 +1,15 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2019 Le Filament + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> <odoo> <data noupdate="1"> - <record id="seq_scop_bordereau" model="ir.sequence"> - <field name="name">SCOP EXONERATION Séquence</field> + <!-- Sequences for scop.cotisation.cg.exo --> + <record id="seq_scop_cotisation_cg_exo" model="ir.sequence"> + <field name="name">CG Scop - Séquence Exonérations</field> <field name="code">scop.cotisation.cg.exo</field> + <field name="prefix">EXO-%(year)s-</field> <field name="padding">4</field> - <field name="prefix">EXO%(year)s</field> <field name="company_id" ref="base.main_company"/> </record> diff --git a/datas/mail_data.xml b/datas/mail_data.xml deleted file mode 100644 index 74c5b65..0000000 --- a/datas/mail_data.xml +++ /dev/null @@ -1,63 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<odoo> - <data noupdate="0"> - - <!-- Template and notification section --> - - <record id="email_template_cotisation_cg" model="mail.template"> - <field name="name">CG Scop - Mail cotisations CG</field> - <field name="model_id" ref="cgscop_cotisation_cg.model_scop_bordereau"/> - <field name="email_from">${object.env.user.email_formatted |safe}</field> - <field name="partner_to">${object.get_recipients()}</field> - <field name="subject">Appel de cotisations ${object.year}</field> - <field name="body_html" type="html"> - <div style="margin: 0px; padding: 0px;"> - <p style="margin: 0px; padding: 0px; font-size: 13px;"> - <p>Chère Coopératrice, Cher Coopérateur,</p> - - <p>Cotisation sur votre espace extranet : lien</p> - - <p>Nous vous prions d'agréer, Chère Coopératrice, Cher Coopérateur, nos sentiments les meilleurs.</p> - - <p>Pour la CG Scop,</p> - - <p>JACQUES LANDRIOT</p> - <p>Président</p> - </p> - </div> - </field> - <field name="lang">${object.partner_id.lang}</field> - <field name="user_signature" eval="False"/> - <field name="auto_delete" eval="False"/> - </record> - - -<!-- <record id="email_template_send_again" model="mail.template">--> -<!-- <field name="name">CG Scop - Liste Ministere: Renvoyer le dossier</field>--> -<!-- <field name="model_id" ref="cgscop_liste_ministere.model_liste_ministere"/>--> -<!-- <field name="email_from">${object.user_id.email_formatted |safe}</field>--> -<!-- <field name="partner_to">${object.get_recipients()}</field>--> -<!-- <field name="subject">Dossier incomplet</field>--> -<!-- <field name="body_html" type="html">--> -<!-- <div style="margin: 0px; padding: 0px;">--> -<!-- <p style="margin: 0px; padding: 0px; font-size: 13px;">--> -<!-- <p>Madame, Monsieur,</p>--> -<!-- --> -<!-- <p>Nous accusons réception de votre dossier de demande de renouvellement d’inscription sur la Liste Ministère, parvenu à la Confédération Générale des Scop qui n’est pas la année de clôture d’exercice demandé<br/>--> -<!-- Nous vous indiquons que votre dossier doit être complété par les pièces suivantes :</p>--> - -<!-- <p>Nous vous invitons à nous retourner ces documents dans les meilleurs délais.</p>--> -<!-- --> -<!-- <p>Dans l’attente de votre retour, nous restons à votre disposition pour toute précision utile.</p>--> -<!-- --> -<!-- <p>Très cordialement</p>--> -<!-- </p>--> -<!-- </div>--> -<!-- </field>--> -<!-- <field name="lang">${object.partner_id.lang}</field>--> -<!-- <field name="user_signature" eval="False"/>--> -<!-- <field name="auto_delete" eval="False"/>--> -<!-- </record>--> - - </data> -</odoo> diff --git a/models/__init__.py b/models/__init__.py index b91725d..9bd897d 100755 --- a/models/__init__.py +++ b/models/__init__.py @@ -1,5 +1,9 @@ # © 2021 Le Filament (<http://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from . import res_partner +from . import scop_bordereau +from . import scop_cotisation_cg from . import scop_cotisation_cg_exo_ur_notice from . import scop_cotisation_cg_exo +from . import scop_cotisation_cg_exo_line diff --git a/models/res_partner.py b/models/res_partner.py new file mode 100644 index 0000000..3d0a346 --- /dev/null +++ b/models/res_partner.py @@ -0,0 +1,15 @@ +# © 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 ResPartner(models.Model): + _inherit = 'res.partner' + + exo_ids = fields.One2many( + comodel_name='scop.cotisation.cg.exo', + inverse_name='partner_id', + domain=[('state', '=', 'done')], + string='Exonérations' + ) diff --git a/models/scop_bordereau.py b/models/scop_bordereau.py new file mode 100644 index 0000000..644c7bf --- /dev/null +++ b/models/scop_bordereau.py @@ -0,0 +1,57 @@ +# © 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, api + + +class ScopBordereau(models.Model): + _inherit = 'scop.bordereau' + + exo_ids = fields.Many2many( + comodel_name='scop.cotisation.cg.exo', + relation='scop_bordereau_exo_rel', + column1='bordereau_id', + column2='exo_id', + string="Exonérations" + ) + exo_count = fields.Integer( + string='Nombre d\'exonérations', + compute='_compute_exo_count' + ) + + # ------------------------------------------------------ + # Compute fields + # ------------------------------------------------------ + @api.multi + def _compute_exo_count(self): + for bdx in self: + bdx.exo_count = len(bdx.exo_ids) + + # ------------------------------------------------------ + # Button Action + # ------------------------------------------------------ + def action_show_exo(self): + """ + Ouvre la vue sur les exonérations liées + """ + return { + 'type': 'ir.actions.act_window', + 'name': 'Exonérations', + 'view_mode': 'tree,form', + 'res_model': 'scop.cotisation.cg.exo', + 'target': 'current', + 'domain': [('id', 'in', self.exo_ids.ids)], + } + + # ------------------------------------------------------ + # Override parent + # ------------------------------------------------------ + def update_bordereau_with_liasse(self): + """ + Recrée les exonérations si nécessaire + :return: + """ + super(ScopBordereau).update_bordereau_with_liasse() + if self.exo_ids: + for exo in self.exo_ids: + exo.create_exo_refund(self) diff --git a/models/scop_cotisation_cg.py b/models/scop_cotisation_cg.py new file mode 100644 index 0000000..3f8e53b --- /dev/null +++ b/models/scop_cotisation_cg.py @@ -0,0 +1,34 @@ +# © 2021 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 ScopCotisation(models.Model): + _inherit = "scop.cotisation.cg" + + # ------------------------------------------------------ + # Override parent + # ------------------------------------------------------ + def create_bordereau( + self, member, nb_quarter, liasse=None, date=False, is_regul=False): + """ + Surcharge la fonction parente pour créer les avoirs si il y a des exonérations + """ + bordereau = super(ScopCotisation, self).create_bordereau( + member, nb_quarter, liasse=liasse, date=date, is_regul=is_regul + ) + bdx_id = self.bordereau_ids.browse(bordereau) + + # Search if exo + exo_ids = self.env['scop.cotisation.cg.exo'].search([ + ('partner_id', '=', bdx_id.partner_id.id), + ('year_exo_start', '<=', bdx_id.year), + ('year_exo_end', '>=', bdx_id.year), + ('state', '=', 'done') + ]) + if exo_ids: + for exo in exo_ids: + exo.create_exo_refund(bdx_id) + + return bordereau diff --git a/models/scop_cotisation_cg_exo.py b/models/scop_cotisation_cg_exo.py index 6fc2bbf..75c55c9 100644 --- a/models/scop_cotisation_cg_exo.py +++ b/models/scop_cotisation_cg_exo.py @@ -1,9 +1,17 @@ # © 2021 Le Filament (<http://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from datetime import datetime +from datetime import datetime, date from odoo import models, fields, api +from odoo.exceptions import ValidationError, UserError + +QUARTER_SELECTION = [ + (1, '1er trimestre'), + (2, '2ème trimestre'), + (3, '3ème trimestre'), + (4, '4ème trimestre') +] class ScopCotisationExo(models.Model): @@ -12,10 +20,16 @@ class ScopCotisationExo(models.Model): _inherit = ['mail.thread', 'mail.activity.mixin'] _order = 'date_request desc' + @api.model + def get_year_selection(self): + return [ + (num, str(num)) for num in range((datetime.now().year + 3), (datetime.now().year - 10))] + name = fields.Char( string='Nom', compute='_compute_name', search='_search_name') + number = fields.Char('Référence', readonly=1, index=True, default='New') partner_id = fields.Many2one( comodel_name='res.partner', string="Coopérative", @@ -24,12 +38,6 @@ class ScopCotisationExo(models.Model): track_visibility='onchange') date_request = fields.Date('Date de la demande', required=True, track_visibility='onchange') motivation = fields.Text('Motivation de la SCOP') - type = fields.Selection([ - ('exo', 'Exonération'), - ('adjustment', 'Ajustement')], - string='Type', - default='exo', - required=True) source = fields.Selection([ ('scop', 'SCOP'), ('ur', 'UR')], @@ -46,8 +54,8 @@ class ScopCotisationExo(models.Model): default='todo', track_visibility='onchange') final_notice = fields.Selection([ - ('favorable', 'Faborable'), - ('unfavorable', 'Défaborable')], + ('favorable', 'Favorable'), + ('unfavorable', 'Défavorable')], string="Avis Final", track_visibility='onchange') ur_notice = fields.Many2one( @@ -55,8 +63,49 @@ class ScopCotisationExo(models.Model): string="Avis UR", required=True, track_visibility='onchange') - date_exo_start = fields.Date('Début Exo', required=True) - date_exo_end = fields.Date('Fin Exo', required=True) + quarter_exo_start = fields.Selection( + selection=QUARTER_SELECTION, + string='Trimestre initial' + ) + year_exo_start = fields.Selection( + selection=[(year, str(year)) for year in + range(2021, 2035)], + string='Année initiale' + ) + quarter_exo_end = fields.Selection( + selection=QUARTER_SELECTION, + string='Trimestre final' + ) + year_exo_end = fields.Selection( + selection=[(year, str(year)) for year in + range(2021, 2035)], + string='Année finale' + ) + date_exo_start = fields.Date( + string='Date Début Exo', + compute='_compute_exo_dates', + track_visibility='onchange', + store=True + ) + date_exo_end = fields.Date( + string='Date Fin Exo', + compute='_compute_exo_dates', + track_visibility='onchange', + store=True + ) + nb_quarter = fields.Integer( + string='Nb trimestres exonérés', + compute='_compute_exo_dates', + store=True + ) + type_exo = fields.Selection([ + ('amount', 'Montant'), + ('percent', 'Pourcentage')], + string="Type d'exonération", + track_visibility='onchange' + ) + amount_quarter = fields.Float('Montant souhaité pour les échéances') + percent_quarter = fields.Integer('Réduction appliquée aux échéances') date_exo_ok = fields.Date('Date Acceptation Exo') head_office_comment = fields.Text('Commentaire du bureau') note = fields.Text('Notes internes') @@ -64,10 +113,64 @@ class ScopCotisationExo(models.Model): comodel_name='scop.instance', string="Instance" ) + bordereau_ids = fields.Many2many( + comodel_name='scop.bordereau', + relation='scop_bordereau_exo_rel', + column2='bordereau_id', + column1='exo_id', + string="Bordereaux" + ) + company_id = fields.Many2one( + comodel_name='res.company', + string='Company', change_default=True, + required=True, readonly=True, + default=lambda self: self.env['res.company']._company_default_get('scop.cotisation.cg.followup')) + exo_line_ids = fields.One2many( + comodel_name='scop.cotisation.cg.exo.line', + inverse_name='exo_id', + string='Ligne Exonération' + ) # ------------------------------------------------------ # Contraintes SQL # ------------------------------------------------------ + @api.constrains('date_exo_start', 'date_exo_end') + def _check_dates(self): + for exo in self: + if exo.date_exo_start and exo.date_exo_end: + if exo.date_exo_start > exo.date_exo_end: + raise ValidationError( + "La date de fin doit êre supérieure à la date de début d'exonération.") + intersect_exo_ids = self.search([ + ('partner_id', '=', exo.partner_id.id), + ('date_exo_end', '>=', exo.date_exo_start), + ('date_exo_start', '<=', exo.date_exo_end), + ('state', '=', 'done') + ]) + if intersect_exo_ids: + raise ValidationError( + "Les périodes d'exonérations ne peuvent pas se chevaucher.") + + @api.constrains('percent_quarter') + def _check_description(self): + for exo in self: + if exo.percent_quarter < 0 or exo.percent_quarter > 100: + raise ValidationError( + "La valeur de la réduction doit être comprise entre 1 et 100") + + # ------------------------------------------------------ + # Onchange fields + # ------------------------------------------------------ + @api.onchange('instance_id') + def _onchange_instance_id(self): + if self.state in ('todo', 'waiting'): + if self.instance_id: + self.state = 'waiting' + if not self.number: + prefix = 5 - len(str(self.id)) + self.number = 'EXO-' + str(datetime.now().year) + '-' + (prefix * '0') + str(self.id) + else: + self.state = 'todo' # ------------------------------------------------------ # Compute fields @@ -86,12 +189,215 @@ class ScopCotisationExo(models.Model): ('date_request', operator, value), ] + @api.depends( + 'quarter_exo_start', 'year_exo_start', + 'quarter_exo_end', 'year_exo_end', + ) + @api.multi + def _compute_exo_dates(self): + for exo in self: + if exo.year_exo_start and exo.quarter_exo_start: + exo.date_exo_start = date(int(exo.year_exo_start), exo.quarter_exo_start * 3 - 2, 1) + if exo.year_exo_end and exo.quarter_exo_end: + end_day = 31 if exo.quarter_exo_end in (1, 4) else 30 + exo.date_exo_end = date(int(exo.year_exo_end), exo.quarter_exo_end * 3, end_day) + if exo.date_exo_start and exo.date_exo_end: + exo.nb_quarter = int( + ((exo.date_exo_end.year - exo.date_exo_start.year) * 12 + + exo.date_exo_end.month - exo.date_exo_start.month + 1) / 3) + # ------------------------------------------------------ # Button functions # ------------------------------------------------------ + def action_view_bordereau(self): + years = list(range(self.year_exo_start, self.year_exo_start + 1)) + return { + 'name': 'Bordereaux de cotisation - ' + self.partner_id.name, + 'type': 'ir.actions.act_window', + 'view_mode': 'tree,form', + 'res_model': 'scop.bordereau', + 'domain': [ + ('partner_id', '=', self.partner_id.id), + ('year', 'in', years), + ], + } + + def action_view_exo(self): + return { + 'name': 'Bordereaux avec exonération - ' + self.partner_id.name, + 'type': 'ir.actions.act_window', + 'view_mode': 'tree,form', + 'res_model': 'scop.bordereau', + 'domain': [('id', 'in', self.bordereau_ids.ids)], + } + + def create_lines(self): + self.exo_line_ids.unlink() + contrib_type = self.partner_id.get_partner_contribution_type() + + # if exo is percent => affects percent to each line + if self.type_exo == 'percent': + for contrib in contrib_type: + self.exo_line_ids.create({ + 'exo_id': self.id, + 'contribution_id': contrib.id, + 'percent': self.percent_quarter + }) + + # if exo is amount + if self.type_exo == 'amount': + # if various contribution type => affects prorate amount to each line + if len(contrib_type) > 1: + # Get last bdx for prorate calculation + last_bdx = self.env['scop.bordereau'].search([ + ('state', 'in', ['validated', 'paid']), + ('partner_id', '=', self.partner_id.id) + ], order='date_cotisation desc', limit=1) + if last_bdx: + last_amount = last_bdx.amount_total_cotiz + amount_by_type = last_bdx.get_contribution_type() + + for contrib in contrib_type: + for amount in amount_by_type: + if contrib.id == amount.get('type_contribution_id')[0]: + self.exo_line_ids.create({ + 'exo_id': self.id, + 'contribution_id': contrib.id, + 'amount': self.amount_quarter * amount.get('amount_total_signed') / last_amount + }) + else: + for contrib in contrib_type: + self.exo_line_ids.create({ + 'exo_id': self.id, + 'contribution_id': contrib.id, + 'amount': round(self.amount_quarter / len(contrib_type), 2) + }) + else: + self.exo_line_ids.create({ + 'exo_id': self.id, + 'contribution_id': contrib_type[0].id, + 'amount': self.amount_quarter + }) + def cancel_exo(self): self.state = 'cancel' + def validate_exo(self): + if not self.date_exo_ok: + raise UserError("Il est nécessaire de renseigner une date d'acceptation pour valider") + else: + # Unfavorable => nothing to do + if self.final_notice == 'unfavorable': + self.state = 'done' + + # Favorable + elif self.final_notice == 'favorable': + bordereau_ids = self.env['scop.bordereau'].search([ + ('partner_id', '=', self.partner_id.id), + ('year', 'in', list(range(self.year_exo_start, self.year_exo_end + 1))), + ('state', '!=', 'cancel') + ], order='year') + + # If no bdx on period => nothing to do + if not bordereau_ids: + self.state = 'done' + + else: + for bdx in bordereau_ids: + self.create_exo_refund(bdx) + self.state = 'done' + + else: + raise UserError("Il est nécessaire de renseigner un avis final pour valider") + + # ------------------------------------------------------ + # Override ORM + # ------------------------------------------------------ + @api.model + def create(self, vals): + if vals.get('number', 'New' == 'New'): + vals['number'] = self.env['ir.sequence'].next_by_code('scop.cotisation.cg.exo') or 'New' + result = super(ScopCotisationExo, self).create(vals) + return result + # ------------------------------------------------------ # Business functions # ------------------------------------------------------ + def get_quarters(self): + """ + Get quarters by year + @return dict(year, [quarters]) + """ + quarters = {} + if self.year_exo_start == self.year_exo_end: + quarters[self.year_exo_start] = range(self.quarter_exo_start, self.quarter_exo_end + 1) + else: + for year in range(self.year_exo_start, self.year_exo_end + 1): + if year == self.year_exo_start: + quarters[str(year)] = list(range(self.quarter_exo_start, 5)) + elif year == self.year_exo_end: + quarters[str(year)] = list(range(1, self.quarter_exo_end + 1)) + else: + quarters[str(year)] = list(range(1, 5)) + return quarters + + def create_exo_refund(self, bordereau_id): + bordereau_id.ensure_one() + exo_quarters = self.get_quarters() + # check exo period + exo_period = exo_quarters[bordereau_id.year] + + # Quarter loop + for quarter in exo_period: + # Get all invoices on specific quarter + amount_period = bordereau_id.invoice_ids.read_group( + [('bordereau_id', '=', bordereau_id.id), ('cotiz_quarter', '=', quarter)], + ['type_contribution_id', 'amount_total_signed'], + ['type_contribution_id']) + + # Get bdx schedule + base_cotiz = bordereau_id.base_cotisation_cg + bdx_quarters = [base_cotiz.trimester_1, base_cotiz.trimester_2, + base_cotiz.trimester_3, base_cotiz.trimester_4] + + # Contribution type loop + for amount_type in amount_period: + inv_type = amount_type.get('type_contribution_id')[0] + inv_amount = amount_type.get('amount_total_signed') + # Get invoice on this type (for refund creation) + inv_id = bordereau_id.invoice_ids.filtered(lambda i: i.type_contribution_id.id == inv_type)[0] + + exo_line_id = self.exo_line_ids.filtered(lambda l: l.contribution_id.id == inv_type) + + if self.type_exo == 'percent': + exo_amount = round(inv_amount * (1 - exo_line_id.percent / 100), 2) + elif self.type_exo == 'amount': + exo_amount = round(inv_amount - exo_line_id.amount, 2) + else: + raise UserError("Erreur, le type d'exonération n'est pas configuré") + + # Create refund + member_refund = bordereau_id.invoice_ids.create({ + 'partner_id': bordereau_id.partner_id.id, + 'liasse_fiscale_id': bordereau_id.liasse_fiscale_id.id, + 'type': 'out_refund', + 'year': bordereau_id.year, + 'is_contribution': True, + 'type_contribution_id': inv_type, + 'journal_id': inv_id.journal_id.id, + 'state': 'draft', + 'account_id': inv_id.account_id.id, + 'payment_mode_id': bordereau_id.payment_mode_id.id, + 'date_invoice': self.date_exo_ok, + 'date_due': bdx_quarters[quarter - 1], + 'bordereau_id': bordereau_id.id, + 'cotiz_quarter': quarter, + }) + member_refund.invoice_line_ids.create({ + 'invoice_id': member_refund.id, + 'product_id': inv_id.invoice_line_ids[0].product_id.id, + 'account_id': inv_id.invoice_line_ids[0].account_id.id, + 'name': inv_id.invoice_line_ids[0].product_id.name + " T" + str(quarter), + 'price_unit': exo_amount + }) + self.update({'bordereau_ids': [(4, bordereau_id.id)]}) diff --git a/models/scop_cotisation_cg_exo_line.py b/models/scop_cotisation_cg_exo_line.py new file mode 100644 index 0000000..4ba250c --- /dev/null +++ b/models/scop_cotisation_cg_exo_line.py @@ -0,0 +1,38 @@ +# © 2021 Le Filament (<http://www.le-filament.com>) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from datetime import datetime, date + +from odoo import models, fields, api +from odoo.exceptions import ValidationError, UserError + + +class ScopCotisationExoLine(models.Model): + _name = "scop.cotisation.cg.exo.line" + _description = "Ligne Exoneration CG" + _order = "create_date desc, contribution_id" + + exo_id = fields.Many2one( + comodel_name='scop.cotisation.cg.exo', + string="Exonération", + required=True) + contribution_id = fields.Many2one( + comodel_name='scop.contribution.type', + required=True + ) + amount = fields.Float('Montant souhaité') + percent = fields.Integer('% réduction') + type_exo = fields.Selection([ + ('amount', 'Montant'), + ('percent', 'Pourcentage')], + string="Type d'exonération", + related='exo_id.type_exo' + ) + + # ------------------------------------------------------ + # Onchange fields + # ------------------------------------------------------ + + # ------------------------------------------------------ + # Compute fields + # ------------------------------------------------------ diff --git a/security/ir.model.access.csv b/security/ir.model.access.csv index f49651d..1ebc59b 100755 --- a/security/ir.model.access.csv +++ b/security/ir.model.access.csv @@ -1,5 +1,8 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_scop_cotisation_cg_exo,access_scop_cotisation_cg_exo,model_scop_cotisation_cg_exo,account.group_account_manager,1,1,1,1 +access_scop_cotisation_cg_exo_user,access_scop_cotisation_cg_exo_user,model_scop_cotisation_cg_exo,base.group_user,1,0,0,0 +access_scop_cotisation_cg_exo_manager,access_scop_cotisation_cg_exo_manager,model_scop_cotisation_cg_exo,account.group_account_manager,1,1,1,0 admin_access_scop_cotisation_cg_exo,admin_access_scop_cotisation_cg_exo,model_scop_cotisation_cg_exo,cgscop_partner.group_cg_administrator,1,1,1,1 -access_scop_cotisation_cg_exo_ur_notice,access_scop_cotisation_cg_exo_ur_notice,model_scop_cotisation_cg_exo_ur_notice,account.group_account_manager,1,1,1,1 +access_scop_cotisation_cg_exo_line_user,access_scop_cotisation_cg_exo_line_user,model_scop_cotisation_cg_exo_line,base.group_user,1,0,0,0 +access_scop_cotisation_cg_exo_line_manager,access_scop_cotisation_cg_exo_line_manager,model_scop_cotisation_cg_exo_line,account.group_account_manager,1,1,1,1 +access_scop_cotisation_cg_exo_ur_notice,access_scop_cotisation_cg_exo_ur_notice,model_scop_cotisation_cg_exo_ur_notice,account.group_account_manager,1,1,1,0 admin_access_scop_cotisation_cg_exo_ur_notice,admin_access_scop_cotisation_cg_exo_ur_notice,model_scop_cotisation_cg_exo_ur_notice,cgscop_partner.group_cg_administrator,1,1,1,1 diff --git a/security/security_rules.xml b/security/security_rules.xml index ebb8d7e..bb99099 100644 --- a/security/security_rules.xml +++ b/security/security_rules.xml @@ -1,29 +1,12 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright 2020 Le Filament - License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> - <odoo> - <data noupdate="0"> - <record id="cg_cotisation_cg_rule" model="ir.rule"> - <field name="name">Cotisations consultables que pour sa société</field> - <field name="model_id" ref="cgscop_cotisation_cg.model_scop_cotisation_cg"/> + <data noupdate="1"> + <record id="invoice_comp_rule" model="ir.rule"> + <field name="name">CG Scop - Cotisation - Exonérations multi-company</field> + <field name="model_id" ref="model_scop_cotisation_cg_exo"/> + <field name="global" eval="True"/> <field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field> - <field name="perm_read" eval="True"/> - <field name="perm_write" eval="True"/> - <field name="perm_create" eval="True"/> - <field name="perm_unlink" eval="True"/> </record> - - <record id="cg_cotisation_cg_rule" model="ir.rule"> - <field name="name">Bordereaux consultables que pour sa société</field> - <field name="model_id" ref="cgscop_cotisation_cg.model_scop_bordereau"/> - <field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field> - <field name="perm_read" eval="True"/> - <field name="perm_write" eval="True"/> - <field name="perm_create" eval="True"/> - <field name="perm_unlink" eval="True"/> - </record> - </data> -</odoo> \ No newline at end of file +</odoo> diff --git a/templates/report_scop_exo.xml b/templates/report_scop_exo.xml index a452d1b..e64c7d9 100644 --- a/templates/report_scop_exo.xml +++ b/templates/report_scop_exo.xml @@ -18,29 +18,66 @@ </div> </div> <div class="row"> - <div class="col-12 text-center"> + <div class="col-12 text-center mb32"> <h2 style="color: #E5074D;"> - Appel de cotisation <span t-esc="str(o.year)"/> + Demande d'exonération de cotisations </h2> </div> </div> <div class="row"> - <div class="col-12 mb16"> + <div class="col-12 mb32"> <p> - Paris, le <span t-esc="o.date_cotisation" t-options="{'widget': 'date', 'format': 'd MMMM YYYY'}"/> + Paris, le <span t-esc="o.date_exo_ok" t-options="{'widget': 'date', 'format': 'd MMMM YYYY'}"/> </p> <p> N° adhérent : <t t-esc="str(o.partner_id.member_number_int)"/><br/> - Objet : <span t-field="o.type"/><br/> + N° exonération : <span t-esc="o.number"/> </p> </div> </div> <div class="row mb16"> <div class="col-12" style="test-align: justify;"> - <p>Chère Coopératrice,</p> - <p>Pour faire suite à votre dernier courrier, Le Bureau de la Direction Nationale qui s’est réuni le «Demande_Exonération_Date_Acceptation» a décidé de vous accorder une exonération exceptionnelle de vos cotisations confédérales.</p> - <p>Le Bureau prend donc acte des modalités suivantes : Exonération des cotisations du 4ème trimestre 2019.</p> - <p>Je vous prie de croire, chère Coopératrice, en l’assurance de toute ma considération coopérative.</p> + <p class="mb32">Cher Coopérateur,</p> + <!-- Avis Favorable--> + <t t-if="o.final_notice == 'favorable'"> + <p>Pour faire suite à votre dernier courrier, Le Bureau de la Direction Nationale qui s’est réuni le<span t-esc="o.instance_id.date" t-options="{'widget': 'date', 'format': 'd MMMM YYYY'}"/> a décidé de vous accorder une exonération exceptionnelle de vos cotisations confédérales.</p> + <p> + Le Bureau prend donc acte des modalités suivantes : + </p> + <p style="padding: 15px;"> + <!-- Exonération totale--> + <t t-if="(o.type_exo == 'percent' and o.percent_quarter == 100) or (o.type_exo == 'amount' and o.amount_quarter == 0)"> + Exonération totale des cotisations pour la période du + </t> + <t t-else=""> + <!-- Réduction des échéances--> + <t t-if="o.type_exo == 'percent'"> + Exonération de <span t-field="o.percent_quarter"/>% du montant des échéances trimestrielles sur la période du + </t> + <!-- Montant fixe des échéances--> + <t t-if="o.type_exo == 'amount'"> + Un montant des prochaines échéances fixé à <span t-field="o.amount_quarter"/>€ pour la période du + </t> + </t> + + <strong> + <t t-if="o.nb_quarter == 1"><span t-field="o.quarter_exo_start"/> <span t-field="o.year_exo_start"/>.</t> + <t t-else=""> + <span t-field="o.quarter_exo_start"/> <span t-field="o.year_exo_start"/> au <span t-field="o.quarter_exo_end"/> <span t-field="o.year_exo_end"/>. + </t> + </strong> + </p> + </t> + + <!-- Avis Défavorable--> + <t t-if="o.final_notice == 'unfavorable'"> + <p>Pour faire suite à votre dernier courrier, Le Bureau de la Direction Nationale qui s’est réuni le<span t-esc="o.instance_id.date" t-options="{'widget': 'date', 'format': 'd MMMM YYYY'}"/> a décidé de na pas vous accorder une exonération exceptionnelle de vos cotisations confédérales pour la raison suivante : </p> + <p> + <t t-esc="o.head_office_comment"/> + </p> + </t> + + <p>Je vous prie de croire, cher Coopérateur, en l’assurance de toute ma considération coopérative.</p> <p>Le Président</p> <p>Jacques LANDRIOT</p> <p>Copie : <t t-esc="o.partner_id.ur_id.name"/></p> diff --git a/views/res_partner.xml b/views/res_partner.xml new file mode 100644 index 0000000..d857daa --- /dev/null +++ b/views/res_partner.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2021 Le Filament + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> +<odoo> + <data> + + <record id="scop_contact_view_form_inherit" model="ir.ui.view"> + <field name="name">scop.contact.view.form.inherit</field> + <field name="model">res.partner</field> + <field name="inherit_id" ref="cgscop_partner.scop_contact_view_form"/> + <field name="arch" type="xml"> + <xpath expr="//page[@name='scop_contribution']" position="after"> + <page name='scop_exo' string="Exonérations" attrs="{'invisible': ['|', ('is_cooperative', '!=', True), ('project_status', '!=', '6_suivi')]}"> + <field name="exo_ids" mode="tree,form" readonly="1"> + <tree create="false" edit="false" delete="false" default_order="date desc"> + <field name="date_request"/> + <field name="source"/> + <field name="date_exo_start"/> + <field name="date_exo_end"/> + <field name="ur_notice"/> + <field name="final_notice"/> + <field name="date_exo_ok"/> + </tree> + <form> + <group string="Demande initiale"> + <group name="request"> + <field name="date_request"/> + <field name="source"/> + <field name="ur_notice" options="{'no_create': True, 'no_open': True}"/> + </group> + <group> + <field name="date_exo_start"/> + <field name="date_exo_end"/> + </group> + </group> + <strong><label for="motivation"/></strong> + <field name="motivation" placeholder=""/> + <group string="Bureau"> + <group> + <field name="date_exo_ok"/> + </group> + <group> + <field name="final_notice"/> + </group> + </group> + <strong><label for="head_office_comment"/></strong> + <field name="head_office_comment" placeholder="Commentaire du bureau"/> + </form> + </field> + </page> + </xpath> + </field> + </record> + </data> +</odoo> \ No newline at end of file diff --git a/views/scop_bordereau_cg.xml b/views/scop_bordereau_cg.xml index 3b5fe37..8ffb246 100644 --- a/views/scop_bordereau_cg.xml +++ b/views/scop_bordereau_cg.xml @@ -4,225 +4,19 @@ <odoo> <data> - <!-- Form --> - <record id="scop_bordereau_form_view" model="ir.ui.view"> - <field name="name">scop.bordereau.form</field> + <!-- Inherit Form View to Modify it --> + <record id="scop_bordereau_exo_form_view" model="ir.ui.view"> + <field name="name">scop.bordereau.exo.form</field> <field name="model">scop.bordereau</field> + <field name="inherit_id" ref="cgscop_cotisation_cg.scop_bordereau_form_view"/> <field name="arch" type="xml"> - <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="print_bordereau" string="Imprimer" type="object" states="validated,paid"/> - <button name="action_send_email" string="Envoyer par mail" type="object" states="validated"/> - <button name="update_cotiz_and_lines" class="btn-info" string="Mettre à jour les cotisations" type="object" states="new"/> - <button name="%(cgscop_cotisation_cg.scop_cotisation_regul_wizard_act_window)d" - class="btn-warning" - string="Effectuer une Régularisation" - type="action" - states="validated,paid"/> - <button name="%(cgscop_bordereau_report_refund)d" - class="btn-info" - string="Imprimer l'avoir" - type="action" - states="cancel"/> - </header> - <sheet> - <div class="oe_button_box" name="button_box"> - <button class="oe_stat_button" name="open_payment" - string="Paiements en cours" type="object" - attrs="{'invisible':['|', ('move_reconciled','=',True), ('state', '!=', 'validated')]}" icon="fa-university"/> - <field name="move_reconciled" invisible="1"/> - </div> - <div class="oe_title"> - <h1> - <field name="name"/> - </h1> - </div> - <h4> - Adhérent : <field name="partner_id"/> <br/> - UR : <field name="partner_ur_id" readonly="True" options="{'no_open': True}"/> - </h4> - <field name="is_regul" invisible="1"/> - <div class="alert alert-warning" role="alert" attrs="{'invisible': [('is_regul', '!=', True)]}"> - <strong>Bordereau annulé le : </strong><field name="date_regul" readonly="True"/><br/> - <strong>Motif : </strong><field name="comment_regul" readonly="True"/><br/> - <strong>Nouveau bordereau : </strong><field name="refund_id" readonly="True"/> - </div> - <group> - <group> - <field name="base_cotisation_cg"/> - <field name="date_cotisation" attrs="{'readonly':[('state','!=','new')]}"/> - <field name="payment_term_id" attrs="{'readonly':[('state','!=','new')]}"/> - <field name="payment_mode_id" attrs="{'readonly':[('state','!=','new')]}"/> - <field name="liasse_fiscale_id"/> - <field name="type_liasse_fiscale" options="{'no_open': True}"/> - </group> - <group> - <field name="year_liasse_retenue" attrs="{'readonly':[('state','!=','new')]}"/> - <field name="type_assiette_retenu"/> - <field name="montant_assiette"/> - <field name="amount_total_cotiz"/> - <field name="dureeExercice"/> - <field name="nb_quarter" attrs="{'readonly':[('state','!=','new')]}"/> - </group> - <hr/> - <field name="invoice_ids" widget="one2many"> - <tree edit="false" create="false" delete="false"> - <field name="type_contribution_id"/> - <field name="date_invoice"/> - <field name="name"/> - <field name="amount_total_signed" string="Montant total" sum="Total"/> - <field name="residual_signed" string="Montant dû" sum="Total"/> - <field name="state"/> - <button name="view_cotiz" string="Afficher" type="object" icon="fa-pencil-square-o"/> - </tree> - <form> - <group> - <field name="type_contribution_id"/> - <field name="date_invoice"/> - <field name="name"/> - <field name="amount_cg_calculated"/> - <field name="amount_total_signed"/> - <field name="residual_signed"/> - <field name="nb_quarter" /> - <field name="state"/> - </group> - </form> - </field> - </group> - <notebook> - <page string="Cotisation CG Scop"> - <group col="2"> - <group string="Données liasse fiscale"> - <field name="type_assiette_connu"/> - <field name="ca_connu"/> - <field name="va_connu"/> - </group> - <group string="Données pour le calcul"> - <field name="type_assiette_retenu"/> - <field name="ca_retenu" attrs="{'readonly':[('state','!=','new')]}"/> - <field name="va_cg_retenu" attrs="{'readonly':[('state','!=','new')]}"/> - </group> - </group> - </page> - <page string="Cotisation Fédé de la com"> - <group col="2"> - <group string="Données liasse fiscale"> - <field name="va_connu"/> - <field name="staff_average_connu"/> - <field name="staff_count_connu"/> - </group> - <group string="Données pour le calcul"> - <field name="va_fede_com_retenu" attrs="{'readonly':[('state','!=','new')]}"/> - <field name="staff_average_retenu" attrs="{'readonly':[('state','!=','new')]}"/> - <field name="staff_fede_com_count_retenu" attrs="{'readonly':[('state','!=','new')]}"/> - </group> - </group> - </page> - <page string="Cotisation UR"> - <group col="2"> - <group string="Données liasse fiscale"> - <field name="net_results_connu"/> - <field name="staff_shareholder_count_connu"/> - <field name="staff_count_connu"/> - <field name="wage_cg_connu"/> - </group> - <group string="Données pour le calcul"> - <field name="net_results_retenu" attrs="{'readonly':[('state','!=','new')]}"/> - <field name="staff_shareholder_count_retenu" attrs="{'readonly':[('state','!=','new')]}"/> - <field name="staff_ur_med_count_retenu" attrs="{'readonly':[('state','!=','new')]}"/> - <field name="wage_cg_retenu" attrs="{'readonly':[('state','!=','new')]}"/> - </group> - </group> - </page> - </notebook> - </sheet> - <div class="oe_chatter"> - <field name="message_follower_ids" widget="mail_followers"/> - <field name="message_ids" widget="mail_thread"/> - </div> - </form> - </field> - </record> + <xpath expr="//button[@name='action_show_cotiz']" position="after"> + <button name="action_show_exo" type="object" class="oe_stat_button" icon="fa-list" attrs="{'invisible':[('exo_count','=',0)]}"> + <field string="Exonération(s)" name="exo_count" widget="statinfo"/> + </button> + </xpath> - <!-- Tree --> - <record id="scop_bordereau_tree_view" model="ir.ui.view"> - <field name="name">scop.bordereau.tree</field> - <field name="model">scop.bordereau</field> - <field name="arch" type="xml"> - <tree decoration-info="state == 'new'" create="false" string="Bordereaux"> - <field name="member_number"/> - <field name="partner_id"/> - <field name="partner_ur_id"/> - <field name="year"/> - <field name="state"/> - <field name="type_assiette_retenu"/> - <field name="montant_assiette"/> - <field name="amount_total_cotiz" sum="Total"/> - <field name="amount_residual" sum="Total"/> - </tree> </field> </record> - - <!-- Search --> - <record id="scop_bordereau_search_view" model="ir.ui.view"> - <field name="name">scop.bordereau.search</field> - <field name="model">scop.bordereau</field> - <field name="arch" type="xml"> - <search string="Bordereaux"> - <field name="partner_id" string="Adhérent"/> - <field name="member_number" string="N° Adhérent"/> - <field name="name" string="Référence du bordereau"/> - <field name="year" string="Année de cotisation"/> - <filter name="state_new" string="Brouillon" - domain="[('state', '=', 'new')]"/> - <filter name="state_validated" string="Validé" - domain="[('state', '=', 'validated')]"/> - <filter name="state_paid" string="Payé" - domain="[('state', '=', 'paid')]"/> - <separator/> - <filter name="current_year" string="Campagne année en cours" - domain="[('year', '=', (context_today()).strftime('%Y'))]"/> - <filter name="previous_year" string="Campagne année précédente" - domain="[('year', '=', (context_today()-datetime.timedelta(weeks=52)).strftime('%Y'))]"/> - <filter name="next_year" string="Campagne année suivante" - domain="[('year', '=', (context_today()+datetime.timedelta(weeks=52)).strftime('%Y'))]"/> - <separator/> - <filter name="bordereau_equal_zero" string="Cotisation(s) égale(s) à zéro" - domain="[('amount_total_cotiz', '=', 0)]"/> - <filter name="assiette_equal_zero" string="Assiette(s) égale(s) à zéro" - domain="[('montant_assiette', '=', 0)]"/> - <separator/> - <filter name="4_quarter" string="Sur 4 trimestres" domain="[('nb_quarter', '=', '4')]"/> - <filter name="3_quarter" string="Sur 3 trimestres" domain="[('nb_quarter', '=', '3')]"/> - <filter name="2_quarter" string="Sur 2 trimestres" domain="[('nb_quarter', '=', '2')]"/> - <filter name="1_quarter" string="Sur 1 trimestre" domain="[('nb_quarter', '=', '1')]"/> - <separator/> - <filter name="is_ca" string="Assiette CA" domain="[('type_assiette_retenu', '=', 'ca')]"/> - <filter name="is_va" string="Assiette VA" domain="[('type_assiette_retenu', '=', 'va')]"/> - <group string="Group By"> - <filter name="by_year" string="Année de cotisation" context="{'group_by':'year'}"/> - </group> - </search> - </field> - </record> - - <!-- Action --> - <record id="scop_bordereau_act_window" model="ir.actions.act_window"> - <field name="name">Bodereaux</field> - <field name="type">ir.actions.act_window</field> - <field name="res_model">scop.bordereau</field> - <field name="view_mode">tree,form</field> - <field name="context">{'search_default_current_year': 1}</field> - </record> - - <!-- Menu --> - <menuitem name="Bordereaux" - id="scop_bordereau_menu" - parent="cgscop_cotisation.menu_scop_cotisation" - action="scop_bordereau_act_window" - sequence="30"/> - </data> </odoo> \ No newline at end of file diff --git a/views/scop_cotisation_cg_exo.xml b/views/scop_cotisation_cg_exo.xml index b663383..d7c82d0 100644 --- a/views/scop_cotisation_cg_exo.xml +++ b/views/scop_cotisation_cg_exo.xml @@ -14,15 +14,16 @@ <field name="partner_id"/> <field name="name"/> <field name="date_request"/> - <filter name="filter_exo" domain="[('type', '=', 'exo')]" string="Exonérations"/> - <filter name="filter_adjustment" domain="[('type', '=', 'adjustment')]" string="Ajustements"/> + <separator/> + <filter name="on_going" domain="[('state', 'in', ('todo', 'waiting'))]" string="En cours de traitement"/> + <filter name="is_done" domain="[('state', '=', 'done')]" string="Traité"/> + <filter name="is_cancel" domain="[('state', '=', 'cancel')]" string="Annulé"/> <separator/> <filter name="is_favorable" domain="[('final_notice', '=', 'favorable')]" string="Favorable"/> <filter name="is_unfavorable" domain="[('final_notice', '=', 'unfavorable')]" string="Défavorable"/> <group expand="0" name="group_by" string="Group By"> <filter name="group_state" string="Statut" context="{'group_by' : 'state'}"/> <filter name="group_instance_id" string="Instance" context="{'group_by': 'instance_id'}"/> - <filter name="group_by_type" string="Type" context="{'group_by': 'type'}"/> </group> </search> </field> @@ -36,7 +37,6 @@ <tree string="Exonerations"> <field name="date_request"/> <field name="partner_id"/> - <field name="type"/> <field name="state"/> <field name="date_exo_start"/> <field name="date_exo_end"/> @@ -53,32 +53,89 @@ <field name="arch" type="xml"> <form string="Exonerations"> <header> + <button name="validate_exo" type="object" string="Valider l'exonération" class="oe_highlight" confirm="Êtes-vous certain(e) de vouloir valider cette exonération ?" attrs="{'invisible': [('state', '!=', 'waiting')]}"/> <button name="cancel_exo" type="object" string="Annuler" confirm="Êtes-vous certain(e) de vouloir annuler cette exonération ?" attrs="{'invisible': [('state', '=', 'cancel')]}"/> - <field name="state" widget="statusbar" clickable="False"/> + <field name="state" widget="statusbar" readonly="1" force_save="1" /> </header> <sheet> - <h1><field name="partner_id" options="{'no_create': True, 'no_open': True}"/></h1> + <div class="oe_button_box" name="button_box"> + <button name="action_view_bordereau" type="object" icon="fa-files-o" attrs="{'invisible': [('state', '=', 'done')]}" string="Borderaux en cours"></button> + <button name="action_view_exo" type="object" class="oe_stat_button" icon="fa-list" attrs="{'invisible': [('state', '!=', 'done')]}" string="Bordereaux Exonérés"></button> + </div> + <label for="partner_id" string="Coopérative"/> + <h1><field name="partner_id" options="{'no_create': True}"/></h1> + <label for="number" string="Référence de l'exonération"/> + <h3><field name="number"/></h3> <group string="Demande initiale"> <group name="request"> <field name="date_request"/> - <field name="type" /> <field name="source"/> + </group> + <group> <field name="ur_notice" options="{'no_create': True, 'no_open': True}"/> </group> + </group> + <strong><label for="motivation"/></strong> + <field name="motivation" placeholder=""/> + <group string="Données de calcul"> <group> + <label for="quarter_exo_start" string="Début de l'exonération"/> + <div> + <field name="quarter_exo_start" class="oe_inline" style="margin-right: 20px;" required="1"/> + <field name="year_exo_start" class="oe_inline" required="1"/> + </div> + <label for="quarter_exo_end" string="Fin de l'exonération"/> + <div> + <field name="quarter_exo_end" class="oe_inline" style="margin-right: 20px;" required="1"/> + <field name="year_exo_end" class="oe_inline" required="1"/> + </div> + <separator></separator> <field name="date_exo_start"/> <field name="date_exo_end"/> + <field name="nb_quarter"/> + </group> + <group> + <field name="type_exo"/> + <div class="alert alert-light oe_edit_only" role="alert" colspan="2" attrs="{'invisible': [('type_exo', '!=', 'amount')]}"> + Le montant saisi dans le champ ci-dessous correspond au <strong>montant de l'échéanche souhaité</strong> pour les échéances exonérées. + </div> + <field name="amount_quarter" attrs="{'invisible': [('type_exo', '!=', 'amount')]}"/> + + <div class="alert alert-light oe_edit_only" role="alert" colspan="2" attrs="{'invisible': [('type_exo', '!=', 'percent')]}"> + Le nombre saisi dans le champ ci-dessous correspond au <strong>pourcentage de réduction</strong> appliqué aux échéances. + </div> + <field name="percent_quarter" attrs="{'invisible': [('type_exo', '!=', 'percent')]}"/> + <button name="create_lines" type="object" class="btn btn-info" string="Créer/Mettre à jour les lignes" attrs="{'invisible': [('state', 'in', ('done', 'cancel'))]}"></button> + + <div colspan="2"> + <field name="exo_line_ids" attrs="{'readonly': [('state', 'in', ('done', 'cancel'))]}"> + <tree create="0" delete="0" editable="top"> + <field name="type_exo" invisible="1"/> + <field name="contribution_id" readonly="1" string="Type de cotisation" options="{'no_open': True}"/> + <field name="amount" attrs="{'readonly': [('type_exo', '!=', 'amount')], 'invisible': [('type_exo', '!=', 'amount')]}" sum="Total"/> + <field name="percent" attrs="{'readonly': [('type_exo', '!=', 'percent')], 'invisible': [('type_exo', '!=', 'percent')]}"/> + </tree> + <form> + <group> + <field name="type_exo" invisible="1"/> + <field name="contribution_id" readonly="1" string="Type de cotisation" options="{'no_open': True}"/> + <field name="amount" attrs="{'readonly': [('type_exo', '!=', 'amount')], 'invisible': [('type_exo', '!=', 'amount')]}"/> + <field name="percent" attrs="{'readonly': [('type_exo', '!=', 'percent')], 'invisible': [('type_exo', '!=', 'percent')]}"/> + </group> + </form> + </field> + </div> + </group> </group> - <strong><label for="motivation"/></strong> - <field name="motivation" placeholder=""/> + <group string="Bureau"> <group> - <field name="date_exo_ok"/> - <field name="final_notice"/> + <field name="instance_id" options="{'no_create': True}" string="Instance de présentation"/> </group> <group> - <field name="instance_id" options="{'no_create': True, 'no_open': True}"/> + <field name="date_exo_ok"/> + <field name="final_notice"/> </group> </group> <strong><label for="head_office_comment"/></strong> diff --git a/wizard/__init__.py b/wizard/__init__.py new file mode 100755 index 0000000..39df84d --- /dev/null +++ b/wizard/__init__.py @@ -0,0 +1,4 @@ +# © 2021 Le Filament (<http://www.le-filament.com>) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import scop_bordereau_update_liasse_wizard diff --git a/wizard/scop_bordereau_update_liasse_wizard.py b/wizard/scop_bordereau_update_liasse_wizard.py new file mode 100644 index 0000000..792f58e --- /dev/null +++ b/wizard/scop_bordereau_update_liasse_wizard.py @@ -0,0 +1,18 @@ +# Copyright 2021 Le Filament +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import models + + +class ScopBordereauChangeLiasse(models.TransientModel): + _inherit = 'scop.bordereau.change.liasse.wizard' + + # ------------------------------------------------------ + # Override Parent + # ------------------------------------------------------ + def update_liasse_fiscale(self): + res = super(ScopBordereauChangeLiasse, self).update_liasse_fiscale() + if self.bordereau_id.exo_ids: + for exo in self.bordereau_id.exo_ids: + exo.create_exo_refund(self.bordereau_id) + return res -- GitLab