first commit

This commit is contained in:
root
2026-03-14 09:42:12 +00:00
commit 0adbd20c2c
10991 changed files with 1646955 additions and 0 deletions

View 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.

View File

@@ -0,0 +1,246 @@
========================
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
>>> from trytond.modules.currency.tests.tools import get_currency
>>> 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)
Get currency::
>>> currency = get_currency()
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.unit_price = Decimal('100')
>>> incoming_move.currency = 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.unit_price = Decimal('200')
>>> incoming_move.currency = 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.unit_price = Decimal('200')
>>> incoming_move.currency = 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.unit_price = Decimal('200')
>>> incoming_move.currency = 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.currency = 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 = 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.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.unit_price = Decimal('3')
>>> incoming_move.currency = 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.unit_price = Decimal('2')
>>> incoming_move.currency = 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')

View File

@@ -0,0 +1,250 @@
========================
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
>>> from trytond.modules.currency.tests.tools import get_currency
>>> from trytond.tests.tools import activate_modules, assertEqual
>>> today = dt.date.today()
Activate modules::
>>> config = activate_modules('stock', create_company)
Get currency::
>>> currency = get_currency()
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.unit_price = Decimal('100')
>>> incoming_move.currency = 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.unit_price = Decimal('70')
>>> incoming_move.currency = 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.unit_price = Decimal('100')
>>> incoming_move.currency = 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.unit_price = Decimal('70')
>>> incoming_move.currency = 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'

View File

@@ -0,0 +1,111 @@
==============================
Stock Inventory Count Scenario
==============================
Imports::
>>> from decimal import Decimal
>>> from proteus import Model
>>> from trytond.modules.company.tests.tools import create_company
>>> from trytond.tests.tools import activate_modules
Activate modules::
>>> config = activate_modules('stock', create_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

View File

@@ -0,0 +1,81 @@
=======================================
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
>>> from trytond.modules.currency.tests.tools import get_currency
>>> from trytond.tests.tools import activate_modules, assertEqual
>>> today = dt.date.today()
Activate modules::
>>> config = activate_modules('stock', create_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.unit_price = Decimal('100')
>>> incoming_move.currency = get_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)

View File

@@ -0,0 +1,67 @@
=============================
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
>>> from trytond.modules.currency.tests.tools import get_currency
>>> 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 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 = get_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'

View File

@@ -0,0 +1,110 @@
=====================
Stock Period Scenario
=====================
Imports::
>>> import datetime as dt
>>> from decimal import Decimal
>>> from proteus import Model
>>> from trytond.modules.company.tests.tools import create_company
>>> from trytond.modules.currency.tests.tools import get_currency
>>> 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)
>>> Location = Model.get('stock.location')
>>> Move = Model.get('stock.move')
>>> Period = Model.get('stock.period')
>>> Product = Model.get('product.product')
>>> ProductTemplate = Model.get('product.template')
>>> ProductUom = Model.get('product.uom')
>>> currency = get_currency()
Create product::
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
>>> template = ProductTemplate()
>>> template.name = 'Product'
>>> template.default_uom = unit
>>> template.type = 'goods'
>>> template.save()
>>> product, = template.products
Get stock locations::
>>> storage_loc, = Location.find([('code', '=', 'STO')])
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
Create a period::
>>> period = Period(date=yesterday)
>>> period.save()
Close the period::
>>> period.click('close')
>>> period.state
'closed'
Try to create a move::
>>> move = Move()
>>> move.product = product
>>> move.quantity = 1
>>> move.from_location = storage_loc
>>> move.to_location = customer_loc
>>> move.planned_date = yesterday
>>> move.unit_price = Decimal('42.0000')
>>> move.currency = currency
>>> move.save()
Traceback (most recent call last):
...
AccessError: ...
Reopen the period::
>>> period.click('draft')
>>> period.state
'draft'
Close the period with draft move::
>>> move.save()
>>> period.click('close')
>>> period.state
'closed'
Reopen the period::
>>> period.click('draft')
>>> period.state
'draft'
Create an assigned move::
>>> Move.write([move], {'state': 'assigned'}, config._context)
>>> move.state
'assigned'
Close the period with assigned move::
>>> period.click('close')
Traceback (most recent call last):
...
PeriodCloseError: ...
Try to close a period on today::
>>> period = Period(date=today)
>>> period.click('close')
Traceback (most recent call last):
...
PeriodCloseError: ...

