Manage move from supplier to customer
The stock move creates two invoices in this case. And it uses the origin of the invoice lines to manage them from the move workflow. issue7523 review70381002
This commit is contained in:
1 parent
6b3b308f21
commit
63419fc6eb
4 files changed
+205
-16
No files matched your search
@@ -1,3 +1,5 @@
|
||||
* Manage move from supplier to customer
|
||||
|
||||
Version 5.0.0 - 2018-10-01
|
||||
* Bug fixes (see mercurial logs for details)
|
||||
* Remove support for Python 2.7
|
||||
|
||||
@@ -48,17 +48,19 @@ def set_origin_consignment(func):
|
||||
def wrapper(cls, moves):
|
||||
pool = Pool()
|
||||
InvoiceLine = pool.get('account.invoice.line')
|
||||
lines = {}
|
||||
to_save = []
|
||||
move2line = {}
|
||||
for move in moves:
|
||||
if not move.origin:
|
||||
line = move.get_invoice_line_consignment()
|
||||
if line:
|
||||
lines[move] = line
|
||||
if lines:
|
||||
InvoiceLine.save(list(lines.values()))
|
||||
for move, line in lines.items():
|
||||
lines = move.get_invoice_lines_consignment()
|
||||
if lines:
|
||||
to_save.extend(lines)
|
||||
move2line[move] = lines[0]
|
||||
if to_save:
|
||||
InvoiceLine.save(to_save)
|
||||
for move, line in move2line.items():
|
||||
move.origin = line
|
||||
cls.save(list(lines.keys()))
|
||||
cls.save(list(move2line.keys()))
|
||||
return func(cls, moves)
|
||||
return wrapper
|
||||
|
||||
@@ -70,9 +72,8 @@ def unset_origin_consignment(func):
|
||||
InvoiceLine = pool.get('account.invoice.line')
|
||||
lines, to_save = [], []
|
||||
for move in moves:
|
||||
if (isinstance(move.origin, InvoiceLine)
|
||||
and move.origin.origin == move):
|
||||
lines.append(move.origin)
|
||||
if isinstance(move.origin, InvoiceLine):
|
||||
lines.extend(move.invoice_lines)
|
||||
move.origin = None
|
||||
to_save.append(move)
|
||||
if lines:
|
||||
@@ -85,6 +86,9 @@ def unset_origin_consignment(func):
|
||||
class Move(metaclass=PoolMeta):
|
||||
__name__ = 'stock.move'
|
||||
|
||||
invoice_lines = fields.One2Many(
|
||||
'account.invoice.line', 'origin', "Invoice Lines", readonly=True)
|
||||
|
||||
@classmethod
|
||||
def _get_origin(cls):
|
||||
return super(Move, cls)._get_origin() + ['account.invoice.line']
|
||||
@@ -102,15 +106,18 @@ class Move(metaclass=PoolMeta):
|
||||
def _get_tax_rule_pattern(self):
|
||||
return {}
|
||||
|
||||
def get_invoice_line_consignment(self):
|
||||
def get_invoice_lines_consignment(self):
|
||||
lines = []
|
||||
if (self.from_location.type == 'supplier'
|
||||
and self.to_location.type in {'storage', 'production'}
|
||||
and self.to_location.type in {
|
||||
'storage', 'production', 'customer'}
|
||||
and self.from_location.consignment_party):
|
||||
return self._get_supplier_invoice_line_consignment()
|
||||
elif (self.from_location.type in {'storage', 'production'}
|
||||
lines.append(self._get_supplier_invoice_line_consignment())
|
||||
if (self.from_location.type in {'storage', 'production', 'supplier'}
|
||||
and self.to_location.type == 'customer'
|
||||
and self.from_location.consignment_party):
|
||||
return self._get_customer_invoice_line_consignment()
|
||||
lines.append(self._get_customer_invoice_line_consignment())
|
||||
return lines
|
||||
|
||||
def _get_supplier_invoice_line_consignment(self):
|
||||
pool = Pool()
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
===============================================
|
||||
Stock Consignment Supplier to Customer 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_chart, \
|
||||
... get_accounts, create_tax
|
||||
|
||||
Install stock_consignment::
|
||||
|
||||
>>> config = activate_modules('stock_consignment')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Create chart of accounts::
|
||||
|
||||
>>> _ = create_chart(company)
|
||||
>>> accounts = get_accounts(company)
|
||||
>>> revenue = accounts['revenue']
|
||||
>>> expense = accounts['expense']
|
||||
|
||||
Create parties::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> supplier = Party(name='Supplier')
|
||||
>>> supplier.save()
|
||||
>>> customer = Party(name='Customer')
|
||||
>>> customer.save()
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> output_loc, = Location.find([('code', '=', 'OUT')])
|
||||
|
||||
Create customer consignment location::
|
||||
|
||||
>>> customer_consignment_loc = Location()
|
||||
>>> customer_consignment_loc.name = "Customer Consignment"
|
||||
>>> customer_consignment_loc.type = 'storage'
|
||||
>>> customer_consignment_loc.parent = customer_loc
|
||||
>>> customer_consignment_loc.consignment_party = customer
|
||||
>>> customer_consignment_loc.save()
|
||||
|
||||
Create supplier consignment location under customer consignment location::
|
||||
|
||||
>>> supplier_consignment_loc = Location()
|
||||
>>> supplier_consignment_loc.name = "Supplier Consignment"
|
||||
>>> supplier_consignment_loc.type = 'supplier'
|
||||
>>> supplier_consignment_loc.parent = customer_consignment_loc
|
||||
>>> supplier_consignment_loc.consignment_party = supplier
|
||||
>>> supplier_consignment_loc.save()
|
||||
|
||||
Create account category::
|
||||
|
||||
>>> ProductCategory = Model.get('product.category')
|
||||
>>> account_category = ProductCategory(name="Account Category")
|
||||
>>> account_category.accounting = True
|
||||
>>> account_category.account_expense = expense
|
||||
>>> account_category.account_revenue = revenue
|
||||
>>> account_category.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> Product = Model.get('product.product')
|
||||
>>> product = Product()
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.purchasable = True
|
||||
>>> template.salable = True
|
||||
>>> template.list_price = Decimal('10')
|
||||
>>> template.account_category = account_category
|
||||
>>> product_supplier = template.product_suppliers.new()
|
||||
>>> product_supplier.party = supplier
|
||||
>>> price = product_supplier.prices.new()
|
||||
>>> price.quantity = 1
|
||||
>>> price.unit_price = Decimal('4')
|
||||
>>> template.save()
|
||||
>>> product.template = template
|
||||
>>> product.save()
|
||||
|
||||
Fill supplier consignment location::
|
||||
|
||||
>>> Shipment = Model.get('stock.shipment.internal')
|
||||
>>> shipment = Shipment()
|
||||
>>> shipment.from_location = supplier_loc
|
||||
>>> shipment.to_location = supplier_consignment_loc
|
||||
>>> move = shipment.moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 10
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = supplier_consignment_loc
|
||||
>>> shipment.click('wait')
|
||||
>>> shipment.state
|
||||
'waiting'
|
||||
>>> shipment.click('assign_try')
|
||||
True
|
||||
>>> shipment.state
|
||||
'assigned'
|
||||
>>> shipment.click('done')
|
||||
>>> shipment.state
|
||||
'done'
|
||||
|
||||
Use supplier consignment stock by customer::
|
||||
|
||||
>>> shipment = Shipment()
|
||||
>>> shipment.from_location = supplier_consignment_loc
|
||||
>>> shipment.to_location = customer_loc
|
||||
>>> move = shipment.moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 4
|
||||
>>> move.from_location = supplier_consignment_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> shipment.click('wait')
|
||||
>>> shipment.state
|
||||
'waiting'
|
||||
>>> shipment.click('assign_try')
|
||||
True
|
||||
>>> shipment.state
|
||||
'assigned'
|
||||
>>> shipment.click('done')
|
||||
>>> shipment.state
|
||||
'done'
|
||||
>>> move, = shipment.moves
|
||||
>>> len(move.invoice_lines)
|
||||
2
|
||||
>>> move.origin in move.invoice_lines
|
||||
True
|
||||
|
||||
Check supplier invoice line::
|
||||
|
||||
>>> InvoiceLine = Model.get('account.invoice.line')
|
||||
>>> invoice_line, = InvoiceLine.find([('invoice_type', '=', 'in')])
|
||||
>>> invoice_line.product == product
|
||||
True
|
||||
>>> invoice_line.quantity
|
||||
4.0
|
||||
>>> invoice_line.unit == unit
|
||||
True
|
||||
>>> invoice_line.unit_price
|
||||
Decimal('4.0000')
|
||||
>>> invoice_line.origin == move
|
||||
True
|
||||
|
||||
Check customer invoice line::
|
||||
|
||||
>>> invoice_line, = InvoiceLine.find([('invoice_type', '=', 'out')])
|
||||
>>> invoice_line.product == product
|
||||
True
|
||||
>>> invoice_line.quantity
|
||||
4.0
|
||||
>>> invoice_line.unit == unit
|
||||
True
|
||||
>>> invoice_line.unit_price
|
||||
Decimal('10.0000')
|
||||
>>> invoice_line.origin == move
|
||||
True
|
||||
@@ -25,4 +25,9 @@ def suite():
|
||||
tearDown=doctest_teardown, encoding='utf-8',
|
||||
checker=doctest_checker,
|
||||
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
|
||||
suite.addTests(doctest.DocFileSuite(
|
||||
'scenario_stock_consignment_supplier_customer.rst',
|
||||
tearDown=doctest_teardown, encoding='utf-8',
|
||||
checker=doctest_checker,
|
||||
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
|
||||
return suite
|
||||
Reference in new issue
Block a user