Skip to content

Commit

Permalink
Merge PR #1367 into 16.0
Browse files Browse the repository at this point in the history
Signed-off-by LoisRForgeFlow
  • Loading branch information
OCA-git-bot committed Nov 7, 2024
2 parents faca5c1 + 33cf4af commit 3f3d838
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 20 deletions.
7 changes: 5 additions & 2 deletions mrp_multi_level/models/mrp_inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,11 @@ def _compute_uom_id(self):
@api.depends("planned_order_ids", "planned_order_ids.qty_released")
def _compute_to_procure(self):
for rec in self:
rec.to_procure = sum(rec.planned_order_ids.mapped("mrp_qty")) - sum(
rec.planned_order_ids.mapped("qty_released")
rec.to_procure = (
0.0
if rec.supply_method == "phantom"
else sum(rec.planned_order_ids.mapped("mrp_qty"))
- sum(rec.planned_order_ids.mapped("qty_released"))
)

@api.depends(
Expand Down
1 change: 1 addition & 0 deletions mrp_multi_level/models/mrp_planned_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class MrpPlannedOrder(models.Model):
mrp_action = fields.Selection(
selection=[
("manufacture", "Manufacturing Order"),
("phantom", "Kit"),
("buy", "Purchase Order"),
("pull", "Pull From"),
("push", "Push To"),
Expand Down
4 changes: 0 additions & 4 deletions mrp_multi_level/models/product_mrp_area.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,3 @@ def _to_be_exploded(self):
def _get_locations(self):
self.ensure_one()
return self.mrp_area_id._get_locations()

def _should_create_planned_order(self):
self.ensure_one()
return not self.supply_method == "phantom"
57 changes: 52 additions & 5 deletions mrp_multi_level/tests/test_mrp_multi_level.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,11 +401,8 @@ def test_16_phantom_comp_planning(self):
sf_3_planned_order_1 = self.planned_order_obj.search(
[("product_mrp_area_id.product_id", "=", self.sf_3.id)]
)
self.assertEqual(len(sf_3_planned_order_1), 0)
sf_3_mrp_parameter = self.product_mrp_area_obj.search(
[("product_id", "=", self.sf_3.id)]
)
self.assertEqual(sf_3_mrp_parameter.supply_method, "phantom")
self.assertEqual(sf_3_planned_order_1.mrp_action, "phantom")
self.assertEqual(sf_3_planned_order_1.mrp_qty, 10.0)
# PP-3
pp_3_line_1 = self.mrp_inventory_obj.search(
[("product_mrp_area_id.product_id", "=", self.pp_3.id)]
Expand Down Expand Up @@ -852,3 +849,53 @@ def test_24_prioritize_safety_stock_with_mrp_moves_today_grouped(self):
f"unexpected value for {key}: {inv[key]} "
f"(expected {test_vals[key]} on {inv.date})",
)

def test_25_phantom_comp_on_hand(self):
"""
A phantom product with positive qty_available (which is computed from the
availability of its components) should not satisfy demand, because this leads
to double counting qty_available of its component products.
"""
quant = self.quant_obj.sudo().create(
{
"product_id": self.pp_3.id,
"inventory_quantity": 10.0,
"location_id": self.stock_location.id,
}
)
quant.action_apply_inventory()
quant = self.quant_obj.sudo().create(
{
"product_id": self.pp_4.id,
"inventory_quantity": 30.0,
"location_id": self.stock_location.id,
}
)
quant.action_apply_inventory()
self.assertEqual(self.sf_3.qty_available, 10.0)
self.mrp_multi_level_wiz.create({}).run_mrp_multi_level()
# PP-3
pp_3_line_1 = self.mrp_inventory_obj.search(
[("product_mrp_area_id.product_id", "=", self.pp_3.id)]
)
self.assertEqual(len(pp_3_line_1), 1)
self.assertEqual(pp_3_line_1.demand_qty, 20.0)
self.assertEqual(pp_3_line_1.to_procure, 10.0)
pp_3_planned_orders = self.planned_order_obj.search(
[("product_mrp_area_id.product_id", "=", self.pp_3.id)]
)
self.assertEqual(len(pp_3_planned_orders), 1)
self.assertEqual(pp_3_planned_orders.mrp_qty, 10)
sf3_planned_orders = self.env["mrp.planned.order"].search(
[("product_id", "=", self.sf_3.id)]
)
self.assertEqual(len(sf3_planned_orders), 1)
# Trying to procure a kit planned order will have no effect.
procure_wizard = (
self.env["mrp.inventory.procure"]
.with_context(
active_model="mrp.planned.order", active_ids=sf3_planned_orders.ids
)
.create({})
)
self.assertEqual(len(procure_wizard.item_ids), 0)
6 changes: 5 additions & 1 deletion mrp_multi_level/views/mrp_planned_order_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
<field name="name">mrp.planned.order.tree</field>
<field name="model">mrp.planned.order</field>
<field name="arch" type="xml">
<tree decoration-info="fixed != True">
<tree
decoration-info="fixed != True and mrp_action != 'phantom'"
decoration-muted="mrp_action == 'phantom'"
>
<field name="name" />
<field name="origin" />
<field name="product_mrp_area_id" />
Expand All @@ -17,6 +20,7 @@
<field name="qty_released" />
<field name="mrp_qty" />
<field name="fixed" />
<field name="mrp_action" optional="hide" />
</tree>
</field>
</record>
Expand Down
2 changes: 2 additions & 0 deletions mrp_multi_level/wizards/mrp_inventory_procure.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ def default_get(self, fields):
elif active_model == "mrp.planned.order":
mrp_planned_order_obj = self.env[active_model]
for line in mrp_planned_order_obj.browse(active_ids):
if line.mrp_action == "phantom":
continue
if line.qty_released < line.mrp_qty:
items += item_obj.create(self._prepare_item(line))
if items:
Expand Down
26 changes: 18 additions & 8 deletions mrp_multi_level/wizards/mrp_multi_level.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,7 @@ def create_planned_order(
order_data = self._prepare_planned_order_data(
product_mrp_area_id, qty, mrp_date_supply, mrp_action_date, name, values
)
# Do not create planned order for products that are Kits
planned_order = False
if product_mrp_area_id._should_create_planned_order():
planned_order = self.env["mrp.planned.order"].create(order_data)
planned_order = self.env["mrp.planned.order"].create(order_data)
qty_ordered = qty_ordered + qty

if product_mrp_area_id._to_be_exploded():
Expand Down Expand Up @@ -536,7 +533,11 @@ def _get_qty_to_order(self, product_mrp_area, date, move_qty, onhand):
def _init_mrp_move_grouped_demand(self, product_mrp_area):
last_date = None
last_qty = 0.00
onhand = product_mrp_area.qty_available
onhand = (
0.0
if product_mrp_area.supply_method == "phantom"
else product_mrp_area.qty_available
)
grouping_delta = product_mrp_area.mrp_nbr_days
demand_origin = []

Expand Down Expand Up @@ -666,7 +667,11 @@ def _get_safety_stock_target_date(self, product_mrp_area):

@api.model
def _init_mrp_move_non_grouped_demand(self, product_mrp_area):
onhand = product_mrp_area.qty_available
onhand = (
0.0
if product_mrp_area.supply_method == "phantom"
else product_mrp_area.qty_available
)
for move in product_mrp_area.mrp_move_ids:
if self._exclude_move(move):
continue
Expand Down Expand Up @@ -815,7 +820,8 @@ def _prepare_mrp_inventory_data(
supply_qty = supply_qty_by_date.get(mdt, 0.0)
mrp_inventory_data["supply_qty"] = abs(supply_qty)
mrp_inventory_data["initial_on_hand_qty"] = on_hand_qty
on_hand_qty += supply_qty + demand_qty
if product_mrp_area.supply_method != "phantom":
on_hand_qty += supply_qty + demand_qty
mrp_inventory_data["final_on_hand_qty"] = on_hand_qty
# Consider that MRP plan is followed exactly:
running_availability += (
Expand Down Expand Up @@ -854,7 +860,11 @@ def _init_mrp_inventory(self, product_mrp_area):
[("product_mrp_area_id", "=", product_mrp_area.id)], order="due_date"
).mapped("due_date")
mrp_dates = set(moves_dates + action_dates)
on_hand_qty = product_mrp_area.qty_available
on_hand_qty = (
0.0
if product_mrp_area.supply_method == "phantom"
else product_mrp_area.qty_available
)
running_availability = on_hand_qty
mrp_inventory_vals = []
for mdt in sorted(mrp_dates):
Expand Down

0 comments on commit 3f3d838

Please sign in to comment.