diff --git a/.copier-answers.yml b/.copier-answers.yml index ccae8b8d79b..81cdf2aff97 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -18,6 +18,8 @@ org_name: Odoo Community Association (OCA) org_slug: OCA rebel_module_groups: - sale_packaging_default,sale_order_product_recommendation,sale_order_product_recommendation_packaging_default,sale_order_product_recommendation_elaboration +- sale_triple_discount +- sale_fixed_discount repo_description: 'TODO: add repo description.' repo_name: sale-workflow repo_slug: sale-workflow diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 012fcccfc24..6d24eb63e7f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -43,10 +43,24 @@ jobs: name: test with OCB makepot: "true" - container: ghcr.io/oca/oca-ci/py3.10-odoo16.0:latest - exclude: "sale_packaging_default,sale_order_product_recommendation,sale_order_product_recommendation_packaging_default,sale_order_product_recommendation_elaboration" + include: "sale_triple_discount" name: test with Odoo - container: ghcr.io/oca/oca-ci/py3.10-ocb16.0:latest - exclude: "sale_packaging_default,sale_order_product_recommendation,sale_order_product_recommendation_packaging_default,sale_order_product_recommendation_elaboration" + include: "sale_triple_discount" + name: test with OCB + makepot: "true" + - container: ghcr.io/oca/oca-ci/py3.10-odoo16.0:latest + include: "sale_fixed_discount" + name: test with Odoo + - container: ghcr.io/oca/oca-ci/py3.10-ocb16.0:latest + include: "sale_fixed_discount" + name: test with OCB + makepot: "true" + - container: ghcr.io/oca/oca-ci/py3.10-odoo16.0:latest + exclude: "sale_packaging_default,sale_order_product_recommendation,sale_order_product_recommendation_packaging_default,sale_order_product_recommendation_elaboration,sale_triple_discount,sale_fixed_discount" + name: test with Odoo + - container: ghcr.io/oca/oca-ci/py3.10-ocb16.0:latest + exclude: "sale_packaging_default,sale_order_product_recommendation,sale_order_product_recommendation_packaging_default,sale_order_product_recommendation_elaboration,sale_triple_discount,sale_fixed_discount" name: test with OCB makepot: "true" services: diff --git a/sale_fixed_discount/__manifest__.py b/sale_fixed_discount/__manifest__.py index e5f30fdb745..8c3eda56986 100644 --- a/sale_fixed_discount/__manifest__.py +++ b/sale_fixed_discount/__manifest__.py @@ -11,6 +11,7 @@ "application": False, "installable": True, "depends": ["sale", "account_invoice_fixed_discount"], + "excludes": ["sale_triple_discount"], "data": [ "security/res_groups.xml", "reports/report_sale_order.xml", diff --git a/sale_fixed_discount/static/description/index.html b/sale_fixed_discount/static/description/index.html index b6852391be2..5f4d9f7bc00 100644 --- a/sale_fixed_discount/static/description/index.html +++ b/sale_fixed_discount/static/description/index.html @@ -8,10 +8,11 @@ /* :Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $ +:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $ :Copyright: This stylesheet has been placed in the public domain. Default cascading style sheet for the HTML output of Docutils. +Despite the name, some widely supported CSS2 features are used. See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to customize this style sheet. @@ -274,7 +275,7 @@ margin-left: 2em ; margin-right: 2em } -pre.code .ln { color: grey; } /* line numbers */ +pre.code .ln { color: gray; } /* line numbers */ pre.code, code { background-color: #eeeeee } pre.code .comment, code .comment { color: #5C6576 } pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } @@ -300,7 +301,7 @@ span.pre { white-space: pre } -span.problematic { +span.problematic, pre.problematic { color: red } span.section-subtitle { @@ -436,7 +437,9 @@

Contributors

Maintainers

This module is maintained by the OCA.

-Odoo Community Association + +Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

diff --git a/sale_order_general_discount/models/sale_order_line.py b/sale_order_general_discount/models/sale_order_line.py index a1f5cd15155..cdb3b096293 100644 --- a/sale_order_general_discount/models/sale_order_line.py +++ b/sale_order_general_discount/models/sale_order_line.py @@ -15,5 +15,9 @@ def _compute_discount(self): # set again to 0 to remove the discount on all the lines at the same # time if line.order_id.general_discount or line.order_id._origin.general_discount: - line.discount = line.order_id.general_discount + if "discount1" in self._fields: + # Compatibility with sale_triple_discount module + line.discount1 = line.order_id.general_discount + else: + line.discount = line.order_id.general_discount return res diff --git a/sale_order_general_discount_triple/models/res_config_settings.py b/sale_order_general_discount_triple/models/res_config_settings.py index ec91613c5fc..fddbdf70903 100644 --- a/sale_order_general_discount_triple/models/res_config_settings.py +++ b/sale_order_general_discount_triple/models/res_config_settings.py @@ -6,7 +6,7 @@ class ResConfigSettings(models.TransientModel): general_discount = fields.Selection( [ - ("discount", "Discount"), + ("discount1", "Discount 1"), ("discount2", "Discount 2"), ("discount3", "Discount 3"), ], @@ -15,7 +15,7 @@ class ResConfigSettings(models.TransientModel): ) pricelist_discount = fields.Selection( [ - ("discount", "Discount"), + ("discount1", "Discount 1"), ("discount2", "Discount 2"), ("discount3", "Discount 3"), ], diff --git a/sale_order_general_discount_triple/models/sale_order.py b/sale_order_general_discount_triple/models/sale_order.py index c9285f09dd5..fbc45478bc5 100644 --- a/sale_order_general_discount_triple/models/sale_order.py +++ b/sale_order_general_discount_triple/models/sale_order.py @@ -10,7 +10,7 @@ def onchange_general_discount(self): self.env["ir.config_parameter"] .sudo() .get_param( - "sale_order_general_discount_triple.general_discount", "discount" + "sale_order_general_discount_triple.general_discount", "discount1" ) ) if general_discount != "no_apply": @@ -20,7 +20,7 @@ def onchange_general_discount(self): def _create_delivery_line(self, carrier, price_unit): res = super()._create_delivery_line(carrier, price_unit) for line in self.order_line: - line._compute_discount() + line._compute_discount1() line._compute_discount2() line._compute_discount3() return res diff --git a/sale_order_general_discount_triple/models/sale_order_line.py b/sale_order_general_discount_triple/models/sale_order_line.py index 90839823ded..fcada4ffdaf 100644 --- a/sale_order_general_discount_triple/models/sale_order_line.py +++ b/sale_order_general_discount_triple/models/sale_order_line.py @@ -4,21 +4,22 @@ class SaleOrderLine(models.Model): _inherit = "sale.order.line" + discount1 = fields.Float(compute="_compute_discount1", store=True, readonly=False) discount2 = fields.Float(compute="_compute_discount2", store=True, readonly=False) discount3 = fields.Float(compute="_compute_discount3", store=True, readonly=False) @api.depends("product_id", "product_uom", "product_uom_qty") - def _compute_discount(self): + def _compute_discount1(self): pricelist_discount = self._get_discount_field_position("pricelist_discount") general_discount = self._get_discount_field_position("general_discount") - if "discount" not in [pricelist_discount, general_discount]: - self.update({"discount": 0.0}) + if "discount1" not in [pricelist_discount, general_discount]: + self.update({"discount1": 0.0}) return for line in self: - if pricelist_discount == "discount": - line.update({"discount": line._get_pricelist_discount()}) - elif general_discount == "discount": - line.update({"discount": line.order_id.general_discount}) + if pricelist_discount == "discount1": + line.update({"discount1": line._get_pricelist_discount()}) + elif general_discount == "discount1": + line.update({"discount1": line.order_id.general_discount}) return @api.depends("product_id", "product_uom", "product_uom_qty") @@ -71,6 +72,6 @@ def _get_discount_field_position(self, field_name): self.env["ir.config_parameter"] .sudo() .get_param( - "sale_order_general_discount_triple.{}".format(field_name), "discount" + "sale_order_general_discount_triple.{}".format(field_name), "discount1" ) ) diff --git a/sale_order_general_discount_triple/tests/test_module.py b/sale_order_general_discount_triple/tests/test_module.py index 3f7f731b4be..706ac9d9297 100644 --- a/sale_order_general_discount_triple/tests/test_module.py +++ b/sale_order_general_discount_triple/tests/test_module.py @@ -29,7 +29,7 @@ def setUpClass(cls): ) setting_form = Form(cls.env["res.config.settings"]) setting_form.general_discount = "discount2" - setting_form.pricelist_discount = "discount" + setting_form.pricelist_discount = "discount1" setting_form.group_discount_per_so_line = True setting_form.save().set_values() @@ -41,4 +41,4 @@ def test_action_result(self): line.product_id = self.product sale = sale_form.save() self.assertEqual(sale.order_line.discount2, 10) - self.assertEqual(sale.order_line.discount, 20) + self.assertEqual(sale.order_line.discount1, 20) diff --git a/sale_triple_discount/README.rst b/sale_triple_discount/README.rst index 2f2c5340362..a2f5ac77854 100644 --- a/sale_triple_discount/README.rst +++ b/sale_triple_discount/README.rst @@ -109,6 +109,7 @@ Contributors * Pimolnat Suntian * Denis Leemann * Manuel Regidor +* Akim Juillerat Maintainers ~~~~~~~~~~~ diff --git a/sale_triple_discount/__init__.py b/sale_triple_discount/__init__.py index 0650744f6bc..f1a5233b277 100644 --- a/sale_triple_discount/__init__.py +++ b/sale_triple_discount/__init__.py @@ -1 +1,2 @@ from . import models +from .hooks import post_load diff --git a/sale_triple_discount/__manifest__.py b/sale_triple_discount/__manifest__.py index 47833af14a1..274dae70748 100644 --- a/sale_triple_discount/__manifest__.py +++ b/sale_triple_discount/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Sale Triple Discount", - "version": "16.0.1.0.4", + "version": "16.0.2.0.0", "category": "Sales", "author": "ADHOC SA, Agile Business Group, Tecnativa, " "Odoo Community Association (OCA)", @@ -14,6 +14,8 @@ "license": "AGPL-3", "summary": "Manage triple discount on sale order lines", "depends": ["sale_management", "account_invoice_triple_discount"], + "excludes": ["sale_fixed_discount"], "data": ["views/sale_order_report.xml", "views/sale_order_view.xml"], "installable": True, + "post_load": "post_load", } diff --git a/sale_triple_discount/hooks.py b/sale_triple_discount/hooks.py new file mode 100644 index 00000000000..7813d820ed2 --- /dev/null +++ b/sale_triple_discount/hooks.py @@ -0,0 +1,24 @@ +# Copyright 2024 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +import logging + +import pkg_resources + +from odoo.modules.module import get_manifest + +_logger = logging.getLogger(__name__) + + +def post_load(): + account_invoice_triple_discount_manifest = get_manifest( + "account_invoice_triple_discount" + ) + if not pkg_resources.parse_version( + account_invoice_triple_discount_manifest["version"] + ) >= pkg_resources.parse_version("16.0.2.0.0"): + msg = ( + "Module sale_triple_discount requires module " + "account_invoice_triple_discount >= 16.0.2.0.0" + ) + _logger.error(msg) + raise Exception(msg) diff --git a/sale_triple_discount/migrations/16.0.2.0.0/post-migrate.py b/sale_triple_discount/migrations/16.0.2.0.0/post-migrate.py new file mode 100644 index 00000000000..9bf77242f30 --- /dev/null +++ b/sale_triple_discount/migrations/16.0.2.0.0/post-migrate.py @@ -0,0 +1,23 @@ +# Copyright 2024 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) + +from openupgradelib import openupgrade + + +@openupgrade.logging() +def compute_discount(env): + lines_with_discount = env["sale.order.line"].search( + [ + "|", + "|", + ("discount1", "!=", 0), + ("discount2", "!=", 0), + ("discount3", "!=", 0), + ] + ) + lines_with_discount._compute_discount_consolidated() + + +@openupgrade.migrate() +def migrate(env, version): + compute_discount(env) diff --git a/sale_triple_discount/migrations/16.0.2.0.0/pre-migrate.py b/sale_triple_discount/migrations/16.0.2.0.0/pre-migrate.py new file mode 100644 index 00000000000..a9dd2eec07d --- /dev/null +++ b/sale_triple_discount/migrations/16.0.2.0.0/pre-migrate.py @@ -0,0 +1,32 @@ +# Copyright 2024 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +from openupgradelib import openupgrade + + +def migrate_discount_to_discount1(env): + openupgrade.add_fields( + env, + [ + ( + "discount1", + "sale.order.line", + "sale_order_line", + "float", + "numeric", + "sale_triple_discount", + 0.0, + ) + ], + ) + openupgrade.logged_query( + env.cr, + """ + UPDATE sale_order_line + SET discount1 = discount; + """, + ) + + +@openupgrade.migrate() +def migrate(env, version): + migrate_discount_to_discount1(env) diff --git a/sale_triple_discount/models/sale_order_line.py b/sale_triple_discount/models/sale_order_line.py index 992ecaec478..3b2c7e6135f 100644 --- a/sale_triple_discount/models/sale_order_line.py +++ b/sale_triple_discount/models/sale_order_line.py @@ -3,9 +3,6 @@ # Copyright 2017 Tecnativa - David Vidal # Copyright 2018 Simone Rubino - Agile Business Group # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from contextlib import contextmanager - from odoo import _, api, fields, models from odoo.exceptions import ValidationError @@ -13,6 +10,24 @@ class SaleOrderLine(models.Model): _inherit = "sale.order.line" + discount = fields.Float( + string="Total discount", + store=True, + compute="_compute_discount_consolidated", + compute_sudo=True, + precompute=True, + readonly=True, + ) + discount1 = fields.Float( + string="Disc. 1 (%)", + digits="Discount", + store=True, + default=0.0, + compute="_compute_discount", + compute_sudo=True, + precompute=True, + readonly=False, + ) discount2 = fields.Float( string="Disc. 2 (%)", digits="Discount", @@ -60,19 +75,61 @@ def _multiplicative_discount(self): final_discount = 1 for discount in discounts: final_discount *= discount - return 100 - final_discount * 100 + result = 100 - final_discount * 100 + dp = self.env.ref("product.decimal_discount").precision_get("Discount") + return round(result, dp) @api.model def _discount_fields(self): - return ["discount", "discount2", "discount3"] + return ["discount1", "discount2", "discount3"] - @api.depends("discount2", "discount3", "discounting_type") - def _compute_amount(self): - with self._aggregated_discount() as lines: - res = super(SaleOrderLine, lines)._compute_amount() - return res + # Copy of Odoo function to change field being assigned from discount to discount1 + @api.depends("product_id", "product_uom", "product_uom_qty") + def _compute_discount(self): + for line in self: + if not line.product_id or line.display_type: + line.discount1 = 0.0 + + if not ( + line.order_id.pricelist_id + and line.order_id.pricelist_id.discount_policy == "without_discount" + ): + continue + + line.discount1 = 0.0 + + if not line.pricelist_item_id: + # No pricelist rule was found for the product + # therefore, the pricelist didn't apply any discount/change + # to the existing sales price. + continue + + line.discount1 = line._calc_discount_from_pricelist() + + def _calc_discount_from_pricelist(self): + self.ensure_one() + self = self.with_company(self.company_id) + pricelist_price = self._get_pricelist_price() + base_price = self._get_pricelist_price_before_discount() + + if base_price != 0: # Avoid division by zero + discount = (base_price - pricelist_price) / base_price * 100 + if (discount > 0 and base_price > 0) or (discount < 0 and base_price < 0): + # only show negative discounts if price is negative + # otherwise it's a surcharge which shouldn't be shown to the customer + return discount + + @api.depends("discount1", "discount2", "discount3", "discounting_type") + def _compute_discount_consolidated(self): + for line in self: + line.discount = line._get_final_discount() _sql_constraints = [ + ( + "discount1_limit", + "CHECK (discount1 <= 100.0)", + "Discount 1 must be lower or equal than 100%.", + ), ( "discount2_limit", "CHECK (discount2 <= 100.0)", @@ -91,51 +148,15 @@ def _prepare_invoice_line(self, **kwargs): more discount fields to the invoice lines """ res = super()._prepare_invoice_line(**kwargs) - res.update({"discount2": self.discount2, "discount3": self.discount3}) + res.pop("discount", None) + if self.discounting_type == "multiplicative": + res.update( + { + "discount1": self.discount1, + "discount2": self.discount2, + "discount3": self.discount3, + } + ) + else: + res.update({"discount1": self.discount}) return res - - @contextmanager - def _aggregated_discount(self): - """A context manager to temporarily change the discount value on the - records and restore it after the context is exited. It temporarily - changes the discount value to the aggregated discount value so that - methods that depend on the discount value will use the aggregated - discount value instead of the original one. - """ - discount_field = self._fields["discount"] - # Protect discount field from triggering recompute of totals. We don't want - # to invalidate the cache to avoid to flush the records to the database. - # This is safe because we are going to restore the original value at the end - # of the method. - with self.env.protecting([discount_field], self): - old_values = {} - for line in self: - old_values[line.id] = line.discount - aggregated_discount = line._get_final_discount() - line.update({"discount": aggregated_discount}) - yield self.with_context(discount_is_aggregated=True) - for line in self: - if line.id not in old_values: - continue - line.with_context( - restoring_triple_discount=True, - ).update({"discount": old_values[line.id]}) - - def _convert_to_tax_base_line_dict(self): - self.ensure_one() - discount = ( - self.discount - if self.env.context.get("discount_is_aggregated") - else self._get_final_discount() - ) - return self.env["account.tax"]._convert_to_tax_base_line_dict( - self, - partner=self.order_id.partner_id, - currency=self.order_id.currency_id, - product=self.product_id, - taxes=self.tax_id, - price_unit=self.price_unit, - quantity=self.product_uom_qty, - discount=discount, - price_subtotal=self.price_subtotal, - ) diff --git a/sale_triple_discount/readme/CONTRIBUTORS.rst b/sale_triple_discount/readme/CONTRIBUTORS.rst index b196f4fa786..96c597e91dd 100644 --- a/sale_triple_discount/readme/CONTRIBUTORS.rst +++ b/sale_triple_discount/readme/CONTRIBUTORS.rst @@ -7,3 +7,4 @@ * Pimolnat Suntian * Denis Leemann * Manuel Regidor +* Akim Juillerat diff --git a/sale_triple_discount/static/description/index.html b/sale_triple_discount/static/description/index.html index 9383f7b48f0..6903072f1a6 100644 --- a/sale_triple_discount/static/description/index.html +++ b/sale_triple_discount/static/description/index.html @@ -457,6 +457,7 @@

Contributors

  • Pimolnat Suntian <pimolnats@ecosoft.co.th>
  • Denis Leemann <denis.leemann@camptocamp.com>
  • Manuel Regidor <manuel.regidor@sygel.es>
  • +
  • Akim Juillerat <akim.juillerat@camptocamp.com>
  • diff --git a/sale_triple_discount/tests/test_sale_triple_discount.py b/sale_triple_discount/tests/test_sale_triple_discount.py index 069e796cb1e..dafba593be3 100644 --- a/sale_triple_discount/tests/test_sale_triple_discount.py +++ b/sale_triple_discount/tests/test_sale_triple_discount.py @@ -51,8 +51,38 @@ def setUpClass(cls): def test_01_sale_order_classic_discount(self): """Tests with single discount""" - self.so_line1.discount = 50.0 - self.so_line2.discount = 75.0 + self.so_line1.discount1 = 50.0 + self.so_line2.discount1 = 75.0 + self.assertAlmostEqual(self.so_line1.discount, 50.0) + self.assertAlmostEqual(self.so_line2.discount, 75.0) + self.assertAlmostEqual(self.so_line1.price_subtotal, 300.0) + self.assertAlmostEqual(self.so_line2.price_subtotal, 150.0) + self.assertAlmostEqual(self.order.amount_untaxed, 450.0) + self.assertAlmostEqual(self.order.amount_tax, 67.5) + # Mix taxed and untaxed: + self.so_line1.tax_id = False + self.assertAlmostEqual(self.order.amount_tax, 22.5) + + def test_01_2_sale_order_classic_discount(self): + """Tests with single discount""" + self.so_line1.discount2 = 50.0 + self.so_line2.discount2 = 75.0 + self.assertAlmostEqual(self.so_line1.discount, 50.0) + self.assertAlmostEqual(self.so_line2.discount, 75.0) + self.assertAlmostEqual(self.so_line1.price_subtotal, 300.0) + self.assertAlmostEqual(self.so_line2.price_subtotal, 150.0) + self.assertAlmostEqual(self.order.amount_untaxed, 450.0) + self.assertAlmostEqual(self.order.amount_tax, 67.5) + # Mix taxed and untaxed: + self.so_line1.tax_id = False + self.assertAlmostEqual(self.order.amount_tax, 22.5) + + def test_01_3_sale_order_classic_discount(self): + """Tests with single discount""" + self.so_line1.discount3 = 50.0 + self.so_line2.discount3 = 75.0 + self.assertAlmostEqual(self.so_line1.discount, 50.0) + self.assertAlmostEqual(self.so_line2.discount, 75.0) self.assertAlmostEqual(self.so_line1.price_subtotal, 300.0) self.assertAlmostEqual(self.so_line2.price_subtotal, 150.0) self.assertAlmostEqual(self.order.amount_untaxed, 450.0) @@ -65,19 +95,22 @@ def test_02_sale_order_simple_triple_discount(self): """Tests on a single line""" self.so_line2.unlink() # Divide by two on every discount: - self.so_line1.discount = 50.0 + self.so_line1.discount1 = 50.0 self.so_line1.discount2 = 50.0 self.so_line1.discount3 = 50.0 + self.assertAlmostEqual(self.so_line1.discount, 87.5) self.assertAlmostEqual(self.so_line1.price_subtotal, 75.0) self.assertAlmostEqual(self.order.amount_untaxed, 75.0) self.assertAlmostEqual(self.order.amount_tax, 11.25) # Unset first discount: - self.so_line1.discount = 0.0 + self.so_line1.discount1 = 0.0 + self.assertAlmostEqual(self.so_line1.discount, 75) self.assertAlmostEqual(self.so_line1.price_subtotal, 150.0) self.assertAlmostEqual(self.order.amount_untaxed, 150.0) self.assertAlmostEqual(self.order.amount_tax, 22.5) # Set a charge instead: self.so_line1.discount2 = -50.0 + self.assertAlmostEqual(self.so_line1.discount, 25) self.assertAlmostEqual(self.so_line1.price_subtotal, 450.0) self.assertAlmostEqual(self.order.amount_untaxed, 450.0) self.assertAlmostEqual(self.order.amount_tax, 67.5) @@ -88,10 +121,11 @@ def test_02_sale_order_simple_triple_discount(self): 67.5, ) # set discount_type to additive - self.so_line1.discount = 10.0 + self.so_line1.discount1 = 10.0 self.so_line1.discount2 = 10.0 self.so_line1.discount3 = 10.0 self.so_line1.discounting_type = "additive" + self.assertAlmostEqual(self.so_line1.discount, 30.0) self.assertAlmostEqual(self.so_line1.price_subtotal, 420.0) self.assertAlmostEqual(self.order.amount_untaxed, 420.0) self.assertAlmostEqual(self.order.amount_tax, 63.0) @@ -102,47 +136,54 @@ def test_02_sale_order_simple_triple_discount(self): 63.0, ) # set discount over 100% - self.so_line1.discount = 30.0 + self.so_line1.discount1 = 30.0 self.so_line1.discount2 = 70.0 self.so_line1.discount3 = 50.0 + self.assertAlmostEqual(self.so_line1.discount, 100.0) self.assertAlmostEqual(self.so_line1.price_subtotal, 0.0) self.assertAlmostEqual(self.order.amount_untaxed, 0.0) self.assertAlmostEqual(self.order.amount_tax, 0.0) # set discount_type to multiplicative - self.so_line1.discount = 50.0 + self.so_line1.discount1 = 50.0 self.so_line1.discount2 = 50.0 self.so_line1.discount3 = 50.0 self.so_line1.discounting_type = "multiplicative" + self.assertAlmostEqual(self.so_line1.discount, 87.5) self.assertAlmostEqual(self.so_line1.price_subtotal, 75.0) self.assertAlmostEqual(self.order.amount_untaxed, 75.0) self.assertAlmostEqual(self.order.amount_tax, 11.25) def test_03_sale_order_complex_triple_discount(self): """Tests on multiple lines""" - self.so_line1.discount = 50.0 + self.so_line1.discount1 = 50.0 self.so_line1.discount2 = 50.0 self.so_line1.discount3 = 50.0 + self.assertAlmostEqual(self.so_line1.discount, 87.5) self.assertAlmostEqual(self.so_line1.price_subtotal, 75.0) self.assertAlmostEqual(self.order.amount_untaxed, 675.0) self.assertAlmostEqual(self.order.amount_tax, 101.25) # additive discount self.so_line2.discount3 = 50.0 + self.assertAlmostEqual(self.so_line2.discount, 50.0) self.assertAlmostEqual(self.so_line2.price_subtotal, 300.0) self.assertAlmostEqual(self.order.amount_untaxed, 375.0) self.assertAlmostEqual(self.order.amount_tax, 56.25) self.so_line2.discounting_type = "additive" self.so_line2.discount2 = 10.0 + self.assertAlmostEqual(self.so_line2.discount, 60.0) self.assertAlmostEqual(self.so_line2.price_subtotal, 240.0) self.assertAlmostEqual(self.order.amount_untaxed, 315.0) self.assertAlmostEqual(self.order.amount_tax, 47.25) # multiplicative discount self.so_line2.discount2 = 0.0 self.so_line2.discount3 = 50.0 + self.assertAlmostEqual(self.so_line2.discount, 50.0) self.assertAlmostEqual(self.so_line2.price_subtotal, 300.0) self.assertAlmostEqual(self.order.amount_untaxed, 375.0) self.assertAlmostEqual(self.order.amount_tax, 56.25) self.so_line2.discounting_type = "multiplicative" self.so_line2.discount2 = 10.0 + self.assertAlmostEqual(self.so_line1.discount, 87.5) self.assertAlmostEqual(self.so_line2.price_subtotal, 270.0) self.assertAlmostEqual(self.order.amount_untaxed, 345.0) self.assertAlmostEqual(self.order.amount_tax, 51.75) @@ -155,6 +196,7 @@ def test_04_sale_order_triple_discount_invoicing(self): self.so_line1.discount3 = 50.0 self.so_line2.discount3 = 50.0 self.order.action_confirm() + # FIXME: AFAIK this is another module messing and shouldn't be in this test if self.order.state == "waiting_approval": self.order.action_approve() self.assertAlmostEqual(self.order.state, "approved") @@ -164,6 +206,9 @@ def test_04_sale_order_triple_discount_invoicing(self): self.assertAlmostEqual( self.so_line1.discount, invoice.invoice_line_ids[0].discount ) + self.assertAlmostEqual( + self.so_line1.discount1, invoice.invoice_line_ids[0].discount1 + ) self.assertAlmostEqual( self.so_line1.discount2, invoice.invoice_line_ids[0].discount2 ) @@ -173,6 +218,9 @@ def test_04_sale_order_triple_discount_invoicing(self): self.assertAlmostEqual( self.so_line1.price_subtotal, invoice.invoice_line_ids[0].price_subtotal ) + self.assertAlmostEqual( + self.so_line2.discount, invoice.invoice_line_ids[1].discount + ) self.assertAlmostEqual( self.so_line2.discount3, invoice.invoice_line_ids[1].discount3 ) @@ -184,7 +232,7 @@ def test_04_sale_order_triple_discount_invoicing(self): def test_05_round_globally(self): """Tests on multiple lines when 'round_globally' is active""" self.env.user.company_id.tax_calculation_rounding_method = "round_globally" - self.so_line1.discount = 50.0 + self.so_line1.discount1 = 50.0 self.so_line1.discount2 = 50.0 self.so_line1.discount3 = 50.0 self.assertEqual(self.so_line1.price_subtotal, 75.0) @@ -197,11 +245,11 @@ def test_05_round_globally(self): def test_06_discount_0(self): self.so_line1.discounting_type = "additive" - self.so_line1.discount = 0.0 + self.so_line1.discount1 = 0.0 self.so_line1.discount2 = 0.0 self.so_line1.discount3 = 0.0 self.so_line2.discounting_type = "additive" - self.so_line2.discount = 0.0 + self.so_line2.discount1 = 0.0 self.so_line2.discount2 = 0.0 self.so_line2.discount3 = 0.0 self.assertAlmostEqual(self.so_line1.price_subtotal, 600.0) diff --git a/sale_triple_discount/views/sale_order_report.xml b/sale_triple_discount/views/sale_order_report.xml index de0402c2cf9..466341e0845 100644 --- a/sale_triple_discount/views/sale_order_report.xml +++ b/sale_triple_discount/views/sale_order_report.xml @@ -4,7 +4,15 @@ id="report_saleorder_document_triple_discount" inherit_id="sale.report_saleorder_document" > + + + False + + + + Disc. 1 (%) + + + + sale.order + + Total discount + hide + + +