diff --git a/.pylintrc b/.pylintrc index 71c476d4f10ac08a7333729b93705c9573d240d5..e625f373eb75ddfe824fa36ca76345eab5dfb655 100644 --- a/.pylintrc +++ b/.pylintrc @@ -5,12 +5,12 @@ load-plugins=pylint_odoo score=n [ODOOLINT] -readme_template_url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst" -manifest_required_authors=Le Filament -manifest_required_keys=license -manifest_deprecated_keys=description,active -license_allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3 -valid_odoo_versions=16.0 +readme-template-url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst" +manifest-required-authors=Le Filament +manifest-required-keys=license +manifest-deprecated-keys=description,active +license-allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3 +valid-odoo-versions=16.0 [MESSAGES CONTROL] disable=all diff --git a/.pylintrc-mandatory b/.pylintrc-mandatory index 7d2afe044815fbbf2157f2b53def485bed60851b..99064933ef82c469ba5fda5b2904447c05c99dbe 100644 --- a/.pylintrc-mandatory +++ b/.pylintrc-mandatory @@ -74,7 +74,7 @@ enable=anomalous-backslash-in-string, manifest-maintainers-list, missing-newline-extrafiles, missing-readme, -# missing-return, + missing-return, odoo-addons-relative-import, old-api7-method-defined, po-msgstr-variables, diff --git a/__manifest__.py b/__manifest__.py index 102aa885af7b04d76de94462749d758aeb7c82cc..2be7ac7382bc8a1d15914cf0e19c678cb82a185e 100644 --- a/__manifest__.py +++ b/__manifest__.py @@ -3,7 +3,7 @@ "summary": "Gestion de la facturation sur les opérations", "author": "Le Filament, Odoo SA", "website": "https://le-filament.com", - "version": "16.0.4.0.2", + "version": "16.0.4.1.0", "license": "AGPL-3", "depends": [ "account_banking_sepa_direct_debit", diff --git a/data/data.xml b/data/data.xml index 9a6cc26e0210dc475c7c94a189176ad835e24b6e..e0e8972dd97afabb4c6e1810b2df1252b2070c09 100644 --- a/data/data.xml +++ b/data/data.xml @@ -2,6 +2,7 @@ <!-- Copyright 2021- Le Filament (https://le-filament.com) License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> <odoo> + <!-- Precisions --> @@ -38,6 +39,18 @@ </record> <data noupdate="1"> + <!-- Default partner and company--> + <record id="default_partner_company_id" model="res.partner"> + <field name="name">Default partner</field> + <field name="is_company">True</field> + <field name="country_id" ref="base.fr" /> + </record> + + <record id="default_company" model="res.company"> + <field name="name">Default FR company</field> + <field name="partner_id" ref="default_partner_company_id" /> + </record> + <!-- Categories d accise--> <record id="accise_category_menage" model="acc.accise.category"> <field name="name">Ménages et assimilés</field> diff --git a/migrations/16.0.4.0.2/post-migration.py b/migrations/16.0.4.0.2/post-migration.py index d29c360b6acbdec5a9e3a6a3d3e6f0942229ffad..1a54342747399bb164fedc7dce86a3b851ae38b9 100644 --- a/migrations/16.0.4.0.2/post-migration.py +++ b/migrations/16.0.4.0.2/post-migration.py @@ -5,7 +5,6 @@ from openupgradelib import openupgrade @openupgrade.migrate() def migrate(env, version): - moves = env["account.move"].search([("move_type", "=", "out_refund")]) for move in moves: move._compute_amount_oacc() diff --git a/migrations/16.0.4.1.0/pre-migration.py b/migrations/16.0.4.1.0/pre-migration.py new file mode 100644 index 0000000000000000000000000000000000000000..945c80827415d3b6c72e59467d67553aa0aba7a4 --- /dev/null +++ b/migrations/16.0.4.1.0/pre-migration.py @@ -0,0 +1,16 @@ +# Copyright 2025- Le Filament (https://le-filament.com) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) +from openupgradelib import openupgrade + + +@openupgrade.migrate() +def migrate(env, version): + openupgrade.logged_query( + env.cr, + """ + INSERT INTO ir_model_data (name, res_id, module, model, noupdate) + VALUES + ('default_company', 21, 'oacc_account', 'res.company', TRUE), + ('default_partner_company_id', 963, 'oacc_account', 'res.partner', TRUE); + """, + ) diff --git a/models/res_company.py b/models/res_company.py index 7eb22c9a9f8f3e0e1917193bfb6b849a11089c3f..565618b1464c350d3b57271f5b1cac53789147b4 100644 --- a/models/res_company.py +++ b/models/res_company.py @@ -9,7 +9,7 @@ class ResCompany(models.Model): # Fields declaration # ------------------------------------------------------ use_invoice_terms_tax = fields.Boolean( - string="Termes & Conditions des taxes par défaut", + string="Termes & Conditions des taxes par défaut", default=True ) invoice_terms_tax = fields.Text( string="Termes & Conditions des taxes", diff --git a/models/res_partner.py b/models/res_partner.py index a1fad2ff64742c0fc030a8f5640c9420755e81b1..56d57f48bdc68947aa389e7a3ebf34c6ac52419a 100644 --- a/models/res_partner.py +++ b/models/res_partner.py @@ -54,37 +54,125 @@ class ResPartner(models.Model): # ------------------------------------------------------ # Business methods # ------------------------------------------------------ + def _get_linked_company_data(self): + """ + Retourne un dictionnaire contenant les données de création de la société liée + """ + company_data = super()._get_linked_company_data() + # mise en page + company_data["external_report_layout_id"] = self.env.ref( + "oacc_account.external_layout_oacc" + ).id + # escompte + company_data["early_pay_discount_computation"] = "excluded" + # devise - # ------------------------------------------------------ - # CRUD methods (ORM overrides) - # ------------------------------------------------------ - @api.model_create_multi - def create(self, vals_list): - for vals in vals_list: - # If billing agent, create a sequence - if any( - role and role[2] and role[2].get("role") == "4_mand" - for role in vals.get("acc_operation_role_ids", [False, False, []]) - ): - vals["ref_producer"] = self.env["ir.sequence"].next_by_code( - "res.partner" - ) - result = super().create(vals_list) - return result + # methode d arrondi + company_data["tax_calculation_rounding_method"] = "round_globally" + # pays fiscal (normalement renseigné via le pays) + if not company_data.get("account_fiscal_country_id"): + company_data["account_fiscal_country_id"] = self.env.ref("base.fr").id + + company_data["chart_template_id"] = self.env.ref( + "l10n_fr.l10n_fr_pcg_chart_template" + ).id + + return company_data - def write(self, vals): + def _company_configuration(self, company): """ - Overwrite write method to initialize ref_producer if empty + Configuration de la société liée """ - if ( - any( - role and role[2] and role[2].get("role") == "4_mand" - for role in vals.get("acc_operation_role_ids", [False, False, []]) - ) - and not self.ref_producer + res = super()._company_configuration(company=company) + + # Sur les utilisateurs qui sont admin d’au moins une opération à laquelle le + # producteur / mandataire appartient ET a l un de ces deux role: + # Ajouter la nouvelle société créée à ses sociétés autorisées + # Si sa société par défaut est “Défaut”, + # la remplacer par la nouvelle société créée + # Si il possède “Défaut” dans ses sociétés autorisées, + # la retirer de ses sociétés autorisées + + default_company = self.env.ref("oacc_account.default_company") + + for role in self.acc_operation_role_ids.filtered( + lambda role: role.role in ["3_prod", "4_mand"] ): - vals["ref_producer"] = self.env["ir.sequence"].next_by_code("res.partner") - return super().write(vals) + for admin in role.acc_operation_id.admin_ids: + admin_user = admin.user_ids[0] if admin.user_ids else None + if admin_user: + admin_user.write({"company_ids": [(4, company.id)]}) + if admin_user.company_id.id == default_company.id: + admin_user.company_id = company + if default_company in admin_user.company_ids: + admin_user.write({"company_ids": [(3, default_company.id)]}) + + if self.env.is_admin(): + company.chart_template_id._load(company.with_company(company.id)) + else: + company.chart_template_id.sudo()._load(company.with_company(company.id)) + + company.account_purchase_tax_id = self.env.ref( + f"l10n_fr.{company.id}_tva_acq_encaissement" + ).id + company.account_sale_tax_id = self.env.ref( + f"l10n_fr.{company.id}_tva_normale_encaissement" + ).id + + iban = "" + bic = "" + if self.bank_ids: + iban = self.bank_ids[0].acc_number + bic = self.bank_ids[0].bank_bic + + # creation des condition de paiement + account_payment_term_data = { + "name": "30 jours", + "days_offset": 30, + "company_id": company.id, + "note": "Indiquez la référence facture ci-dessus " + "sur votre ordre de virement.<br/>" + "Nos coordonnées bancaires :<br/>" + f"IBAN : {iban}<br/>" + f"Code BIC : {bic}<br/>", + } + + self.with_company(company.id).property_payment_term_id = ( + self.env["account.payment.term"] + .with_company(company.id) + .create(account_payment_term_data) + ) + + sale_journal = ( + self.env["account.journal"] + .with_company(company.id) + .search([("type", "=", "sale"), ("company_id", "=", company.id)], limit=1) + ) + + if sale_journal: + sale_journal.write( + { + "restrict_mode_hash_table": True, + "edi_format_ids": [ + (4, self.env.ref("account_edi_ubl_cii.edi_facturx_1_0_05").id) + ], + } + ) + + if sale_journal.sequence_id: + sale_journal.sequence_id.prefix = ( + f"F-{self.ref_producer}-%(range_year)s-" + ) + + if sale_journal.refund_sequence_id: + sale_journal.refund_sequence_id.prefix = ( + f"A-{self.ref_producer}-%(range_year)s-" + ) + return res + + # ------------------------------------------------------ + # CRUD methods (ORM overrides) + # ------------------------------------------------------ def _fields_sync(self, values): res = super()._fields_sync(values) diff --git a/views/res_partner_views.xml b/views/res_partner_views.xml index 530e8416914ab8661ee6f8b86e9d6e0dd74aec9e..f2abb21528f87b2f06219b5f738eca8b06d40caf 100644 --- a/views/res_partner_views.xml +++ b/views/res_partner_views.xml @@ -52,7 +52,7 @@ </attribute> </xpath> - <xpath expr="//button[@name='create_company']" position="attributes"> + <xpath expr="//button[@name='action_create_company']" position="attributes"> <attribute name="attrs"> {'invisible': [ '|', '&', ('is_producer', '!=', True),