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