View 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
>>> from trytond.modules.currency.tests.tools import get_currency
>>> 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)
Get currency::
>>> currency = get_currency()
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 = 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 = 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 = 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 = 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)])

View File

@@ -0,0 +1,115 @@
==============================
Stock Product Replace Scenario
==============================
Imports::
>>> 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, assertTrue)
Activate modules::
>>> config = activate_modules('stock')
>>> Cron = Model.get('ir.cron')
>>> Location = Model.get('stock.location')
>>> Move = Model.get('stock.move')
>>> ProductTemplate = Model.get('product.template')
>>> UoM = Model.get('product.uom')
Create company::
>>> _ = create_company()
>>> company = get_company()
Get stock locations::
>>> supplier_loc, = Location.find([('code', '=', "SUP")])
>>> storage_loc, = Location.find([('code', '=', "STO")])
>>> customer_loc, = Location.find([('code', '=', "CUS")])
Create a product::
>>> unit, = UoM.find([('name', '=', "Unit")])
>>> template = ProductTemplate()
>>> template.name = "Product"
>>> template.type = 'goods'
>>> template.default_uom = unit
>>> template.save()
>>> product1, = template.products
Create a second product::
>>> template = ProductTemplate()
>>> template.name = "Product"
>>> template.type = 'goods'
>>> template.default_uom = unit
>>> template.save()
>>> product2, = template.products
Fill storage location::
>>> move = Move(product=product1)
>>> move.quantity = 1
>>> move.from_location = supplier_loc
>>> move.to_location = storage_loc
>>> move.unit_price = Decimal('10.0000')
>>> move.currency = company.currency
>>> move.click('do')
>>> move.state
'done'
Replace the product::
>>> replace = Wizard('product.product.replace', models=[product1])
>>> replace.form.destination = product2
>>> replace.execute('replace')
>>> assertEqual(product1.replaced_by, product2)
>>> assertTrue(product1.active)
Create a draft move::
>>> move = Move(product=product1)
>>> move.quantity = 1
>>> move.from_location = storage_loc
>>> move.to_location = customer_loc
>>> move.unit_price = Decimal('20.0000')
>>> move.currency = company.currency
>>> move.save()
>>> move.state
'draft'
Empty storage location::
>>> move = Move(product=product1)
>>> move.quantity = 1
>>> move.from_location = storage_loc
>>> move.to_location = customer_loc
>>> move.unit_price = Decimal('20.0000')
>>> move.currency = company.currency
>>> move.click('do')
>>> move.state
'done'
Check replaced product is deactivated and draft move is deleted::
>>> product1.reload()
>>> assertFalse(product1.active)
>>> Move.find([('state', '=', 'draft')])
[]
Create a move for replaced product change the product::
>>> move = Move(product=product1)
>>> move.quantity = 1
>>> move.from_location = storage_loc
>>> move.to_location = customer_loc
>>> move.unit_price = Decimal('20.0000')
>>> move.currency = company.currency
>>> move.save()
>>> assertEqual(move.product, product2)

View File

@@ -0,0 +1,161 @@
==================================
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)
Get 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')]

View 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
>>> from trytond.modules.currency.tests.tools import get_currency
>>> 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)
>>> Location = Model.get('stock.location')
>>> ProductTemplate = Model.get('product.template')
>>> ProductUom = Model.get('product.uom')
>>> StockMove = Model.get('stock.move')
Get currency::
>>> currency = get_currency()
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=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=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')

View File

@@ -0,0 +1,157 @@
=================================
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
>>> from trytond.modules.currency.tests.tools import get_currency
>>> 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)
Get currency::
>>> currency = get_currency()
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
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.unit_price = Decimal('1')
>>> move.currency = 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
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.unit_price = Decimal('1')
>>> move.currency = 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.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
>>> 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'

View File

