From 67767fb5b685f25fafa9ac8a6f25bd02d88e3b61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Thu, 13 May 2021 16:17:07 +0200 Subject: [PATCH] [IMP] stock_available_mrp: black, isort, prettier --- stock_available_mrp/__manifest__.py | 24 +- stock_available_mrp/demo/mrp_data.xml | 81 +-- stock_available_mrp/models/product_product.py | 79 ++- .../tests/test_potential_qty.py | 491 ++++++++++-------- 4 files changed, 363 insertions(+), 312 deletions(-) diff --git a/stock_available_mrp/__manifest__.py b/stock_available_mrp/__manifest__.py index 27725f4ad..eafbba1d1 100644 --- a/stock_available_mrp/__manifest__.py +++ b/stock_available_mrp/__manifest__.py @@ -1,19 +1,13 @@ # Copyright 2014 Numérigraphe SARL, Camptocamp # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { - 'name': 'Consider the production potential is available to promise', - 'version': '12.0.1.0.2', - "author": "Numérigraphe," - "Odoo Community Association (OCA)", - 'website': 'https://github.com/OCA/stock-logistics-warehouse', - 'category': 'Hidden', - 'depends': [ - 'stock_available', - 'mrp' - ], - 'demo': [ - 'demo/mrp_data.xml', - ], - 'license': 'AGPL-3', - 'installable': True, + "name": "Consider the production potential is available to promise", + "version": "12.0.1.0.2", + "author": "Numérigraphe," "Odoo Community Association (OCA)", + "website": "https://github.com/OCA/stock-logistics-warehouse", + "category": "Hidden", + "depends": ["stock_available", "mrp"], + "demo": ["demo/mrp_data.xml",], + "license": "AGPL-3", + "installable": True, } diff --git a/stock_available_mrp/demo/mrp_data.xml b/stock_available_mrp/demo/mrp_data.xml index 1dc82fee9..ae3e3c4fc 100644 --- a/stock_available_mrp/demo/mrp_data.xml +++ b/stock_available_mrp/demo/mrp_data.xml @@ -1,38 +1,47 @@ - + - - PCSC234-WHITE - - - - - - - - - - - - - - Bolt - - 1.0 - 5.0 - product - - - BOLT-WHITE - - - - - 4 - - 5 - - - + + PCSC234-WHITE + + + + + + + + + + + Bolt + + 1.0 + 5.0 + product + + + BOLT-WHITE + + + + 4 + + 5 + + + diff --git a/stock_available_mrp/models/product_product.py b/stock_available_mrp/models/product_product.py index aa7111ca9..668112101 100644 --- a/stock_available_mrp/models/product_product.py +++ b/stock_available_mrp/models/product_product.py @@ -2,21 +2,18 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from collections import Counter + from odoo import api, fields, models from odoo.fields import first class ProductProduct(models.Model): - _inherit = 'product.product' + _inherit = "product.product" - bom_id = fields.Many2one( - 'mrp.bom', - compute='_compute_bom_id', - string='BOM' - ) + bom_id = fields.Many2one("mrp.bom", compute="_compute_bom_id", string="BOM") - @api.depends('virtual_available', 'bom_id', 'bom_id.product_qty') + @api.depends("virtual_available", "bom_id", "bom_id.product_qty") def _compute_available_quantities(self): super(ProductProduct, self)._compute_available_quantities() @@ -27,49 +24,46 @@ class ProductProduct(models.Model): :return: """ return [ - '|', - ('product_id', 'in', self.ids), - '&', - ('product_id', '=', False), - ('product_tmpl_id', 'in', self.mapped('product_tmpl_id.id')) + "|", + ("product_id", "in", self.ids), + "&", + ("product_id", "=", False), + ("product_tmpl_id", "in", self.mapped("product_tmpl_id.id")), ] @api.multi - @api.depends('product_tmpl_id') + @api.depends("product_tmpl_id") def _compute_bom_id(self): - bom_obj = self.env['mrp.bom'] - boms = bom_obj.search( - self._get_bom_id_domain(), - order='sequence, product_id', - ) + bom_obj = self.env["mrp.bom"] + boms = bom_obj.search(self._get_bom_id_domain(), order="sequence, product_id",) for product in self: product_boms = boms.filtered( - lambda b: b.product_id == product or - (not b.product_id and - b.product_tmpl_id == product.product_tmpl_id) + lambda b: b.product_id == product + or (not b.product_id and b.product_tmpl_id == product.product_tmpl_id) ) if product_boms: product.bom_id = first(product_boms) @api.multi def _compute_available_quantities_dict(self): - res, stock_dict = super(ProductProduct, - self)._compute_available_quantities_dict() + res, stock_dict = super( + ProductProduct, self + )._compute_available_quantities_dict() # compute qty for product with bom - product_with_bom = self.filtered('bom_id') + product_with_bom = self.filtered("bom_id") if not product_with_bom: return res, stock_dict - icp = self.env['ir.config_parameter'] + icp = self.env["ir.config_parameter"] stock_available_mrp_based_on = icp.sudo().get_param( - 'stock_available_mrp_based_on', 'qty_available' + "stock_available_mrp_based_on", "qty_available" ) # explode all boms at once exploded_boms = product_with_bom._explode_boms() # extract the list of product used as bom component - component_products = self.env['product.product'].browse() + component_products = self.env["product.product"].browse() for exploded_components in exploded_boms.values(): for bom_component in exploded_components: component_products |= first(bom_component).product_id @@ -79,22 +73,19 @@ class ProductProduct(models.Model): if res and stock_available_mrp_based_on in list(res.values())[0]: # If the qty is computed by the same method use it to avoid # stressing the cache - component_qties, _ = \ - component_products._compute_available_quantities_dict() + component_qties, _ = component_products._compute_available_quantities_dict() else: # The qty is a field computed by an other method than the # current one. Take the value on the record. component_qties = { - p.id: { - stock_available_mrp_based_on: p[ - stock_available_mrp_based_on]} for p in - component_products} + p.id: {stock_available_mrp_based_on: p[stock_available_mrp_based_on]} + for p in component_products + } for product in product_with_bom: # Need by product (same product can be in many BOM lines/levels) exploded_components = exploded_boms[product.id] - component_needs = product._get_components_needs( - exploded_components) + component_needs = product._get_components_needs(exploded_components) if not component_needs: # The BoM has no line we can use potential_qty = 0.0 @@ -102,13 +93,15 @@ class ProductProduct(models.Model): else: # Find the lowest quantity we can make with the stock at hand components_potential_qty = min( - [component_qties[component.id][ - stock_available_mrp_based_on] / need - for component, need in component_needs.items()] + [ + component_qties[component.id][stock_available_mrp_based_on] + / need + for component, need in component_needs.items() + ] ) bom_id = product.bom_id - potential_qty = (bom_id.product_qty * components_potential_qty) + potential_qty = bom_id.product_qty * components_potential_qty potential_qty = potential_qty > 0.0 and potential_qty or 0.0 # We want to respect the rounding factor of the potential_qty @@ -116,11 +109,11 @@ class ProductProduct(models.Model): potential_qty = bom_id.product_uom_id._compute_quantity( potential_qty, product.bom_id.product_tmpl_id.uom_id, - rounding_method='DOWN' + rounding_method="DOWN", ) - res[product.id]['potential_qty'] = potential_qty - res[product.id]['immediately_usable_qty'] += potential_qty + res[product.id]["potential_qty"] = potential_qty + res[product.id]["immediately_usable_qty"] += potential_qty return res, stock_dict @@ -145,6 +138,6 @@ class ProductProduct(models.Model): needs = Counter() for bom_component in exploded_components: component = bom_component[0].product_id - needs += Counter({component: bom_component[1]['qty']}) + needs += Counter({component: bom_component[1]["qty"]}) return needs diff --git a/stock_available_mrp/tests/test_potential_qty.py b/stock_available_mrp/tests/test_potential_qty.py index a2ede76c3..48f19e98b 100644 --- a/stock_available_mrp/tests/test_potential_qty.py +++ b/stock_available_mrp/tests/test_potential_qty.py @@ -1,8 +1,8 @@ # Copyright 2014 Numérigraphe SARL # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo.tests.common import TransactionCase from odoo.osv.expression import TRUE_LEAF +from odoo.tests.common import TransactionCase class TestPotentialQty(TransactionCase): @@ -15,91 +15,90 @@ class TestPotentialQty(TransactionCase): self.bom_model = self.env["mrp.bom"] self.bom_line_model = self.env["mrp.bom.line"] self.stock_quant_model = self.env["stock.quant"] - self.config = self.env['ir.config_parameter'] - self.location = self.env['stock.location'] + self.config = self.env["ir.config_parameter"] + self.location = self.env["stock.location"] # Get the warehouses - self.wh_main = self.browse_ref('stock.warehouse0') - self.wh_ch = self.browse_ref('stock.stock_warehouse_shop0') + self.wh_main = self.browse_ref("stock.warehouse0") + self.wh_ch = self.browse_ref("stock.stock_warehouse_shop0") # We need to compute parent_left and parent_right of the locations as # they are used to compute qty_available of the product. self.location._parent_store_compute() #  An interesting product (multi-line BoM, variants) - self.tmpl = self.browse_ref( - 'mrp.product_product_table_kit_product_template') + self.tmpl = self.browse_ref("mrp.product_product_table_kit_product_template") #  First variant - self.var1 = self.browse_ref('mrp.product_product_table_kit') + self.var1 = self.browse_ref("mrp.product_product_table_kit") #  Second variant - self.var2 = self.browse_ref( - 'stock_available_mrp.product_kit_1a') + self.var2 = self.browse_ref("stock_available_mrp.product_kit_1a") # 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 = 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' + bolt.type = "product" # Components that can be used to make the product component_ids = [ # Bolt bolt.id, # Wood Panel - self.ref('mrp.product_product_wood_panel'), + self.ref("mrp.product_product_wood_panel"), ] # Zero-out the inventory of all variants and components - for component_id in ( - component_ids + [v.id - for v in self.tmpl.product_variant_ids]): + for component_id in component_ids + [ + v.id for v in self.tmpl.product_variant_ids + ]: prod = self.product_model.browse(component_id) - self.env['stock.quant'].search([ - ('product_id', '=', prod.id) - ]).unlink() + self.env["stock.quant"].search([("product_id", "=", prod.id)]).unlink() self.product_model.invalidate_cache() #  A product without a BoM - self.product_wo_bom = self.browse_ref('product.product_product_11') + self.product_wo_bom = self.browse_ref("product.product_product_11") # Record the initial quantity available for sale - self.initial_usable_qties = {i.id: i.immediately_usable_qty - for i in [self.tmpl, - self.var1, - self.var2, - self.product_wo_bom]} + self.initial_usable_qties = { + i.id: i.immediately_usable_qty + for i in [self.tmpl, self.var1, self.var2, self.product_wo_bom] + } def create_inventory(self, product_id, qty, location_id=None): if location_id is None: location_id = self.wh_main.lot_stock_id.id - inventory = self.env['stock.inventory'].create({ - 'name': 'Test inventory', - 'location_id': location_id, - 'filter': 'partial' - }) + inventory = self.env["stock.inventory"].create( + {"name": "Test inventory", "location_id": location_id, "filter": "partial"} + ) inventory.action_start() - self.env['stock.inventory.line'].create({ - 'inventory_id': inventory.id, - 'product_id': product_id, - 'location_id': location_id, - 'product_qty': qty - }) + self.env["stock.inventory.line"].create( + { + "inventory_id": inventory.id, + "product_id": product_id, + "location_id": location_id, + "product_qty": qty, + } + ) inventory._action_done() - def create_simple_bom(self, product, sub_product, - product_qty=1, sub_product_qty=1, - routing_id=False): - bom = self.bom_model.create({ - 'product_tmpl_id': product.product_tmpl_id.id, - 'product_id': product.id, - 'product_qty': product_qty, - 'routing_id': routing_id, - }) - self.bom_line_model.create({ - 'bom_id': bom.id, - 'product_id': sub_product.id, - 'product_qty': sub_product_qty, - }) + def create_simple_bom( + self, product, sub_product, product_qty=1, sub_product_qty=1, routing_id=False + ): + bom = self.bom_model.create( + { + "product_tmpl_id": product.product_tmpl_id.id, + "product_id": product.id, + "product_qty": product_qty, + "routing_id": routing_id, + } + ) + self.bom_line_model.create( + { + "bom_id": bom.id, + "product_id": sub_product.id, + "product_qty": sub_product_qty, + } + ) return bom @@ -109,235 +108,294 @@ class TestPotentialQty(TransactionCase): self.assertEqual(record.potential_qty, qty, msg) # Check the variation of quantity available for sale self.assertEqual( - (record.immediately_usable_qty - - self.initial_usable_qties[record.id]), qty, msg) + (record.immediately_usable_qty - self.initial_usable_qties[record.id]), + qty, + msg, + ) def test_potential_qty_no_bom(self): #  Check the potential when there's no BoM self.assertPotentialQty( - self.product_wo_bom, 0.0, - "The potential without a BoM should be 0") + self.product_wo_bom, 0.0, "The potential without a BoM should be 0" + ) 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 Wood Panel owned by Chicago - inventory = self.env['stock.inventory'].create( - {'name': 'Receive CPUa8', - 'company_id': chicago_id, - 'location_id': self.wh_ch.lot_stock_id.id, - 'filter': 'partial'}) + inventory = self.env["stock.inventory"].create( + { + "name": "Receive CPUa8", + "company_id": chicago_id, + "location_id": self.wh_ch.lot_stock_id.id, + "filter": "partial", + } + ) inventory.action_start() - self.env['stock.inventory.line'].create( - {'inventory_id': inventory.id, - 'company_id': chicago_id, - 'product_id': self.ref('mrp.product_product_wood_panel'), - 'location_id': self.wh_ch.lot_stock_id.id, - 'product_qty': 1000.0}) + self.env["stock.inventory.line"].create( + { + "inventory_id": inventory.id, + "company_id": chicago_id, + "product_id": self.ref("mrp.product_product_wood_panel"), + "location_id": self.wh_ch.lot_stock_id.id, + "product_qty": 1000.0, + } + ) inventory._action_done() # Put Bolt owned by Chicago for 1000x the 1st variant in main WH - inventory = self.env['stock.inventory'].create( - {'name': 'components for 1st variant', - 'company_id': chicago_id, - 'location_id': self.wh_ch.lot_stock_id.id, - 'filter': 'partial'}) + inventory = self.env["stock.inventory"].create( + { + "name": "components for 1st variant", + "company_id": chicago_id, + "location_id": self.wh_ch.lot_stock_id.id, + "filter": "partial", + } + ) inventory.action_start() - self.env['stock.inventory.line'].create( - {'inventory_id': inventory.id, - 'company_id': chicago_id, - 'product_id': self.ref('mrp.product_product_computer_desk_bolt'), - 'location_id': self.wh_ch.lot_stock_id.id, - 'product_qty': 1000.0}) + self.env["stock.inventory.line"].create( + { + "inventory_id": inventory.id, + "company_id": chicago_id, + "product_id": self.ref("mrp.product_product_computer_desk_bolt"), + "location_id": self.wh_ch.lot_stock_id.id, + "product_qty": 1000.0, + } + ) inventory._action_done() self.assertPotentialQty( - self.tmpl, 250.0, - "Wrong template potential after receiving components") + self.tmpl, 250.0, "Wrong template potential after receiving components" + ) - test_user = self.env['res.users'].create( - {'name': 'test_demo', - 'login': 'test_demo', - 'company_id': self.ref('base.main_company'), - 'company_ids': [(4, self.ref('base.main_company'))], - 'groups_id': [(4, self.ref('stock.group_stock_user')), - (4, self.ref('mrp.group_mrp_user'))]}) + test_user = self.env["res.users"].create( + { + "name": "test_demo", + "login": "test_demo", + "company_id": self.ref("base.main_company"), + "company_ids": [(4, self.ref("base.main_company"))], + "groups_id": [ + (4, self.ref("stock.group_stock_user")), + (4, self.ref("mrp.group_mrp_user")), + ], + } + ) - bom = self.env['mrp.bom'].search( - [('product_tmpl_id', '=', self.tmpl.id)]) + bom = self.env["mrp.bom"].search([("product_tmpl_id", "=", self.tmpl.id)]) test_user_tmpl = self.tmpl.sudo(test_user) self.assertPotentialQty( - test_user_tmpl, 250.0, - "Simple user can access to the potential_qty") + test_user_tmpl, 250.0, "Simple user can access to the potential_qty" + ) # Set the bom on the main company (visible to members of main company) # and all products without company (visible to all) # and the demo user on Chicago (child of main company) - self.env['product.product'].search([ - TRUE_LEAF]).write({'company_id': False}) - test_user.write({'company_id': chicago_id, - 'company_ids': [(4, chicago_id)]}) - bom.company_id = self.ref('base.main_company') + self.env["product.product"].search([TRUE_LEAF]).write({"company_id": False}) + test_user.write({"company_id": chicago_id, "company_ids": [(4, chicago_id)]}) + bom.company_id = self.ref("base.main_company") self.assertPotentialQty( - test_user_tmpl, 0, + test_user_tmpl, + 0, "The bom should not be visible to non members of the bom's " - "company or company child of the bom's company") + "company or company child of the bom's company", + ) bom.company_id = chicago_id - self.assertPotentialQty( - test_user_tmpl, 250.0, '') + self.assertPotentialQty(test_user_tmpl, 250.0, "") def test_potential_qty(self): for i in [self.tmpl, self.var1, self.var2]: - self.assertPotentialQty( - i, 0.0, - "The potential quantity should start at 0") + self.assertPotentialQty(i, 0.0, "The potential quantity should start at 0") # Receive 1000x Wood Panel - inventory = self.env['stock.inventory'].create( - {'name': 'Receive Mouses', - 'location_id': self.wh_main.lot_stock_id.id, - 'filter': 'partial'}) + inventory = self.env["stock.inventory"].create( + { + "name": "Receive Mouses", + "location_id": self.wh_main.lot_stock_id.id, + "filter": "partial", + } + ) inventory.action_start() - self.env['stock.inventory.line'].create( - {'inventory_id': inventory.id, - 'product_id': self.ref('mrp.product_product_wood_panel'), - 'location_id': self.wh_main.lot_stock_id.id, - 'product_qty': 1000.0}) + self.env["stock.inventory.line"].create( + { + "inventory_id": inventory.id, + "product_id": self.ref("mrp.product_product_wood_panel"), + "location_id": self.wh_main.lot_stock_id.id, + "product_qty": 1000.0, + } + ) inventory._action_done() for i in [self.tmpl, self.var1, self.var2]: self.assertPotentialQty( - i, 0.0, + i, + 0.0, "Receiving a single component should not change the " - "potential of %s" % i) + "potential of %s" % i, + ) # Receive enough bolt to make 1000x the 1st variant in main WH - inventory = self.env['stock.inventory'].create( - {'name': 'components for 1st variant', - 'location_id': self.wh_main.lot_stock_id.id, - 'filter': 'partial'}) + inventory = self.env["stock.inventory"].create( + { + "name": "components for 1st variant", + "location_id": self.wh_main.lot_stock_id.id, + "filter": "partial", + } + ) inventory.action_start() - self.env['stock.inventory.line'].create( - {'inventory_id': inventory.id, - 'product_id': self.ref( - 'mrp.product_product_computer_desk_bolt'), - 'location_id': self.wh_main.lot_stock_id.id, - 'product_qty': 1000.0}) + self.env["stock.inventory.line"].create( + { + "inventory_id": inventory.id, + "product_id": self.ref("mrp.product_product_computer_desk_bolt"), + "location_id": self.wh_main.lot_stock_id.id, + "product_qty": 1000.0, + } + ) inventory._action_done() self.assertPotentialQty( - self.tmpl, 250.0, - "Wrong template potential after receiving components") + self.tmpl, 250.0, "Wrong template potential after receiving components" + ) self.assertPotentialQty( - self.var1, 250.0, - "Wrong variant 1 potential after receiving components") + self.var1, 250.0, "Wrong variant 1 potential after receiving components" + ) self.assertPotentialQty( - self.var2, 0.0, + self.var2, + 0.0, "Receiving variant 1's component should not change " - "variant 2's potential") + "variant 2's potential", + ) # Receive enough components to make 213 the 2nd variant at Chicago - inventory = self.env['stock.inventory'].create( - {'name': 'components for 2nd variant', - 'location_id': self.wh_ch.lot_stock_id.id, - 'filter': 'partial'}) + inventory = self.env["stock.inventory"].create( + { + "name": "components for 2nd variant", + "location_id": self.wh_ch.lot_stock_id.id, + "filter": "partial", + } + ) inventory.action_start() - self.env['stock.inventory.line'].create( - {'inventory_id': inventory.id, - 'product_id': self.ref('mrp.product_product_wood_panel'), - 'location_id': self.wh_ch.lot_stock_id.id, - 'product_qty': 1000.0}) - self.env['stock.inventory.line'].create( - {'inventory_id': inventory.id, - 'product_id': self.ref( - 'stock_available_mrp.product_computer_desk_bolt_white'), - 'location_id': self.wh_ch.lot_stock_id.id, - 'product_qty': 852.0}) + self.env["stock.inventory.line"].create( + { + "inventory_id": inventory.id, + "product_id": self.ref("mrp.product_product_wood_panel"), + "location_id": self.wh_ch.lot_stock_id.id, + "product_qty": 1000.0, + } + ) + self.env["stock.inventory.line"].create( + { + "inventory_id": inventory.id, + "product_id": self.ref( + "stock_available_mrp.product_computer_desk_bolt_white" + ), + "location_id": self.wh_ch.lot_stock_id.id, + "product_qty": 852.0, + } + ) inventory._action_done() self.assertPotentialQty( - self.tmpl.with_context(test=True), 250.0, - "Wrong template potential after receiving components") + self.tmpl.with_context(test=True), + 250.0, + "Wrong template potential after receiving components", + ) self.assertPotentialQty( - self.var1, 250.0, + self.var1, + 250.0, "Receiving variant 2's component should not change " - "variant 1's potential") + "variant 1's potential", + ) self.assertPotentialQty( - self.var2, 213.0, - "Wrong variant 2 potential after receiving components") + self.var2, 213.0, "Wrong variant 2 potential after receiving components" + ) # Check by warehouse self.assertPotentialQty( - self.tmpl.with_context(warehouse=self.wh_main.id), 250.0, - "Wrong potential quantity in main WH") + self.tmpl.with_context(warehouse=self.wh_main.id), + 250.0, + "Wrong potential quantity in main WH", + ) self.assertPotentialQty( - self.tmpl.with_context(warehouse=self.wh_ch.id), 213.0, - "Wrong potential quantity in Chicago WH") + self.tmpl.with_context(warehouse=self.wh_ch.id), + 213.0, + "Wrong potential quantity in Chicago WH", + ) # Check by location self.assertPotentialQty( - self.tmpl.with_context( - location=self.wh_main.lot_stock_id.id), 250.0, - "Wrong potential quantity in main WH location") + self.tmpl.with_context(location=self.wh_main.lot_stock_id.id), + 250.0, + "Wrong potential quantity in main WH location", + ) self.assertPotentialQty( - self.tmpl.with_context( - location=self.wh_ch.lot_stock_id.id), + self.tmpl.with_context(location=self.wh_ch.lot_stock_id.id), 213.0, - "Wrong potential quantity in Chicago WH location") + "Wrong potential quantity in Chicago WH location", + ) def test_multi_unit_recursive_bom(self): # Test multi-level and multi-units BOM - uom_unit = self.env.ref('uom.product_uom_unit') + uom_unit = self.env.ref("uom.product_uom_unit") uom_unit.rounding = 1.0 - p1 = self.product_model.create({ - 'name': 'Test product with BOM', - 'type': 'product', - 'uom_id': self.env.ref('uom.product_uom_unit').id, - }) + p1 = self.product_model.create( + { + "name": "Test product with BOM", + "type": "product", + "uom_id": self.env.ref("uom.product_uom_unit").id, + } + ) - p2 = self.product_model.create({ - 'name': 'Test sub product with BOM', - 'type': 'consu', - 'uom_id': self.env.ref('uom.product_uom_unit').id, - }) + p2 = self.product_model.create( + { + "name": "Test sub product with BOM", + "type": "consu", + "uom_id": self.env.ref("uom.product_uom_unit").id, + } + ) - p3 = self.product_model.create({ - 'name': 'Test component', - 'type': 'product', - 'uom_id': self.env.ref('uom.product_uom_unit').id, - }) + p3 = self.product_model.create( + { + "name": "Test component", + "type": "product", + "uom_id": self.env.ref("uom.product_uom_unit").id, + } + ) - bom_p1 = self.bom_model.create({ - 'product_tmpl_id': p1.product_tmpl_id.id, - 'product_id': p1.id, - }) + bom_p1 = self.bom_model.create( + {"product_tmpl_id": p1.product_tmpl_id.id, "product_id": p1.id,} + ) - self.bom_line_model.create({ - 'bom_id': bom_p1.id, - 'product_id': p3.id, - 'product_qty': 1, - 'product_uom_id': self.env.ref('uom.product_uom_unit').id, - - }) + self.bom_line_model.create( + { + "bom_id": bom_p1.id, + "product_id": p3.id, + "product_qty": 1, + "product_uom_id": self.env.ref("uom.product_uom_unit").id, + } + ) # Two p2 which have a bom - self.bom_line_model.create({ - 'bom_id': bom_p1.id, - 'product_id': p2.id, - 'product_qty': 2, - 'product_uom_id': self.env.ref('uom.product_uom_unit').id, + self.bom_line_model.create( + { + "bom_id": bom_p1.id, + "product_id": p2.id, + "product_qty": 2, + "product_uom_id": self.env.ref("uom.product_uom_unit").id, + } + ) - }) - - bom_p2 = self.bom_model.create({ - 'product_tmpl_id': p2.product_tmpl_id.id, - 'product_id': p2.id, - 'type': 'phantom', - }) + bom_p2 = self.bom_model.create( + { + "product_tmpl_id": p2.product_tmpl_id.id, + "product_id": p2.id, + "type": "phantom", + } + ) # p2 need 2 unit of component - self.bom_line_model.create({ - 'bom_id': bom_p2.id, - 'product_id': p3.id, - 'product_qty': 2, - 'product_uom_id': self.env.ref('uom.product_uom_unit').id, - - }) + self.bom_line_model.create( + { + "bom_id": bom_p2.id, + "product_id": p3.id, + "product_qty": 2, + "product_uom_id": self.env.ref("uom.product_uom_unit").id, + } + ) p1.refresh() @@ -369,12 +427,11 @@ class TestPotentialQty(TransactionCase): # a recordset with multiple products # Recursive compute is not working - p1 = self.product_model.create({'name': 'Test P1'}) - p2 = self.product_model.create({'name': 'Test P2'}) - p3 = self.product_model.create({'name': 'Test P3', 'type': 'product'}) + p1 = self.product_model.create({"name": "Test P1"}) + p2 = self.product_model.create({"name": "Test P2"}) + p3 = self.product_model.create({"name": "Test P3", "type": "product"}) - self.config.set_param('stock_available_mrp_based_on', - 'immediately_usable_qty') + self.config.set_param("stock_available_mrp_based_on", "immediately_usable_qty") # P1 need one P2 self.create_simple_bom(p1, p2) @@ -385,11 +442,9 @@ class TestPotentialQty(TransactionCase): self.product_model.invalidate_cache() - products = self.product_model.search( - [('id', 'in', [p1.id, p2.id, p3.id])] - ) + products = self.product_model.search([("id", "in", [p1.id, p2.id, p3.id])]) self.assertEqual( {p1.id: 3.0, p2.id: 3.0, p3.id: 0.0}, - {p.id: p.potential_qty for p in products} + {p.id: p.potential_qty for p in products}, )