first commit
This commit is contained in:
2
modules/product_kit/tests/__init__.py
Normal file
2
modules/product_kit/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/product_kit/tests/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
modules/product_kit/tests/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
155
modules/product_kit/tests/scenario_product_kit.rst
Normal file
155
modules/product_kit/tests/scenario_product_kit.rst
Normal file
@@ -0,0 +1,155 @@
|
||||
====================
|
||||
Product Kit Scenario
|
||||
====================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
Activate product_kit and stock::
|
||||
|
||||
>>> config = activate_modules(['product_kit', 'stock'], create_company)
|
||||
|
||||
Get company::
|
||||
|
||||
>>> company = get_company()
|
||||
|
||||
Create products::
|
||||
|
||||
>>> Uom = Model.get('product.uom')
|
||||
>>> unit, = Uom.find([('name', '=', 'Unit')])
|
||||
>>> meter, = Uom.find([('name', '=', "Meter")])
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> Product = Model.get('product.product')
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product 1"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.save()
|
||||
>>> product1, = template.products
|
||||
>>> product1.cost_price = Decimal('10.0000')
|
||||
>>> product1.save()
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product 2"
|
||||
>>> template.default_uom = meter
|
||||
>>> template.type = 'goods'
|
||||
>>> template.save()
|
||||
>>> product2, = template.products
|
||||
>>> product2.cost_price = Decimal('20.0000')
|
||||
>>> product2.save()
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product 3"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.save()
|
||||
>>> product3, = template.products
|
||||
>>> product3.cost_price = Decimal('1.0000')
|
||||
>>> product3.save()
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Service"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'service'
|
||||
>>> template.save()
|
||||
>>> service, = template.products
|
||||
>>> service.cost_price = Decimal('5.0000')
|
||||
>>> service.save()
|
||||
|
||||
Create composed product::
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Composed Product"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.save()
|
||||
>>> composed_product, = template.products
|
||||
>>> composed_product.cost_price = Decimal('10.0000')
|
||||
|
||||
>>> component = composed_product.components.new()
|
||||
>>> component.product = product1
|
||||
>>> component.quantity = 2
|
||||
>>> component = composed_product.components.new()
|
||||
>>> component.product = service
|
||||
>>> component.quantity = 1
|
||||
>>> composed_product.save()
|
||||
|
||||
>>> composed_product.cost_price
|
||||
Decimal('10.0000')
|
||||
|
||||
Create a kit::
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Kit"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'kit'
|
||||
>>> template.save()
|
||||
>>> kit, = template.products
|
||||
|
||||
>>> component = template.components.new()
|
||||
>>> component.product = product1
|
||||
>>> component.quantity = 1
|
||||
>>> component = template.components.new()
|
||||
>>> component.product = product2
|
||||
>>> component.quantity = 2
|
||||
>>> component = template.components.new()
|
||||
>>> component.product = product3
|
||||
>>> component.quantity = 1
|
||||
>>> component.fixed = True
|
||||
>>> template.save()
|
||||
|
||||
>>> kit.cost_price
|
||||
Decimal('51.0000')
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
|
||||
Fill stock with some components::
|
||||
|
||||
>>> StockMove = Model.get('stock.move')
|
||||
>>> moves = []
|
||||
|
||||
>>> move = StockMove()
|
||||
>>> move.product = product1
|
||||
>>> move.quantity = 10
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.unit_price = Decimal('10')
|
||||
>>> move.currency = company.currency
|
||||
>>> moves.append(move)
|
||||
|
||||
>>> move = StockMove()
|
||||
>>> move.product = product2
|
||||
>>> move.quantity = 15
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.unit_price = Decimal('20')
|
||||
>>> move.currency = company.currency
|
||||
>>> moves.append(move)
|
||||
|
||||
>>> move = StockMove()
|
||||
>>> move.product = product3
|
||||
>>> move.quantity = 20
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.unit_price = Decimal('1')
|
||||
>>> move.currency = company.currency
|
||||
>>> moves.append(move)
|
||||
|
||||
>>> StockMove.click(moves, 'do')
|
||||
|
||||
Check kit quantity::
|
||||
|
||||
>>> with config.set_context(locations=[storage_loc.id]):
|
||||
... kit = Product(kit.id)
|
||||
>>> kit.quantity
|
||||
7.0
|
||||
82
modules/product_kit/tests/scenario_product_kit_duplicate.rst
Normal file
82
modules/product_kit/tests/scenario_product_kit_duplicate.rst
Normal file
@@ -0,0 +1,82 @@
|
||||
==============================
|
||||
Product Kit Duplicate 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 product_kit::
|
||||
|
||||
>>> config = activate_modules('product_kit', create_company)
|
||||
|
||||
>>> Uom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> Product = Model.get('product.product')
|
||||
|
||||
Create products::
|
||||
|
||||
>>> unit, = Uom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product 1"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.save()
|
||||
>>> product1, = template.products
|
||||
>>> product1.cost_price = Decimal('10.0000')
|
||||
>>> product1.save()
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product 2"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.save()
|
||||
>>> product2, = template.products
|
||||
>>> product2.cost_price = Decimal('20.0000')
|
||||
>>> product2.save()
|
||||
|
||||
Create composed product::
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Composed Product"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.save()
|
||||
>>> composed_product, = template.products
|
||||
>>> composed_product.cost_price = Decimal('10.0000')
|
||||
|
||||
>>> component = composed_product.components.new()
|
||||
>>> component.product = product1
|
||||
>>> component.quantity = 2
|
||||
>>> composed_product.save()
|
||||
|
||||
Create a kit::
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Kit"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'kit'
|
||||
>>> template.save()
|
||||
>>> kit, = template.products
|
||||
|
||||
>>> component = template.components.new()
|
||||
>>> component.product = product1
|
||||
>>> component.quantity = 1
|
||||
>>> component = template.components.new()
|
||||
>>> component.product = product2
|
||||
>>> component.parent_product = kit
|
||||
>>> component.quantity = 2
|
||||
>>> template.save()
|
||||
|
||||
Test duplicate copies components::
|
||||
|
||||
>>> duplicated, = template.duplicate()
|
||||
>>> len(duplicated.components)
|
||||
2
|
||||
>>> duplicated_product, = composed_product.duplicate()
|
||||
>>> len(duplicated_product.components)
|
||||
1
|
||||
287
modules/product_kit/tests/scenario_product_kit_purchase.rst
Normal file
287
modules/product_kit/tests/scenario_product_kit_purchase.rst
Normal file
@@ -0,0 +1,287 @@
|
||||
=============================
|
||||
Purchase Product Kit Scenario
|
||||
=============================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.account.tests.tools import (
|
||||
... create_chart, create_fiscalyear, get_accounts)
|
||||
>>> from trytond.modules.account_invoice.tests.tools import (
|
||||
... set_fiscalyear_invoice_sequences)
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
>>> today = dt.date.today()
|
||||
|
||||
Activate product_kit, purchase and account_invoice::
|
||||
|
||||
>>> config = activate_modules(
|
||||
... ['product_kit', 'purchase', 'account_invoice',
|
||||
... 'account_invoice_stock'],
|
||||
... create_company, create_chart)
|
||||
|
||||
Create fiscal year::
|
||||
|
||||
>>> fiscalyear = set_fiscalyear_invoice_sequences(
|
||||
... create_fiscalyear(today=today))
|
||||
>>> fiscalyear.click('create_period')
|
||||
|
||||
Get accounts::
|
||||
|
||||
>>> accounts = get_accounts()
|
||||
|
||||
Create party::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> supplier = Party(name="Supplier")
|
||||
>>> supplier.save()
|
||||
|
||||
Create account categories::
|
||||
|
||||
>>> ProductCategory = Model.get('product.category')
|
||||
>>> account_category = ProductCategory(name="Account Category")
|
||||
>>> account_category.accounting = True
|
||||
>>> account_category.account_expense = accounts['expense']
|
||||
>>> account_category.account_revenue = accounts['revenue']
|
||||
>>> account_category.save()
|
||||
|
||||
Create products::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> meter, = ProductUom.find([('name', '=', "Meter")])
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product 1"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.purchasable = True
|
||||
>>> template.list_price = Decimal('10')
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> product1, = template.products
|
||||
>>> product1.cost_price = Decimal('5')
|
||||
>>> product1.save()
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product 2"
|
||||
>>> template.default_uom = meter
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> product2, = template.products
|
||||
>>> product2.cost_price = Decimal('8')
|
||||
>>> product2.save()
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product 3"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('30')
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> product3, = template.products
|
||||
>>> product3.cost_price = Decimal('10')
|
||||
>>> product3.save()
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Service"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'service'
|
||||
>>> template.purchasable = True
|
||||
>>> template.list_price = Decimal('30')
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> service, = template.products
|
||||
>>> service.cost_price = Decimal('20')
|
||||
>>> service.save()
|
||||
|
||||
Create composed product::
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Composed Product"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.purchasable = True
|
||||
>>> template.list_price = Decimal('10')
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> composed_product, = template.products
|
||||
>>> composed_product.cost_price = Decimal('5')
|
||||
|
||||
>>> component = composed_product.components.new()
|
||||
>>> component.product = product1
|
||||
>>> component.quantity = 1
|
||||
>>> component = composed_product.components.new()
|
||||
>>> component.product = service
|
||||
>>> component.quantity = 2
|
||||
>>> component.fixed = True
|
||||
>>> composed_product.save()
|
||||
|
||||
Create kit product::
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Kit"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'kit'
|
||||
>>> template.purchasable = True
|
||||
>>> template.list_price = Decimal('40')
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> kit, = template.products
|
||||
|
||||
>>> component = kit.components.new()
|
||||
>>> component.product = product2
|
||||
>>> component.quantity = 2
|
||||
>>> component = kit.components.new()
|
||||
>>> component.product = product3
|
||||
>>> component.quantity = 1
|
||||
>>> component.fixed = True
|
||||
>>> kit.save()
|
||||
|
||||
Purchase composed and kit products::
|
||||
|
||||
>>> Purchase = Model.get('purchase.purchase')
|
||||
>>> purchase = Purchase()
|
||||
>>> purchase.party = supplier
|
||||
>>> purchase.invoice_method = 'shipment'
|
||||
>>> line = purchase.lines.new()
|
||||
>>> line.product = composed_product
|
||||
>>> line.quantity = 1
|
||||
>>> line.unit_price = Decimal('5.0000')
|
||||
>>> line = purchase.lines.new()
|
||||
>>> line.product = kit
|
||||
>>> line.quantity = 2
|
||||
>>> line.unit_price = Decimal('26.0000')
|
||||
>>> purchase.click('quote')
|
||||
>>> len(purchase.lines)
|
||||
4
|
||||
>>> [l.quantity for l in purchase.lines]
|
||||
[1.0, 1.0, 2.0, 2.0]
|
||||
>>> line_kit, = [l for l in purchase.lines if l.product == kit]
|
||||
>>> [c.quantity for c in line_kit.components]
|
||||
[4.0, 1.0]
|
||||
|
||||
Reset to draft remove components::
|
||||
|
||||
>>> purchase.click('draft')
|
||||
>>> line_kit, = [l for l in purchase.lines if l.product == kit]
|
||||
>>> bool(line_kit.components)
|
||||
False
|
||||
>>> purchase.click('quote')
|
||||
|
||||
Process purchase::
|
||||
|
||||
>>> purchase.click('confirm')
|
||||
>>> purchase.state
|
||||
'processing'
|
||||
>>> len(purchase.shipments), len(purchase.invoices)
|
||||
(0, 1)
|
||||
|
||||
Check invoice::
|
||||
|
||||
>>> invoice, = purchase.invoices
|
||||
>>> line, = invoice.lines
|
||||
>>> assertEqual(line.product, service)
|
||||
|
||||
Check stock moves::
|
||||
|
||||
>>> Move = Model.get('stock.move')
|
||||
>>> len(purchase.moves)
|
||||
4
|
||||
>>> len(Move.find([('purchase', '!=', None)]))
|
||||
4
|
||||
>>> len(Move.find([('purchase', '!=', purchase.id)]))
|
||||
0
|
||||
>>> len(Move.find([('purchase', '=', purchase.id)]))
|
||||
4
|
||||
>>> product2quantity = {
|
||||
... m.product: m.quantity for m in purchase.moves}
|
||||
>>> product2quantity[composed_product]
|
||||
1.0
|
||||
>>> product2quantity[product1]
|
||||
1.0
|
||||
>>> product2quantity[product2]
|
||||
4.0
|
||||
>>> product2quantity[product3]
|
||||
1.0
|
||||
|
||||
Receive partial shipment::
|
||||
|
||||
>>> ShipmentIn = Model.get('stock.shipment.in')
|
||||
>>> shipment = ShipmentIn()
|
||||
>>> shipment.supplier = supplier
|
||||
>>> for move in purchase.moves:
|
||||
... incoming_move = Move(move.id)
|
||||
... shipment.incoming_moves.append(incoming_move)
|
||||
>>> shipment.save()
|
||||
|
||||
>>> product2move = {
|
||||
... m.product: m for m in shipment.incoming_moves}
|
||||
>>> product2move[product2].quantity = 2.0
|
||||
>>> shipment.click('receive')
|
||||
>>> shipment.click('do')
|
||||
>>> shipment.state
|
||||
'done'
|
||||
|
||||
Check new invoice::
|
||||
|
||||
>>> purchase.reload()
|
||||
>>> _, invoice = purchase.invoices
|
||||
>>> len(invoice.lines)
|
||||
3
|
||||
>>> product2quantity = {l.product: l.quantity for l in invoice.lines}
|
||||
>>> product2quantity[composed_product]
|
||||
1.0
|
||||
>>> product2quantity[product1]
|
||||
1.0
|
||||
>>> product2quantity[kit]
|
||||
1.0
|
||||
|
||||
Post invoice::
|
||||
|
||||
>>> invoice.invoice_date = today
|
||||
>>> invoice.click('post')
|
||||
>>> invoice.state
|
||||
'posted'
|
||||
|
||||
Check unit price of moves::
|
||||
|
||||
>>> shipment.reload()
|
||||
>>> invoice.reload()
|
||||
>>> sorted([m.unit_price for m in shipment.incoming_moves])
|
||||
[Decimal('0.0000'), Decimal('5.0000'), Decimal('9.4545'), Decimal('14.1818')]
|
||||
|
||||
Check backorder moves::
|
||||
|
||||
>>> len(purchase.moves)
|
||||
5
|
||||
>>> backorder, = [m for m in purchase.moves if m.state == 'draft']
|
||||
|
||||
Cancel backorder::
|
||||
|
||||
>>> backorder.click('cancel')
|
||||
>>> backorder.state
|
||||
'cancelled'
|
||||
>>> purchase.reload()
|
||||
>>> purchase.shipment_state
|
||||
'exception'
|
||||
|
||||
Handle shipment exception::
|
||||
|
||||
>>> shipment_exception = purchase.click('handle_shipment_exception')
|
||||
>>> shipment_exception.form.recreate_moves.extend(
|
||||
... shipment_exception.form.recreate_moves.find())
|
||||
>>> shipment_exception.execute('handle')
|
||||
|
||||
>>> len(purchase.moves)
|
||||
6
|
||||
>>> backorder.reload()
|
||||
>>> backorder.purchase_exception_state
|
||||
'recreated'
|
||||
280
modules/product_kit/tests/scenario_product_kit_sale.rst
Normal file
280
modules/product_kit/tests/scenario_product_kit_sale.rst
Normal file
@@ -0,0 +1,280 @@
|
||||
=========================
|
||||
Sale Product Kit Scenario
|
||||
=========================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.account.tests.tools import (
|
||||
... create_chart, create_fiscalyear, get_accounts)
|
||||
>>> from trytond.modules.account_invoice.tests.tools import (
|
||||
... set_fiscalyear_invoice_sequences)
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
Activate product_kit, sale and account_invoice::
|
||||
|
||||
>>> config = activate_modules(
|
||||
... ['product_kit', 'sale', 'account_invoice',
|
||||
... 'account_invoice_stock'],
|
||||
... create_company, create_chart)
|
||||
|
||||
Create fiscal year::
|
||||
|
||||
>>> fiscalyear = set_fiscalyear_invoice_sequences(create_fiscalyear())
|
||||
>>> fiscalyear.click('create_period')
|
||||
|
||||
Get accounts::
|
||||
|
||||
>>> accounts = get_accounts()
|
||||
|
||||
Create party::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> customer = Party(name='Customer')
|
||||
>>> customer.save()
|
||||
|
||||
Create account categories::
|
||||
|
||||
>>> ProductCategory = Model.get('product.category')
|
||||
>>> account_category = ProductCategory(name="Account Category")
|
||||
>>> account_category.accounting = True
|
||||
>>> account_category.account_expense = accounts['expense']
|
||||
>>> account_category.account_revenue = accounts['revenue']
|
||||
>>> account_category.save()
|
||||
|
||||
Create products::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> meter, = ProductUom.find([('name', '=', "Meter")])
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product 1"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.salable = True
|
||||
>>> template.list_price = Decimal('10')
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> product1, = template.products
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product 2"
|
||||
>>> template.default_uom = meter
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> product2, = template.products
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product 3"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('30')
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> product3, = template.products
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Service"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'service'
|
||||
>>> template.salable = True
|
||||
>>> template.list_price = Decimal('30')
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> service, = template.products
|
||||
|
||||
Create composed product::
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Composed Product"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.salable = True
|
||||
>>> template.list_price = Decimal('10')
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> composed_product, = template.products
|
||||
|
||||
>>> component = composed_product.components.new()
|
||||
>>> component.product = product1
|
||||
>>> component.quantity = 2
|
||||
>>> component = composed_product.components.new()
|
||||
>>> component.product = service
|
||||
>>> component.quantity = 1
|
||||
>>> component.fixed = True
|
||||
>>> composed_product.save()
|
||||
|
||||
Create kit product::
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Kit"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'kit'
|
||||
>>> template.salable = True
|
||||
>>> template.list_price = Decimal('40')
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> kit, = template.products
|
||||
|
||||
>>> component = kit.components.new()
|
||||
>>> component.product = product2
|
||||
>>> component.quantity = 1
|
||||
>>> component = kit.components.new()
|
||||
>>> component.product = product3
|
||||
>>> component.quantity = 2
|
||||
>>> component.fixed = True
|
||||
>>> kit.save()
|
||||
|
||||
Sale composed and kit products::
|
||||
|
||||
>>> Sale = Model.get('sale.sale')
|
||||
>>> sale = Sale()
|
||||
>>> sale.party = customer
|
||||
>>> sale.invoice_method = 'shipment'
|
||||
>>> line = sale.lines.new()
|
||||
>>> line.product = composed_product
|
||||
>>> line.quantity = 2
|
||||
>>> line = sale.lines.new()
|
||||
>>> line.product = kit
|
||||
>>> line.quantity = 5
|
||||
>>> sale.click('quote')
|
||||
>>> len(sale.lines)
|
||||
4
|
||||
>>> [l.quantity for l in sale.lines]
|
||||
[2.0, 4.0, 1.0, 5.0]
|
||||
>>> line_kit, = [l for l in sale.lines if l.product == kit]
|
||||
>>> [c.quantity for c in line_kit.components]
|
||||
[5.0, 2.0]
|
||||
|
||||
Reset to draft remove components::
|
||||
|
||||
>>> sale.click('draft')
|
||||
>>> line_kit, = [l for l in sale.lines if l.product == kit]
|
||||
>>> bool(line_kit.components)
|
||||
False
|
||||
>>> sale.click('quote')
|
||||
|
||||
Process sale::
|
||||
|
||||
>>> sale.click('confirm')
|
||||
>>> sale.state
|
||||
'processing'
|
||||
>>> len(sale.shipments), len(sale.invoices)
|
||||
(1, 1)
|
||||
|
||||
Check invoice::
|
||||
|
||||
>>> invoice, = sale.invoices
|
||||
>>> line, = invoice.lines
|
||||
>>> assertEqual(line.product, service)
|
||||
|
||||
Check shipment::
|
||||
|
||||
>>> Move = Model.get('stock.move')
|
||||
>>> shipment, = sale.shipments
|
||||
>>> len(shipment.outgoing_moves)
|
||||
4
|
||||
>>> len(sale.moves)
|
||||
4
|
||||
>>> len(Move.find([('sale', '!=', None)]))
|
||||
4
|
||||
>>> len(Move.find([('sale', '!=', sale.id)]))
|
||||
0
|
||||
>>> len(Move.find([('sale', '=', sale.id)]))
|
||||
4
|
||||
>>> product2quantity = {
|
||||
... m.product: m.quantity for m in shipment.outgoing_moves}
|
||||
>>> product2quantity[composed_product]
|
||||
2.0
|
||||
>>> product2quantity[product1]
|
||||
4.0
|
||||
>>> product2quantity[product2]
|
||||
5.0
|
||||
>>> product2quantity[product3]
|
||||
2.0
|
||||
|
||||
Ship partially::
|
||||
|
||||
>>> product2move = {
|
||||
... m.product: m for m in shipment.inventory_moves}
|
||||
>>> product2move[product1].quantity = 2.0
|
||||
>>> product2move[product2].quantity = 3.0
|
||||
>>> shipment.click('assign_force')
|
||||
>>> shipment.click('pick')
|
||||
>>> shipment.click('pack')
|
||||
>>> shipment.click('do')
|
||||
>>> shipment.state
|
||||
'done'
|
||||
|
||||
Check new invoice::
|
||||
|
||||
>>> sale.reload()
|
||||
>>> _, invoice = sale.invoices
|
||||
>>> len(invoice.lines)
|
||||
3
|
||||
>>> product2quantity = {l.product: l.quantity for l in invoice.lines}
|
||||
>>> product2quantity[composed_product]
|
||||
2.0
|
||||
>>> product2quantity[product1]
|
||||
2.0
|
||||
>>> product2quantity[kit]
|
||||
3.0
|
||||
|
||||
Post invoice::
|
||||
|
||||
>>> invoice.click('post')
|
||||
>>> invoice.state
|
||||
'posted'
|
||||
|
||||
Check unit price of moves::
|
||||
|
||||
>>> shipment.reload()
|
||||
>>> invoice.reload()
|
||||
>>> sorted([m.unit_price for m in shipment.outgoing_moves])
|
||||
[Decimal('10.0000'), Decimal('10.0000'), Decimal('25.0000'), Decimal('37.5000')]
|
||||
|
||||
Check backorder::
|
||||
|
||||
>>> _, backorder = sale.shipments
|
||||
>>> len(backorder.outgoing_moves)
|
||||
2
|
||||
>>> product2quantity = {
|
||||
... m.product: m.quantity for m in backorder.outgoing_moves}
|
||||
>>> product2quantity[product1]
|
||||
2.0
|
||||
>>> product2quantity[product2]
|
||||
2.0
|
||||
|
||||
Cancel backorder::
|
||||
|
||||
>>> backorder.click('cancel')
|
||||
>>> backorder.state
|
||||
'cancelled'
|
||||
>>> sale.reload()
|
||||
>>> sale.shipment_state
|
||||
'exception'
|
||||
|
||||
Handle shipment exception::
|
||||
|
||||
>>> shipment_exception = sale.click('handle_shipment_exception')
|
||||
>>> shipment_exception.form.recreate_moves.extend(
|
||||
... shipment_exception.form.recreate_moves.find(
|
||||
... [('product', '!=', product1.id)]))
|
||||
>>> shipment_exception.form.ignore_moves.extend(
|
||||
... shipment_exception.form.ignore_moves.find(
|
||||
... [('product', '=', product1.id)]))
|
||||
>>> shipment_exception.execute('handle')
|
||||
|
||||
>>> _, _, shipment = sale.shipments
|
||||
>>> len(shipment.outgoing_moves)
|
||||
1
|
||||
>>> backorder.reload()
|
||||
>>> list(sorted(m.sale_exception_state for m in backorder.outgoing_moves))
|
||||
['ignored', 'recreated']
|
||||
14
modules/product_kit/tests/test_module.py
Normal file
14
modules/product_kit/tests/test_module.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# 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.modules.company.tests import CompanyTestMixin
|
||||
from trytond.tests.test_tryton import ModuleTestCase
|
||||
|
||||
|
||||
class ProductKitTestCase(CompanyTestMixin, ModuleTestCase):
|
||||
'Test Product Kit module'
|
||||
module = 'product_kit'
|
||||
extras = ['sale', 'purchase', 'sale_amendment', 'purchase_amendment']
|
||||
|
||||
|
||||
del ModuleTestCase
|
||||
8
modules/product_kit/tests/test_scenario.py
Normal file
8
modules/product_kit/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