@@ -0,0 +1,239 @@
==================================
Stock Reporting Inventory Scenario
==================================
Imports::
>>> import datetime as dt
>>> from decimal import Decimal
>>> from unittest.mock import patch
>>> from proteus import Model
>>> from trytond.ir.date import Date
>>> from trytond.modules.company.tests.tools import create_company
>>> from trytond.modules.currency.tests.tools import get_currency
>>> from trytond.tests.tools import activate_modules, assertEqual
>>> period_close = globals().get('period_close', False)
>>> product_type = globals().get('product_type', 'product.template')
Patch today::
>>> mock = patch.object(Date, 'today', return_value=dt.date(2025, 1, 15))
>>> _ = mock.start()
Activate modules::
>>> config = activate_modules('stock', create_company)
>>> Inventory = Model.get('stock.reporting.inventory')
>>> InventoryMove = Model.get('stock.reporting.inventory.move')
>>> InventoryDaily = Model.get('stock.reporting.inventory.daily')
>>> InventoryTurnover = Model.get('stock.reporting.inventory.turnover')
>>> Location = Model.get('stock.location')
>>> Move = Model.get('stock.move')
>>> Period = Model.get('stock.period')
>>> ProductTemplate = Model.get('product.template')
>>> ProductUom = Model.get('product.uom')
Get currency::
>>> currency = get_currency()
Create product::
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
>>> template = ProductTemplate()
>>> template.name = 'Product'
>>> template.default_uom = unit
>>> template.type = 'goods'
>>> template.save()
>>> product, = template.products
Get stock locations::
>>> 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 = Move()
>>> move.product = product
>>> move.from_location = supplier_loc
>>> move.to_location = storage_loc
>>> move.quantity = 10
>>> move.effective_date = dt.date(2025, 1, 1)
>>> move.unit_price = Decimal('10.0000')
>>> move.currency = currency
>>> move.click('do')
>>> move.state
'done'
>>> move = Move()
>>> move.product = product
>>> move.from_location = storage_loc
>>> move.to_location = customer_loc
>>> move.unit = unit
>>> move.quantity = 1
>>> move.effective_date = dt.date(2025, 1, 1)
>>> move.unit_price = Decimal('20.0000')
>>> move.currency = currency
>>> move.click('do')
>>> move.state
'done'
>>> move = Move()
>>> move.product = product
>>> move.from_location = storage_loc
>>> move.to_location = customer_loc
>>> move.unit = unit
>>> move.quantity = 2
>>> move.effective_date = dt.date(2025, 1, 10)
>>> move.unit_price = Decimal('20.0000')
>>> move.currency = currency
>>> move.click('do')
>>> move.state
'done'
Forecast some moves::
>>> move = Move()
>>> move.product = product
>>> move.from_location = supplier_loc
>>> move.to_location = storage_loc
>>> move.quantity = 10
>>> move.effective_date = dt.date(2025, 1, 5)
>>> move.unit_price = Decimal('10.0000')
>>> move.currency = currency
>>> move.save()
>>> move.state
'draft'
>>> move = Move()
>>> move.product = product
>>> move.from_location = storage_loc
>>> move.to_location = customer_loc
>>> move.unit = unit
>>> move.quantity = 3
>>> move.planned_date = dt.date(2025, 1, 20)
>>> move.unit_price = Decimal('20.0000')
>>> move.currency = currency
>>> move.save()
>>> move.state
'draft'
Close period::
>>> period = Period(date=dt.date(2025, 1, 5))
>>> if period_close:
... period.click('close')
Check inventory::
>>> with config.set_context(
... location=warehouse_loc.id,
... product_type=product_type,
... date=dt.date(2024, 1, 1)):
... Inventory.find([])
[]
>>> with config.set_context(
... location=warehouse_loc.id,
... product_type=product_type,
... date=dt.date(2025, 1, 1)):
... inventory, = Inventory.find([])
>>> inventory.quantity
9.0
>>> assertEqual(inventory.product.__class__.__name__, product_type)
>>> with config.set_context(
... location=warehouse_loc.id,
... product_type=product_type,
... date=dt.date(2025, 1, 15)):
... inventory, = Inventory.find([])
>>> inventory.quantity
7.0
>>> with config.set_context(
... location=warehouse_loc.id,
... product_type=product_type,
... date=dt.date(2025, 1, 20)):
... inventory, = Inventory.find([])
>>> inventory.quantity
4.0
>>> with config.set_context(
... location=warehouse_loc.id,
... product_type=product_type):
... inventory_moves = InventoryMove.find([])
... inventories_daily = InventoryDaily.find([])
>>> [i.quantity for i in inventory_moves]
[4.0, 7.0, 9.0, 10.0]
>>> [(i.input_quantity, i.output_quantity) for i in inventory_moves]
[(None, 3.0), (None, 2.0), (None, 1.0), (10.0, None)]
>>> [i.quantity for i in inventories_daily]
[4.0, 7.0, 9.0]
>>> [(i.input_quantity, i.output_quantity) for i in inventories_daily]
[(None, 3.0), (None, 2.0), (10.0, 1.0)]
>>> with config.set_context(
... location=warehouse_loc.id,
... from_date=dt.date(2025, 1, 15),
... to_date=dt.date(2025, 1, 29),
... product_type=product_type):
... inventory_moves = InventoryMove.find([])
... inventories_daily = InventoryDaily.find([])
>>> [i.quantity for i in inventory_moves]
[4.0, 7.0]
>>> [(i.input_quantity, i.output_quantity) for i in inventory_moves]
[(None, 3.0), (None, None)]
>>> [i.quantity for i in inventories_daily]
[4.0, 7.0]
>>> [(i.input_quantity, i.output_quantity) for i in inventories_daily]
[(None, 3.0), (None, None)]
>>> with config.set_context(
... location=warehouse_loc.id,
... from_date=dt.date(2025, 1, 10),
... to_date=dt.date(2025, 1, 29),
... product_type=product_type):
... inventory_moves = InventoryMove.find([])
... inventories_daily = InventoryDaily.find([])
>>> assertEqual(
... [i.quantity for i in inventory_moves],
... [4.0, 7.0] if period_close else [4.0, 7.0, 9.0])
>>> assertEqual(
... [(i.input_quantity, i.output_quantity) for i in inventory_moves],
... [(None, 3.0), (None, 2.0)] if period_close
... else [(None, 3.0), (None, 2.0), (None, None)])
>>> [i.quantity for i in inventories_daily]
[4.0, 7.0]
>>> [(i.input_quantity, i.output_quantity) for i in inventories_daily]
[(None, 3.0), (None, 2.0)]
Check Inventory turnover::
>>> with config.set_context(
... location=warehouse_loc.id,
... from_date=dt.date(2025, 1, 10),
... to_date=dt.date(2025, 1, 29),
... product_type=product_type):
... turnover, = InventoryTurnover.find([])
>>> turnover.output_quantity
0.25
>>> turnover.average_quantity
5.5
>>> turnover.turnover
0.045
>>> assertEqual(turnover.product.__class__.__name__, product_type)

