mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
Migrate stock_available_mrp to v12
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
{
|
{
|
||||||
'name': 'Consider the production potential is available to promise',
|
'name': 'Consider the production potential is available to promise',
|
||||||
'version': '11.0.1.0.0',
|
'version': '12.0.1.0.0',
|
||||||
"author": "Numérigraphe,"
|
"author": "Numérigraphe,"
|
||||||
"Odoo Community Association (OCA)",
|
"Odoo Community Association (OCA)",
|
||||||
'website': 'https://github.com/OCA/stock-logistics-warehouse',
|
'website': 'https://github.com/OCA/stock-logistics-warehouse',
|
||||||
|
|||||||
@@ -3,11 +3,11 @@
|
|||||||
<record id="product_kit_1a" model="product.product">
|
<record id="product_kit_1a" model="product.product">
|
||||||
<field name="default_code">PCSC234-WHITE</field>
|
<field name="default_code">PCSC234-WHITE</field>
|
||||||
<field name="product_tmpl_id"
|
<field name="product_tmpl_id"
|
||||||
ref="mrp.product_product_build_kit_product_template"/>
|
ref="mrp.product_product_table_kit_product_template"/>
|
||||||
<field name="attribute_value_ids" eval="[(6,0,[ref('product.product_attribute_value_3')])]"/>
|
<field name="attribute_value_ids" eval="[(6,0,[ref('product.product_attribute_value_3')])]"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="mrp.product_product_build_kit" model="product.product">
|
<record id="mrp.product_product_table_kit" model="product.product">
|
||||||
<field name="attribute_value_ids"
|
<field name="attribute_value_ids"
|
||||||
eval="[(6,0,[ref('product.product_attribute_value_4')])]"/>
|
eval="[(6,0,[ref('product.product_attribute_value_4')])]"/>
|
||||||
</record>
|
</record>
|
||||||
@@ -16,21 +16,21 @@
|
|||||||
<field name="attribute_value_ids" eval="[(6,0,[ref('product.product_attribute_value_4')])]"/>
|
<field name="attribute_value_ids" eval="[(6,0,[ref('product.product_attribute_value_4')])]"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="product_product_9_white" model="product.product">
|
<record id="product_computer_desk_bolt_white" model="product.product">
|
||||||
<field name="name">Apple Wireless Keyboard</field>
|
<field name="name">Bolt</field>
|
||||||
<field name="categ_id" ref="product.product_category_5"/>
|
<field name="categ_id" ref="product.product_category_5"/>
|
||||||
<field name="standard_price">10.0</field>
|
<field name="standard_price">1.0</field>
|
||||||
<field name="list_price">47.0</field>
|
<field name="list_price">5.0</field>
|
||||||
<field name="type">product</field>
|
<field name="type">product</field>
|
||||||
<field name="uom_id" ref="product.product_uom_unit"/>
|
<field name="uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="uom_po_id" ref="product.product_uom_unit"/>
|
<field name="uom_po_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="default_code">E-COM10-WHITE</field>
|
<field name="default_code">BOLT-WHITE</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="mrp_bom_kit_line_3" model="mrp.bom.line">
|
<record id="mrp_bom_kit_line_3" model="mrp.bom.line">
|
||||||
<field name="product_id" ref="product_product_9_white"/>
|
<field name="product_id" ref="product_computer_desk_bolt_white"/>
|
||||||
<field name="product_qty">1</field>
|
<field name="product_qty">4</field>
|
||||||
<field name="product_uom_id" ref="product.product_uom_unit"/>
|
<field name="product_uom_id" ref="uom.product_uom_unit"/>
|
||||||
<field name="sequence">5</field>
|
<field name="sequence">5</field>
|
||||||
<field name="bom_id" ref="mrp.mrp_bom_kit"/>
|
<field name="bom_id" ref="mrp.mrp_bom_kit"/>
|
||||||
<field name="attribute_value_ids" eval="[(6,0,[ref('product.product_attribute_value_3')])]"/>
|
<field name="attribute_value_ids" eval="[(6,0,[ref('product.product_attribute_value_3')])]"/>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class ProductProduct(models.Model):
|
|||||||
bom_id = fields.Many2one(
|
bom_id = fields.Many2one(
|
||||||
'mrp.bom',
|
'mrp.bom',
|
||||||
compute='_compute_bom_id',
|
compute='_compute_bom_id',
|
||||||
string='Bill of Materials'
|
string='BOM'
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.depends('virtual_available', 'bom_id', 'bom_id.product_qty')
|
@api.depends('virtual_available', 'bom_id', 'bom_id.product_qty')
|
||||||
|
|||||||
5
stock_available_mrp/readme/CONTRIBUTORS.rst
Normal file
5
stock_available_mrp/readme/CONTRIBUTORS.rst
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
* Loïc Bellier (Numérigraphe) <lb@numerigraphe.com>
|
||||||
|
* Lionel Sausin (Numérigraphe) <ls@numerigraphe.com>
|
||||||
|
* many thanks to Graeme Gellatly for his advice and code review
|
||||||
|
* Laurent Mignon <laurent.mignon@acsone.eu>
|
||||||
|
* Cédric Pigeon <cedric.pigeon@acsone.eu>
|
||||||
6
stock_available_mrp/readme/DESCRIPTION.rst
Normal file
6
stock_available_mrp/readme/DESCRIPTION.rst
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
This module takes the potential quantities available for Products into account in
|
||||||
|
the quantity available to promise, where the "Potential quantity" is the
|
||||||
|
quantity that can be manufactured with the components immediately at hand.
|
||||||
|
By configuration, the "Potential quantity" can be computed based on other product field.
|
||||||
|
For example, "Potential quantity" can be the quantity that can be manufactured
|
||||||
|
with the components available to promise.
|
||||||
24
stock_available_mrp/readme/ROADMAP.rst
Normal file
24
stock_available_mrp/readme/ROADMAP.rst
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
Known issues
|
||||||
|
------------
|
||||||
|
The manufacturing delays are not taken into account : this module assumes that
|
||||||
|
if you have components in stock goods, you can manufacture finished goods
|
||||||
|
quickly enough.
|
||||||
|
|
||||||
|
As a consequence, and to avoid overestimating, **only the first level** of Bill of Materials is
|
||||||
|
considered.
|
||||||
|
However Sets (a.k.a "phantom" BoMs) are taken into account: if a component must be replaced with a set, it's the stock of the set's product which will decide the potential.
|
||||||
|
|
||||||
|
If a product has several variants, only the variant with the biggest potential will be taken into account when reporting the production potential.
|
||||||
|
For example, even if you actually have enough components to make 10 iPads 16Go AND 42 iPads 32Go, we'll consider that you can promise only 42 iPads.
|
||||||
|
|
||||||
|
Removed features
|
||||||
|
----------------
|
||||||
|
Previous versions of this module used to let programmers demand to get the potential quantity in an arbitrary Unit of Measure using the `context`. This feature was present in the standard computations too until v8.0, but it has been dropped from the standard from v8.0 on.
|
||||||
|
For the sake of consistency the potential quantity is now always reported in the product's main Unit of Measure too.
|
||||||
|
|
||||||
|
Roadmap
|
||||||
|
-------
|
||||||
|
Possible improvements for future versions:
|
||||||
|
* take manufacturing delays into account: we should not promise goods to customers if they want them delivered earlier that we can make them
|
||||||
|
* Compute the quantity of finished product that can be made directly on each Bill of Material: this would be useful for production managers, and may make the computations faster by avoiding to compute the same BoM several times when several variants share the same BoM
|
||||||
|
* add an option (probably as a sub-module) to consider all raw materials as available if they can be bought from the suppliers in time for the manufacturing.
|
||||||
@@ -29,20 +29,28 @@ class TestPotentialQty(TransactionCase):
|
|||||||
def setup_demo_data(self):
|
def setup_demo_data(self):
|
||||||
# An interesting product (multi-line BoM, variants)
|
# An interesting product (multi-line BoM, variants)
|
||||||
self.tmpl = self.browse_ref(
|
self.tmpl = self.browse_ref(
|
||||||
'mrp.product_product_build_kit_product_template')
|
'mrp.product_product_table_kit_product_template')
|
||||||
# First variant
|
# First variant
|
||||||
self.var1 = self.browse_ref('mrp.product_product_build_kit')
|
self.var1 = self.browse_ref('mrp.product_product_table_kit')
|
||||||
self.var1.type = 'product'
|
self.var1.type = 'product'
|
||||||
# Second variant
|
# Second variant
|
||||||
self.var2 = self.browse_ref(
|
self.var2 = self.browse_ref(
|
||||||
'stock_available_mrp.product_kit_1a')
|
'stock_available_mrp.product_kit_1a')
|
||||||
self.var2.type = 'product'
|
self.var2.type = 'product'
|
||||||
|
# Make bolt a stockable product to be able to change its stock
|
||||||
|
# we need to unreserve the existing move before being able to do it.
|
||||||
|
bolt = self.env.ref('mrp.product_product_computer_desk_bolt')
|
||||||
|
bolt_moves = self.env['stock.move'].search(
|
||||||
|
[('product_id', '=', bolt.id),
|
||||||
|
('state', 'not in', ('done', 'cancel'))])
|
||||||
|
bolt_moves._do_unreserve()
|
||||||
|
bolt.type = 'product'
|
||||||
# Components that can be used to make the product
|
# Components that can be used to make the product
|
||||||
component_ids = [
|
component_ids = [
|
||||||
# KeyBoard
|
# Bolt
|
||||||
self.ref('product.product_product_9'),
|
bolt.id,
|
||||||
# Mouse
|
# Wood Panel
|
||||||
self.ref('product.product_product_12'),
|
self.ref('mrp.product_product_wood_panel'),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Zero-out the inventory of all variants and components
|
# Zero-out the inventory of all variants and components
|
||||||
@@ -81,7 +89,7 @@ class TestPotentialQty(TransactionCase):
|
|||||||
'location_id': location_id,
|
'location_id': location_id,
|
||||||
'product_qty': qty
|
'product_qty': qty
|
||||||
})
|
})
|
||||||
inventory.action_done()
|
inventory._action_done()
|
||||||
|
|
||||||
def create_simple_bom(self, product, sub_product,
|
def create_simple_bom(self, product, sub_product,
|
||||||
product_qty=1, sub_product_qty=1,
|
product_qty=1, sub_product_qty=1,
|
||||||
@@ -118,7 +126,7 @@ class TestPotentialQty(TransactionCase):
|
|||||||
def test_potential_qty_no_bom_for_company(self):
|
def test_potential_qty_no_bom_for_company(self):
|
||||||
chicago_id = self.ref('stock.res_company_1')
|
chicago_id = self.ref('stock.res_company_1')
|
||||||
|
|
||||||
# Receive 1000x CPUI5s owned by Chicago
|
# Receive 1000x Wood Panel owned by Chicago
|
||||||
inventory = self.env['stock.inventory'].create(
|
inventory = self.env['stock.inventory'].create(
|
||||||
{'name': 'Receive CPUa8',
|
{'name': 'Receive CPUa8',
|
||||||
'company_id': chicago_id,
|
'company_id': chicago_id,
|
||||||
@@ -128,12 +136,12 @@ class TestPotentialQty(TransactionCase):
|
|||||||
self.env['stock.inventory.line'].create(
|
self.env['stock.inventory.line'].create(
|
||||||
{'inventory_id': inventory.id,
|
{'inventory_id': inventory.id,
|
||||||
'company_id': chicago_id,
|
'company_id': chicago_id,
|
||||||
'product_id': self.ref('product.product_product_9'),
|
'product_id': self.ref('mrp.product_product_wood_panel'),
|
||||||
'location_id': self.wh_ch.lot_stock_id.id,
|
'location_id': self.wh_ch.lot_stock_id.id,
|
||||||
'product_qty': 1000.0})
|
'product_qty': 1000.0})
|
||||||
inventory.action_done()
|
inventory._action_done()
|
||||||
|
|
||||||
# Put RAM-SR5 owned by Chicago for 1000x the 1st variant in main WH
|
# Put Bolt owned by Chicago for 1000x the 1st variant in main WH
|
||||||
inventory = self.env['stock.inventory'].create(
|
inventory = self.env['stock.inventory'].create(
|
||||||
{'name': 'components for 1st variant',
|
{'name': 'components for 1st variant',
|
||||||
'company_id': chicago_id,
|
'company_id': chicago_id,
|
||||||
@@ -143,12 +151,12 @@ class TestPotentialQty(TransactionCase):
|
|||||||
self.env['stock.inventory.line'].create(
|
self.env['stock.inventory.line'].create(
|
||||||
{'inventory_id': inventory.id,
|
{'inventory_id': inventory.id,
|
||||||
'company_id': chicago_id,
|
'company_id': chicago_id,
|
||||||
'product_id': self.ref('product.product_product_12'),
|
'product_id': self.ref('mrp.product_product_computer_desk_bolt'),
|
||||||
'location_id': self.wh_ch.lot_stock_id.id,
|
'location_id': self.wh_ch.lot_stock_id.id,
|
||||||
'product_qty': 1000.0})
|
'product_qty': 1000.0})
|
||||||
inventory.action_done()
|
inventory._action_done()
|
||||||
self.assertPotentialQty(
|
self.assertPotentialQty(
|
||||||
self.tmpl, 1000.0,
|
self.tmpl, 250.0,
|
||||||
"Wrong template potential after receiving components")
|
"Wrong template potential after receiving components")
|
||||||
|
|
||||||
test_user = self.env['res.users'].create(
|
test_user = self.env['res.users'].create(
|
||||||
@@ -164,7 +172,7 @@ class TestPotentialQty(TransactionCase):
|
|||||||
|
|
||||||
test_user_tmpl = self.tmpl.sudo(test_user)
|
test_user_tmpl = self.tmpl.sudo(test_user)
|
||||||
self.assertPotentialQty(
|
self.assertPotentialQty(
|
||||||
test_user_tmpl, 1000.0,
|
test_user_tmpl, 250.0,
|
||||||
"Simple user can access to the potential_qty")
|
"Simple user can access to the potential_qty")
|
||||||
|
|
||||||
# Set the bom on the main company (visible to members of main company)
|
# Set the bom on the main company (visible to members of main company)
|
||||||
@@ -181,7 +189,7 @@ class TestPotentialQty(TransactionCase):
|
|||||||
"company or company child of the bom's company")
|
"company or company child of the bom's company")
|
||||||
bom.company_id = chicago_id
|
bom.company_id = chicago_id
|
||||||
self.assertPotentialQty(
|
self.assertPotentialQty(
|
||||||
test_user_tmpl, 1000.0, '')
|
test_user_tmpl, 250.0, '')
|
||||||
|
|
||||||
def test_potential_qty(self):
|
def test_potential_qty(self):
|
||||||
for i in [self.tmpl, self.var1, self.var2]:
|
for i in [self.tmpl, self.var1, self.var2]:
|
||||||
@@ -189,7 +197,7 @@ class TestPotentialQty(TransactionCase):
|
|||||||
i, 0.0,
|
i, 0.0,
|
||||||
"The potential quantity should start at 0")
|
"The potential quantity should start at 0")
|
||||||
|
|
||||||
# Receive 1000x Mouses
|
# Receive 1000x Wood Panel
|
||||||
inventory = self.env['stock.inventory'].create(
|
inventory = self.env['stock.inventory'].create(
|
||||||
{'name': 'Receive Mouses',
|
{'name': 'Receive Mouses',
|
||||||
'location_id': self.wh_main.lot_stock_id.id,
|
'location_id': self.wh_main.lot_stock_id.id,
|
||||||
@@ -197,17 +205,17 @@ class TestPotentialQty(TransactionCase):
|
|||||||
inventory.action_start()
|
inventory.action_start()
|
||||||
self.env['stock.inventory.line'].create(
|
self.env['stock.inventory.line'].create(
|
||||||
{'inventory_id': inventory.id,
|
{'inventory_id': inventory.id,
|
||||||
'product_id': self.ref('product.product_product_12'),
|
'product_id': self.ref('mrp.product_product_wood_panel'),
|
||||||
'location_id': self.wh_main.lot_stock_id.id,
|
'location_id': self.wh_main.lot_stock_id.id,
|
||||||
'product_qty': 1000.0})
|
'product_qty': 1000.0})
|
||||||
inventory.action_done()
|
inventory._action_done()
|
||||||
for i in [self.tmpl, self.var1, self.var2]:
|
for i in [self.tmpl, self.var1, self.var2]:
|
||||||
self.assertPotentialQty(
|
self.assertPotentialQty(
|
||||||
i, 0.0,
|
i, 0.0,
|
||||||
"Receiving a single component should not change the "
|
"Receiving a single component should not change the "
|
||||||
"potential of %s" % i)
|
"potential of %s" % i)
|
||||||
|
|
||||||
# Receive enough keyboard to make 1000x the 1st variant in main WH
|
# Receive enough bolt to make 1000x the 1st variant in main WH
|
||||||
inventory = self.env['stock.inventory'].create(
|
inventory = self.env['stock.inventory'].create(
|
||||||
{'name': 'components for 1st variant',
|
{'name': 'components for 1st variant',
|
||||||
'location_id': self.wh_main.lot_stock_id.id,
|
'location_id': self.wh_main.lot_stock_id.id,
|
||||||
@@ -216,22 +224,22 @@ class TestPotentialQty(TransactionCase):
|
|||||||
self.env['stock.inventory.line'].create(
|
self.env['stock.inventory.line'].create(
|
||||||
{'inventory_id': inventory.id,
|
{'inventory_id': inventory.id,
|
||||||
'product_id': self.ref(
|
'product_id': self.ref(
|
||||||
'product.product_product_9'),
|
'mrp.product_product_computer_desk_bolt'),
|
||||||
'location_id': self.wh_main.lot_stock_id.id,
|
'location_id': self.wh_main.lot_stock_id.id,
|
||||||
'product_qty': 1000.0})
|
'product_qty': 1000.0})
|
||||||
inventory.action_done()
|
inventory._action_done()
|
||||||
self.assertPotentialQty(
|
self.assertPotentialQty(
|
||||||
self.tmpl, 1000.0,
|
self.tmpl, 250.0,
|
||||||
"Wrong template potential after receiving components")
|
"Wrong template potential after receiving components")
|
||||||
self.assertPotentialQty(
|
self.assertPotentialQty(
|
||||||
self.var1, 1000.0,
|
self.var1, 250.0,
|
||||||
"Wrong variant 1 potential after receiving components")
|
"Wrong variant 1 potential after receiving components")
|
||||||
self.assertPotentialQty(
|
self.assertPotentialQty(
|
||||||
self.var2, 0.0,
|
self.var2, 0.0,
|
||||||
"Receiving variant 1's component should not change "
|
"Receiving variant 1's component should not change "
|
||||||
"variant 2's potential")
|
"variant 2's potential")
|
||||||
|
|
||||||
# Receive enough components to make 313 the 2nd variant at Chicago
|
# Receive enough components to make 213 the 2nd variant at Chicago
|
||||||
inventory = self.env['stock.inventory'].create(
|
inventory = self.env['stock.inventory'].create(
|
||||||
{'name': 'components for 2nd variant',
|
{'name': 'components for 2nd variant',
|
||||||
'location_id': self.wh_ch.lot_stock_id.id,
|
'location_id': self.wh_ch.lot_stock_id.id,
|
||||||
@@ -239,64 +247,64 @@ class TestPotentialQty(TransactionCase):
|
|||||||
inventory.action_start()
|
inventory.action_start()
|
||||||
self.env['stock.inventory.line'].create(
|
self.env['stock.inventory.line'].create(
|
||||||
{'inventory_id': inventory.id,
|
{'inventory_id': inventory.id,
|
||||||
'product_id': self.ref('product.product_product_12'),
|
'product_id': self.ref('mrp.product_product_wood_panel'),
|
||||||
'location_id': self.wh_ch.lot_stock_id.id,
|
'location_id': self.wh_ch.lot_stock_id.id,
|
||||||
'product_qty': 1000.0})
|
'product_qty': 1000.0})
|
||||||
self.env['stock.inventory.line'].create(
|
self.env['stock.inventory.line'].create(
|
||||||
{'inventory_id': inventory.id,
|
{'inventory_id': inventory.id,
|
||||||
'product_id': self.ref(
|
'product_id': self.ref(
|
||||||
'stock_available_mrp.product_product_9_white'),
|
'stock_available_mrp.product_computer_desk_bolt_white'),
|
||||||
'location_id': self.wh_ch.lot_stock_id.id,
|
'location_id': self.wh_ch.lot_stock_id.id,
|
||||||
'product_qty': 313.0})
|
'product_qty': 852.0})
|
||||||
inventory.action_done()
|
inventory._action_done()
|
||||||
self.assertPotentialQty(
|
self.assertPotentialQty(
|
||||||
self.tmpl, 1000.0,
|
self.tmpl.with_context(test=True), 250.0,
|
||||||
"Wrong template potential after receiving components")
|
"Wrong template potential after receiving components")
|
||||||
self.assertPotentialQty(
|
self.assertPotentialQty(
|
||||||
self.var1, 1000.0,
|
self.var1, 250.0,
|
||||||
"Receiving variant 2's component should not change "
|
"Receiving variant 2's component should not change "
|
||||||
"variant 1's potential")
|
"variant 1's potential")
|
||||||
self.assertPotentialQty(
|
self.assertPotentialQty(
|
||||||
self.var2, 313.0,
|
self.var2, 213.0,
|
||||||
"Wrong variant 2 potential after receiving components")
|
"Wrong variant 2 potential after receiving components")
|
||||||
# Check by warehouse
|
# Check by warehouse
|
||||||
self.assertPotentialQty(
|
self.assertPotentialQty(
|
||||||
self.tmpl.with_context(warehouse=self.wh_main.id), 1000.0,
|
self.tmpl.with_context(warehouse=self.wh_main.id), 250.0,
|
||||||
"Wrong potential quantity in main WH")
|
"Wrong potential quantity in main WH")
|
||||||
self.assertPotentialQty(
|
self.assertPotentialQty(
|
||||||
self.tmpl.with_context(warehouse=self.wh_ch.id), 313.0,
|
self.tmpl.with_context(warehouse=self.wh_ch.id), 213.0,
|
||||||
"Wrong potential quantity in Chicago WH")
|
"Wrong potential quantity in Chicago WH")
|
||||||
# Check by location
|
# Check by location
|
||||||
self.assertPotentialQty(
|
self.assertPotentialQty(
|
||||||
self.tmpl.with_context(
|
self.tmpl.with_context(
|
||||||
location=self.wh_main.lot_stock_id.id), 1000.0,
|
location=self.wh_main.lot_stock_id.id), 250.0,
|
||||||
"Wrong potential quantity in main WH location")
|
"Wrong potential quantity in main WH location")
|
||||||
self.assertPotentialQty(
|
self.assertPotentialQty(
|
||||||
self.tmpl.with_context(
|
self.tmpl.with_context(
|
||||||
location=self.wh_ch.lot_stock_id.id),
|
location=self.wh_ch.lot_stock_id.id),
|
||||||
313.0,
|
213.0,
|
||||||
"Wrong potential quantity in Chicago WH location")
|
"Wrong potential quantity in Chicago WH location")
|
||||||
|
|
||||||
def test_multi_unit_recursive_bom(self):
|
def test_multi_unit_recursive_bom(self):
|
||||||
# Test multi-level and multi-units BOM
|
# Test multi-level and multi-units BOM
|
||||||
uom_unit = self.env.ref('product.product_uom_unit')
|
uom_unit = self.env.ref('uom.product_uom_unit')
|
||||||
uom_unit.rounding = 1.0
|
uom_unit.rounding = 1.0
|
||||||
p1 = self.product_model.create({
|
p1 = self.product_model.create({
|
||||||
'name': 'Test product with BOM',
|
'name': 'Test product with BOM',
|
||||||
'type': 'product',
|
'type': 'product',
|
||||||
'uom_id': self.env.ref('product.product_uom_unit').id,
|
'uom_id': self.env.ref('uom.product_uom_unit').id,
|
||||||
})
|
})
|
||||||
|
|
||||||
p2 = self.product_model.create({
|
p2 = self.product_model.create({
|
||||||
'name': 'Test sub product with BOM',
|
'name': 'Test sub product with BOM',
|
||||||
'type': 'product',
|
'type': 'product',
|
||||||
'uom_id': self.env.ref('product.product_uom_unit').id,
|
'uom_id': self.env.ref('uom.product_uom_unit').id,
|
||||||
})
|
})
|
||||||
|
|
||||||
p3 = self.product_model.create({
|
p3 = self.product_model.create({
|
||||||
'name': 'Test component',
|
'name': 'Test component',
|
||||||
'type': 'product',
|
'type': 'product',
|
||||||
'uom_id': self.env.ref('product.product_uom_unit').id,
|
'uom_id': self.env.ref('uom.product_uom_unit').id,
|
||||||
})
|
})
|
||||||
|
|
||||||
bom_p1 = self.bom_model.create({
|
bom_p1 = self.bom_model.create({
|
||||||
@@ -308,7 +316,7 @@ class TestPotentialQty(TransactionCase):
|
|||||||
'bom_id': bom_p1.id,
|
'bom_id': bom_p1.id,
|
||||||
'product_id': p3.id,
|
'product_id': p3.id,
|
||||||
'product_qty': 1,
|
'product_qty': 1,
|
||||||
'product_uom_id': self.env.ref('product.product_uom_unit').id,
|
'product_uom_id': self.env.ref('uom.product_uom_unit').id,
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -317,7 +325,7 @@ class TestPotentialQty(TransactionCase):
|
|||||||
'bom_id': bom_p1.id,
|
'bom_id': bom_p1.id,
|
||||||
'product_id': p2.id,
|
'product_id': p2.id,
|
||||||
'product_qty': 2,
|
'product_qty': 2,
|
||||||
'product_uom_id': self.env.ref('product.product_uom_unit').id,
|
'product_uom_id': self.env.ref('uom.product_uom_unit').id,
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -332,7 +340,7 @@ class TestPotentialQty(TransactionCase):
|
|||||||
'bom_id': bom_p2.id,
|
'bom_id': bom_p2.id,
|
||||||
'product_id': p3.id,
|
'product_id': p3.id,
|
||||||
'product_qty': 2,
|
'product_qty': 2,
|
||||||
'product_uom_id': self.env.ref('product.product_uom_unit').id,
|
'product_uom_id': self.env.ref('uom.product_uom_unit').id,
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -365,7 +373,7 @@ class TestPotentialQty(TransactionCase):
|
|||||||
# Test to change component stock for compute BOM stock
|
# Test to change component stock for compute BOM stock
|
||||||
|
|
||||||
# Get a demo product with outgoing move (qty: 3)
|
# Get a demo product with outgoing move (qty: 3)
|
||||||
prod = self.browse_ref('product.product_product_20')
|
prod = self.browse_ref('product.product_product_16')
|
||||||
|
|
||||||
# Set on hand qty
|
# Set on hand qty
|
||||||
self.create_inventory(prod.id, 3)
|
self.create_inventory(prod.id, 3)
|
||||||
|
|||||||
Reference in New Issue
Block a user