Skip to content

Commit

Permalink
[MIG] mrp_production_auto_validate: Migration to 18.0
Browse files Browse the repository at this point in the history
  • Loading branch information
chaule97 committed Feb 3, 2025
1 parent cffa538 commit 667df2b
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 88 deletions.
8 changes: 8 additions & 0 deletions mrp_production_auto_validate/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ Contributors

- Sébastien Alix <[email protected]>
- Simone Orsi <[email protected]>
- Chau Le <[email protected]>

Other credits
-------------

The development of this module has been financially supported by:

- Camptocamp

Maintainers
-----------
Expand Down
2 changes: 1 addition & 1 deletion mrp_production_auto_validate/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{
"name": "Manufacturing Order Auto-Validate",
"summary": "Manufacturing Order Auto-Validation when components are picked",
"version": "14.0.1.0.0",
"version": "18.0.1.0.0",
"license": "AGPL-3",
"website": "https://github.com/OCA/manufacture",
"author": "Camptocamp, Odoo Community Association (OCA)",
Expand Down
19 changes: 2 additions & 17 deletions mrp_production_auto_validate/models/mrp_bom.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright 2022 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

from odoo import _, api, fields, models
from odoo import api, fields, models


class MrpBom(models.Model):
Expand All @@ -15,24 +15,9 @@ class MrpBom(models.Model):
"This behavior is available only if the warehouse is configured "
"with 2 or 3 steps."
),
default=False,
)
mo_auto_validation_warning = fields.Char(
string="Order Auto Validation (warning)",
compute="_compute_mo_auto_validation_warning",
)

@api.onchange("type")
def onchange_type_auto_validation(self):
if self.type != "normal":
self.mo_auto_validation = self.mo_auto_validation_warning = False

@api.depends("mo_auto_validation")
def _compute_mo_auto_validation_warning(self):
for bom in self:
bom.mo_auto_validation_warning = False
if bom.mo_auto_validation:
bom.mo_auto_validation_warning = _(
"The Quantity To Produce of an order is now "
"restricted to the BoM Quantity."
)
self.mo_auto_validation = False

Check warning on line 23 in mrp_production_auto_validate/models/mrp_bom.py

View check run for this annotation

Codecov / codecov/patch

mrp_production_auto_validate/models/mrp_bom.py#L23

Added line #L23 was not covered by tests
85 changes: 44 additions & 41 deletions mrp_production_auto_validate/models/mrp_production.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import logging

from odoo import _, api, exceptions, fields, models, tools
from odoo import api, exceptions, fields, models, tools

_logger = logging.getLogger(__name__)

Expand All @@ -12,36 +12,38 @@ class MrpProduction(models.Model):
_inherit = "mrp.production"

auto_validate = fields.Boolean(
string="Auto Validate",
compute="_compute_auto_validate",
store=True,
states={"draft": [("readonly", False)]},
)

@api.constrains("bom_id", "auto_validate", "product_qty")
def check_bom_auto_validate(self):
bypass_check = self.env.context.get("disable_check_mo_auto_validate")
if bypass_check:
return