View 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
>>> from trytond.modules.currency.tests.tools import get_currency
>>> 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)
Get currency::
>>> currency = get_currency()
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 = 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 = 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 = 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 = 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 = 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'))

View 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
>>> from trytond.modules.currency.tests.tools import get_currency
>>> 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)
>>> 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')
Get currency::
>>> currency = get_currency()
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 = 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 = 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

View File

@@ -0,0 +1,115 @@
==========================
Stock Shipment In Scenario
==========================
Imports::
>>> from decimal import Decimal
>>> from proteus import Model, Report
>>> from trytond.modules.company.tests.tools import create_company
>>> from trytond.modules.currency.tests.tools import get_currency
>>> from trytond.tests.tools import activate_modules, assertNotEqual
Activate modules::
>>> config = activate_modules('stock', create_company)
>>> 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 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 = get_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']

View File

@@ -0,0 +1,78 @@
=================================
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
>>> from trytond.modules.currency.tests.tools import get_currency
>>> 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 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.unit_price = Decimal('1')
>>> move.currency = get_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)

View File

@@ -0,0 +1,81 @@
=================================================
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
>>> from trytond.modules.currency.tests.tools import get_currency
>>> from trytond.tests.tools import activate_modules
Activate modules::
>>> config = activate_modules('stock', create_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
>>> move = shipment_in.incoming_moves.new()
>>> move.product = product
>>> move.unit = unit
>>> move.quantity = 1
>>> move.unit_price = Decimal('5')
>>> move.currency = get_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

View File

@@ -0,0 +1,141 @@
================================
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
>>> 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)
>>> Employee = Model.get('company.employee')
>>> Party = Model.get('party.party')
>>> User = Model.get('res.user')
Set employee::
>>> employee_party = Party(name="Employee")
>>> employee_party.save()
>>> employee = Employee(party=employee_party)
>>> employee.save()
>>> user = User(config.user)
>>> user.employees.append(employee)
>>> user.employee = employee
>>> user.save()
>>> set_user(user.id)
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 Internal Shipment::
>>> 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
>>> 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.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
>>> 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')
>>> 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)

