Initial import from Docker volume
This commit is contained in:
2
modules/stock/tests/__init__.py
Executable file
2
modules/stock/tests/__init__.py
Executable file
@@ -0,0 +1,2 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
BIN
modules/stock/tests/__pycache__/__init__.cpython-311.opt-1.pyc
Executable file
BIN
modules/stock/tests/__pycache__/__init__.cpython-311.opt-1.pyc
Executable file
Binary file not shown.
BIN
modules/stock/tests/__pycache__/__init__.cpython-311.pyc
Executable file
BIN
modules/stock/tests/__pycache__/__init__.cpython-311.pyc
Executable file
Binary file not shown.
BIN
modules/stock/tests/__pycache__/test_module.cpython-311.opt-1.pyc
Executable file
BIN
modules/stock/tests/__pycache__/test_module.cpython-311.opt-1.pyc
Executable file
Binary file not shown.
BIN
modules/stock/tests/__pycache__/test_module.cpython-311.pyc
Executable file
BIN
modules/stock/tests/__pycache__/test_module.cpython-311.pyc
Executable file
Binary file not shown.
BIN
modules/stock/tests/__pycache__/test_scenario.cpython-311.opt-1.pyc
Executable file
BIN
modules/stock/tests/__pycache__/test_scenario.cpython-311.opt-1.pyc
Executable file
Binary file not shown.
BIN
modules/stock/tests/__pycache__/test_scenario.cpython-311.pyc
Executable file
BIN
modules/stock/tests/__pycache__/test_scenario.cpython-311.pyc
Executable file
Binary file not shown.
254
modules/stock/tests/scenario_stock_average_cost_price.rst
Executable file
254
modules/stock/tests/scenario_stock_average_cost_price.rst
Executable file
@@ -0,0 +1,254 @@
|
||||
========================
|
||||
Stock Average Cost Price
|
||||
========================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Wizard
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> next_day = today + dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
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.list_price = Decimal('300')
|
||||
>>> template.cost_price_method = 'average'
|
||||
>>> product, = template.products
|
||||
>>> product.cost_price = Decimal('80')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Negative Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('28')
|
||||
>>> template.cost_price_method = 'average'
|
||||
>>> negative_product, = template.products
|
||||
>>> negative_product.cost_price = Decimal('5.0000')
|
||||
>>> template.save()
|
||||
>>> negative_product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> storage_sub_loc = Location(
|
||||
... name="Storage Sub", type='storage', parent=storage_loc)
|
||||
>>> storage_sub_loc.save()
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
|
||||
Make 1 unit of the product available @ 100 ::
|
||||
|
||||
>>> StockMove = Model.get('stock.move')
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_sub_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.company = company
|
||||
>>> incoming_move.unit_price = Decimal('100')
|
||||
>>> incoming_move.currency = company.currency
|
||||
>>> incoming_move.click('do')
|
||||
|
||||
Check Cost Price is 100::
|
||||
|
||||
>>> product.reload()
|
||||
>>> product.cost_price
|
||||
Decimal('100.0000')
|
||||
|
||||
Add 1 more unit @ 200::
|
||||
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.company = company
|
||||
>>> incoming_move.unit_price = Decimal('200')
|
||||
>>> incoming_move.currency = company.currency
|
||||
>>> incoming_move.click('do')
|
||||
|
||||
Check Cost Price Average is 150::
|
||||
|
||||
>>> product.reload()
|
||||
>>> product.cost_price
|
||||
Decimal('150.0000')
|
||||
|
||||
Add twice 1 more unit @ 200::
|
||||
|
||||
>>> incoming_moves = []
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.company = company
|
||||
>>> incoming_move.unit_price = Decimal('200')
|
||||
>>> incoming_move.currency = company.currency
|
||||
>>> incoming_move.save()
|
||||
>>> incoming_moves.append(incoming_move)
|
||||
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.company = company
|
||||
>>> incoming_move.unit_price = Decimal('200')
|
||||
>>> incoming_move.currency = company.currency
|
||||
>>> incoming_move.save()
|
||||
>>> incoming_moves.append(incoming_move)
|
||||
|
||||
>>> StockMove.click(incoming_moves, 'do')
|
||||
|
||||
Check Cost Price Average is 175::
|
||||
|
||||
>>> product.reload()
|
||||
>>> product.cost_price
|
||||
Decimal('175.0000')
|
||||
|
||||
Reduce Cost Price by 80%, to force to write recomputed price later::
|
||||
|
||||
>>> modify_cost_price = Wizard('product.modify_cost_price', [product])
|
||||
>>> modify_cost_price.form.cost_price = 'cost_price * 0.8'
|
||||
>>> modify_cost_price.form.date = next_day
|
||||
>>> modify_cost_price.execute('modify')
|
||||
>>> product.cost_price
|
||||
Decimal('140.0000')
|
||||
|
||||
Increase Cost Price by 10% using Template wizard::
|
||||
|
||||
>>> modify_cost_price = Wizard(
|
||||
... 'product.modify_cost_price', [product.template])
|
||||
>>> modify_cost_price.form.cost_price = 'cost_price * 1.1'
|
||||
>>> modify_cost_price.form.date = next_day
|
||||
>>> modify_cost_price.execute('modify')
|
||||
>>> product.reload()
|
||||
>>> product.cost_price
|
||||
Decimal('154.0000')
|
||||
|
||||
Send one product we don't have in stock::
|
||||
|
||||
>>> outgoing_move = StockMove()
|
||||
>>> outgoing_move.product = negative_product
|
||||
>>> outgoing_move.unit = unit
|
||||
>>> outgoing_move.quantity = 1
|
||||
>>> outgoing_move.unit_price = Decimal('28')
|
||||
>>> outgoing_move.from_location = storage_loc
|
||||
>>> outgoing_move.to_location = customer_loc
|
||||
>>> outgoing_move.planned_date = today
|
||||
>>> outgoing_move.effective_date = today
|
||||
>>> outgoing_move.company = company
|
||||
>>> outgoing_move.currency = company.currency
|
||||
>>> outgoing_move.click('do')
|
||||
|
||||
Cost price should stay 5::
|
||||
|
||||
>>> negative_product.cost_price
|
||||
Decimal('5.0000')
|
||||
|
||||
Return one product to the supplier::
|
||||
|
||||
>>> outgoing_move = StockMove()
|
||||
>>> outgoing_move.product = negative_product
|
||||
>>> outgoing_move.unit = unit
|
||||
>>> outgoing_move.quantity = 1
|
||||
>>> outgoing_move.unit_price = Decimal('28')
|
||||
>>> outgoing_move.currency = company.currency
|
||||
>>> outgoing_move.from_location = storage_loc
|
||||
>>> outgoing_move.to_location = supplier_loc
|
||||
>>> outgoing_move.planned_date = today
|
||||
>>> outgoing_move.effective_date = today
|
||||
>>> outgoing_move.company = company
|
||||
>>> outgoing_move.click('do')
|
||||
|
||||
Cost price should stay 5::
|
||||
|
||||
>>> negative_product.cost_price
|
||||
Decimal('5.0000')
|
||||
|
||||
Receive one unit of the product with negative stock so the stock stays negative::
|
||||
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = negative_product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.company = company
|
||||
>>> incoming_move.unit_price = Decimal('3')
|
||||
>>> incoming_move.currency = company.currency
|
||||
>>> incoming_move.click('do')
|
||||
|
||||
Cost price should be set to last unit price::
|
||||
|
||||
>>> negative_product.reload()
|
||||
>>> negative_product.cost_price
|
||||
Decimal('3.0000')
|
||||
|
||||
Receive two units of the product so the stock becomes positive::
|
||||
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = negative_product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 2
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.company = company
|
||||
>>> incoming_move.unit_price = Decimal('2')
|
||||
>>> incoming_move.currency = company.currency
|
||||
>>> incoming_move.click('do')
|
||||
|
||||
Cost price should be set to last unit price::
|
||||
|
||||
>>> negative_product.reload()
|
||||
>>> negative_product.cost_price
|
||||
Decimal('2.0000')
|
||||
|
||||
Recompute Cost Price::
|
||||
|
||||
>>> recompute = Wizard('product.recompute_cost_price', [negative_product])
|
||||
>>> recompute.execute('recompute')
|
||||
>>> negative_product.cost_price
|
||||
Decimal('2.0000')
|
||||
254
modules/stock/tests/scenario_stock_inventory.rst
Executable file
254
modules/stock/tests/scenario_stock_inventory.rst
Executable file
@@ -0,0 +1,254 @@
|
||||
========================
|
||||
Stock Inventory Scenario
|
||||
========================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
>>> today = dt.date.today()
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> lost_found_loc, = Location.find([('type', '=', 'lost_found')])
|
||||
|
||||
Create products::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('300')
|
||||
>>> template.cost_price_method = 'average'
|
||||
>>> product, = template.products
|
||||
>>> product.cost_price = Decimal('80')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
>>> kg, = ProductUom.find([('name', '=', 'Kilogram')])
|
||||
>>> template2 = ProductTemplate()
|
||||
>>> template2.name = 'Product'
|
||||
>>> template2.default_uom = kg
|
||||
>>> template2.type = 'goods'
|
||||
>>> template2.list_price = Decimal('140')
|
||||
>>> template2.cost_price_method = 'average'
|
||||
>>> product2, = template2.products
|
||||
>>> product2.cost_price = Decimal('60')
|
||||
>>> template2.save()
|
||||
>>> product2, = template2.products
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.consumable = True
|
||||
>>> template.list_price = Decimal('300')
|
||||
>>> template.cost_price_method = 'average'
|
||||
>>> consumable, = template.products
|
||||
>>> consumable.cost_price = Decimal('80')
|
||||
>>> template.save()
|
||||
>>> consumable, = template.products
|
||||
|
||||
Fill storage::
|
||||
|
||||
>>> StockMove = Model.get('stock.move')
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.company = company
|
||||
>>> incoming_move.unit_price = Decimal('100')
|
||||
>>> incoming_move.currency = company.currency
|
||||
>>> incoming_moves = [incoming_move]
|
||||
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product2
|
||||
>>> incoming_move.unit = kg
|
||||
>>> incoming_move.quantity = 2.5
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.company = company
|
||||
>>> incoming_move.unit_price = Decimal('70')
|
||||
>>> incoming_move.currency = company.currency
|
||||
>>> incoming_moves.append(incoming_move)
|
||||
>>> StockMove.click(incoming_moves, 'do')
|
||||
|
||||
Create an inventory::
|
||||
|
||||
>>> Inventory = Model.get('stock.inventory')
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = storage_loc
|
||||
>>> inventory.empty_quantity = 'keep'
|
||||
>>> inventory.save()
|
||||
>>> inventory.click('complete_lines')
|
||||
>>> line_by_product = {l.product.id: l for l in inventory.lines}
|
||||
>>> line_p1 = line_by_product[product.id]
|
||||
>>> line_p1.expected_quantity
|
||||
1.0
|
||||
>>> line_p1.quantity = 3
|
||||
>>> line_p2 = line_by_product[product2.id]
|
||||
>>> line_p2.expected_quantity
|
||||
2.5
|
||||
>>> inventory.save()
|
||||
|
||||
Fill storage with more quantities::
|
||||
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.company = company
|
||||
>>> incoming_move.unit_price = Decimal('100')
|
||||
>>> incoming_move.currency = company.currency
|
||||
>>> incoming_moves = [incoming_move]
|
||||
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product2
|
||||
>>> incoming_move.unit = kg
|
||||
>>> incoming_move.quantity = 1.3
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.company = company
|
||||
>>> incoming_move.unit_price = Decimal('70')
|
||||
>>> incoming_move.currency = company.currency
|
||||
>>> incoming_moves.append(incoming_move)
|
||||
>>> StockMove.click(incoming_moves, 'do')
|
||||
|
||||
Update the inventory::
|
||||
|
||||
>>> inventory.click('complete_lines')
|
||||
>>> line_p1.reload()
|
||||
>>> line_p1.expected_quantity
|
||||
2.0
|
||||
>>> line_p1.quantity
|
||||
3.0
|
||||
>>> line_p2.reload()
|
||||
>>> line_p2.expected_quantity
|
||||
3.8
|
||||
>>> line_p2.quantity = 3.8
|
||||
>>> line_p2.save()
|
||||
|
||||
Confirm the inventory::
|
||||
|
||||
>>> inventory.click('confirm')
|
||||
>>> line_p1.reload()
|
||||
>>> line_p1.expected_quantity
|
||||
2.0
|
||||
>>> move, = line_p1.moves
|
||||
>>> move.quantity
|
||||
1.0
|
||||
>>> assertEqual(move.from_location, lost_found_loc)
|
||||
>>> assertEqual(move.to_location, inventory.location)
|
||||
>>> line_p2.reload()
|
||||
>>> len(line_p2.moves)
|
||||
0
|
||||
|
||||
Creating an inventory with empty quantities::
|
||||
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = storage_loc
|
||||
>>> inventory.empty_quantity = 'keep'
|
||||
>>> line = inventory.lines.new()
|
||||
>>> line.product = product
|
||||
>>> inventory.click('confirm')
|
||||
>>> line, = inventory.lines
|
||||
>>> len(line.moves)
|
||||
0
|
||||
|
||||
Empty storage::
|
||||
|
||||
>>> Inventory = Model.get('stock.inventory')
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = storage_loc
|
||||
>>> inventory.empty_quantity = 'keep'
|
||||
>>> line = inventory.lines.new()
|
||||
>>> line.product = product
|
||||
>>> line.quantity = 0
|
||||
>>> line = inventory.lines.new()
|
||||
>>> line.product = product2
|
||||
>>> line.quantity = 0
|
||||
>>> inventory.save()
|
||||
>>> line_p1, line_p2 = inventory.lines
|
||||
>>> line_p1.quantity
|
||||
0.0
|
||||
>>> line_p1.expected_quantity
|
||||
3.0
|
||||
>>> line_p2.quantity
|
||||
0.0
|
||||
>>> line_p2.expected_quantity
|
||||
3.8
|
||||
>>> inventory.click('confirm')
|
||||
|
||||
Add quantity of consumable product::
|
||||
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = storage_loc
|
||||
>>> inventory.empty_quantity = 'keep'
|
||||
>>> line = inventory.lines.new()
|
||||
>>> line.product = consumable
|
||||
>>> line.quantity = 5.0
|
||||
>>> inventory.click('complete_lines')
|
||||
>>> len(inventory.lines)
|
||||
1
|
||||
>>> inventory.click('confirm')
|
||||
>>> line, = inventory.lines
|
||||
>>> move, = line.moves
|
||||
>>> move.quantity
|
||||
5.0
|
||||
>>> assertEqual(move.from_location, lost_found_loc)
|
||||
>>> assertEqual(move.to_location, inventory.location)
|
||||
|
||||
Create an inventory that should be empty after completion::
|
||||
|
||||
>>> Inventory = Model.get('stock.inventory')
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = storage_loc
|
||||
>>> inventory.empty_quantity = 'keep'
|
||||
>>> inventory.click('complete_lines')
|
||||
>>> len(inventory.lines)
|
||||
0
|
||||
|
||||
Create an inventory and check rec_name::
|
||||
|
||||
>>> Inventory = Model.get('stock.inventory')
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.date = dt.date(2023, 1, 31)
|
||||
>>> inventory.location = storage_loc
|
||||
>>> inventory.empty_quantity = 'keep'
|
||||
>>> inventory.save()
|
||||
>>> inventory.rec_name
|
||||
'[6] [STO] Storage Zone @ 01/31/2023'
|
||||
116
modules/stock/tests/scenario_stock_inventory_count.rst
Executable file
116
modules/stock/tests/scenario_stock_inventory_count.rst
Executable file
@@ -0,0 +1,116 @@
|
||||
==============================
|
||||
Stock Inventory Count Scenario
|
||||
==============================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
|
||||
Create products::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('300')
|
||||
>>> template.cost_price_method = 'average'
|
||||
>>> product, = template.products
|
||||
>>> product.cost_price = Decimal('80')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
>>> kg, = ProductUom.find([('name', '=', 'Kilogram')])
|
||||
>>> template2 = ProductTemplate()
|
||||
>>> template2.name = 'Product'
|
||||
>>> template2.default_uom = kg
|
||||
>>> template2.type = 'goods'
|
||||
>>> template2.list_price = Decimal('140')
|
||||
>>> template2.cost_price_method = 'average'
|
||||
>>> product2, = template2.products
|
||||
>>> product2.cost_price = Decimal('60')
|
||||
>>> template2.save()
|
||||
>>> product2, = template2.products
|
||||
|
||||
Create an inventory::
|
||||
|
||||
>>> Inventory = Model.get('stock.inventory')
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = storage_loc
|
||||
>>> inventory.empty_quantity = 'keep'
|
||||
>>> inventory.save()
|
||||
|
||||
Count inventory::
|
||||
|
||||
>>> count = inventory.click('do_count')
|
||||
|
||||
>>> count.form.search = product
|
||||
|
||||
>>> count.execute('quantity')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
InventoryCountWarning: ...
|
||||
|
||||
>>> Model.get('res.user.warning')(user=config.user,
|
||||
... name='stock.inventory,%s.product.product,%s.count_create' % (
|
||||
... inventory.id, product.id)).save()
|
||||
>>> count.execute('quantity')
|
||||
>>> count.form.quantity
|
||||
1.0
|
||||
>>> count.form.total_quantity
|
||||
1.0
|
||||
>>> count.execute('add')
|
||||
|
||||
>>> count.form.search = product
|
||||
>>> count.execute('quantity')
|
||||
>>> count.form.total_quantity
|
||||
2.0
|
||||
>>> count.execute('add')
|
||||
|
||||
>>> count.form.search = product2
|
||||
>>> Model.get('res.user.warning')(user=config.user,
|
||||
... name='stock.inventory,%s.product.product,%s.count_create' % (
|
||||
... inventory.id, product2.id)).save()
|
||||
>>> count.execute('quantity')
|
||||
>>> count.form.quantity
|
||||
>>> count.form.total_quantity
|
||||
>>> count.form.quantity = 10
|
||||
>>> count.form.total_quantity
|
||||
10.0
|
||||
>>> count.execute('add')
|
||||
|
||||
>>> count.execute('end')
|
||||
|
||||
Check inventory::
|
||||
|
||||
>>> len(inventory.lines)
|
||||
2
|
||||
>>> line1, = [l for l in inventory.lines if l.product == product]
|
||||
>>> line1.quantity
|
||||
2.0
|
||||
>>> line2, = [l for l in inventory.lines if l.product == product2]
|
||||
>>> line2.quantity
|
||||
10.0
|
||||
86
modules/stock/tests/scenario_stock_inventory_empty_quantity.rst
Executable file
86
modules/stock/tests/scenario_stock_inventory_empty_quantity.rst
Executable file
@@ -0,0 +1,86 @@
|
||||
=======================================
|
||||
Stock Inventory Scenario Empty Quantity
|
||||
=======================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
>>> today = dt.date.today()
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> lost_found_loc, = Location.find([('type', '=', 'lost_found')])
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('300')
|
||||
>>> template.cost_price_method = 'average'
|
||||
>>> product, = template.products
|
||||
>>> product.cost_price = Decimal('80')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Fill storage::
|
||||
|
||||
>>> StockMove = Model.get('stock.move')
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.company = company
|
||||
>>> incoming_move.unit_price = Decimal('100')
|
||||
>>> incoming_move.currency = company.currency
|
||||
>>> incoming_move.click('do')
|
||||
|
||||
Creating an inventory with empty quantities creates and empty move::
|
||||
|
||||
>>> Inventory = Model.get('stock.inventory')
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = storage_loc
|
||||
>>> inventory.empty_quantity = 'empty'
|
||||
>>> inventory.save()
|
||||
>>> inventory.click('complete_lines')
|
||||
>>> line, = inventory.lines
|
||||
>>> line.expected_quantity
|
||||
1.0
|
||||
>>> line.quantity
|
||||
>>> inventory.click('confirm')
|
||||
>>> line.reload()
|
||||
>>> line.expected_quantity
|
||||
1.0
|
||||
>>> move, = line.moves
|
||||
>>> move.quantity
|
||||
1.0
|
||||
>>> assertEqual(move.from_location, inventory.location)
|
||||
>>> assertEqual(move.to_location, lost_found_loc)
|
||||
71
modules/stock/tests/scenario_stock_move_in_future.rst
Executable file
71
modules/stock/tests/scenario_stock_move_in_future.rst
Executable file
@@ -0,0 +1,71 @@
|
||||
=============================
|
||||
Stock Move In Future Scenario
|
||||
=============================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> tomorrow = today + dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
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.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
>>> product.cost_price = Decimal('1')
|
||||
>>> product.save()
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
|
||||
A warning is raised when doing a move in the future::
|
||||
|
||||
>>> Move = Model.get('stock.move')
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.currency = company.currency
|
||||
>>> move.effective_date = tomorrow
|
||||
>>> move.quantity = 2
|
||||
>>> move.unit_price = Decimal('1')
|
||||
>>> move.save()
|
||||
>>> move.click('do')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
MoveFutureWarning: ...
|
||||
|
||||
But it can be done for today::
|
||||
|
||||
>>> move.effective_date = today
|
||||
>>> move.click('do')
|
||||
>>> move.state
|
||||
'done'
|
||||
126
modules/stock/tests/scenario_stock_product_quantities_by_warehouse.rst
Executable file
126
modules/stock/tests/scenario_stock_product_quantities_by_warehouse.rst
Executable file
@@ -0,0 +1,126 @@
|
||||
=====================================
|
||||
Stock Product Quantities by Warehouse
|
||||
=====================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
>>> tomorrow = today + dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
|
||||
Fill warehouse::
|
||||
|
||||
>>> Move = Model.get('stock.move')
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 10
|
||||
>>> move.effective_date = yesterday
|
||||
>>> move.unit_price = Decimal('10')
|
||||
>>> move.currency = company.currency
|
||||
>>> move.click('do')
|
||||
|
||||
Forecast some moves::
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 6
|
||||
>>> move.planned_date = tomorrow
|
||||
>>> move.unit_price = Decimal('20')
|
||||
>>> move.currency = company.currency
|
||||
>>> move.save()
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 5
|
||||
>>> move.planned_date = tomorrow
|
||||
>>> move.unit_price = Decimal('10')
|
||||
>>> move.currency = company.currency
|
||||
>>> move.save()
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 3
|
||||
>>> move.planned_date = tomorrow
|
||||
>>> move.unit_price = Decimal('20')
|
||||
>>> move.currency = company.currency
|
||||
>>> move.save()
|
||||
|
||||
|
||||
Check Product Quantities by Warehouse::
|
||||
|
||||
>>> ProductQuantitiesByWarehouse = Model.get('stock.product_quantities_warehouse')
|
||||
>>> with config.set_context(
|
||||
... product_template=template.id, warehouse=warehouse_loc.id):
|
||||
... records = ProductQuantitiesByWarehouse.find([])
|
||||
>>> len(records)
|
||||
3
|
||||
>>> assertEqual([(r.date, r.quantity) for r in records],
|
||||
... [(yesterday, 10), (today, 10), (tomorrow, 6)])
|
||||
|
||||
Check Product Quantities by Warehouse Moves::
|
||||
|
||||
>>> ProductQuantitiesByWarehouseMove = Model.get(
|
||||
... 'stock.product_quantities_warehouse.move')
|
||||
>>> with config.set_context(
|
||||
... product_template=template.id, warehouse=warehouse_loc.id):
|
||||
... records = ProductQuantitiesByWarehouseMove.find([])
|
||||
>>> len(records)
|
||||
4
|
||||
>>> assertEqual([
|
||||
... (r.date, r.cumulative_quantity_start, r.quantity,
|
||||
... r.cumulative_quantity_end)
|
||||
... for r in records],
|
||||
... [
|
||||
... (yesterday, 0, 10, 10),
|
||||
... (tomorrow, 10, -6, 4),
|
||||
... (tomorrow, 4, 5, 9),
|
||||
... (tomorrow, 9, -3, 6)])
|
||||
162
modules/stock/tests/scenario_stock_recompute_average_cost_price.rst
Executable file
162
modules/stock/tests/scenario_stock_recompute_average_cost_price.rst
Executable file
@@ -0,0 +1,162 @@
|
||||
==================================
|
||||
Stock Recompute Average Cost Price
|
||||
==================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Wizard
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual, assertFalse
|
||||
|
||||
>>> today = dt.date.today()
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('300')
|
||||
>>> template.cost_price_method = 'average'
|
||||
>>> product, = template.products
|
||||
>>> product.cost_price = Decimal('80')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
|
||||
Create some moves::
|
||||
|
||||
>>> StockMove = Model.get('stock.move')
|
||||
>>> StockMove(
|
||||
... product=product,
|
||||
... quantity=1,
|
||||
... from_location=supplier_loc,
|
||||
... to_location=storage_loc,
|
||||
... unit_price=Decimal('100'),
|
||||
... currency=company.currency,
|
||||
... effective_date=today - dt.timedelta(days=2)).click('do')
|
||||
>>> StockMove(
|
||||
... product=product,
|
||||
... quantity=2,
|
||||
... from_location=storage_loc,
|
||||
... to_location=customer_loc,
|
||||
... unit_price=Decimal('300'),
|
||||
... currency=company.currency,
|
||||
... effective_date=today - dt.timedelta(days=1)).click('do')
|
||||
>>> StockMove(
|
||||
... product=product,
|
||||
... quantity=2,
|
||||
... from_location=supplier_loc,
|
||||
... to_location=storage_loc,
|
||||
... unit_price=Decimal('120'),
|
||||
... currency=company.currency,
|
||||
... effective_date=today - dt.timedelta(days=1)).click('do')
|
||||
>>> StockMove(
|
||||
... product=product,
|
||||
... quantity=3,
|
||||
... from_location=supplier_loc,
|
||||
... to_location=storage_loc,
|
||||
... unit_price=Decimal('100'),
|
||||
... currency=company.currency,
|
||||
... effective_date=today).click('do')
|
||||
|
||||
>>> [m.cost_price for m in StockMove.find([])]
|
||||
[Decimal('105.0000'), Decimal('120.0000'), Decimal('100.0000'), Decimal('100.0000')]
|
||||
|
||||
>>> product.reload()
|
||||
>>> product.cost_price
|
||||
Decimal('105.0000')
|
||||
|
||||
Recompute cost price::
|
||||
|
||||
>>> recompute = Wizard('product.recompute_cost_price', [product])
|
||||
>>> recompute.execute('recompute')
|
||||
|
||||
>>> [m.cost_price for m in StockMove.find([])]
|
||||
[Decimal('105.0000'), Decimal('120.0000'), Decimal('120.0000'), Decimal('100.0000')]
|
||||
|
||||
>>> product.reload()
|
||||
>>> product.cost_price
|
||||
Decimal('105.0000')
|
||||
|
||||
Recompute cost price from a date::
|
||||
|
||||
>>> recompute = Wizard('product.recompute_cost_price', [product])
|
||||
>>> recompute.form.from_ = today - dt.timedelta(days=1)
|
||||
>>> recompute.execute('recompute')
|
||||
|
||||
>>> [m.cost_price for m in StockMove.find([])]
|
||||
[Decimal('105.0000'), Decimal('120.0000'), Decimal('120.0000'), Decimal('100.0000')]
|
||||
|
||||
>>> product.reload()
|
||||
>>> product.cost_price
|
||||
Decimal('105.0000')
|
||||
|
||||
Update unit price of a move::
|
||||
|
||||
>>> move, = StockMove.find([
|
||||
... ('from_location', '=', supplier_loc.id),
|
||||
... ('effective_date', '=', today - dt.timedelta(days=1)),
|
||||
... ])
|
||||
>>> bool(move.unit_price_updated)
|
||||
False
|
||||
>>> move.unit_price = Decimal('130')
|
||||
>>> move.save()
|
||||
>>> bool(move.unit_price_updated)
|
||||
True
|
||||
|
||||
>>> recompute = Wizard('product.recompute_cost_price', [product])
|
||||
>>> recompute.form.from_ = move.effective_date + dt.timedelta(days=1)
|
||||
>>> recompute.execute('recompute')
|
||||
>>> move.reload()
|
||||
>>> bool(move.unit_price_updated)
|
||||
True
|
||||
|
||||
>>> recompute = Wizard('product.recompute_cost_price', [product])
|
||||
>>> assertEqual(recompute.form.from_, move.effective_date)
|
||||
>>> recompute.execute('recompute')
|
||||
>>> move.reload()
|
||||
>>> assertFalse(move.unit_price_updated)
|
||||
>>> [m.cost_price for m in StockMove.find([])]
|
||||
[Decimal('107.5000'), Decimal('130.0000'), Decimal('130.0000'), Decimal('100.0000')]
|
||||
|
||||
Launch cron task::
|
||||
|
||||
>>> move.unit_price = Decimal('120')
|
||||
>>> move.save()
|
||||
|
||||
>>> Cron = Model.get('ir.cron')
|
||||
>>> Company = Model.get('company.company')
|
||||
>>> cron_recompute, = Cron.find([
|
||||
... ('method', '=', 'product.product|recompute_cost_price_from_moves'),
|
||||
... ])
|
||||
>>> cron_recompute.companies.append(Company(company.id))
|
||||
>>> cron_recompute.click('run_once')
|
||||
|
||||
>>> move.reload()
|
||||
>>> bool(move.unit_price_updated)
|
||||
False
|
||||
>>> [m.cost_price for m in StockMove.find([])]
|
||||
[Decimal('105.0000'), Decimal('120.0000'), Decimal('120.0000'), Decimal('100.0000')]
|
||||
106
modules/stock/tests/scenario_stock_recompute_average_cost_price_production.rst
Executable file
106
modules/stock/tests/scenario_stock_recompute_average_cost_price_production.rst
Executable file
@@ -0,0 +1,106 @@
|
||||
=============================================
|
||||
Stock Recompute Average Cost Price Production
|
||||
=============================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Wizard
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> StockMove = Model.get('stock.move')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('50.0000')
|
||||
>>> template.cost_price_method = 'average'
|
||||
>>> product, = template.products
|
||||
>>> product.cost_price = Decimal('40.0000')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> production_loc = Location(name="Production", type='production')
|
||||
>>> production_loc.save()
|
||||
|
||||
Consume product for production and reverse some::
|
||||
|
||||
>>> StockMove(
|
||||
... product=product,
|
||||
... quantity=10,
|
||||
... from_location=storage_loc,
|
||||
... to_location=production_loc,
|
||||
... effective_date=today).click('do')
|
||||
>>> StockMove(
|
||||
... product=product,
|
||||
... quantity=2,
|
||||
... from_location=production_loc,
|
||||
... to_location=storage_loc,
|
||||
... unit_price=Decimal('40.0000'),
|
||||
... currency=company.currency,
|
||||
... effective_date=today).click('do')
|
||||
|
||||
>>> [m.cost_price for m in StockMove.find([])]
|
||||
[Decimal('40.0000'), Decimal('40.0000')]
|
||||
|
||||
Recompute cost price::
|
||||
|
||||
>>> recompute = Wizard('product.recompute_cost_price', [product])
|
||||
>>> recompute.execute('recompute')
|
||||
|
||||
>>> [m.cost_price for m in StockMove.find([])]
|
||||
[Decimal('0.0000'), Decimal('0.0000')]
|
||||
|
||||
>>> product.reload()
|
||||
>>> product.cost_price
|
||||
Decimal('0.0000')
|
||||
|
||||
Receive product yesterday at new cost::
|
||||
|
||||
>>> StockMove(
|
||||
... product=product,
|
||||
... quantity=16,
|
||||
... from_location=supplier_loc,
|
||||
... to_location=storage_loc,
|
||||
... unit_price=Decimal('20.0000'),
|
||||
... currency=company.currency,
|
||||
... effective_date=yesterday).click('do')
|
||||
|
||||
Recompute cost price::
|
||||
|
||||
>>> recompute = Wizard('product.recompute_cost_price', [product])
|
||||
>>> recompute.execute('recompute')
|
||||
|
||||
>>> [m.cost_price for m in StockMove.find([])]
|
||||
[Decimal('20.0000'), Decimal('20.0000'), Decimal('20.0000')]
|
||||
|
||||
>>> product.reload()
|
||||
>>> product.cost_price
|
||||
Decimal('20.0000')
|
||||
165
modules/stock/tests/scenario_stock_reporting.rst
Executable file
165
modules/stock/tests/scenario_stock_reporting.rst
Executable file
@@ -0,0 +1,165 @@
|
||||
=================================
|
||||
Stock Shipment Reporting Scenario
|
||||
=================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Report
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Create customer & supplier::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> customer = Party(name='Customer')
|
||||
>>> customer.save()
|
||||
>>> supplier = Party(name='Supplier')
|
||||
>>> supplier.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.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> input_loc, = Location.find([('code', '=', 'IN')])
|
||||
>>> output_loc, = Location.find([('code', '=', 'OUT')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> lost_loc, = Location.find([('type', '=', 'lost_found')])
|
||||
|
||||
Create Shipment In::
|
||||
|
||||
>>> ShipmentIn = Model.get('stock.shipment.in')
|
||||
>>> shipment_in = ShipmentIn()
|
||||
>>> shipment_in.planned_date = today
|
||||
>>> shipment_in.supplier = supplier
|
||||
>>> shipment_in.warehouse = warehouse_loc
|
||||
>>> shipment_in.company = company
|
||||
|
||||
Receive a bunch of products::
|
||||
|
||||
>>> move = shipment_in.incoming_moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 100
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = input_loc
|
||||
>>> move.company = company
|
||||
>>> move.unit_price = Decimal('1')
|
||||
>>> move.currency = company.currency
|
||||
>>> shipment_in.save()
|
||||
>>> shipment_in.click('receive')
|
||||
>>> shipment_in.click('do')
|
||||
|
||||
Testing the report::
|
||||
|
||||
>>> supplier_restocking_list = Report('stock.shipment.in.restocking_list')
|
||||
>>> ext, _, _, name = supplier_restocking_list.execute([shipment_in], {})
|
||||
>>> ext
|
||||
'odt'
|
||||
>>> name
|
||||
'Restocking List-1'
|
||||
|
||||
Create Shipment Out::
|
||||
|
||||
>>> ShipmentOut = Model.get('stock.shipment.out')
|
||||
>>> shipment_out = ShipmentOut()
|
||||
>>> shipment_out.planned_date = today
|
||||
>>> shipment_out.customer = customer
|
||||
>>> shipment_out.warehouse = warehouse_loc
|
||||
>>> shipment_out.company = company
|
||||
|
||||
Add two shipment lines of same product and go through the workflow::
|
||||
|
||||
>>> move = shipment_out.outgoing_moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = output_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.company = company
|
||||
>>> move.unit_price = Decimal('1')
|
||||
>>> move.currency = company.currency
|
||||
>>> shipment_out.save()
|
||||
>>> shipment_out.click('wait')
|
||||
>>> shipment_out.click('assign_try')
|
||||
>>> shipment_out.click('pick')
|
||||
>>> shipment_out.click('pack')
|
||||
>>> shipment_out.click('do')
|
||||
|
||||
Testing the reports::
|
||||
|
||||
>>> delivery_note = Report('stock.shipment.out.delivery_note')
|
||||
>>> ext, _, _, name = delivery_note.execute([shipment_out], {})
|
||||
>>> ext
|
||||
'odt'
|
||||
>>> name
|
||||
'Delivery Note-1'
|
||||
|
||||
>>> picking_list = Report('stock.shipment.out.picking_list')
|
||||
>>> ext, _, _, name = picking_list.execute([shipment_out], {})
|
||||
>>> ext
|
||||
'odt'
|
||||
>>> name
|
||||
'Picking List-1'
|
||||
|
||||
Create an internal shipment::
|
||||
|
||||
>>> ShipmentInternal = Model.get('stock.shipment.internal')
|
||||
>>> shipment_internal = ShipmentInternal()
|
||||
>>> shipment_internal.planned_date = today
|
||||
>>> shipment_internal.company = company
|
||||
>>> shipment_internal.from_location = storage_loc
|
||||
>>> shipment_internal.to_location = lost_loc
|
||||
>>> move = shipment_internal.moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = lost_loc
|
||||
>>> move.company = company
|
||||
>>> move.unit_price = Decimal('1')
|
||||
>>> move.currency = company.currency
|
||||
>>> shipment_internal.save()
|
||||
>>> shipment_internal.click('wait')
|
||||
>>> shipment_internal.click('assign_try')
|
||||
>>> shipment_internal.click('do')
|
||||
|
||||
Testing the report::
|
||||
|
||||
>>> internal_report = Report('stock.shipment.internal.report')
|
||||
>>> ext, _, _, name = internal_report.execute([shipment_internal], {})
|
||||
>>> ext
|
||||
'odt'
|
||||
>>> name
|
||||
'Internal Shipment-1'
|
||||
|
||||
217
modules/stock/tests/scenario_stock_reporting_margin.rst
Executable file
217
modules/stock/tests/scenario_stock_reporting_margin.rst
Executable file
@@ -0,0 +1,217 @@
|
||||
===============================
|
||||
Stock Reporting Margin Scenario
|
||||
===============================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('40')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
>>> product.cost_price = Decimal('20')
|
||||
>>> product.save()
|
||||
>>> template2, = template.duplicate()
|
||||
>>> product2, = template2.products
|
||||
|
||||
>>> Category = Model.get('product.category')
|
||||
>>> category_root = Category(name="Root")
|
||||
>>> category_root.save()
|
||||
>>> category1 = Category(name="Child1", parent=category_root)
|
||||
>>> category1.save()
|
||||
>>> category2 = Category(name="Child2", parent=category_root)
|
||||
>>> category2.save()
|
||||
|
||||
>>> template.categories.append(Category(category1.id))
|
||||
>>> template.save()
|
||||
>>> template2.categories.append(Category(category2.id))
|
||||
>>> template2.save()
|
||||
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> lost_loc, = Location.find([('type', '=', 'lost_found')])
|
||||
|
||||
Create some moves::
|
||||
|
||||
>>> Move = Model.get('stock.move')
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.quantity = 8
|
||||
>>> move.unit_price = Decimal('20')
|
||||
>>> move.currency = company.currency
|
||||
>>> move.effective_date = yesterday
|
||||
>>> move.click('do')
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.quantity = 2
|
||||
>>> move.unit_price = Decimal('40')
|
||||
>>> move.currency = company.currency
|
||||
>>> move.effective_date = yesterday
|
||||
>>> move.click('do')
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.quantity = 4
|
||||
>>> move.unit_price = Decimal('30')
|
||||
>>> move.currency = company.currency
|
||||
>>> move.effective_date = today
|
||||
>>> move.click('do')
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = customer_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.quantity = 1
|
||||
>>> move.unit_price = Decimal('30')
|
||||
>>> move.currency = company.currency
|
||||
>>> move.effective_date = today
|
||||
>>> move.click('do')
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product2
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.quantity = 2
|
||||
>>> move.unit_price = Decimal('50')
|
||||
>>> move.currency = company.currency
|
||||
>>> move.effective_date = today
|
||||
>>> move.click('do')
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = lost_loc
|
||||
>>> move.quantity = 1
|
||||
>>> move.effective_date = today
|
||||
>>> move.click('do')
|
||||
|
||||
Check reporting margin per product::
|
||||
|
||||
>>> MarginProduct = Model.get('stock.reporting.margin.product')
|
||||
>>> MarginProductTimeseries = Model.get(
|
||||
... 'stock.reporting.margin.product.time_series')
|
||||
>>> context = {
|
||||
... 'from_date': yesterday,
|
||||
... 'to_date': today,
|
||||
... 'period': 'day',
|
||||
... }
|
||||
>>> with config.set_context(context=context):
|
||||
... reports = MarginProduct.find([])
|
||||
... time_series = MarginProductTimeseries.find([])
|
||||
>>> len(reports)
|
||||
2
|
||||
>>> report, = [r for r in reports if r.product == product]
|
||||
>>> (report.quantity, report.cost, report.revenue, report.profit, report.margin)
|
||||
(5.0, Decimal('100.00'), Decimal('170.00'), Decimal('70.00'), Decimal('0.4118'))
|
||||
>>> len(time_series)
|
||||
3
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({(
|
||||
... r.product.id, str(r.date), r.quantity, r.cost, r.revenue,
|
||||
... r.profit, r.margin)
|
||||
... for r in time_series},
|
||||
... {
|
||||
... (product.id, str(yesterday), 2, Decimal('40.00'),
|
||||
... Decimal('80.00'), Decimal('40.00'), Decimal('0.5000')),
|
||||
... (product.id, str(today), 3, Decimal('60.00'),
|
||||
... Decimal('90.00'), Decimal('30.00'), Decimal('0.3333')),
|
||||
... (product2.id, str(today), 2, Decimal('40.00'),
|
||||
... Decimal('100.00'), Decimal('60.00'), Decimal('0.6000'))})
|
||||
|
||||
Check reporting margin per categories::
|
||||
|
||||
>>> MarginCategory = Model.get('stock.reporting.margin.category')
|
||||
>>> MarginCategoryTimeseries = Model.get(
|
||||
... 'stock.reporting.margin.category.time_series')
|
||||
>>> MarginCategoryTree = Model.get(
|
||||
... 'stock.reporting.margin.category.tree')
|
||||
>>> with config.set_context(context=context):
|
||||
... reports = MarginCategory.find([])
|
||||
... time_series = MarginCategoryTimeseries.find([])
|
||||
... tree = MarginCategoryTree.find([])
|
||||
>>> len(reports)
|
||||
2
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({(r.category.id, r.cost, r.revenue, r.profit, r.margin)
|
||||
... for r in reports},
|
||||
... {(category1.id, Decimal('100.00'), Decimal('170.00'),
|
||||
... Decimal('70.00'), Decimal('0.4118')),
|
||||
... (category2.id, Decimal('40.00'), Decimal('100.00'),
|
||||
... Decimal('60.00'), Decimal('0.6000'))})
|
||||
>>> len(time_series)
|
||||
3
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({
|
||||
... (r.category.id, str(r.date), r.cost, r.revenue, r.profit, r.margin)
|
||||
... for r in time_series},
|
||||
... {
|
||||
... (category1.id, str(yesterday), Decimal('40.00'), Decimal('80.00'),
|
||||
... Decimal('40.00'), Decimal('0.5000')),
|
||||
... (category1.id, str(today), Decimal('60.00'), Decimal('90.00'),
|
||||
... Decimal('30.00'), Decimal('0.3333')),
|
||||
... (category2.id, str(today), Decimal('40.00'), Decimal('100.00'),
|
||||
... Decimal('60.00'), Decimal('0.6000'))})
|
||||
>>> len(tree)
|
||||
3
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({(r.name, r.cost, r.revenue, r.profit, r.margin)
|
||||
... for r in tree},
|
||||
... {("Root", Decimal('140.00'), Decimal('270.00'),
|
||||
... Decimal('130.00'), Decimal('0.4815')),
|
||||
... ("Child1", Decimal('100.00'), Decimal('170.00'),
|
||||
... Decimal('70.00'), Decimal('0.4118')),
|
||||
... ('Child2', Decimal('40.00'), Decimal('100.00'),
|
||||
... Decimal('60.00'), Decimal('0.6000'))})
|
||||
>>> child1, = MarginCategoryTree.find([('rec_name', '=', 'Child1')])
|
||||
>>> child1.rec_name
|
||||
'Child1'
|
||||
|
||||
Check reporting margin including lost::
|
||||
|
||||
>>> context['include_lost'] = True
|
||||
|
||||
>>> with config.set_context(context=context):
|
||||
... reports = MarginProduct.find([])
|
||||
>>> len(reports)
|
||||
2
|
||||
>>> report, = [r for r in reports if r.product == product]
|
||||
>>> (report.quantity, report.cost, report.revenue, report.profit, report.margin)
|
||||
(6.0, Decimal('120.00'), Decimal('170.00'), Decimal('50.00'), Decimal('0.2941'))
|
||||
137
modules/stock/tests/scenario_stock_shipment_cron_assign.rst
Executable file
137
modules/stock/tests/scenario_stock_shipment_cron_assign.rst
Executable file
@@ -0,0 +1,137 @@
|
||||
==========================
|
||||
Stock Shipment Cron Assign
|
||||
==========================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
>>> Cron = Model.get('ir.cron')
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> Move = Model.get('stock.move')
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> ShipmentInternal = Model.get('stock.shipment.internal')
|
||||
>>> ShipmentOut = Model.get('stock.shipment.out')
|
||||
>>> UoM = Model.get('product.uom')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Create a product::
|
||||
|
||||
>>> unit, = UoM.find([('name', '=', "Unit")])
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product"
|
||||
>>> template.type = 'goods'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Create customer::
|
||||
|
||||
>>> customer = Party(name="Customer")
|
||||
>>> customer.save()
|
||||
|
||||
Get locations::
|
||||
|
||||
>>> storage_loc, = Location.find([('code', '=', "STO")])
|
||||
>>> supplier_loc, = Location.find([('code', '=', "SUP")])
|
||||
>>> lost_loc, = Location.find([('type', '=', 'lost_found')], limit=1)
|
||||
|
||||
Fill storage::
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 5
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.unit_price = Decimal('10.0000')
|
||||
>>> move.currency = company.currency
|
||||
>>> move.effective_date = yesterday
|
||||
>>> move.click('do')
|
||||
>>> move.state
|
||||
'done'
|
||||
|
||||
Create different shipments with different planned dates::
|
||||
|
||||
>>> shipment_int_1 = ShipmentInternal()
|
||||
>>> shipment_int_1.planned_date = today
|
||||
>>> shipment_int_1.from_location = storage_loc
|
||||
>>> shipment_int_1.to_location = lost_loc
|
||||
>>> move = shipment_int_1.moves.new()
|
||||
>>> move.from_location = shipment_int_1.from_location
|
||||
>>> move.to_location = shipment_int_1.to_location
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 2
|
||||
>>> shipment_int_1.click('wait')
|
||||
>>> shipment_int_1.state
|
||||
'waiting'
|
||||
|
||||
>>> shipment_out_1 = ShipmentOut()
|
||||
>>> shipment_out_1.planned_date = today
|
||||
>>> shipment_out_1.customer = customer
|
||||
>>> move = shipment_out_1.outgoing_moves.new()
|
||||
>>> move.from_location = shipment_out_1.warehouse_output
|
||||
>>> move.to_location = shipment_out_1.customer_location
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 2
|
||||
>>> move.unit_price = Decimal('10.0000')
|
||||
>>> move.currency = company.currency
|
||||
>>> shipment_out_1.click('wait')
|
||||
>>> shipment_out_1.state
|
||||
'waiting'
|
||||
|
||||
>>> shipment_int_2, = shipment_int_1.duplicate()
|
||||
>>> shipment_int_2.click('wait')
|
||||
>>> shipment_int_2.state
|
||||
'waiting'
|
||||
|
||||
>>> shipment_out_2, = shipment_out_1.duplicate()
|
||||
>>> shipment_out_2.click('wait')
|
||||
>>> shipment_out_2.state
|
||||
'waiting'
|
||||
|
||||
Run assignation cron::
|
||||
|
||||
>>> cron = Cron(method='ir.cron|stock_shipment_assign_try')
|
||||
>>> cron.interval_number = 1
|
||||
>>> cron.interval_type = 'days'
|
||||
>>> cron.click('run_once')
|
||||
|
||||
Check assignations::
|
||||
|
||||
>>> shipment_int_1.reload()
|
||||
>>> shipment_int_1.state
|
||||
'assigned'
|
||||
|
||||
>>> shipment_out_1.reload()
|
||||
>>> shipment_out_1.state
|
||||
'assigned'
|
||||
|
||||
>>> shipment_int_2.reload()
|
||||
>>> shipment_int_2.state
|
||||
'waiting'
|
||||
>>> shipment_int_2.partially_assigned
|
||||
True
|
||||
|
||||
>>> shipment_out_2.reload()
|
||||
>>> shipment_out_2.state
|
||||
'waiting'
|
||||
>>> shipment_out_2.partially_assigned
|
||||
False
|
||||
119
modules/stock/tests/scenario_stock_shipment_in.rst
Executable file
119
modules/stock/tests/scenario_stock_shipment_in.rst
Executable file
@@ -0,0 +1,119 @@
|
||||
==========================
|
||||
Stock Shipment In Scenario
|
||||
==========================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Report
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertNotEqual
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ShipmentIn = Model.get('stock.shipment.in')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Create supplier::
|
||||
|
||||
>>> supplier = Party(name='Supplier')
|
||||
>>> supplier.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> unit, = ProductUom.find([('name', '=', "Unit")])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> input_loc, = Location.find([('code', '=', 'IN')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
|
||||
Create a shipment::
|
||||
|
||||
>>> shipment = ShipmentIn()
|
||||
>>> shipment.supplier = supplier
|
||||
>>> 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('5')
|
||||
>>> move.currency = company.currency
|
||||
>>> shipment.save()
|
||||
>>> assertNotEqual(shipment.number, None)
|
||||
|
||||
>>> len(shipment.incoming_moves)
|
||||
1
|
||||
>>> len(shipment.inventory_moves)
|
||||
0
|
||||
|
||||
Receive the shipment::
|
||||
|
||||
>>> shipment.click('receive')
|
||||
>>> shipment.state
|
||||
'received'
|
||||
>>> [m.state for m in shipment.incoming_moves]
|
||||
['done']
|
||||
>>> [m.state for m in shipment.inventory_moves]
|
||||
['draft']
|
||||
|
||||
>>> restocking_list = Report('stock.shipment.in.restocking_list')
|
||||
>>> _ = restocking_list.execute([shipment])
|
||||
|
||||
Change inventory quantity and try to finish::
|
||||
|
||||
>>> inventory_move, = shipment.inventory_moves
|
||||
>>> inventory_move.quantity = 11
|
||||
>>> shipment.click('do')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ShipmentCheckQuantityWarning: ...
|
||||
>>> inventory_move.reload()
|
||||
>>> inventory_move.quantity = 10
|
||||
>>> inventory_move.save()
|
||||
|
||||
Add extra product to inventory and try to finish::
|
||||
|
||||
>>> product2, = product.duplicate()
|
||||
|
||||
>>> move = shipment.inventory_moves.new()
|
||||
>>> move.product = product2
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = input_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> shipment.click('do')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ShipmentCheckQuantityWarning: ...
|
||||
>>> move = shipment.inventory_moves[-1]
|
||||
>>> shipment.inventory_moves.remove(move)
|
||||
>>> shipment.save()
|
||||
|
||||
Finish the shipment::
|
||||
|
||||
>>> shipment.click('do')
|
||||
>>> shipment.state
|
||||
'done'
|
||||
>>> len(shipment.incoming_moves)
|
||||
1
|
||||
>>> [m.state for m in shipment.inventory_moves]
|
||||
['done']
|
||||
83
modules/stock/tests/scenario_stock_shipment_in_return.rst
Executable file
83
modules/stock/tests/scenario_stock_shipment_in_return.rst
Executable file
@@ -0,0 +1,83 @@
|
||||
=================================
|
||||
Stock Shipment In Return Scenario
|
||||
=================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual, assertNotEqual
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Create supplier::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> supplier = Party(name='Supplier')
|
||||
>>> supplier.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.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
|
||||
Create Shipment In::
|
||||
|
||||
>>> ShipmentInReturn = Model.get('stock.shipment.in.return')
|
||||
>>> shipment_return = ShipmentInReturn()
|
||||
>>> shipment_return.planned_date = yesterday
|
||||
>>> shipment_return.supplier = supplier
|
||||
>>> shipment_return.from_location = storage_loc
|
||||
>>> move = shipment_return.moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = supplier_loc
|
||||
>>> move.company = company
|
||||
>>> move.unit_price = Decimal('1')
|
||||
>>> move.currency = company.currency
|
||||
>>> shipment_return.save()
|
||||
>>> shipment_return.number
|
||||
>>> shipment_return.click('wait')
|
||||
>>> shipment_return.state
|
||||
'waiting'
|
||||
>>> assertNotEqual(shipment_return.number, None)
|
||||
|
||||
Reschedule shipment::
|
||||
|
||||
>>> Cron = Model.get('ir.cron')
|
||||
>>> cron = Cron(method='stock.shipment.in.return|reschedule')
|
||||
>>> cron.interval_number = 1
|
||||
>>> cron.interval_type = 'months'
|
||||
>>> cron.click('run_once')
|
||||
>>> shipment_return.reload()
|
||||
>>> assertEqual(shipment_return.planned_date, today)
|
||||
86
modules/stock/tests/scenario_stock_shipment_in_same_storage_input.rst
Executable file
86
modules/stock/tests/scenario_stock_shipment_in_same_storage_input.rst
Executable file
@@ -0,0 +1,86 @@
|
||||
=================================================
|
||||
Stock Shipment In Same Storage and Input Scenario
|
||||
=================================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Create supplier::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> supplier = Party(name='Supplier')
|
||||
>>> supplier.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
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')])
|
||||
>>> storage1 = Location(name="Storage 1", parent=storage_loc)
|
||||
>>> storage1.save()
|
||||
|
||||
Use storage location as input location::
|
||||
|
||||
>>> warehouse_loc.input_location = storage_loc
|
||||
>>> warehouse_loc.save()
|
||||
|
||||
Create Shipment In::
|
||||
|
||||
>>> ShipmentIn = Model.get('stock.shipment.in')
|
||||
>>> shipment_in = ShipmentIn()
|
||||
>>> shipment_in.supplier = supplier
|
||||
>>> shipment_in.warehouse = warehouse_loc
|
||||
>>> shipment_in.company = company
|
||||
>>> move = shipment_in.incoming_moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 1
|
||||
>>> move.unit_price = Decimal('5')
|
||||
>>> move.currency = company.currency
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = storage1
|
||||
>>> shipment_in.save()
|
||||
|
||||
>>> len(shipment_in.incoming_moves)
|
||||
1
|
||||
>>> len(shipment_in.inventory_moves)
|
||||
0
|
||||
|
||||
Incoming moves are done when receiving the shipment::
|
||||
|
||||
>>> shipment_in.click('receive')
|
||||
>>> shipment_in.state
|
||||
'done'
|
||||
>>> move, = shipment_in.incoming_moves
|
||||
>>> move.state
|
||||
'done'
|
||||
>>> len(shipment_in.inventory_moves)
|
||||
0
|
||||
154
modules/stock/tests/scenario_stock_shipment_internal.rst
Executable file
154
modules/stock/tests/scenario_stock_shipment_internal.rst
Executable file
@@ -0,0 +1,154 @@
|
||||
================================
|
||||
Stock Shipment Internal Scenario
|
||||
================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Report
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import (
|
||||
... activate_modules, assertEqual, assertNotEqual, set_user)
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
>>> tomorrow = today + dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
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.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> lost_found_loc, = Location.find([('type', '=', 'lost_found')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> internal_loc = Location(
|
||||
... name="Internal", type='storage', parent=storage_loc.parent)
|
||||
>>> internal_loc.save()
|
||||
|
||||
Create stock user::
|
||||
|
||||
>>> User = Model.get('res.user')
|
||||
>>> Group = Model.get('res.group')
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> Employee = Model.get('company.employee')
|
||||
>>> stock_user = User()
|
||||
>>> stock_user.name = 'Stock'
|
||||
>>> stock_user.login = 'stock'
|
||||
>>> stock_group, = Group.find([('name', '=', 'Stock')])
|
||||
>>> stock_user.groups.append(stock_group)
|
||||
>>> employee_party = Party(name="Employee")
|
||||
>>> employee_party.save()
|
||||
>>> employee = Employee(party=employee_party)
|
||||
>>> employee.save()
|
||||
>>> stock_user.employees.append(employee)
|
||||
>>> stock_user.employee = employee
|
||||
>>> stock_user.save()
|
||||
|
||||
Create Internal Shipment::
|
||||
|
||||
>>> set_user(stock_user)
|
||||
>>> Shipment = Model.get('stock.shipment.internal')
|
||||
>>> StockMove = Model.get('stock.move')
|
||||
>>> shipment = Shipment()
|
||||
>>> shipment.planned_date = today
|
||||
>>> shipment.from_location = internal_loc
|
||||
>>> shipment.to_location = storage_loc
|
||||
>>> move = shipment.moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = internal_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.currency = company.currency
|
||||
>>> shipment.save()
|
||||
>>> shipment.number
|
||||
>>> shipment.assigned_by
|
||||
>>> shipment.done_by
|
||||
|
||||
>>> shipment.click('wait')
|
||||
>>> shipment.state
|
||||
'waiting'
|
||||
>>> assertNotEqual(shipment.number, None)
|
||||
>>> shipment.click('assign_try')
|
||||
>>> shipment.state
|
||||
'waiting'
|
||||
>>> shipment.assigned_by
|
||||
>>> shipment.done_by
|
||||
|
||||
>>> report = Report('stock.shipment.internal.report')
|
||||
>>> _ = report.execute([shipment])
|
||||
|
||||
Create Internal Shipment from lost_found location::
|
||||
|
||||
>>> lost_found_shipment = Shipment()
|
||||
>>> lost_found_shipment.planned_date = today
|
||||
>>> lost_found_shipment.company = company
|
||||
>>> lost_found_shipment.from_location = lost_found_loc
|
||||
>>> lost_found_shipment.to_location = internal_loc
|
||||
>>> move = StockMove()
|
||||
>>> move = lost_found_shipment.moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 2
|
||||
>>> move.from_location = lost_found_loc
|
||||
>>> move.to_location = internal_loc
|
||||
>>> move.currency = company.currency
|
||||
>>> lost_found_shipment.click('wait')
|
||||
>>> lost_found_shipment.click('assign_try')
|
||||
>>> lost_found_shipment.state
|
||||
'assigned'
|
||||
>>> lost_found_shipment.click('do')
|
||||
>>> lost_found_shipment.state
|
||||
'done'
|
||||
|
||||
Check that now we can finish the older shipment::
|
||||
|
||||
>>> shipment.click('assign_try')
|
||||
>>> assertEqual(shipment.assigned_by, employee)
|
||||
>>> shipment.done_by
|
||||
|
||||
>>> shipment.click('do')
|
||||
>>> shipment.state
|
||||
'done'
|
||||
>>> assertEqual(shipment.done_by, employee)
|
||||
|
||||
Duplicate Internal Shipment::
|
||||
|
||||
>>> shipment_copy, = shipment.duplicate()
|
||||
>>> len(shipment_copy.moves)
|
||||
1
|
||||
|
||||
Reschedule shipment::
|
||||
|
||||
>>> shipment_copy.planned_date = yesterday
|
||||
>>> shipment_copy.click('wait')
|
||||
>>> set_user(1)
|
||||
>>> Cron = Model.get('ir.cron')
|
||||
>>> cron = Cron(method='stock.shipment.internal|reschedule')
|
||||
>>> cron.interval_number = 1
|
||||
>>> cron.interval_type = 'months'
|
||||
>>> cron.click('run_once')
|
||||
>>> shipment_copy.reload()
|
||||
>>> assertEqual(shipment_copy.planned_date, today)
|
||||
102
modules/stock/tests/scenario_stock_shipment_internal_transit.rst
Executable file
102
modules/stock/tests/scenario_stock_shipment_internal_transit.rst
Executable file
@@ -0,0 +1,102 @@
|
||||
=============================================
|
||||
Stock Shipment Internal with Transit Scenario
|
||||
=============================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
>>> tomorrow = today + dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> Shipment = Model.get('stock.shipment.internal')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> warehouse1, = Location.find([('type', '=', 'warehouse')])
|
||||
>>> warehouse2, = warehouse1.duplicate()
|
||||
|
||||
Add lead time between warehouses::
|
||||
|
||||
>>> LeadTime = Model.get('stock.location.lead_time')
|
||||
>>> lead_time = LeadTime()
|
||||
>>> lead_time.warehouse_from = warehouse1
|
||||
>>> lead_time.warehouse_to = warehouse2
|
||||
>>> lead_time.lead_time = dt.timedelta(1)
|
||||
>>> lead_time.save()
|
||||
|
||||
Create Internal Shipment with lead time::
|
||||
|
||||
>>> shipment = Shipment()
|
||||
>>> shipment.planned_date = tomorrow
|
||||
>>> shipment.from_location = warehouse1.storage_location
|
||||
>>> shipment.to_location = warehouse2.storage_location
|
||||
>>> bool(shipment.transit_location)
|
||||
True
|
||||
>>> assertEqual(shipment.planned_start_date, today)
|
||||
>>> move = shipment.moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 2
|
||||
>>> move.from_location = shipment.from_location
|
||||
>>> move.to_location = shipment.to_location
|
||||
>>> shipment.click('wait')
|
||||
>>> len(shipment.moves)
|
||||
2
|
||||
>>> outgoing_move, = shipment.outgoing_moves
|
||||
>>> outgoing_move.quantity
|
||||
2.0
|
||||
>>> assertEqual(outgoing_move.from_location, shipment.from_location)
|
||||
>>> assertEqual(outgoing_move.to_location, shipment.transit_location)
|
||||
>>> assertEqual(outgoing_move.planned_date, today)
|
||||
>>> incoming_move, = shipment.incoming_moves
|
||||
>>> incoming_move.quantity
|
||||
2.0
|
||||
>>> assertEqual(incoming_move.from_location, shipment.transit_location)
|
||||
>>> assertEqual(incoming_move.to_location, shipment.to_location)
|
||||
>>> assertEqual(incoming_move.planned_date, tomorrow)
|
||||
|
||||
>>> outgoing_move.quantity = 1
|
||||
>>> outgoing_move.save()
|
||||
|
||||
>>> shipment.click('assign_force')
|
||||
>>> shipment.effective_start_date = yesterday
|
||||
>>> shipment.click('ship')
|
||||
>>> incoming_move, = shipment.incoming_moves
|
||||
>>> incoming_move.quantity
|
||||
1.0
|
||||
>>> shipment.outgoing_moves[0].state
|
||||
'done'
|
||||
>>> assertEqual(shipment.outgoing_moves[0].effective_date, yesterday)
|
||||
>>> shipment.click('do')
|
||||
>>> shipment.incoming_moves[0].state
|
||||
'done'
|
||||
>>> assertEqual(shipment.incoming_moves[0].effective_date, today)
|
||||
286
modules/stock/tests/scenario_stock_shipment_out.rst
Executable file
286
modules/stock/tests/scenario_stock_shipment_out.rst
Executable file
@@ -0,0 +1,286 @@
|
||||
===========================
|
||||
Stock Shipment Out Scenario
|
||||
===========================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Report
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import (
|
||||
... activate_modules, assertEqual, assertNotEqual, set_user)
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Create customer::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> customer = Party(name='Customer')
|
||||
>>> customer.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.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Create stock user::
|
||||
|
||||
>>> User = Model.get('res.user')
|
||||
>>> Group = Model.get('res.group')
|
||||
>>> Employee = Model.get('company.employee')
|
||||
>>> stock_user = User()
|
||||
>>> stock_user.name = "Stock"
|
||||
>>> stock_user.login = 'stock'
|
||||
>>> stock_user.groups.extend(Group.find([
|
||||
... ('name', '=', 'Stock'),
|
||||
... ]))
|
||||
>>> employee_party = Party(name="Employee")
|
||||
>>> employee_party.save()
|
||||
>>> employee = Employee(party=employee_party)
|
||||
>>> employee.save()
|
||||
>>> stock_user.employees.append(employee)
|
||||
>>> stock_user.employee = employee
|
||||
>>> stock_user.save()
|
||||
|
||||
>>> set_user(stock_user)
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> output_loc, = Location.find([('code', '=', 'OUT')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
|
||||
Create Shipment Out::
|
||||
|
||||
>>> ShipmentOut = Model.get('stock.shipment.out')
|
||||
>>> shipment_out = ShipmentOut()
|
||||
>>> shipment_out.planned_date = today
|
||||
>>> shipment_out.customer = customer
|
||||
>>> shipment_out.warehouse = warehouse_loc
|
||||
>>> shipment_out.company = company
|
||||
|
||||
Add two shipment lines of same product::
|
||||
|
||||
>>> StockMove = Model.get('stock.move')
|
||||
>>> shipment_out.outgoing_moves.extend([StockMove(), StockMove()])
|
||||
>>> for move in shipment_out.outgoing_moves:
|
||||
... move.product = product
|
||||
... move.unit = unit
|
||||
... move.quantity = 1
|
||||
... move.from_location = output_loc
|
||||
... move.to_location = customer_loc
|
||||
... move.company = company
|
||||
... move.unit_price = Decimal('1')
|
||||
... move.currency = company.currency
|
||||
>>> shipment_out.save()
|
||||
>>> shipment_out.number
|
||||
>>> shipment_out.picked_by
|
||||
>>> shipment_out.packed_by
|
||||
>>> shipment_out.done_by
|
||||
|
||||
Set the shipment state to waiting::
|
||||
|
||||
>>> shipment_out.click('wait')
|
||||
>>> shipment_out.state
|
||||
'waiting'
|
||||
>>> assertNotEqual(shipment_out.number, None)
|
||||
>>> len(shipment_out.outgoing_moves)
|
||||
2
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
2
|
||||
>>> assertEqual(
|
||||
... {m.origin for m in shipment_out.inventory_moves},
|
||||
... {m for m in shipment_out.outgoing_moves})
|
||||
|
||||
Make 1 unit of the product available::
|
||||
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.company = company
|
||||
>>> incoming_move.unit_price = Decimal('1')
|
||||
>>> incoming_move.currency = company.currency
|
||||
>>> incoming_move.click('do')
|
||||
|
||||
Assign the shipment now::
|
||||
|
||||
>>> shipment_assign = shipment_out.click('assign_wizard')
|
||||
>>> len(shipment_assign.form.moves)
|
||||
1
|
||||
>>> shipment_assign.execute('end')
|
||||
>>> shipment_out.reload()
|
||||
>>> len(shipment_out.outgoing_moves)
|
||||
2
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
2
|
||||
>>> states = [m.state for m in shipment_out.inventory_moves]
|
||||
>>> states.sort()
|
||||
>>> states
|
||||
['assigned', 'draft']
|
||||
>>> effective_dates = [m.effective_date for m in
|
||||
... shipment_out.inventory_moves]
|
||||
>>> len(set(effective_dates))
|
||||
1
|
||||
>>> planned_dates = [m.planned_date for m in
|
||||
... shipment_out.outgoing_moves]
|
||||
>>> len(set(planned_dates))
|
||||
1
|
||||
|
||||
Ignore non assigned moves and pack shipment::
|
||||
|
||||
>>> shipment_assign = shipment_out.click('assign_wizard')
|
||||
>>> shipment_assign.execute('ignore')
|
||||
>>> sorted([m.quantity for m in shipment_out.inventory_moves])
|
||||
[0.0, 1.0]
|
||||
>>> shipment_out.picked_by
|
||||
>>> shipment_out.packed_by
|
||||
>>> shipment_out.done_by
|
||||
|
||||
>>> picking_list = Report('stock.shipment.out.picking_list')
|
||||
>>> _ = picking_list.execute([shipment_out])
|
||||
|
||||
>>> shipment_out.click('pick')
|
||||
>>> assertEqual(shipment_out.picked_by, employee)
|
||||
>>> shipment_out.packed_by
|
||||
>>> shipment_out.done_by
|
||||
|
||||
>>> shipment_out.click('pack')
|
||||
>>> assertEqual(shipment_out.packed_by, employee)
|
||||
>>> shipment_out.done_by
|
||||
>>> [m.state for m in shipment_out.outgoing_moves]
|
||||
['assigned']
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
1
|
||||
>>> shipment_out.inventory_moves[0].state
|
||||
'done'
|
||||
>>> assertEqual(sum([m.quantity for m in shipment_out.inventory_moves]),
|
||||
... sum([m.quantity for m in shipment_out.outgoing_moves]))
|
||||
|
||||
>>> delivery_note = Report('stock.shipment.out.delivery_note')
|
||||
>>> _ = delivery_note.execute([shipment_out])
|
||||
|
||||
Set the state as Done::
|
||||
|
||||
>>> shipment_out.click('do')
|
||||
>>> assertEqual(shipment_out.done_by, employee)
|
||||
>>> [m.state for m in shipment_out.outgoing_moves]
|
||||
['done']
|
||||
>>> planned_dates = [m.planned_date for m in
|
||||
... shipment_out.outgoing_moves]
|
||||
>>> assertEqual(planned_dates, [today])
|
||||
>>> effective_dates = [m.effective_date for m in
|
||||
... shipment_out.outgoing_moves]
|
||||
>>> len(set(effective_dates))
|
||||
1
|
||||
>>> len(shipment_out.outgoing_moves)
|
||||
1
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
1
|
||||
>>> shipment_out.inventory_moves[0].state
|
||||
'done'
|
||||
>>> assertEqual(sum([m.quantity for m in shipment_out.inventory_moves]),
|
||||
... sum([m.quantity for m in shipment_out.outgoing_moves]))
|
||||
|
||||
Create Shipment Out with effective date::
|
||||
|
||||
>>> ShipmentOut = Model.get('stock.shipment.out')
|
||||
>>> shipment_out = ShipmentOut()
|
||||
>>> shipment_out.planned_date = yesterday
|
||||
>>> shipment_out.effective_date = yesterday
|
||||
>>> shipment_out.customer = customer
|
||||
>>> shipment_out.warehouse = warehouse_loc
|
||||
>>> shipment_out.company = company
|
||||
>>> move = shipment_out.outgoing_moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = output_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.company = company
|
||||
>>> move.unit_price = Decimal('1')
|
||||
>>> move.currency = company.currency
|
||||
>>> shipment_out.click('wait')
|
||||
|
||||
Make 1 unit of the product available::
|
||||
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = yesterday
|
||||
>>> incoming_move.effective_date = yesterday
|
||||
>>> incoming_move.company = company
|
||||
>>> incoming_move.unit_price = Decimal('1')
|
||||
>>> incoming_move.currency = company.currency
|
||||
>>> incoming_move.click('do')
|
||||
|
||||
Finish the shipment::
|
||||
|
||||
>>> shipment_out.click('assign_try')
|
||||
>>> shipment_out.click('pick')
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
1
|
||||
>>> len(shipment_out.outgoing_moves)
|
||||
1
|
||||
>>> shipment_out.click('pack')
|
||||
>>> shipment_out.click('pick')
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
1
|
||||
>>> len(shipment_out.outgoing_moves)
|
||||
1
|
||||
>>> shipment_out.click('pack')
|
||||
|
||||
Finish the shipment::
|
||||
|
||||
>>> shipment_out.click('do')
|
||||
>>> shipment_out.state
|
||||
'done'
|
||||
>>> outgoing_move, = shipment_out.outgoing_moves
|
||||
>>> assertEqual(outgoing_move.effective_date, yesterday)
|
||||
>>> inventory_move, = shipment_out.inventory_moves
|
||||
>>> assertEqual(inventory_move.effective_date, yesterday)
|
||||
|
||||
Reschedule shipment::
|
||||
|
||||
>>> shipment_copy, = shipment_out.duplicate()
|
||||
>>> shipment_copy.planned_date = yesterday
|
||||
>>> shipment_copy.click('wait')
|
||||
>>> set_user(1)
|
||||
>>> Cron = Model.get('ir.cron')
|
||||
>>> cron = Cron(method='stock.shipment.out|reschedule')
|
||||
>>> cron.interval_number = 1
|
||||
>>> cron.interval_type = 'months'
|
||||
>>> cron.click('run_once')
|
||||
>>> shipment_copy.reload()
|
||||
>>> assertEqual(shipment_copy.planned_date, today)
|
||||
94
modules/stock/tests/scenario_stock_shipment_out_return.rst
Executable file
94
modules/stock/tests/scenario_stock_shipment_out_return.rst
Executable file
@@ -0,0 +1,94 @@
|
||||
==================================
|
||||
Stock Shipment Out Return Scenario
|
||||
==================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Report
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertNotEqual
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Create customer::
|
||||
|
||||
>>> customer = Party(name='Customer')
|
||||
>>> customer.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
|
||||
Create Shipment Out Return::
|
||||
|
||||
>>> ShipmentOutReturn = Model.get('stock.shipment.out.return')
|
||||
>>> shipment = ShipmentOutReturn()
|
||||
>>> shipment.customer = customer
|
||||
>>> shipment.warehouse = warehouse_loc
|
||||
>>> shipment.company = company
|
||||
>>> move = shipment.incoming_moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = customer_loc
|
||||
>>> move.to_location = warehouse_loc.input_location
|
||||
>>> move.unit_price = Decimal('20')
|
||||
>>> move.currency = company.currency
|
||||
>>> shipment.save()
|
||||
>>> assertNotEqual(shipment.number, None)
|
||||
|
||||
>>> len(shipment.incoming_moves)
|
||||
1
|
||||
>>> len(shipment.inventory_moves)
|
||||
0
|
||||
|
||||
Receive shipment::
|
||||
|
||||
>>> shipment.click('receive')
|
||||
>>> shipment.state
|
||||
'received'
|
||||
|
||||
>>> [m.state for m in shipment.incoming_moves]
|
||||
['done']
|
||||
>>> [m.state for m in shipment.inventory_moves]
|
||||
['draft']
|
||||
|
||||
>>> restocking_list = Report('stock.shipment.out.return.restocking_list')
|
||||
>>> _ = restocking_list.execute([shipment])
|
||||
|
||||
Finish the shipment::
|
||||
|
||||
>>> shipment.click('do')
|
||||
>>> shipment.state
|
||||
'done'
|
||||
>>> len(shipment.incoming_moves)
|
||||
1
|
||||
>>> [m.state for m in shipment.inventory_moves]
|
||||
['done']
|
||||
@@ -0,0 +1,87 @@
|
||||
=========================================================
|
||||
Stock Shipment Out Return Same Storage and Input Scenario
|
||||
=========================================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Create customer::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> customer = Party(name='Customer')
|
||||
>>> customer.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.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> storage1 = Location(name="Storage 1", parent=storage_loc)
|
||||
>>> storage1.save()
|
||||
|
||||
Use storage location as input location::
|
||||
|
||||
>>> warehouse_loc.input_location = storage_loc
|
||||
>>> warehouse_loc.save()
|
||||
|
||||
Create Shipment Out Return::
|
||||
|
||||
>>> ShipmentOutReturn = Model.get('stock.shipment.out.return')
|
||||
>>> shipment = ShipmentOutReturn()
|
||||
>>> shipment.customer = customer
|
||||
>>> shipment.warehouse = warehouse_loc
|
||||
>>> shipment.company = company
|
||||
>>> move = shipment.incoming_moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = customer_loc
|
||||
>>> move.to_location = storage1
|
||||
>>> move.unit_price = Decimal('20')
|
||||
>>> move.currency = company.currency
|
||||
>>> shipment.save()
|
||||
|
||||
>>> len(shipment.incoming_moves)
|
||||
1
|
||||
>>> len(shipment.inventory_moves)
|
||||
0
|
||||
|
||||
Shipment is done when receiving::
|
||||
|
||||
>>> shipment.click('receive')
|
||||
>>> shipment.state
|
||||
'done'
|
||||
>>> move, = shipment.incoming_moves
|
||||
>>> move.state
|
||||
'done'
|
||||
>>> len(shipment.inventory_moves)
|
||||
0
|
||||
122
modules/stock/tests/scenario_stock_shipment_out_same_storage_output.rst
Executable file
122
modules/stock/tests/scenario_stock_shipment_out_same_storage_output.rst
Executable file
@@ -0,0 +1,122 @@
|
||||
===================================================
|
||||
Stock Shipment Out Same Storage and Output Scenario
|
||||
===================================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
>>> Move = Model.get('stock.move')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Create customer::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> customer = Party(name='Customer')
|
||||
>>> customer.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.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> warehouse_loc.output_location = storage_loc
|
||||
>>> warehouse_loc.save()
|
||||
|
||||
Create Shipment Out::
|
||||
|
||||
>>> ShipmentOut = Model.get('stock.shipment.out')
|
||||
>>> shipment_out = ShipmentOut()
|
||||
>>> shipment_out.customer = customer
|
||||
>>> shipment_out.warehouse = warehouse_loc
|
||||
>>> shipment_out.company = company
|
||||
>>> move = shipment_out.outgoing_moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 1
|
||||
>>> move.unit_price = Decimal('5')
|
||||
>>> move.currency = company.currency
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> shipment_out.save()
|
||||
|
||||
>>> len(shipment_out.outgoing_moves)
|
||||
1
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
0
|
||||
|
||||
Set the shipment state to waiting::
|
||||
|
||||
>>> shipment_out.click('wait')
|
||||
>>> shipment_out.state
|
||||
'waiting'
|
||||
>>> len(shipment_out.outgoing_moves)
|
||||
1
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
0
|
||||
|
||||
Try to assign::
|
||||
|
||||
>>> shipment_out.click('assign_try')
|
||||
>>> shipment_out.state
|
||||
'waiting'
|
||||
>>> move, = shipment_out.outgoing_moves
|
||||
>>> move.state
|
||||
'draft'
|
||||
|
||||
Fill storage location::
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.from_location = warehouse_loc.lost_found_location
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 1
|
||||
>>> move.click('do')
|
||||
>>> move.state
|
||||
'done'
|
||||
|
||||
Try to assign again::
|
||||
|
||||
>>> shipment_out.click('assign_try')
|
||||
>>> shipment_out.state
|
||||
'assigned'
|
||||
>>> move, = shipment_out.outgoing_moves
|
||||
>>> move.state
|
||||
'assigned'
|
||||
|
||||
Pack the shipment::
|
||||
|
||||
>>> shipment_out.click('pack')
|
||||
>>> shipment_out.state
|
||||
'packed'
|
||||
>>> len(shipment_out.outgoing_moves)
|
||||
1
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
0
|
||||
1738
modules/stock/tests/test_module.py
Executable file
1738
modules/stock/tests/test_module.py
Executable file
File diff suppressed because it is too large
Load Diff
8
modules/stock/tests/test_scenario.py
Executable file
8
modules/stock/tests/test_scenario.py
Executable file
@@ -0,0 +1,8 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from trytond.tests.test_tryton import load_doc_tests
|
||||
|
||||
|
||||
def load_tests(*args, **kwargs):
|
||||
return load_doc_tests(__name__, __file__, *args, **kwargs)
|
||||
Reference in New Issue
Block a user