first commit
This commit is contained in:
2
modules/stock_supply/tests/__init__.py
Normal file
2
modules/stock_supply/tests/__init__.py
Normal 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_supply/tests/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
modules/stock_supply/tests/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,4 @@
|
||||
[
|
||||
{"with_warehouses": true}
|
||||
,{"with_warehouses": false}
|
||||
]
|
||||
152
modules/stock_supply/tests/scenario_stock_internal_supply.rst
Normal file
152
modules/stock_supply/tests/scenario_stock_internal_supply.rst
Normal file
@@ -0,0 +1,152 @@
|
||||
===========================
|
||||
Stock Shipment Out Scenario
|
||||
===========================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Wizard
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
>>> with_warehouses = globals().get('with_warehouses', False)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock_supply', create_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')])
|
||||
>>> output_loc, = Location.find([('code', '=', 'OUT')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> lost_loc, = Location.find([('type', '=', 'lost_found')])
|
||||
|
||||
Create provisioning location::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> provisioning_loc = Location()
|
||||
>>> provisioning_loc.name = 'Provisioning Location'
|
||||
>>> provisioning_loc.type = 'storage'
|
||||
>>> provisioning_loc.parent = warehouse_loc
|
||||
>>> provisioning_loc.save()
|
||||
|
||||
Create a new storage location::
|
||||
|
||||
>>> sec_storage_loc = Location()
|
||||
>>> sec_storage_loc.name = 'Second Storage'
|
||||
>>> sec_storage_loc.type = 'storage'
|
||||
>>> sec_storage_loc.parent = warehouse_loc
|
||||
>>> sec_storage_loc.provisioning_location = provisioning_loc
|
||||
>>> sec_storage_loc.save()
|
||||
|
||||
Create internal order point::
|
||||
|
||||
>>> OrderPoint = Model.get('stock.order_point')
|
||||
>>> order_point = OrderPoint()
|
||||
>>> order_point.product = product
|
||||
>>> order_point.location = storage_loc
|
||||
>>> order_point.provisioning_location = provisioning_loc
|
||||
>>> order_point.type = 'internal'
|
||||
>>> order_point.min_quantity = 10
|
||||
>>> order_point.target_quantity = 15
|
||||
>>> order_point.save()
|
||||
|
||||
Create inventory to add enough quantity in Provisioning Location::
|
||||
|
||||
>>> Inventory = Model.get('stock.inventory')
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = provisioning_loc
|
||||
>>> inventory_line = inventory.lines.new(product=product)
|
||||
>>> inventory_line.quantity = 100.0
|
||||
>>> inventory_line.expected_quantity = 0.0
|
||||
>>> inventory.click('confirm')
|
||||
>>> inventory.state
|
||||
'done'
|
||||
|
||||
Execute internal supply::
|
||||
|
||||
>>> ShipmentInternal = Model.get('stock.shipment.internal')
|
||||
>>> Wizard('stock.supply').execute('create_')
|
||||
>>> shipment, = ShipmentInternal.find([])
|
||||
>>> shipment.state
|
||||
'request'
|
||||
>>> len(shipment.moves)
|
||||
1
|
||||
>>> move, = shipment.moves
|
||||
>>> move.product.template.name
|
||||
'Product'
|
||||
>>> move.quantity
|
||||
15.0
|
||||
>>> move.from_location.name
|
||||
'Provisioning Location'
|
||||
>>> move.to_location.code
|
||||
'STO'
|
||||
|
||||
Create negative quantity in Second Storage::
|
||||
|
||||
>>> Move = Model.get('stock.move')
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 10
|
||||
>>> move.from_location = sec_storage_loc
|
||||
>>> move.to_location = lost_loc
|
||||
>>> move.click('do')
|
||||
>>> move.state
|
||||
'done'
|
||||
|
||||
Execute internal supply::
|
||||
|
||||
>>> stock_supply = Wizard('stock.supply')
|
||||
>>> if with_warehouses:
|
||||
... stock_supply.form.warehouses.append(warehouse_loc)
|
||||
... else:
|
||||
... while stock_supply.form.warehouses:
|
||||
... _ = stock_supply.form.warehouses.pop()
|
||||
>>> stock_supply.execute('create_')
|
||||
>>> shipment, = ShipmentInternal.find(
|
||||
... [('to_location', '=', sec_storage_loc.id)])
|
||||
>>> shipment.state
|
||||
'request'
|
||||
>>> len(shipment.moves)
|
||||
1
|
||||
>>> move, = shipment.moves
|
||||
>>> move.product.template.name
|
||||
'Product'
|
||||
>>> move.quantity
|
||||
10.0
|
||||
>>> move.from_location.name
|
||||
'Provisioning Location'
|
||||
>>> move.to_location.name
|
||||
'Second Storage'
|
||||
|
||||
Create stock_supply cron and execute it::
|
||||
|
||||
>>> Cron = Model.get('ir.cron')
|
||||
>>> shipment.delete()
|
||||
>>> cron = Cron(method='stock.order_point|supply_stock')
|
||||
>>> cron.interval_number = 1
|
||||
>>> cron.interval_type = 'months'
|
||||
>>> cron.click('run_once')
|
||||
>>> shipment, = ShipmentInternal.find(
|
||||
... [('to_location', '=', sec_storage_loc.id)])
|
||||
>>> shipment.state
|
||||
'request'
|
||||
@@ -0,0 +1,134 @@
|
||||
========================================
|
||||
Stock Internal Supply Lead Time Scenario
|
||||
========================================
|
||||
|
||||
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, assertEqual
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> tomorrow = today + dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock_supply', 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')
|
||||
>>> 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')])
|
||||
>>> lost_loc, = Location.find([('type', '=', 'lost_found')])
|
||||
|
||||
Create second warehouse::
|
||||
|
||||
>>> sec_warehouse_loc, = warehouse_loc.duplicate()
|
||||
|
||||
Add lead time between warehouses::
|
||||
|
||||
>>> LeadTime = Model.get('stock.location.lead_time')
|
||||
>>> lead_time = LeadTime()
|
||||
>>> lead_time.warehouse_from = warehouse_loc
|
||||
>>> lead_time.warehouse_to = sec_warehouse_loc
|
||||
>>> lead_time.lead_time = dt.timedelta(1)
|
||||
>>> lead_time.save()
|
||||
|
||||
Create internal order point::
|
||||
|
||||
>>> OrderPoint = Model.get('stock.order_point')
|
||||
>>> order_point = OrderPoint()
|
||||
>>> order_point.product = product
|
||||
>>> order_point.location = sec_warehouse_loc.storage_location
|
||||
>>> order_point.provisioning_location = warehouse_loc.storage_location
|
||||
>>> order_point.type = 'internal'
|
||||
>>> order_point.min_quantity = 10
|
||||
>>> order_point.target_quantity = 15
|
||||
>>> order_point.save()
|
||||
|
||||
Create inventory to add enough quantity in first warehouse::
|
||||
|
||||
>>> Inventory = Model.get('stock.inventory')
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = warehouse_loc.storage_location
|
||||
>>> inventory_line = inventory.lines.new(product=product)
|
||||
>>> inventory_line.quantity = 100.0
|
||||
>>> inventory_line.expected_quantity = 0.0
|
||||
>>> inventory.click('confirm')
|
||||
>>> inventory.state
|
||||
'done'
|
||||
|
||||
Create needs for tomorrow in second warehouse::
|
||||
|
||||
>>> ShipmentOut = Model.get('stock.shipment.out')
|
||||
>>> shipment = ShipmentOut()
|
||||
>>> shipment.planned_date = tomorrow
|
||||
>>> shipment.customer = customer
|
||||
>>> shipment.warehouse = sec_warehouse_loc
|
||||
>>> move = shipment.outgoing_moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 10
|
||||
>>> move.from_location = sec_warehouse_loc.output_location
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.unit_price = Decimal('20')
|
||||
>>> move.currency = get_currency()
|
||||
>>> shipment.click('wait')
|
||||
>>> shipment.state
|
||||
'waiting'
|
||||
|
||||
Execute internal supply::
|
||||
|
||||
>>> ShipmentInternal = Model.get('stock.shipment.internal')
|
||||
>>> Wizard('stock.supply').execute('create_')
|
||||
>>> shipments = ShipmentInternal.find([], order=[('planned_date', 'ASC')])
|
||||
>>> len(shipments)
|
||||
2
|
||||
>>> first, second = shipments
|
||||
|
||||
>>> assertEqual(first.planned_date, today)
|
||||
>>> first.state
|
||||
'request'
|
||||
>>> len(first.moves)
|
||||
1
|
||||
>>> move, = first.moves
|
||||
>>> assertEqual(move.from_location, warehouse_loc.storage_location)
|
||||
>>> assertEqual(move.to_location, sec_warehouse_loc.storage_location)
|
||||
>>> move.quantity
|
||||
15.0
|
||||
|
||||
>>> assertEqual(second.planned_date, tomorrow)
|
||||
>>> second.state
|
||||
'request'
|
||||
>>> len(second.moves)
|
||||
1
|
||||
>>> move, = second.moves
|
||||
>>> assertEqual(move.from_location, warehouse_loc.storage_location)
|
||||
>>> assertEqual(move.to_location, sec_warehouse_loc.storage_location)
|
||||
>>> move.quantity
|
||||
10.0
|
||||
@@ -0,0 +1,131 @@
|
||||
====================================================
|
||||
Stock supply scenario: Internal supply with overflow
|
||||
====================================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Wizard
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock_supply', create_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')])
|
||||
>>> output_loc, = Location.find([('code', '=', 'OUT')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> lost_loc, = Location.find([('type', '=', 'lost_found')])
|
||||
|
||||
Using order point to control the overflow
|
||||
-----------------------------------------
|
||||
|
||||
Create the overflow location::
|
||||
|
||||
>>> overflow_loc = Location()
|
||||
>>> overflow_loc.name = 'Overflow Location'
|
||||
>>> overflow_loc.type = 'storage'
|
||||
>>> overflow_loc.parent = warehouse_loc
|
||||
>>> overflow_loc.save()
|
||||
|
||||
Create the overflowed location::
|
||||
|
||||
>>> overflowed_storage_loc = Location()
|
||||
>>> overflowed_storage_loc.name = 'Overflowed Location'
|
||||
>>> overflowed_storage_loc.type = 'storage'
|
||||
>>> overflowed_storage_loc.parent = warehouse_loc
|
||||
>>> overflowed_storage_loc.save()
|
||||
|
||||
Create an internal order point::
|
||||
|
||||
>>> OrderPoint = Model.get('stock.order_point')
|
||||
>>> overflow_order_point = OrderPoint()
|
||||
>>> overflow_order_point.product = product
|
||||
>>> overflow_order_point.location = overflowed_storage_loc
|
||||
>>> overflow_order_point.overflowing_location = overflow_loc
|
||||
>>> overflow_order_point.type = 'internal'
|
||||
>>> overflow_order_point.max_quantity = 80
|
||||
>>> overflow_order_point.target_quantity = 60
|
||||
>>> overflow_order_point.save()
|
||||
|
||||
Put too much quantity in the overflowed location::
|
||||
|
||||
>>> Move = Model.get('stock.move')
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 100
|
||||
>>> move.from_location = lost_loc
|
||||
>>> move.to_location = overflowed_storage_loc
|
||||
>>> move.click('do')
|
||||
|
||||
Execute internal supply::
|
||||
|
||||
>>> ShipmentInternal = Model.get('stock.shipment.internal')
|
||||
>>> Wizard('stock.supply').execute('create_')
|
||||
>>> shipment, = ShipmentInternal.find([
|
||||
... ('to_location', '=', overflow_loc.id),
|
||||
... ])
|
||||
>>> shipment.state
|
||||
'request'
|
||||
>>> move, = shipment.moves
|
||||
>>> assertEqual(move.product, product)
|
||||
>>> move.quantity
|
||||
40.0
|
||||
>>> assertEqual(move.from_location, overflowed_storage_loc)
|
||||
>>> assertEqual(move.to_location, overflow_loc)
|
||||
|
||||
Using an overflow location
|
||||
--------------------------
|
||||
|
||||
Create the overflowed location::
|
||||
|
||||
>>> sec_overflowed_storage_loc = Location()
|
||||
>>> sec_overflowed_storage_loc.name = 'Second Overflowed Location'
|
||||
>>> sec_overflowed_storage_loc.type = 'storage'
|
||||
>>> sec_overflowed_storage_loc.parent = warehouse_loc
|
||||
>>> sec_overflowed_storage_loc.overflowing_location = overflow_loc
|
||||
>>> sec_overflowed_storage_loc.save()
|
||||
|
||||
Create positive quantity in this location::
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 10
|
||||
>>> move.from_location = lost_loc
|
||||
>>> move.to_location = sec_overflowed_storage_loc
|
||||
>>> move.click('do')
|
||||
|
||||
Execute internal supply::
|
||||
|
||||
>>> Wizard('stock.supply').execute('create_')
|
||||
>>> shipment, = ShipmentInternal.find(
|
||||
... [('from_location', '=', sec_overflowed_storage_loc.id)])
|
||||
>>> shipment.state
|
||||
'request'
|
||||
>>> move, = shipment.moves
|
||||
>>> assertEqual(move.product, product)
|
||||
>>> move.quantity
|
||||
10.0
|
||||
>>> assertEqual(move.from_location, sec_overflowed_storage_loc)
|
||||
>>> assertEqual(move.to_location, overflow_loc)
|
||||
@@ -0,0 +1,182 @@
|
||||
=========================
|
||||
Purchase Request Scenario
|
||||
=========================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Wizard
|
||||
>>> from trytond.modules.account.tests.tools import create_chart, get_accounts
|
||||
>>> 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_supply', create_company, create_chart)
|
||||
|
||||
Get accounts::
|
||||
|
||||
>>> accounts = get_accounts()
|
||||
>>> expense = accounts['expense']
|
||||
|
||||
Create parties::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> customer = Party(name='Customer')
|
||||
>>> customer.save()
|
||||
>>> supplier = Party(name='Supplier')
|
||||
>>> supplier.save()
|
||||
|
||||
Configure supply period::
|
||||
|
||||
>>> PurchaseConfig = Model.get('purchase.configuration')
|
||||
>>> purchase_config = PurchaseConfig(1)
|
||||
>>> purchase_config.supply_period = dt.timedelta(days=30)
|
||||
>>> purchase_config.save()
|
||||
|
||||
Create account category::
|
||||
|
||||
>>> ProductCategory = Model.get('product.category')
|
||||
>>> account_category = ProductCategory(name="Account Category")
|
||||
>>> account_category.accounting = True
|
||||
>>> account_category.account_expense = expense
|
||||
>>> account_category.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.purchasable = True
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Define a product supplier::
|
||||
|
||||
>>> ProductSupplier = Model.get('purchase.product_supplier')
|
||||
>>> product_supplier = ProductSupplier(template=template)
|
||||
>>> product_supplier.party = supplier
|
||||
>>> product_supplier.lead_time = dt.timedelta(days=1)
|
||||
>>> product_supplier.save()
|
||||
|
||||
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 needs for missing product::
|
||||
|
||||
>>> ShipmentOut = Model.get('stock.shipment.out')
|
||||
>>> shipment_out = ShipmentOut()
|
||||
>>> shipment_out.planned_date = today
|
||||
>>> shipment_out.effective_date = today
|
||||
>>> 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 = get_currency()
|
||||
>>> shipment_out.click('wait')
|
||||
|
||||
>>> shipment_out, = shipment_out.duplicate(
|
||||
... default={'planned_date': today + dt.timedelta(days=10)})
|
||||
>>> shipment_out.click('wait')
|
||||
|
||||
There is no purchase request::
|
||||
|
||||
>>> PurchaseRequest = Model.get('purchase.request')
|
||||
>>> PurchaseRequest.find([])
|
||||
[]
|
||||
|
||||
Create the purchase request::
|
||||
|
||||
>>> create_pr = Wizard('stock.supply')
|
||||
>>> create_pr.execute('create_')
|
||||
|
||||
There is now a draft purchase request::
|
||||
|
||||
>>> pr, = PurchaseRequest.find([('state', '=', 'draft')])
|
||||
>>> assertEqual(pr.product, product)
|
||||
>>> pr.quantity
|
||||
2.0
|
||||
|
||||
Create an order point with negative minimal quantity::
|
||||
|
||||
>>> OrderPoint = Model.get('stock.order_point')
|
||||
>>> order_point = OrderPoint()
|
||||
>>> order_point.type = 'purchase'
|
||||
>>> order_point.product = product
|
||||
>>> order_point.location = warehouse_loc
|
||||
>>> order_point.min_quantity = -2
|
||||
>>> order_point.target_quantity = 10
|
||||
>>> order_point.save()
|
||||
|
||||
Create purchase request::
|
||||
|
||||
>>> create_pr = Wizard('stock.supply')
|
||||
>>> create_pr.execute('create_')
|
||||
|
||||
There is no more purchase request::
|
||||
|
||||
>>> PurchaseRequest.find([])
|
||||
[]
|
||||
|
||||
Set a positive minimal quantity on order point create purchase request::
|
||||
|
||||
>>> order_point.min_quantity = 5
|
||||
>>> order_point.save()
|
||||
>>> create_pr = Wizard('stock.supply')
|
||||
>>> create_pr.execute('create_')
|
||||
|
||||
There is now a draft purchase request::
|
||||
|
||||
>>> pr, = PurchaseRequest.find([('state', '=', 'draft')])
|
||||
>>> assertEqual(pr.product, product)
|
||||
>>> pr.quantity
|
||||
12.0
|
||||
|
||||
Using zero as minimal quantity on order point also creates purchase request::
|
||||
|
||||
>>> order_point.min_quantity = 0
|
||||
>>> order_point.save()
|
||||
>>> create_pr = Wizard('stock.supply')
|
||||
>>> create_pr.execute('create_')
|
||||
|
||||
There is now a draft purchase request::
|
||||
|
||||
>>> pr, = PurchaseRequest.find([('state', '=', 'draft')])
|
||||
>>> assertEqual(pr.product, product)
|
||||
>>> pr.quantity
|
||||
12.0
|
||||
|
||||
Re-run with purchased request::
|
||||
|
||||
>>> create_purchase = Wizard('purchase.request.create_purchase', [pr])
|
||||
>>> pr.state
|
||||
'purchased'
|
||||
|
||||
>>> create_pr = Wizard('stock.supply')
|
||||
>>> create_pr.execute('create_')
|
||||
|
||||
>>> len(PurchaseRequest.find([('state', '=', 'draft')]))
|
||||
0
|
||||
164
modules/stock_supply/tests/test_module.py
Normal file
164
modules/stock_supply/tests/test_module.py
Normal file
@@ -0,0 +1,164 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
import datetime
|
||||
|
||||
from trytond.modules.account.tests import create_chart
|
||||
from trytond.modules.company.tests import (
|
||||
CompanyTestMixin, create_company, set_company)
|
||||
from trytond.pool import Pool
|
||||
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
|
||||
|
||||
DATES = [
|
||||
# purchase date, lead time, supply date
|
||||
(datetime.date(2011, 11, 21), datetime.timedelta(10),
|
||||
datetime.date(2011, 12, 1)),
|
||||
(datetime.date(2011, 11, 21), datetime.timedelta(9),
|
||||
datetime.date(2011, 11, 30)),
|
||||
(datetime.date(2011, 11, 21), datetime.timedelta(8),
|
||||
datetime.date(2011, 11, 29)),
|
||||
(datetime.date(2011, 11, 21), datetime.timedelta(7),
|
||||
datetime.date(2011, 11, 28)),
|
||||
(datetime.date(2011, 11, 21), datetime.timedelta(6),
|
||||
datetime.date(2011, 11, 27)),
|
||||
(datetime.date(2011, 11, 21), datetime.timedelta(5),
|
||||
datetime.date(2011, 11, 26)),
|
||||
(datetime.date(2011, 11, 21), datetime.timedelta(4),
|
||||
datetime.date(2011, 11, 25)),
|
||||
]
|
||||
|
||||
|
||||
class StockSupplyTestCase(CompanyTestMixin, ModuleTestCase):
|
||||
'Test StockSupply module'
|
||||
module = 'stock_supply'
|
||||
|
||||
def test_compute_supply_date(self):
|
||||
'Test compute_supply_date'
|
||||
@with_transaction()
|
||||
def run(purchase_date, lead_time, supply_date):
|
||||
pool = Pool()
|
||||
ProductSupplier = pool.get('purchase.product_supplier')
|
||||
product_supplier = self.create_product_supplier(lead_time)
|
||||
date = ProductSupplier.compute_supply_date(
|
||||
product_supplier, purchase_date)
|
||||
self.assertEqual(date, supply_date)
|
||||
for purchase_date, lead_time, supply_date in DATES:
|
||||
run(purchase_date, lead_time, supply_date)
|
||||
|
||||
def test_compute_purchase_date(self):
|
||||
'Test compute_purchase_date'
|
||||
@with_transaction()
|
||||
def run(purchase_date, lead_time, supply_date):
|
||||
pool = Pool()
|
||||
ProductSupplier = pool.get('purchase.product_supplier')
|
||||
product_supplier = self.create_product_supplier(lead_time)
|
||||
date = ProductSupplier.compute_purchase_date(
|
||||
product_supplier, supply_date)
|
||||
self.assertEqual(date, purchase_date)
|
||||
for purchase_date, lead_time, supply_date in DATES:
|
||||
run(purchase_date, lead_time, supply_date)
|
||||
|
||||
def create_product_supplier(self, lead_time):
|
||||
'''
|
||||
Create a Product with a Product Supplier
|
||||
|
||||
:param lead_time: timedelta needed to supply
|
||||
:return: the id of the Product Supplier
|
||||
'''
|
||||
pool = Pool()
|
||||
Uom = pool.get('product.uom')
|
||||
UomCategory = pool.get('product.uom.category')
|
||||
Template = pool.get('product.template')
|
||||
Product = pool.get('product.product')
|
||||
Party = pool.get('party.party')
|
||||
Account = pool.get('account.account')
|
||||
ProductSupplier = pool.get('purchase.product_supplier')
|
||||
|
||||
uom_category, = UomCategory.create([{'name': 'Test'}])
|
||||
uom, = Uom.create([{
|
||||
'name': 'Test',
|
||||
'symbol': 'T',
|
||||
'category': uom_category.id,
|
||||
'rate': 1.0,
|
||||
'factor': 1.0,
|
||||
}])
|
||||
template, = Template.create([{
|
||||
'name': 'ProductTest',
|
||||
'default_uom': uom.id,
|
||||
}])
|
||||
product, = Product.create([{
|
||||
'template': template.id,
|
||||
}])
|
||||
company = create_company()
|
||||
with set_company(company):
|
||||
create_chart(company)
|
||||
receivable, = Account.search([
|
||||
('closed', '!=', True),
|
||||
('type.receivable', '=', True),
|
||||
('party_required', '=', True),
|
||||
('company', '=', company.id),
|
||||
], limit=1)
|
||||
payable, = Account.search([
|
||||
('closed', '!=', True),
|
||||
('type.payable', '=', True),
|
||||
('party_required', '=', True),
|
||||
('company', '=', company.id),
|
||||
], limit=1)
|
||||
supplier, = Party.create([{
|
||||
'name': 'supplier',
|
||||
'account_receivable': receivable.id,
|
||||
'account_payable': payable.id,
|
||||
}])
|
||||
product_supplier, = ProductSupplier.create([{
|
||||
'template': template.id,
|
||||
'company': company.id,
|
||||
'party': supplier.id,
|
||||
'lead_time': lead_time,
|
||||
}])
|
||||
return product_supplier
|
||||
|
||||
@with_transaction()
|
||||
def test_order_point_location_searcher(self):
|
||||
pool = Pool()
|
||||
Uom = pool.get('product.uom')
|
||||
Template = pool.get('product.template')
|
||||
Product = pool.get('product.product')
|
||||
Location = pool.get('stock.location')
|
||||
OrderPoint = pool.get('stock.order_point')
|
||||
unit, = Uom.search([('symbol', '=', 'u')])
|
||||
template, = Template.create([{
|
||||
'name': 'ProductTest',
|
||||
'type': 'goods',
|
||||
'default_uom': unit.id,
|
||||
'purchase_uom': unit.id,
|
||||
'purchasable': True,
|
||||
}])
|
||||
product, = Product.create([{
|
||||
'template': template.id,
|
||||
}])
|
||||
|
||||
warehouse, = Location.search([('type', '=', 'warehouse')])
|
||||
storage, = Location.search([('code', '=', 'STO')])
|
||||
|
||||
company = create_company()
|
||||
with set_company(company):
|
||||
order_point, = OrderPoint.create([{
|
||||
'product': product.id,
|
||||
'type': 'purchase',
|
||||
'location': warehouse.id,
|
||||
'min_quantity': 0.0,
|
||||
'target_quantity': 5.0,
|
||||
}])
|
||||
|
||||
for clause, result in [
|
||||
(('location.rec_name', '=', warehouse.name),
|
||||
[order_point]),
|
||||
(('location.type', '=', 'storage'), []),
|
||||
(('location.rec_name', '!=', warehouse.name), []),
|
||||
(('location.type', '!=', 'storage'), [order_point]),
|
||||
]:
|
||||
self.assertListEqual(
|
||||
OrderPoint.search(clause), result, msg=clause)
|
||||
|
||||
|
||||
del ModuleTestCase
|
||||
8
modules/stock_supply/tests/test_scenario.py
Normal file
8
modules/stock_supply/tests/test_scenario.py
Normal 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