[IMP] stock_whole_kit_constraint: black, isort, prettier

This commit is contained in:
david
2021-09-28 12:20:05 +02:00
committed by ferran-73
parent 80fc3b5c45
commit e4fb8707c7
6 changed files with 70 additions and 79 deletions

View File

@@ -9,8 +9,6 @@
"author": "Tecnativa, Odoo Community Association (OCA)", "author": "Tecnativa, Odoo Community Association (OCA)",
"license": "AGPL-3", "license": "AGPL-3",
"installable": True, "installable": True,
"depends": [ "depends": ["mrp"],
"mrp", "data": ["views/product_template_views.xml"],
],
"data": ["views/product_template_views.xml"]
} }

View File

@@ -9,5 +9,5 @@ class ProductTemplate(models.Model):
allow_partial_kit_delivery = fields.Boolean( allow_partial_kit_delivery = fields.Boolean(
default=True, default=True,
help="If not set, and this product is delivered with a BoM of type " help="If not set, and this product is delivered with a BoM of type "
"kit, partial deliveries of the components won't be allowed.", "kit, partial deliveries of the components won't be allowed.",
) )

View File

@@ -7,13 +7,10 @@ class StockMove(models.Model):
_inherit = "stock.move" _inherit = "stock.move"
allow_partial_kit_delivery = fields.Boolean( allow_partial_kit_delivery = fields.Boolean(
compute="_compute_allow_partial_kit_delivery", compute="_compute_allow_partial_kit_delivery", compute_sudo=True,
compute_sudo=True,
) )
@api.depends( @api.depends("product_id.product_tmpl_id.allow_partial_kit_delivery", "state")
"product_id.product_tmpl_id.allow_partial_kit_delivery", "state"
)
def _compute_allow_partial_kit_delivery(self): def _compute_allow_partial_kit_delivery(self):
"""Take it from the product only if it's a kit""" """Take it from the product only if it's a kit"""
self.write({"allow_partial_kit_delivery": True}) self.write({"allow_partial_kit_delivery": True})
@@ -21,9 +18,7 @@ class StockMove(models.Model):
lambda x: x.product_id and x.state not in ["done", "cancel"] lambda x: x.product_id and x.state not in ["done", "cancel"]
): ):
# If it isn't a kit it will always be True # If it isn't a kit it will always be True
if ( if not move.bom_line_id or move.bom_line_id.bom_id.type != "phantom":
not move.bom_line_id or move.bom_line_id.bom_id.type != "phantom"
):
move.allow_partial_kit_delivery = True move.allow_partial_kit_delivery = True
continue continue
move.allow_partial_kit_delivery = ( move.allow_partial_kit_delivery = (
@@ -48,7 +43,7 @@ class StockMove(models.Model):
quantity_todo[move.product_id.id] += move.product_uom_qty quantity_todo[move.product_id.id] += move.product_uom_qty
quantity_done[move.product_id.id] += move.quantity_done quantity_done[move.product_id.id] += move.quantity_done
for ops in self.mapped("move_line_ids").filtered( for ops in self.mapped("move_line_ids").filtered(
lambda x: x.package_id and not x.product_id and not x.move_id lambda x: x.package_id and not x.product_id and not x.move_id
): ):
for quant in ops.package_id.quant_ids: for quant in ops.package_id.quant_ids:
quantity_done.setdefault(quant.product_id.id, 0) quantity_done.setdefault(quant.product_id.id, 0)
@@ -57,12 +52,7 @@ class StockMove(models.Model):
lambda x: x.product_id and not x.move_id lambda x: x.product_id and not x.move_id
): ):
quantity_done.setdefault(pack.product_id.id, 0) quantity_done.setdefault(pack.product_id.id, 0)
quantity_done[pack.product_id.id] += ( quantity_done[pack.product_id.id] += pack.product_uom_id._compute_quantity(
pack.product_uom_id._compute_quantity( pack.qty_done, pack.product_id.uom_id
pack.qty_done, pack.product_id.uom_id
)
) )
return any( return any(quantity_done[x] < quantity_todo.get(x, 0) for x in quantity_done)
quantity_done[x] < quantity_todo.get(x, 0)
for x in quantity_done
)

View File

@@ -20,8 +20,10 @@ class StockPicking(models.Model):
if not sum(bom_moves.mapped("quantity_done")): if not sum(bom_moves.mapped("quantity_done")):
continue continue
if bom_moves._check_backorder_moves(): if bom_moves._check_backorder_moves():
raise ValidationError(_( raise ValidationError(
"You can't make a partial delivery of components of the " _(
"%s kit" % bom.product_tmpl_id.display_name "You can't make a partial delivery of components of the "
)) "%s kit" % bom.product_tmpl_id.display_name
)
)
return super()._check_backorder() return super()._check_backorder()

