changeset 53918955ac8b in modules/account_invoice_stock:default
details:
https://hg.tryton.org/modules/account_invoice_stock?cmd=changeset&node=53918955ac8b
description:
Manage price correction from supplier invoice
issue10191
review332231002
diffstat:
CHANGELOG | 1 +
account.py | 13 +
stock.py | 5 +-
tests/scenario_account_invoice_stock_correction.rst | 133 ++++++++++++++++++++
tests/test_account_invoice_stock.py | 5 +
view/invoice_line_form.xml | 4 +
6 files changed, 159 insertions(+), 2 deletions(-)
diffs (223 lines):
diff -r af0e374fc258 -r 53918955ac8b CHANGELOG
--- a/CHANGELOG Sat Feb 27 15:23:46 2021 +0100
+++ b/CHANGELOG Sun Mar 21 16:07:45 2021 +0100
@@ -1,3 +1,4 @@
+* Manage price correction from supplier invoice
* Update unit price after invoice posted and move done
Version 5.8.0 - 2020-11-02
diff -r af0e374fc258 -r 53918955ac8b account.py
--- a/account.py Sat Feb 27 15:23:46 2021 +0100
+++ b/account.py Sun Mar 21 16:07:45 2021 +0100
@@ -54,12 +54,24 @@
| ~Eval('product')),
},
depends=['type', 'product_uom_category', 'invoice', 'invoice_type'])
+ correction = fields.Boolean(
+ "Correction",
+ states={
+ 'invisible': ((Eval('_parent_invoice', {}).get('type') == 'out')
+ | (Eval('invoice_type') == 'out')),
+ },
+ depends=['invoice_type'],
+ help="Check to correct price of already posted invoice.")
@classmethod
def __setup__(cls):
super().__setup__()
cls._check_modify_exclude.add('stock_moves')
+ @classmethod
+ def default_correction(cls):
+ return False
+
@property
def moved_quantity(self):
'The quantity from linked stock moves in line unit'
@@ -88,6 +100,7 @@
default = {}
else:
default = default.copy()
+ default.setdefault('correction', False)
if not Transaction().context.get('_account_invoice_correction'):
default.setdefault('stock_moves', None)
return super(InvoiceLine, cls).copy(lines, default=default)
diff -r af0e374fc258 -r 53918955ac8b stock.py
--- a/stock.py Sat Feb 27 15:23:46 2021 +0100
+++ b/stock.py Sun Mar 21 16:07:45 2021 +0100
@@ -108,8 +108,9 @@
with Transaction().set_context(date=self.effective_date):
amount += Currency.compute(
line.invoice.currency, line.amount, self.currency)
- quantity += UoM.compute_qty(
- line.unit, line.quantity, self.uom)
+ if line.invoice.type == 'out' or not line.correction:
+ quantity += UoM.compute_qty(
+ line.unit, line.quantity, self.uom)
if not quantity:
unit_price = self.unit_price
else:
diff -r af0e374fc258 -r 53918955ac8b
tests/scenario_account_invoice_stock_correction.rst
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/scenario_account_invoice_stock_correction.rst Sun Mar 21
16:07:45 2021 +0100
@@ -0,0 +1,133 @@
+===================================
+Invoice - Stock Correction Scenario
+===================================
+
+Imports::
+
+ >>> import datetime as dt
+ >>> from decimal import Decimal
+ >>> from proteus import Model
+ >>> 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)
+
+ >>> today = dt.date.today()
+
+Activate modules::
+
+ >>> config = activate_modules('account_invoice_stock')
+
+ >>> Invoice = Model.get('account.invoice')
+ >>> Location = Model.get('stock.location')
+ >>> Move = Model.get('stock.move')
+ >>> Party = Model.get('party.party')
+ >>> ProductCategory = Model.get('product.category')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> ProductUom = Model.get('product.uom')
+ >>> Shipment = Model.get('stock.shipment.in')
+
+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)
+
+Create a party::
+
+ >>> party = Party(name="Party")
+ >>> party.save()
+
+Create an account category::
+
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_expense = accounts['expense']
+ >>> account_category.account_revenue = accounts['revenue']
+ >>> account_category.save()
+
+Create a product::
+
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> template = ProductTemplate()
+ >>> template.name = 'product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.list_price = Decimal('40')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+Get stock locations::
+
+ >>> input_loc, = Location.find([('code', '=', 'IN')])
+ >>> supplier_loc, = Location.find([('code', '=', 'SUP')])
+
+Create a shipment::
+
+ >>> shipment = Shipment()
+ >>> shipment.supplier = party
+ >>> move = shipment.incoming_moves.new()
+ >>> move.product = product
+ >>> move.quantity = 10
+ >>> move.from_location = supplier_loc
+ >>> move.to_location = input_loc
+ >>> move.unit_price = Decimal('40.0000')
+ >>> shipment.click('receive')
+ >>> shipment.state
+ 'received'
+ >>> move, = shipment.incoming_moves
+
+Create an invoice::
+
+ >>> invoice = Invoice(type='in')
+ >>> invoice.party = party
+ >>> invoice.invoice_date = today
+ >>> line = invoice.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 10
+ >>> line.unit_price = Decimal('40.0000')
+ >>> line.stock_moves.append(Move(move.id))
+ >>> invoice.click('post')
+ >>> invoice.state
+ 'posted'
+
+Check move unit price::
+
+ >>> move.reload()
+ >>> move.unit_price
+ Decimal('40.0000')
+
+Post a price correction::
+
+ >>> invoice = Invoice(type='in')
+ >>> invoice.party = party
+ >>> invoice.invoice_date = today
+ >>> line = invoice.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 1
+ >>> line.unit_price = Decimal('-10.0000')
+ >>> line.correction = True
+ >>> line.stock_moves.append(Move(move.id))
+ >>> invoice.click('post')
+ >>> invoice.state
+ 'posted'
+
+Check move unit price::
+
+ >>> move.reload()
+ >>> move.unit_price
+ Decimal('39.0000')
diff -r af0e374fc258 -r 53918955ac8b tests/test_account_invoice_stock.py
--- a/tests/test_account_invoice_stock.py Sat Feb 27 15:23:46 2021 +0100
+++ b/tests/test_account_invoice_stock.py Sun Mar 21 16:07:45 2021 +0100
@@ -22,4 +22,9 @@
tearDown=doctest_teardown, encoding='utf-8',
checker=doctest_checker,
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_account_invoice_stock_correction.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
return suite
diff -r af0e374fc258 -r 53918955ac8b view/invoice_line_form.xml
--- a/view/invoice_line_form.xml Sat Feb 27 15:23:46 2021 +0100
+++ b/view/invoice_line_form.xml Sun Mar 21 16:07:45 2021 +0100
@@ -2,6 +2,10 @@
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<data>
+ <xpath expr="//field[@name='amount']" position="after">
+ <label name="correction"/>
+ <field name="correction"/>
+ </xpath>
<xpath expr="/form/notebook/page[@id='general']" position="after">
<page string="Stock" name="stock_moves">
<field name="stock_moves" colspan="4"/>