From 8f4390177fae9eda3939e4c6c24b8e105651b42c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 22 Mar 2018 14:53:56 +0100 Subject: [PATCH] Create requests depending on the shipment method If the shipment method is on invoice paid, the purchase request should be created only when all the invoice lines are paid and the quantity should be the quantity invoiced. issue7200 review44101002 --- CHANGELOG | 2 + doc/index.rst | 5 + sale.py | 14 ++- ...enario_sale_supply_shipment_on_invoice.rst | 117 ++++++++++++++++++ tests/test_sale_supply.py | 5 + 5 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 tests/scenario_sale_supply_shipment_on_invoice.rst diff --git a/CHANGELOG b/CHANGELOG index 643782f1cb..c57baf585e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,5 @@ +* Create requests depending on the shipment method + Version 4.6.0 - 2017-10-30 * Bug fixes (see mercurial logs for details) diff --git a/doc/index.rst b/doc/index.rst index ff0156d57e..98994d9aa6 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -5,3 +5,8 @@ The Sale Supply module adds a supply on sale option on product. If checked, it will generate a purchase request for each sale line of this product regardless of the stock levels. Once the purchased products are received they are assigned on the customer shipments. + +.. warning:: + If the shiment method is *On Invoice Paid*, the purchase request will be + created only when all the invoice lines are paid +.. diff --git a/sale.py b/sale.py index 393611bef5..cf3f6e205c 100644 --- a/sale.py +++ b/sale.py @@ -124,11 +124,23 @@ class SaleLine: if not self.supply_on_sale or self.purchase_request: return + # Ensure to create the request for the maximum paid + if self.sale.shipment_method == 'invoice': + invoice_skips = (set(self.sale.invoices_ignored) + | set(self.sale.invoices_recreated)) + invoice_lines = [l for l in self.invoice_lines + if l.invoice not in invoice_skips] + if (not invoice_lines + or any((not l.invoice) or l.invoice.state != 'paid' + for l in invoice_lines)): + return + product = self.product supplier, purchase_date = Request.find_best_supplier(product, self.shipping_date) uom = product.purchase_uom or product.default_uom - quantity = Uom.compute_qty(self.unit, self.quantity, uom) + quantity = self._get_move_quantity('out') + quantity = Uom.compute_qty(self.unit, quantity, uom) return Request( product=product, party=supplier, diff --git a/tests/scenario_sale_supply_shipment_on_invoice.rst b/tests/scenario_sale_supply_shipment_on_invoice.rst new file mode 100644 index 0000000000..7acc748108 --- /dev/null +++ b/tests/scenario_sale_supply_shipment_on_invoice.rst @@ -0,0 +1,117 @@ +============================================= +Sale Supply with Shipment on Invoice Scenario +============================================= + +Imports:: + + >>> 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 + +Install sale_supply:: + + >>> config = activate_modules('sale_supply') + +Create company:: + + >>> _ = create_company() + >>> company = get_company() + +Create fiscal year:: + + >>> fiscalyear = set_fiscalyear_invoice_sequences( + ... create_fiscalyear(company)) + >>> fiscalyear.click('create_period') + +Create chart of accounts:: + + >>> _ = create_chart(company) + >>> accounts = get_accounts(company) + + >>> Journal = Model.get('account.journal') + >>> cash_journal, = Journal.find([('type', '=', 'cash')]) + >>> cash_journal.credit_account = accounts['cash'] + >>> cash_journal.debit_account = accounts['cash'] + >>> cash_journal.save() + +Create parties:: + + >>> Party = Model.get('party.party') + >>> customer = Party(name='Customer') + >>> customer.save() + +Create product:: + + >>> ProductUom = Model.get('product.uom') + >>> unit, = ProductUom.find([('name', '=', 'Unit')]) + >>> ProductTemplate = Model.get('product.template') + + >>> template = ProductTemplate() + >>> template.name = 'product' + >>> template.default_uom = unit + >>> template.type = 'goods' + >>> template.salable = True + >>> template.purchasable = True + >>> template.list_price = Decimal('10') + >>> template.account_revenue = accounts['revenue'] + >>> template.account_expense = accounts['expense'] + >>> template.supply_on_sale = True + >>> template.save() + >>> product, = template.products + +Sale 5 products with shipment method on invoice:: + + >>> Sale = Model.get('sale.sale') + >>> sale = Sale() + >>> sale.party = customer + >>> sale.shipment_method = 'invoice' + >>> sale_line = sale.lines.new() + >>> sale_line.product = product + >>> sale_line.quantity = 5 + >>> sale.click('quote') + >>> sale.click('confirm') + >>> sale.click('process') + >>> sale.state + u'processing' + >>> len(sale.shipments) + 0 + >>> invoice, = sale.invoices + >>> sale_line, = sale.lines + >>> sale_line.purchase_request + +Pay for 4 products:: + + >>> invoice_line, = invoice.lines + >>> invoice_line.quantity = 4 + >>> invoice.click('post') + >>> pay = Wizard('account.invoice.pay', [invoice]) + >>> pay.form.journal = cash_journal + >>> pay.execute('choice') + +Not yet a purchase request:: + + >>> sale_line.reload() + >>> sale_line.purchase_request + +Pay for remaining products:: + + >>> sale.reload() + >>> _, invoice = sale.invoices + >>> invoice.click('post') + >>> pay = Wizard('account.invoice.pay', [invoice]) + >>> pay.form.journal = cash_journal + >>> pay.execute('choice') + +Check purchase request:: + + >>> sale_line.reload() + >>> bool(sale_line.purchase_request) + True + >>> sale_line.purchase_request.quantity + 5.0 diff --git a/tests/test_sale_supply.py b/tests/test_sale_supply.py index 0d9067f7a5..015b13389c 100644 --- a/tests/test_sale_supply.py +++ b/tests/test_sale_supply.py @@ -21,4 +21,9 @@ def suite(): tearDown=doctest_teardown, encoding='utf-8', checker=doctest_checker, optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)) + suite.addTests(doctest.DocFileSuite( + 'scenario_sale_supply_shipment_on_invoice.rst', + tearDown=doctest_teardown, encoding='utf-8', + checker=doctest_checker, + optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)) return suite