View File

@@ -1,29 +1,24 @@
# Copyright 2021 Tecnativa - David Vidal # Copyright 2021 Tecnativa - David Vidal
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo.tests import Form, common
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError
from odoo.tests import Form, common
class TestStockWholeKitConstraint(common.SavepointCase): class TestStockWholeKitConstraint(common.SavepointCase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
super().setUpClass() super().setUpClass()
cls.customer = cls.env["res.partner"].create({ cls.customer = cls.env["res.partner"].create({"name": "Mr. Odoo"})
"name": "Mr. Odoo",
})
# Kit 1 that can be partially delivered # Kit 1 that can be partially delivered
cls.product_kit_1 = cls.env["product.product"].create({ cls.product_kit_1 = cls.env["product.product"].create(
"name": "Product Kit 1", {"name": "Product Kit 1", "type": "consu"}
"type": "consu", )
}) cls.component_1_kit_1 = cls.env["product.product"].create(
cls.component_1_kit_1 = cls.env["product.product"].create({ {"name": "Component 1 Kit 1", "type": "product"}
"name": "Component 1 Kit 1", )
"type": "product", cls.component_2_kit_1 = cls.env["product.product"].create(
}) {"name": "Component 2 Kit 1", "type": "product"}
cls.component_2_kit_1 = cls.env["product.product"].create({ )
"name": "Component 2 Kit 1",
"type": "product",
})
bom_form = Form(cls.env["mrp.bom"]) bom_form = Form(cls.env["mrp.bom"])
bom_form.product_tmpl_id = cls.product_kit_1.product_tmpl_id bom_form.product_tmpl_id = cls.product_kit_1.product_tmpl_id
bom_form.product_id = cls.product_kit_1 bom_form.product_id = cls.product_kit_1
@@ -34,19 +29,19 @@ class TestStockWholeKitConstraint(common.SavepointCase):
line.product_id = cls.component_2_kit_1 line.product_id = cls.component_2_kit_1
cls.bom_kit_1 = bom_form.save() cls.bom_kit_1 = bom_form.save()
# Kit 2 - disallow partial deliveries # Kit 2 - disallow partial deliveries
cls.product_kit_2 = cls.env["product.product"].create({ cls.product_kit_2 = cls.env["product.product"].create(
"name": "Product Kit 2", {
"type": "consu", "name": "Product Kit 2",
"allow_partial_kit_delivery": False, "type": "consu",
}) "allow_partial_kit_delivery": False,
cls.component_1_kit_2 = cls.env["product.product"].create({ }
"name": "Component 1 Kit 2", )
"type": "product", cls.component_1_kit_2 = cls.env["product.product"].create(
}) {"name": "Component 1 Kit 2", "type": "product"}
cls.component_2_kit_2 = cls.env["product.product"].create({ )
"name": "Component 2 Kit 2", cls.component_2_kit_2 = cls.env["product.product"].create(
"type": "product", {"name": "Component 2 Kit 2", "type": "product"}
}) )
bom_form = Form(cls.env["mrp.bom"]) bom_form = Form(cls.env["mrp.bom"])
bom_form.product_tmpl_id = cls.product_kit_2.product_tmpl_id bom_form.product_tmpl_id = cls.product_kit_2.product_tmpl_id
bom_form.product_id = cls.product_kit_2 bom_form.product_id = cls.product_kit_2
@@ -57,13 +52,15 @@ class TestStockWholeKitConstraint(common.SavepointCase):
line.product_id = cls.component_2_kit_2 line.product_id = cls.component_2_kit_2
cls.bom_kit_2 = bom_form.save() cls.bom_kit_2 = bom_form.save()
# Manufactured product as control # Manufactured product as control
cls.product_mrp = cls.env["product.product"].create({ cls.product_mrp = cls.env["product.product"].create(
"name": "Product Kit 2", {
"type": "consu", "name": "Product Kit 2",
# Force the setting in a manufactured product. "type": "consu",
# It should not affect it # Force the setting in a manufactured product.
"allow_partial_kit_delivery": False, # It should not affect it
}) "allow_partial_kit_delivery": False,
}
)
bom_form = Form(cls.env["mrp.bom"]) bom_form = Form(cls.env["mrp.bom"])
bom_form.product_tmpl_id = cls.product_mrp.product_tmpl_id bom_form.product_tmpl_id = cls.product_mrp.product_tmpl_id
bom_form.product_id = cls.product_mrp bom_form.product_id = cls.product_mrp
@@ -72,12 +69,14 @@ class TestStockWholeKitConstraint(common.SavepointCase):
line.product_id = cls.component_1_kit_2 line.product_id = cls.component_1_kit_2
cls.bom_mrp = bom_form.save() cls.bom_mrp = bom_form.save()
# Not a kit product as control # Not a kit product as control
cls.regular_product = cls.env["product.product"].create({ cls.regular_product = cls.env["product.product"].create(
"name": "Regular test product", {
"type": "product", "name": "Regular test product",
# Force the setting in a regular product. It should not affect it "type": "product",
"allow_partial_kit_delivery": False, # Force the setting in a regular product. It should not affect it
}) "allow_partial_kit_delivery": False,
}
)
# Delivery picking # Delivery picking
picking_form = Form(cls.env["stock.picking"]) picking_form = Form(cls.env["stock.picking"])
picking_form.picking_type_id = cls.env.ref("stock.picking_type_out") picking_form.picking_type_id = cls.env.ref("stock.picking_type_out")
@@ -105,9 +104,7 @@ class TestStockWholeKitConstraint(common.SavepointCase):
) )
moves_allowed.write({"quantity_done": 1}) moves_allowed.write({"quantity_done": 1})
response = self.customer_picking.button_validate() response = self.customer_picking.button_validate()
self.assertEqual( self.assertEqual("stock.backorder.confirmation", response.get("res_model"))
"stock.backorder.confirmation", response.get("res_model")
)
def test_02_all_done_but_partial_disallow_partial_kit(self): def test_02_all_done_but_partial_disallow_partial_kit(self):
"""We try to deliver partially the disallowed kit""" """We try to deliver partially the disallowed kit"""
@@ -121,9 +118,7 @@ class TestStockWholeKitConstraint(common.SavepointCase):
moves_disallowed.write({"quantity_done": 3}) moves_disallowed.write({"quantity_done": 3})
# We've got a backorder on the rest of the lines # We've got a backorder on the rest of the lines
response = self.customer_picking.button_validate() response = self.customer_picking.button_validate()
self.assertEqual( self.assertEqual("stock.backorder.confirmation", response.get("res_model"))
"stock.backorder.confirmation", response.get("res_model")
)
def test_03_all_done(self): def test_03_all_done(self):
"""Deliver the whole picking normally""" """Deliver the whole picking normally"""

