From 42bbfa7eb45b80a85e95a068ddf627e2a36ca74f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 22 Dec 2020 00:24:04 +0100 Subject: [PATCH] Exclude by default shipment cost from promotion amount issue9776 review322501006 --- CHANGELOG | 1 + sale.py | 22 ++++ sale.xml | 8 +- .../scenario_sale_shipment_cost_promotion.rst | 122 ++++++++++++++++++ tests/test_sale_shipment_cost.py | 5 + view/promotion_form.xml | 9 ++ 6 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 tests/scenario_sale_shipment_cost_promotion.rst create mode 100644 view/promotion_form.xml diff --git a/CHANGELOG b/CHANGELOG index c2dcbda33f..3ebf1426cc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Exclude by default shipment cost from promotion amount * Allow shipment cost price to be edited Version 5.8.0 - 2020-11-02 diff --git a/sale.py b/sale.py index 4a6e654974..531383fc69 100644 --- a/sale.py +++ b/sale.py @@ -338,8 +338,30 @@ class ReturnSale(metaclass=PoolMeta): class Promotion(metaclass=PoolMeta): __name__ = 'sale.promotion' + amount_shipment_cost_included = fields.Boolean( + "Amount with Shipment Cost Included", + states={ + 'invisible': ~Eval('amount'), + }, + depends=['amount']) + + @classmethod + def default_amount_shipment_cost_included(cls): + return False + def get_context_formula(self, sale_line): context = super(Promotion, self).get_context_formula(sale_line) if sale_line and sale_line.shipment_cost: context['names']['unit_price'] = sale_line.shipment_cost return context + + def get_sale_amount(self, sale): + amount = super().get_sale_amount(sale) + if not self.amount_shipment_cost_included: + amount -= sum(l.amount for l in sale.lines if l.shipment_cost) + if not self.untaxed_amount: + amount -= sum( + v['amount'] + for l in sale.lines if l.shipment_cost + for v in l._get_taxes().values()) + return amount diff --git a/sale.xml b/sale.xml index 2c2699a96a..d261f951d7 100644 --- a/sale.xml +++ b/sale.xml @@ -23,6 +23,12 @@ this repository contains the full copyright notices and license terms. --> sale_line_tree_sequence - + + + + sale.promotion + + promotion_form + diff --git a/tests/scenario_sale_shipment_cost_promotion.rst b/tests/scenario_sale_shipment_cost_promotion.rst new file mode 100644 index 0000000000..fc7aa7f30a --- /dev/null +++ b/tests/scenario_sale_shipment_cost_promotion.rst @@ -0,0 +1,122 @@ +===================================== +Sale Shipment Cost Promotion Scenario +===================================== + +Imports:: + + >>> import datetime + >>> from dateutil.relativedelta import relativedelta + >>> from decimal import Decimal + >>> from proteus import Model, Wizard + >>> from trytond.tests.tools import activate_modules + >>> from trytond.modules.company.tests.tools import create_company, \ + ... get_company + >>> from trytond.modules.account.tests.tools import create_fiscalyear, \ + ... create_chart, get_accounts + >>> from trytond.modules.account_invoice.tests.tools import \ + ... set_fiscalyear_invoice_sequences, create_payment_term + >>> today = datetime.date.today() + +Activate modules:: + + >>> config = activate_modules([ + ... 'sale_shipment_cost', + ... 'sale', + ... 'sale_promotion', + ... ]) + +Create company:: + + >>> _ = create_company() + >>> company = get_company() + +Create chart of accounts:: + + >>> _ = create_chart(company) + >>> accounts = get_accounts(company) + +Create customer:: + + >>> Party = Model.get('party.party') + >>> customer = Party(name='Customer') + >>> customer.save() + +Create account category:: + + >>> ProductCategory = Model.get('product.category') + >>> account_category = ProductCategory(name="Account Category") + >>> account_category.accounting = True + >>> account_category.account_revenue = accounts['revenue'] + >>> account_category.save() + +Create product:: + + >>> ProductUom = Model.get('product.uom') + >>> ProductTemplate = Model.get('product.template') + >>> Product = Model.get('product.product') + >>> unit, = ProductUom.find([('name', '=', 'Unit')]) + + >>> template = ProductTemplate() + >>> template.name = 'Product' + >>> template.default_uom = unit + >>> template.type = 'goods' + >>> template.salable = True + >>> template.list_price = Decimal('20') + >>> template.account_category = account_category + >>> template.save() + >>> product, = template.products + + >>> carrier_template = ProductTemplate() + >>> carrier_template.name = 'Carrier Product' + >>> carrier_template.default_uom = unit + >>> carrier_template.type = 'service' + >>> carrier_template.salable = True + >>> carrier_template.list_price = Decimal('3') + >>> carrier_template.account_category = account_category + >>> carrier_template.save() + >>> carrier_product, = carrier_template.products + +Create Promotion:: + + >>> Promotion = Model.get('sale.promotion') + >>> promotion = Promotion(name='product 2 free') + >>> promotion.amount = Decimal('101') + >>> promotion.amount_shipment_cost_included = False + >>> promotion.currency = company.currency + >>> promotion.products.extend([Product(carrier_product.id)]) + >>> promotion.formula = '0.0' + >>> promotion.save() + +Create carrier:: + + >>> Carrier = Model.get('carrier') + >>> carrier = Carrier() + >>> party = Party(name='Carrier') + >>> party.save() + >>> carrier.party = party + >>> carrier.carrier_product = carrier_product + >>> carrier.save() + +Sale products without the promotion:: + + >>> Sale = Model.get('sale.sale') + >>> sale = Sale() + >>> sale.party = customer + >>> sale.carrier = carrier + >>> sale_line = sale.lines.new() + >>> sale_line.product = product + >>> sale_line.quantity = 5.0 + >>> sale.click('quote') + >>> cost_line = sale.lines[-1] + >>> cost_line.amount + Decimal('3.00') + +Increase sale to get the promotion:: + + >>> sale.click('draft') + >>> line = sale.lines[0] + >>> line.quantity = 6.0 + >>> sale.click('quote') + >>> cost_line = sale.lines[-1] + >>> cost_line.amount + Decimal('0.00') diff --git a/tests/test_sale_shipment_cost.py b/tests/test_sale_shipment_cost.py index ab5edc426f..33bd31e783 100644 --- a/tests/test_sale_shipment_cost.py +++ b/tests/test_sale_shipment_cost.py @@ -27,4 +27,9 @@ def suite(): tearDown=doctest_teardown, encoding='utf-8', checker=doctest_checker, optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)) + suite.addTests(doctest.DocFileSuite( + 'scenario_sale_shipment_cost_promotion.rst', + tearDown=doctest_teardown, encoding='utf-8', + checker=doctest_checker, + optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)) return suite diff --git a/view/promotion_form.xml b/view/promotion_form.xml new file mode 100644 index 0000000000..67d5e46326 --- /dev/null +++ b/view/promotion_form.xml @@ -0,0 +1,9 @@ + + + + + +