diff --git a/account_global_discount/__manifest__.py b/account_global_discount/__manifest__.py index 108d6f25cb3..454712a926e 100644 --- a/account_global_discount/__manifest__.py +++ b/account_global_discount/__manifest__.py @@ -3,7 +3,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { "name": "Account Global Discount", - "version": "16.0.1.0.1", + "version": "17.0.1.0.0", "category": "Accounting", "author": "Tecnativa, Odoo Community Association (OCA)", "website": "https://github.com/OCA/account-invoicing", diff --git a/account_global_discount/hooks.py b/account_global_discount/hooks.py index 78d49f7b840..8674427236e 100644 --- a/account_global_discount/hooks.py +++ b/account_global_discount/hooks.py @@ -1,27 +1,29 @@ from odoo.tools.sql import column_exists -def _pre_init_global_discount_fields(cr): - if not column_exists(cr, "account_move", "amount_global_discount"): - cr.execute( +def _pre_init_global_discount_fields(env): + if not column_exists(env.cr, "account_move", "amount_global_discount"): + env.cr.execute( """ ALTER TABLE "account_move" ADD COLUMN "amount_global_discount" double precision DEFAULT 0 """ ) - cr.execute( + env.cr.execute( """ ALTER TABLE "account_move" ALTER COLUMN "amount_global_discount" DROP DEFAULT """ ) - if not column_exists(cr, "account_move", "amount_untaxed_before_global_discounts"): - cr.execute( + if not column_exists( + env.cr, "account_move", "amount_untaxed_before_global_discounts" + ): + env.cr.execute( """ ALTER TABLE "account_move" ADD COLUMN "amount_untaxed_before_global_discounts" double precision """ ) - cr.execute( + env.cr.execute( """ update account_move set amount_untaxed_before_global_discounts = amount_untaxed """ diff --git a/account_global_discount/models/account_move.py b/account_global_discount/models/account_move.py index a86ed3b8005..d18a7cc0d83 100644 --- a/account_global_discount/models/account_move.py +++ b/account_global_discount/models/account_move.py @@ -30,8 +30,9 @@ class AccountMove(models.Model): " 'in_invoice': ['purchase']" "}.get(move_type, [])), ('account_id', '!=', False), '|', " "('company_id', '=', company_id), ('company_id', '=', False)]", - readonly=True, - states={"draft": [("readonly", False)]}, + compute="_compute_global_discount_ids", + store=True, + readonly=False, ) amount_global_discount = fields.Monetary( string="Total Global Discounts", @@ -87,7 +88,7 @@ def _set_global_discounts_by_tax(self): # incorrect data in discounts _self = self.filtered("global_discount_ids") for inv_line in _self.invoice_line_ids.filtered( - lambda l: l.display_type not in ["line_section", "line_note"] + lambda line: line.display_type not in ["line_section", "line_note"] ): if inv_line.product_id.bypass_global_discount: continue @@ -161,8 +162,9 @@ def _recompute_global_discount_lines(self): { "invoice_global_discount_id": discount.id, "move_id": self.id, - "name": "%s - %s" - % (discount.name, ", ".join(discount.tax_ids.mapped("name"))), + "name": "{} - {}".format( + discount.name, ", ".join(discount.tax_ids.mapped("name")) + ), "debit": disc_amount_company_currency > 0.0 and disc_amount_company_currency or 0.0, @@ -179,27 +181,25 @@ def _recompute_global_discount_lines(self): } ) - @api.onchange("partner_id", "company_id") - def _onchange_partner_id(self): - res = super()._onchange_partner_id() - discounts = False - if ( - self.move_type in ["out_invoice", "out_refund"] - and self.partner_id.customer_global_discount_ids - ): - discounts = self.partner_id.customer_global_discount_ids.filtered( - lambda d: d.company_id == self.company_id - ) - elif ( - self.move_type in ["in_refund", "in_invoice"] - and self.partner_id.supplier_global_discount_ids - ): - discounts = self.partner_id.supplier_global_discount_ids.filtered( - lambda d: d.company_id == self.company_id - ) - if discounts: - self.global_discount_ids = discounts - return res + @api.depends("partner_id", "company_id", "move_type") + def _compute_global_discount_ids(self): + for move in self: + discounts = self.env["global.discount"] + move_discounts = self.env["global.discount"] + if ( + move.move_type in ["out_invoice", "out_refund"] + and move.partner_id.customer_global_discount_ids + ): + move_discounts = move.partner_id.customer_global_discount_ids + elif ( + move.move_type in ["in_refund", "in_invoice"] + and move.partner_id.supplier_global_discount_ids + ): + move_discounts = move.partner_id.supplier_global_discount_ids + for discount in move_discounts: + if discount.company_id == move.company_id: + discounts |= discount + move.global_discount_ids = discounts def _compute_amount_one(self): """Perform totals computation of a move with global discounts.""" @@ -320,8 +320,8 @@ class AccountMoveLine(models.Model): string="Amount Untaxed Before Discounts", readonly=True, ) - # TODO: To be removed on future versions if invoice_global_discount_id is properly filled - # Provided for compatibility in stable branch + # TODO: To be removed on future versions if invoice_global_discount_id + # is properly filled Provided for compatibility in stable branch # UPD: can be removed past version 16.0 global_discount_item = fields.Boolean() @@ -368,7 +368,9 @@ class AccountInvoiceGlobalDiscount(models.Model): comodel_name="account.account", required=True, string="Account", - domain="[('account_type', 'not in', ['asset_receivable', 'liability_payable'])]", + domain=( + "[('account_type', 'not in', ['asset_receivable', 'liability_payable'])]" + ), ) account_analytic_id = fields.Many2one( comodel_name="account.analytic.account", diff --git a/account_global_discount/models/global_discount.py b/account_global_discount/models/global_discount.py index 3778b520df5..99d20682814 100644 --- a/account_global_discount/models/global_discount.py +++ b/account_global_discount/models/global_discount.py @@ -10,7 +10,9 @@ class GlobalDiscount(models.Model): account_id = fields.Many2one( comodel_name="account.account", string="Account", - domain="[('account_type', 'not in', ['asset_receivable', 'liability_payable'])]", + domain=( + "[('account_type', 'not in', ['asset_receivable', 'liability_payable'])]" + ), check_company=True, ) account_analytic_id = fields.Many2one( diff --git a/account_global_discount/readme/CONTRIBUTORS.md b/account_global_discount/readme/CONTRIBUTORS.md index 29efa70b8b8..32eaae2c42e 100644 --- a/account_global_discount/readme/CONTRIBUTORS.md +++ b/account_global_discount/readme/CONTRIBUTORS.md @@ -6,3 +6,6 @@ - Ernesto Tejeda - Víctor Martínez - Omar Castiñeira \<\> + +- [Studio73](https://www.studio73.es/) + - Miguel Gandia diff --git a/account_global_discount/tests/test_global_discount.py b/account_global_discount/tests/test_global_discount.py index a491b9c054d..949a333fde1 100644 --- a/account_global_discount/tests/test_global_discount.py +++ b/account_global_discount/tests/test_global_discount.py @@ -101,6 +101,13 @@ def setUpClass(cls, chart_template_ref=None): cls.journal = cls.env["account.journal"].create( {"name": "Test purchase journal", "code": "TPUR", "type": "purchase"} ) + cls.product_3 = cls.env["product.product"].create( + { + "name": "Test Product 3", + "type": "service", + "bypass_global_discount": True, + } + ) cls.invoice_line = cls.env["account.move.line"] invoice_form = Form( cls.env["account.move"].with_context( @@ -116,6 +123,13 @@ def setUpClass(cls, chart_template_ref=None): line_form.quantity = 1 line_form.tax_ids.clear() line_form.tax_ids.add(cls.tax) + with invoice_form.invoice_line_ids.new() as line_form: + line_form.name = "Line 1" + line_form.product_id = cls.product_3 + line_form.price_unit = 200.0 + line_form.quantity = 1 + line_form.tax_ids.clear() + line_form.tax_ids.add(cls.tax_0) cls.invoice = invoice_form.save() def test_01_global_invoice_succesive_discounts(self): @@ -188,7 +202,7 @@ def test_02_global_invoice_discounts_from_partner(self): self.assertAlmostEqual(self.invoice.amount_global_discount, -60.0) def test_03_multiple_taxes_multi_line(self): - tax2 = self.tax.copy(default={"amount": 20.0}) + tax2 = self.tax.copy(default={"amount": 20.0, "name": "Tax 2"}) with Form(self.invoice) as invoice_form: invoice_form.global_discount_ids.add(self.global_discount_1) with invoice_form.invoice_line_ids.new() as line_form: @@ -230,7 +244,7 @@ def test_03_multiple_taxes_multi_line(self): def test_04_multiple_taxes_same_line(self): tax2 = self.tax.copy( - default={"amount": -20.0} + default={"amount": -20.0, "name": "Tax 2"} ) # negative for testing more use cases with Form(self.invoice.with_context(check_move_validity=False)) as invoice_form: invoice_form.global_discount_ids.add(self.global_discount_1) @@ -261,7 +275,7 @@ def test_05_incompatible_taxes(self): # Line 1 with tax and tax2 # Line 2 with only tax2 tax2 = self.tax.copy( - default={"amount": -20.0} + default={"amount": -20.0, "name": "Tax 2"} ) # negative for testing more use cases with self.assertRaises(exceptions.UserError): with Form(self.invoice) as invoice_form: @@ -320,7 +334,7 @@ def test_09_customer_invoice(self): "sequence": 1, } ) - tax = self.tax_sale_a.copy(default={"amount": 15.0}) + tax = self.tax_sale_a.copy(default={"amount": 15.0, "name": "Tax 2"}) invoice = ( self.env["account.move"] .with_context(test_account_global_discount=True) @@ -370,7 +384,11 @@ def test_10_customer_invoice_currency(self): self.assertAlmostEqual(invoice.amount_untaxed, 200.0) self.assertAlmostEqual(invoice.amount_global_discount, 0) base_line = invoice.line_ids.filtered( - lambda l: l.tax_ids and not l.invoice_global_discount_id + lambda line: ( + line.tax_ids + and not line.invoice_global_discount_id + and not line.product_id + ) ) self.assertEqual(len(base_line), 1) self.assertAlmostEqual( @@ -380,7 +398,7 @@ def test_10_customer_invoice_currency(self): ), ) tax_line = invoice.line_ids.filtered( - lambda l: l.tax_line_id and not l.invoice_global_discount_id + lambda line: line.tax_line_id and not line.invoice_global_discount_id ) self.assertEqual(len(tax_line), 1) tax_line_balance_before_discount = tax_line.balance @@ -413,7 +431,11 @@ def test_10_customer_invoice_currency(self): self.assertAlmostEqual(invoice.amount_untaxed, 160.0) self.assertAlmostEqual(invoice.amount_global_discount, -40.0) base_line = invoice.line_ids.filtered( - lambda l: l.tax_ids and not l.invoice_global_discount_id + lambda line: ( + line.tax_ids + and not line.invoice_global_discount_id + and not line.product_id + ) ) self.assertEqual(len(base_line), 1) self.assertAlmostEqual( @@ -426,7 +448,7 @@ def test_10_customer_invoice_currency(self): ), ) tax_line = invoice.line_ids.filtered( - lambda l: l.tax_line_id and not l.invoice_global_discount_id + lambda line: line.tax_line_id and not line.invoice_global_discount_id ) self.assertEqual(len(tax_line), 1) self.assertAlmostEqual( diff --git a/account_global_discount/views/account_invoice_views.xml b/account_global_discount/views/account_invoice_views.xml index c4124aade5a..7180f5d41f0 100644 --- a/account_global_discount/views/account_invoice_views.xml +++ b/account_global_discount/views/account_invoice_views.xml @@ -16,6 +16,7 @@ name="global_discount_ids" widget="many2many_tags" placeholder="Discounts..." + readonly="state != 'draft'" groups="base_global_discount.group_global_discount" /> @@ -65,7 +66,7 @@ name="invoice_global_discount_ids" nolabel="1" readonly="1" - attrs="{'invisible': [('global_discount_ids', '=', [])]}" + invisible="global_discount_ids" force_save="1" groups="base_global_discount.group_global_discount" > @@ -100,7 +101,7 @@ name="invoice_global_discount_ids" nolabel="1" readonly="1" - attrs="{'invisible': [('global_discount_ids_readonly', '=', [])]}" + invisible="global_discount_ids_readonly" force_save="1" groups="!base_global_discount.group_global_discount" >