View File

@@ -1,23 +1,29 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8" ?>
<odoo> <odoo>
<record model="ir.ui.view" id="product_template_form_view_bom_button"> <record model="ir.ui.view" id="product_template_form_view_bom_button">
<field name="model">product.template</field> <field name="model">product.template</field>
<field name="inherit_id" ref="mrp.product_template_form_view_bom_button"/> <field name="inherit_id" ref="mrp.product_template_form_view_bom_button" />
<field name="groups_id" eval="[(4, ref('stock.group_stock_manager'))]" /> <field name="groups_id" eval="[(4, ref('stock.group_stock_manager'))]" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//group[@name='group_lots_and_weight']" position="inside"> <xpath expr="//group[@name='group_lots_and_weight']" position="inside">
<field name="allow_partial_kit_delivery" attrs="{'invisible': [('bom_count', '=', 0), ('type', '!=', 'consu')]}" /> <field
name="allow_partial_kit_delivery"
attrs="{'invisible': [('bom_count', '=', 0), ('type', '!=', 'consu')]}"
/>
</xpath> </xpath>
</field> </field>
</record> </record>
<record id="product_product_form_view_bom_button" model="ir.ui.view"> <record id="product_product_form_view_bom_button" model="ir.ui.view">
<field name="model">product.product</field> <field name="model">product.product</field>
<field name="inherit_id" ref="mrp.product_product_form_view_bom_button"/> <field name="inherit_id" ref="mrp.product_product_form_view_bom_button" />
<field name="groups_id" eval="[(4, ref('stock.group_stock_manager'))]" /> <field name="groups_id" eval="[(4, ref('stock.group_stock_manager'))]" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//group[@name='group_lots_and_weight']" position="inside"> <xpath expr="//group[@name='group_lots_and_weight']" position="inside">
<field name="allow_partial_kit_delivery" attrs="{'invisible': [('bom_count', '=', 0), ('type', '!=', 'consu')]}" /> <field
name="allow_partial_kit_delivery"
attrs="{'invisible': [('bom_count', '=', 0), ('type', '!=', 'consu')]}"
/>
</xpath> </xpath>
</field> </field>
</record> </record>