View File

@@ -0,0 +1,98 @@
=============================================
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
>>> 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)
>>> ProductTemplate = Model.get('product.template')
>>> ProductUom = Model.get('product.uom')
>>> Shipment = Model.get('stock.shipment.internal')
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('pack')
>>> 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)

View File

@@ -0,0 +1,284 @@
===========================
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
>>> from trytond.modules.currency.tests.tools import get_currency
>>> 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)
>>> Employee = Model.get('company.employee')
>>> Party = Model.get('party.party')
>>> User = Model.get('res.user')
Set employee::
>>> employee_party = Party(name="Employee")
>>> employee_party.save()
>>> employee = Employee(party=employee_party)
>>> employee.save()
>>> user = User(config.user)
>>> user.employees.append(employee)
>>> user.employee = employee
>>> user.save()
>>> set_user(user.id)
Get currency::
>>> currency = get_currency()
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')])
>>> 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
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.unit_price = Decimal('1')
... move.currency = currency
>>> shipment_out.save()
>>> shipment_out.number
>>> shipment_out.picked_by
>>> shipment_out.packed_by
>>> shipment_out.shipped_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.unit_price = Decimal('1')
>>> incoming_move.currency = 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.shipped_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.shipped_by
>>> shipment_out.done_by
>>> shipment_out.click('pack')
>>> assertEqual(shipment_out.packed_by, employee)
>>> shipment_out.shipped_by
>>> 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 Shipped::
>>> shipment_out.click('ship')
>>> assertEqual(shipment_out.shipped_by, employee)
>>> shipment_out.done_by
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
>>> 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.unit_price = Decimal('1')
>>> move.currency = 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.unit_price = Decimal('1')
>>> incoming_move.currency = 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')
>>> 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)

View File

@@ -0,0 +1,89 @@
==================================
Stock Shipment Out Return Scenario
==================================
Imports::
>>> from decimal import Decimal
>>> from proteus import Model, Report
>>> from trytond.modules.company.tests.tools import create_company
>>> from trytond.modules.currency.tests.tools import get_currency
>>> from trytond.tests.tools import activate_modules, assertNotEqual
Activate modules::
>>> config = activate_modules('stock', create_company)
>>> Party = Model.get('party.party')
>>> ProductUom = Model.get('product.uom')
>>> ProductTemplate = Model.get('product.template')
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
>>> 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 = get_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']

View File

@@ -0,0 +1,82 @@
=========================================================
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
>>> from trytond.modules.currency.tests.tools import get_currency
>>> from trytond.tests.tools import activate_modules
Activate modules::
>>> config = activate_modules('stock', create_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
>>> 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 = get_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

View File

@@ -0,0 +1,117 @@
===================================================
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
>>> from trytond.modules.currency.tests.tools import get_currency
>>> from trytond.tests.tools import activate_modules
Activate modules::
>>> config = activate_modules('stock', create_company)
>>> Move = Model.get('stock.move')
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
>>> move = shipment_out.outgoing_moves.new()
>>> move.product = product
>>> move.unit = unit
>>> move.quantity = 1
>>> move.unit_price = Decimal('5')
>>> move.currency = get_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

File diff suppressed because it is too large Load Diff

View 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)