Skip to content

Commit

Permalink
[MIG] mrp_component_operation: Migration to 17.0
Browse files Browse the repository at this point in the history
  • Loading branch information
ThiagoMForgeFlow committed Jan 22, 2025
1 parent ab0e0d4 commit 58a614d
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 75 deletions.
2 changes: 1 addition & 1 deletion mrp_component_operation/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

{
"name": "MRP Components Operations",
"version": "14.0.1.2.0",
"version": "17.0.1.0.0",
"author": "ForgeFlow, Odoo Community Association (OCA)",
"summary": "Allows to operate the components from a MO",
"website": "https://github.com/OCA/manufacture",
Expand Down
16 changes: 16 additions & 0 deletions mrp_component_operation/migrations/17.0.1.0.0/pre-migration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from openupgradelib import openupgrade


@openupgrade.migrate()
def migrate(env, version):
field_spec = [
(
"mrp_component_operation",
"mrp_component_operation",
"source_location_id",
"manufacture_location_id",
),
]
openupgrade.rename_fields(env=env, field_spec=field_spec, no_deep=True)
2 changes: 1 addition & 1 deletion mrp_component_operation/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from . import mrp_component_operation
from . import mrp_production
from . import stock_location_route
from . import stock_route
8 changes: 4 additions & 4 deletions mrp_component_operation/models/mrp_component_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ class MrpComponentOperation(models.Model):

name = fields.Char(help="Component Operation Reference", required=True)

source_location_id = fields.Many2one(
manufacture_location_id = fields.Many2one(
"stock.location",
"Source Location",
"Manufacture Location",
help="The Location where the components are.",
)

source_route_id = fields.Many2one(
comodel_name="stock.location.route",
comodel_name="stock.route",
string="Source Route",
help="The Route used to pick the components.",
domain=[("mo_component_selectable", "=", True)],
Expand All @@ -30,7 +30,7 @@ class MrpComponentOperation(models.Model):
)

destination_route_id = fields.Many2one(
comodel_name="stock.location.route",
comodel_name="stock.route",
string="Destination Route",
help="The Route used to transfer the components to the destination location.",
domain=[("mo_component_selectable", "=", True)],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from odoo import fields, models


class StockLocationRoute(models.Model):
_inherit = "stock.location.route"
class StockRoute(models.Model):
_inherit = "stock.route"

mo_component_selectable = fields.Boolean(string="Selectable on MO Components")
91 changes: 45 additions & 46 deletions mrp_component_operation/tests/test_component_operate.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).

from odoo import api, fields
from odoo.tests import common
from odoo.tests.common import TransactionCase


class TestComponentOperation(common.SavepointCase):
class TestComponentOperation(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
Expand All @@ -14,7 +14,6 @@ def setUpClass(cls):
cls.ProcurementGroup = cls.env["procurement.group"]
cls.MrpProduction = cls.env["mrp.production"]
cls.env.user.company_id.manufacturing_lead = 0
cls.env.user.tz = False # Make sure there's no timezone in user

cls.picking_type = cls.env["stock.picking.type"].search(
[
Expand All @@ -30,7 +29,6 @@ def setUpClass(cls):
(6, 0, [cls.env.ref("mrp.route_warehouse0_manufacture").id])
],
"type": "product",
"produce_delay": 0,
}
)
cls.product2 = cls.env["product.product"].create(
Expand All @@ -43,6 +41,7 @@ def setUpClass(cls):
{
"product_id": cls.product1.id,
"product_tmpl_id": cls.product1.product_tmpl_id.id,
"produce_delay": 0,
"type": "normal",
"bom_line_ids": [
(0, 0, {"product_id": cls.product2.id, "product_qty": 2}),
Expand All @@ -56,7 +55,7 @@ def setUpClass(cls):
)
cls.warehouse.manufacture_steps = "pbm"
cls.ressuply_loc1 = cls.warehouse.lot_stock_id
cls.source_location = cls.env.ref("stock.stock_location_stock")
cls.manufacture_location = cls.warehouse.pbm_loc_id
cls.destination_location = cls.env.ref("stock.stock_location_output")
stock_location_locations_virtual = cls.env["stock.location"].create(
{"name": "Virtual Locations", "usage": "view", "posz": 1}
Expand All @@ -69,15 +68,15 @@ def setUpClass(cls):
"usage": "inventory",
}
)
cls.source_route = cls.env["stock.location.route"].create(
cls.source_route = cls.env["stock.route"].create(
{
"name": "Source Route",
"mo_component_selectable": True,
"sequence": 10,
}
)

cls.destination_route = cls.env["stock.location.route"].create(
cls.destination_route = cls.env["stock.route"].create(
{
"name": "Destination Route",
"mo_component_selectable": True,
Expand All @@ -90,7 +89,7 @@ def setUpClass(cls):
"name": "Transfer",
"route_id": cls.source_route.id,
"location_src_id": cls.ressuply_loc1.id,
"location_id": cls.source_location.id,
"location_dest_id": cls.manufacture_location.id,
"action": "pull",
"picking_type_id": cls.warehouse.int_type_id.id,
"procure_method": "make_to_stock",
Expand All @@ -102,8 +101,8 @@ def setUpClass(cls):
{
"name": "Transfer 2",
"route_id": cls.destination_route.id,
"location_src_id": cls.source_location.id,
"location_id": cls.destination_location.id,
"location_src_id": cls.manufacture_location.id,
"location_dest_id": cls.destination_location.id,
"action": "pull",
"picking_type_id": cls.warehouse.int_type_id.id,
"procure_method": "make_to_stock",
Expand All @@ -117,7 +116,7 @@ def setUpClass(cls):
"name": "Operation Scrap and Replace",
"incoming_operation": "replace",
"outgoing_operation": "scrap",
"source_location_id": cls.source_location.id,
"manufacture_location_id": cls.manufacture_location.id,
"source_route_id": cls.source_route.id,
"scrap_location_id": cls.scrapped_location.id,
}
Expand All @@ -128,7 +127,7 @@ def setUpClass(cls):
"name": "Operation Scrap and Replace",
"incoming_operation": "no",
"outgoing_operation": "no",
"source_location_id": cls.source_location.id,
"manufacture_location_id": cls.manufacture_location.id,
}
)

Expand All @@ -137,7 +136,7 @@ def setUpClass(cls):
"name": "Operation Move",
"incoming_operation": "replace",
"outgoing_operation": "move",
"source_location_id": cls.source_location.id,
"manufacture_location_id": cls.manufacture_location.id,
"source_route_id": cls.source_route.id,
"destination_location_id": cls.destination_location.id,
"destination_route_id": cls.destination_route.id,
Expand All @@ -149,17 +148,17 @@ def _do_picking(cls, picking):
picking.action_assign()
date = fields.Datetime.now()
picking.action_confirm()
picking.move_lines.quantity_done = picking.move_lines.product_uom_qty
picking.move_ids.picked = True
picking._action_done()
for move in picking.move_lines:
for move in picking.move_ids:
move.date = date

def test_01_scrap_and_replace(self):
nb_product_todo = 5
serials_p2 = []
for i in range(nb_product_todo):
serials_p2.append(
self.env["stock.production.lot"].create(
self.env["stock.lot"].create(
{
"name": f"lot_consumed_2_{i}",
"product_id": self.product3.id,
Expand All @@ -180,20 +179,21 @@ def test_01_scrap_and_replace(self):
"product_qty": 2,
"product_uom_id": self.product1.uom_id.id,
"date_deadline": "2023-01-01 15:00:00",
"date_planned_start": "2023-01-01 15:00:00",
"date_start": "2023-01-01 15:00:00",
}
)
mo._onchange_move_raw()
mo._onchange_move_finished()
mo.action_confirm()
picking = mo.move_raw_ids.move_orig_ids.picking_id
picking.move_ids.write({"picked": True})
picking.button_validate()
mo.action_assign()
move_product_2 = mo.move_raw_ids.filtered(
lambda m: m.product_id == self.product2
)
raw_move_product_3 = mo.move_raw_ids.filtered(
lambda m: m.product_id == self.product3
)
self.assertEqual(move_product_2.move_line_ids.product_uom_qty, 4)
self.assertEqual(move_product_2.move_line_ids.quantity_product_uom, 4)
self.assertEqual(len(raw_move_product_3.move_line_ids), 2)
lot = raw_move_product_3.move_line_ids[0].lot_id
wizard = self.env["mrp.component.operate"].create(
Expand All @@ -205,29 +205,28 @@ def test_01_scrap_and_replace(self):
}
)
self.assertEqual(wizard.product_qty, 1)
old_pickings = mo.picking_ids
wizard.action_operate_component()
self.assertEqual(len(mo.picking_ids), 1)
new_pickings = mo.picking_ids - old_pickings
self.assertEqual(mo.scrap_ids.product_id, self.product3)
self.assertEqual(mo.scrap_ids.lot_id, lot)
self.assertEqual(mo.scrap_ids.state, "done")
self.assertEqual(len(raw_move_product_3.move_line_ids), 1)
self.assertEqual(len(raw_move_product_3.move_orig_ids.move_line_ids), 0)
self.assertEqual(mo.picking_ids.product_id, self.product3)
self._do_picking(mo.picking_ids)
self.assertEqual(mo.picking_ids.state, "done")
self._do_picking(new_pickings)
self.assertEqual(new_pickings.state, "done")
self.assertEqual(
len(raw_move_product_3.move_line_ids),
2,
"Two lines, the operated one and the other one. (2 units required)",
)
self.assertEqual(len(raw_move_product_3.move_orig_ids.move_line_ids), 1)
self.assertEqual(len(raw_move_product_3.move_orig_ids[-1].move_line_ids), 1)

def test_02_move_and_replace(self):
nb_product_todo = 5
serials_p2 = []
for i in range(nb_product_todo):
serials_p2.append(
self.env["stock.production.lot"].create(
self.env["stock.lot"].create(
{
"name": f"lot_consumed_2_{i}",
"product_id": self.product3.id,
Expand All @@ -248,12 +247,13 @@ def test_02_move_and_replace(self):
"product_qty": 1,
"product_uom_id": self.product1.uom_id.id,
"date_deadline": "2023-01-01 15:00:00",
"date_planned_start": "2023-01-01 15:00:00",
"date_start": "2023-01-01 15:00:00",
}
)
mo._onchange_move_raw()
mo._onchange_move_finished()
mo.action_confirm()
picking = mo.move_raw_ids.move_orig_ids.picking_id
picking.move_ids.write({"picked": True})
picking.button_validate()
mo.action_assign()
self.assertEqual(len(mo.move_raw_ids), 2)
move_product_2 = mo.move_raw_ids.filtered(
Expand All @@ -262,10 +262,9 @@ def test_02_move_and_replace(self):
raw_move_product_3 = mo.move_raw_ids.filtered(
lambda m: m.product_id == self.product3
)
self.assertEqual(move_product_2.move_line_ids.product_uom_qty, 2)
self.assertEqual(move_product_2.move_line_ids.quantity_product_uom, 2)
self.assertEqual(len(raw_move_product_3.move_line_ids), 1)
lot = raw_move_product_3.move_line_ids[0].lot_id
self.assertFalse(raw_move_product_3.move_orig_ids)
wizard = self.env["mrp.component.operate"].create(
{
"product_id": self.product3.id,
Expand All @@ -275,10 +274,12 @@ def test_02_move_and_replace(self):
}
)
self.assertEqual(wizard.product_qty, 1)
self.assertEqual(len(mo.picking_ids), 0)
old_pickings = mo.picking_ids
self.assertEqual(len(old_pickings), 1)
wizard.action_operate_component()
self.assertEqual(len(mo.picking_ids), 2)
moves_for_replacement = mo.mapped("picking_ids.move_lines")
self.assertEqual(len(mo.picking_ids), 3)
new_pickings = mo.picking_ids - old_pickings
moves_for_replacement = new_pickings.mapped("move_ids")
self.assertEqual(len(moves_for_replacement), 2)
for move in moves_for_replacement:
self.assertEqual(
Expand All @@ -290,16 +291,15 @@ def test_02_move_and_replace(self):
)
self.assertTrue(replacement_first_move)
replacement_second_move = moves_for_replacement.filtered(
lambda m: m.location_dest_id == self.source_location
lambda m: m.location_dest_id == self.manufacture_location
)
self.assertTrue(replacement_second_move)
self.assertEqual(
len(raw_move_product_3.move_line_ids),
0,
"Reservation for product3 should have been cleared",
)
self.assertEqual(raw_move_product_3.move_orig_ids, replacement_second_move)
self.assertEqual(len(replacement_second_move.move_line_ids), 0)
self.assertEqual(raw_move_product_3.move_orig_ids[-1], replacement_second_move)
self._do_picking(replacement_first_move.picking_id)
self.assertEqual(replacement_first_move.state, "done")
self.assertEqual(replacement_first_move.move_line_ids.lot_id, lot)
Expand All @@ -308,7 +308,6 @@ def test_02_move_and_replace(self):
0,
"raw move for product 3 still not reserved.",
)
self.assertEqual(len(replacement_second_move.move_line_ids), 0)
self._do_picking(replacement_second_move.picking_id)
self.assertEqual(replacement_second_move.state, "done")
self.assertEqual(replacement_first_move.product_id, self.product3)
Expand All @@ -320,7 +319,7 @@ def test_03_nothing_and_nothing(self):
serials_p2 = []
for i in range(nb_product_todo):
serials_p2.append(
self.env["stock.production.lot"].create(
self.env["stock.lot"].create(
{
"name": f"lot_consumed_2_{i}",
"product_id": self.product3.id,
Expand All @@ -341,20 +340,21 @@ def test_03_nothing_and_nothing(self):
"product_qty": 2,
"product_uom_id": self.product1.uom_id.id,
"date_deadline": "2023-01-01 15:00:00",
"date_planned_start": "2023-01-01 15:00:00",
"date_start": "2023-01-01 15:00:00",
}
)
mo._onchange_move_raw()
mo._onchange_move_finished()
mo.action_confirm()
picking = mo.move_raw_ids.move_orig_ids.picking_id
picking.move_ids.write({"picked": True})
picking.button_validate()
mo.action_assign()
move_product_2 = mo.move_raw_ids.filtered(
lambda m: m.product_id == self.product2
)
raw_move_product_3 = mo.move_raw_ids.filtered(
lambda m: m.product_id == self.product3
)
self.assertEqual(move_product_2.move_line_ids.product_uom_qty, 4)
self.assertEqual(move_product_2.move_line_ids.quantity_product_uom, 4)
self.assertEqual(len(raw_move_product_3.move_line_ids), 2)
wizard = self.env["mrp.component.operate"].create(
{
Expand All @@ -367,6 +367,5 @@ def test_03_nothing_and_nothing(self):
self.assertEqual(wizard.product_qty, 1)
self.assertEqual(wizard.product_id, self.product3)
wizard.action_operate_component()
self.assertEqual(len(mo.picking_ids), 0)
self.assertEqual(move_product_2.move_line_ids.product_uom_qty, 4)
self.assertEqual(move_product_2.move_line_ids.quantity_product_uom, 4)
self.assertEqual(len(mo.move_raw_ids[1].move_line_ids), 2)
Loading

0 comments on commit 58a614d

Please sign in to comment.