for mo in self:
# FIXME: Handle different UOM between BOM and MO
qty_ok = (
tools.float_compare(
mo.product_qty,
mo.bom_id.product_qty,
precision_rounding=mo.product_uom_id.rounding,
if mo.bom_id:
qty_in_mo_uom = mo.bom_id.product_uom_id._compute_quantity(
mo.bom_id.product_qty, mo.product_uom_id
)
== 0
)
bypass_check = self.env.context.get("disable_check_mo_auto_validate")
if bypass_check:
return
if mo.bom_id and mo.auto_validate and not qty_ok:
raise exceptions.ValidationError(
_(
"The quantity to produce is restricted to {qty} "
"as the BoM is configured with the "
"'Order Auto Validation' option."
).format(qty=mo.bom_id.product_qty)

qty_ok = tools.float_is_zero(
mo.product_qty - qty_in_mo_uom,
precision_rounding=mo.product_uom_id.rounding,
)

if mo.auto_validate and not qty_ok:
raise exceptions.ValidationError(
self.env._(
"The quantity to produce is restricted to %(qty)s %(uom)s "
"as the BoM is configured with the "
"'Order Auto Validation' option.",
qty=mo.bom_id.product_qty,
uom=mo.bom_id.product_uom_id.name,
)
)

@api.depends("bom_id.mo_auto_validation", "state")
def _compute_auto_validate(self):
for prod in self:
Expand Down Expand Up @@ -79,12 +81,13 @@ def handle_mark_done_result(self, res):
return True

Check warning on line 81 in mrp_production_auto_validate/models/mrp_production.py

View check run for this annotation

Codecov / codecov/patch

mrp_production_auto_validate/models/mrp_production.py#L80-L81

Added lines #L80 - L81 were not covered by tests
return handler(res)

def _handle_wiz_mrp_immediate_production(self, action):
def _handle_wiz_mrp_batch_produce(self, action):
wiz_model = self.env[action["res_model"]].with_context(
**action.get("context", {})
)
wiz = wiz_model.create({})
return wiz.process()
wiz.action_generate_production_text()
return wiz.action_done()

def _handle_wiz_mrp_production_backorder(self, action):
wiz_model = self.env[action["res_model"]].with_context(

Check warning on line 93 in mrp_production_auto_validate/models/mrp_production.py

View check run for this annotation

Codecov / codecov/patch

mrp_production_auto_validate/models/mrp_production.py#L93

Added line #L93 was not covered by tests
Expand Down Expand Up @@ -153,15 +156,15 @@ def adapt_values_qty_for_auto_validation(self, values_list):
procure_qty = values.get("product_qty")
values["product_qty"] = bom_qty
values["product_uom_id"] = bom_uom.id
msg = _(
"Quantity in procurement (%s %s) was increased to %s %s due to auto "
msg = self.env._(
"Quantity in procurement (%(product_qty)s %(product_uom_name)s) "
"was increased to %(bom_qty)s %(bom_uom_name)s due to auto "
"validation feature preventing to create an MO with a different "
"qty than defined on the BOM."
) % (
procure_qty,
create_uom.display_name,
bom_qty,
bom_uom.display_name,
"qty than defined on the BOM.",
product_qty=procure_qty,
product_uom_name=create_uom.display_name,
bom_qty=bom_qty,
bom_uom_name=bom_uom.display_name,
)
messages_to_post[len(new_values_list)] = msg
new_values_list.append(values)
Expand All @@ -175,16 +178,16 @@ def adapt_values_qty_for_auto_validation(self, values_list):
new_values = values.copy()
new_values["product_qty"] = bom_qty
new_values["product_uom_id"] = bom_uom.id
msg = _(
"Quantity in procurement (%s %s) was split to multiple production "
"orders of %s %s due to auto validation feature preventing to "
"set a quantity to produce different than the quantity defined "
"on the Bill of Materials."
) % (
values.get("product_qty"),
create_uom.display_name,
bom_qty,
bom_uom.display_name,
msg = self.env._(
"Quantity in procurement (%(product_qty)s %(product_uom_name)s) "
"was split to multiple production orders of %(bom_qty)s "
"%(bom_uom_name)s due to auto validation feature preventing to set "
"a quantity to produce different than the quantity defined "
"on the Bill of Materials.",
product_qty=values.get("product_qty"),
product_uom_name=create_uom.display_name,
bom_qty=bom_qty,
bom_uom_name=bom_uom.display_name,
)
messages_to_post[len(new_values_list)] = msg
new_values_list.append(new_values)
Expand Down
2 changes: 1 addition & 1 deletion mrp_production_auto_validate/models/stock_picking.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def _get_manufacturing_orders(self, states=None):
self.ensure_one()
if states is None:
states = ("confirmed", "progress")
return self.move_lines.move_dest_ids.raw_material_production_id.filtered(
return self.move_ids.move_dest_ids.raw_material_production_id.filtered(
lambda o: o.state in states
)

Expand Down
1 change: 1 addition & 0 deletions mrp_production_auto_validate/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
- Sébastien Alix \<<[email protected]>\>
- Simone Orsi \<<[email protected]>\>
- Chau Le \<<[email protected]>\>
3 changes: 3 additions & 0 deletions mrp_production_auto_validate/readme/CREDITS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The development of this module has been financially supported by:

- Camptocamp
13 changes: 11 additions & 2 deletions mrp_production_auto_validate/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,8 @@ <h1 class="title">Manufacturing Order Auto-Validate</h1>
<li><a class="reference internal" href="#credits" id="toc-entry-6">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-7">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-8">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-9">Maintainers</a></li>
<li><a class="reference internal" href="#other-credits" id="toc-entry-9">Other credits</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-10">Maintainers</a></li>
</ul>
</li>
</ul>
Expand Down Expand Up @@ -442,10 +443,18 @@ <h2><a class="toc-backref" href="#toc-entry-8">Contributors</a></h2>
<ul class="simple">
<li>Sébastien Alix &lt;<a class="reference external" href="mailto:sebastien.alix&#64;camptocamp.com">sebastien.alix&#64;camptocamp.com</a>&gt;</li>
<li>Simone Orsi &lt;<a class="reference external" href="mailto:simone.orsi&#64;camptocamp.com">simone.orsi&#64;camptocamp.com</a>&gt;</li>
<li>Chau Le &lt;<a class="reference external" href="mailto:chaulb&#64;trobz.com">chaulb&#64;trobz.com</a>&gt;</li>
</ul>
</div>
<div class="section" id="other-credits">
<h2><a class="toc-backref" href="#toc-entry-9">Other credits</a></h2>
<p>The development of this module has been financially supported by:</p>
<ul class="simple">
<li>Camptocamp</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-9">Maintainers</a></h2>
<h2><a class="toc-backref" href="#toc-entry-10">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
Expand Down
31 changes: 15 additions & 16 deletions mrp_production_auto_validate/tests/test_auto_validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

from odoo.exceptions import ValidationError
from odoo.tests.common import Form, SavepointCase
from odoo.tests import Form

from odoo.addons.base.tests.common import BaseCommon

class TestManufacturingOrderAutoValidate(SavepointCase):

class TestManufacturingOrderAutoValidate(BaseCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
# Configure the WH to manufacture in at least two steps to get a
# "pick components" transfer operation
cls.wh = cls.env.ref("stock.warehouse0")
Expand Down Expand Up @@ -48,33 +49,29 @@ def _create_manufacturing_order(cls, bom, product_qty=1):
form.bom_id = bom
form.product_qty = product_qty
order = form.save()
order.invalidate_cache()
order.invalidate_model()
return order

@classmethod
def _validate_picking(cls, picking, moves=None):
"""Validate a stock transfer.
`moves` can be set with a list of tuples [(move, quantity_done)] to
`moves` can be set with a list of tuples [(move, quantity)] to
process the transfer partially.
"""
if moves is None:
moves = []
for move in picking.move_lines:
for move in picking.move_ids:
# Try to match a move to set a given qty
for move2, qty_done in moves:
if move == move2:
move.quantity_done = qty_done
move.quantity = qty_done
break
else:
move.quantity_done = move.product_uom_qty
move.quantity = move.product_uom_qty
move.picked = True
picking._action_done()

def test_bom_alert(self):
self.assertIn(
"restricted to the BoM Quantity", self.bom.mo_auto_validation_warning
)

def test_get_manufacturing_orders_pbm(self):
"""Get the MO from transfers in a 2 steps configuration."""
# WH already configured as 'Pick components and then manufacture (2 steps)'
Expand All @@ -91,10 +88,12 @@ def test_get_manufacturing_orders_pbm_sam(self):
picking_pick = order.picking_ids.filtered(
lambda o: "Pick" in o.picking_type_id.name
)
self.assertEqual(picking_pick._get_manufacturing_orders(), order)
picking_pick.action_assign()
self._validate_picking(picking_pick)
picking_store = order.picking_ids.filtered(
lambda o: "Store" in o.picking_type_id.name
)
self.assertEqual(picking_pick._get_manufacturing_orders(), order)
self.assertFalse(picking_store._get_manufacturing_orders())

def test_create_order_too_much_qty_to_produce(self):
Expand Down Expand Up @@ -154,9 +153,9 @@ def test_auto_validate_with_not_enough_components(self):
picking = order.picking_ids
picking.action_assign()
self.assertEqual(picking.state, "assigned")
self._validate_picking(picking, moves=[(picking.move_lines, 1)])
self._validate_picking(picking, moves=[(picking.move_ids, 1)])
self.assertEqual(picking.state, "done")
self.assertEqual(picking.backorder_ids.move_lines.product_uom_qty, 3)
self.assertEqual(picking.backorder_ids.move_ids.product_uom_qty, 3)
# Check that no MO gets validated in the process
order_done = picking._get_manufacturing_orders(states=("done",))
self.assertFalse(order_done)
Expand Down
18 changes: 8 additions & 10 deletions mrp_production_auto_validate/views/mrp_bom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,16 @@
<field name="inherit_id" ref="mrp.mrp_bom_form_view" />
<field name="arch" type="xml">
<field name="type" position="after">
<field
name="mo_auto_validation"
attrs="{'invisible': [('type', '!=', 'normal')]}"
/>
<field
name="mo_auto_validation_warning"
nolabel="1"
colspan="2"
<field name="mo_auto_validation" invisible="type != 'normal'" />
<div
class="alert alert-warning"
colspan="2"
role="alert"
attrs="{'invisible': ['|', ('type', '!=', 'normal'), ('mo_auto_validation', '=', False)]}"
/>
invisible="type != 'normal' or mo_auto_validation == False"
>
<span
>The Quantity To Produce of an order is now restricted to the BoM Quantity.</span>
</div>
</field>
</field>
</record>
Expand Down
1 change: 1 addition & 0 deletions mrp_production_auto_validate/wizards/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from . import mrp_batch_produce
from . import mrp_production_backorder
14 changes: 14 additions & 0 deletions mrp_production_auto_validate/wizards/mrp_batch_produce.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright 2025 Camptocamp
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

from odoo import models


class MrpBatchProduct(models.TransientModel):
_inherit = "mrp.batch.produce"

def action_done(self):
# Bypass the 'auto_validate' constraint regarding qty to produce
# when creating a backorder.
self = self.with_context(disable_check_mo_auto_validate=True)
return super().action_done()

0 comments on commit 667df2b

Please sign in to comment.