diff --git a/rma/__manifest__.py b/rma/__manifest__.py
index 015ed11d1..9993ce8f2 100644
--- a/rma/__manifest__.py
+++ b/rma/__manifest__.py
@@ -3,7 +3,7 @@
{
"name": "RMA (Return Merchandise Authorization)",
- "version": "16.0.1.0.0",
+ "version": "16.0.1.1.0",
"license": "LGPL-3",
"category": "RMA",
"summary": "Introduces the return merchandise authorization (RMA) process in odoo",
diff --git a/rma/data/rma_operation.xml b/rma/data/rma_operation.xml
index 92e3fec00..fb642255a 100644
--- a/rma/data/rma_operation.xml
+++ b/rma/data/rma_operation.xml
@@ -8,6 +8,8 @@
customer
+ True
+ False
@@ -18,6 +20,8 @@
supplier
+ False
+ True
diff --git a/rma/migrations/16.0.1.1.0/post-migration.py b/rma/migrations/16.0.1.1.0/post-migration.py
new file mode 100644
index 000000000..55cf245b8
--- /dev/null
+++ b/rma/migrations/16.0.1.1.0/post-migration.py
@@ -0,0 +1,28 @@
+# Copyright 2024 ForgeFlow S.L. (https://www.forgeflow.com)
+import logging
+
+_logger = logging.getLogger(__name__)
+
+
+def _update_rma_operations(cr):
+ _logger.info(
+ "Updating rma operations to preset in_force_same_lot and out_force_same_lot"
+ )
+ cr.execute(
+ """
+ UPDATE rma_operation
+ SET in_force_same_lot=True
+ WHERE type='customer';
+ """
+ )
+ cr.execute(
+ """
+ UPDATE rma_operation
+ SET out_force_same_lot=True
+ WHERE type='supplier';
+ """
+ )
+
+
+def migrate(cr, version):
+ _update_rma_operations(cr)
diff --git a/rma/models/rma_operation.py b/rma/models/rma_operation.py
index bd3d0f167..2806fcb32 100644
--- a/rma/models/rma_operation.py
+++ b/rma/models/rma_operation.py
@@ -94,3 +94,22 @@ def _default_routes(self):
required=True,
default=lambda self: self.env.user.company_id,
)
+ in_force_same_lot = fields.Boolean(
+ string="Force same lot in incoming shipments",
+ help="Forces the same lot to be used "
+ "in incoming pickings as the one indicated in the RMA",
+ )
+ out_force_same_lot = fields.Boolean(
+ string="Force same lot in outgoing shipments",
+ help="Forces the same lot to be used "
+ "in outgoing pickings as the one indicated in the RMA",
+ )
+
+ @api.onchange("type")
+ def _onchange_type(self):
+ if self.type == "customer":
+ self.in_force_same_lot = True
+ self.out_force_same_lot = False
+ elif self.type == "supplier":
+ self.in_force_same_lot = False
+ self.out_force_same_lot = True
diff --git a/rma/models/stock_move.py b/rma/models/stock_move.py
index 9a839f180..52cbf72fe 100644
--- a/rma/models/stock_move.py
+++ b/rma/models/stock_move.py
@@ -62,6 +62,7 @@ def _get_available_quantity(
not lot_id
and self.rma_line_id.lot_id
and self.location_id.usage == "internal"
+ and self.rma_line_id.operation_id.out_force_same_lot
):
# In supplier RMA deliveries we can only send the RMA lot/serial.
lot_id = self.rma_line_id.lot_id
@@ -88,6 +89,7 @@ def _update_reserved_quantity(
not lot_id
and self.rma_line_id.lot_id
and self.location_id.usage == "internal"
+ and self.rma_line_id.operation_id.out_force_same_lot
):
# In supplier RMA deliveries we can only send the RMA lot/serial.
lot_id = self.rma_line_id.lot_id
diff --git a/rma/views/rma_operation_view.xml b/rma/views/rma_operation_view.xml
index c2bb1b59e..08a00f286 100644
--- a/rma/views/rma_operation_view.xml
+++ b/rma/views/rma_operation_view.xml
@@ -53,6 +53,10 @@
name="customer_to_supplier"
attrs="{'invisible':[('type', '=', 'supplier')]}"
/>
+
@@ -61,6 +65,10 @@
name="supplier_to_customer"
attrs="{'invisible':[('type', '=', 'customer')]}"
/>
+
diff --git a/rma/wizards/rma_make_picking.py b/rma/wizards/rma_make_picking.py
index 637caea9b..2982b75f0 100644
--- a/rma/wizards/rma_make_picking.py
+++ b/rma/wizards/rma_make_picking.py
@@ -210,15 +210,16 @@ def action_create_picking(self):
else:
pickings = self.mapped("item_ids.line_id")._get_in_pickings()
action = self.item_ids.line_id.action_view_in_shipments()
- # Force the reservation of the RMA specific lot for incoming shipments.
- # FIXME: still needs fixing, not reserving appropriate serials.
+
for move in pickings.move_ids.filtered(
lambda x: x.state not in ("draft", "cancel", "done", "waiting")
and x.rma_line_id
and x.product_id.tracking in ("lot", "serial")
and x.rma_line_id.lot_id
+ and x.rma_line_id.operation_id.in_force_same_lot
+ and x.location_dest_id.usage == "internal"
):
- # Force the reservation of the RMA specific lot for incoming shipments.
+ # Force the reservation of the RMA specific lot for incoming shipments if required.
move.move_line_ids.unlink()
if move.product_id.tracking == "serial":
move.write(
@@ -226,14 +227,10 @@ def action_create_picking(self):
"lot_ids": [(6, 0, move.rma_line_id.lot_id.ids)],
}
)
- quants = self.env["stock.quant"]._gather(
- move.product_id, move.location_id, lot_id=move.rma_line_id.lot_id
- )
move.move_line_ids.write(
{
- "reserved_uom_qty": 1 if picking_type == "incoming" else 0,
+ "reserved_uom_qty": 1,
"qty_done": 0,
- "package_id": len(quants) == 1 and quants.package_id.id,
}
)
elif move.product_id.tracking == "lot":
@@ -251,10 +248,11 @@ def action_create_picking(self):
"lot_id": move.rma_line_id.lot_id.id,
"product_uom_id": move.product_id.uom_id.id,
"qty_done": 0,
- "reserved_uom_qty": qty if picking_type == "incoming" else 0,
+ "reserved_uom_qty": qty,
}
)
move_line_model.create(move_line_data)
+
pickings.with_context(force_no_bypass_reservation=True).action_assign()
return action
diff --git a/rma_put_away/tests/test_rma_put_away.py b/rma_put_away/tests/test_rma_put_away.py
index b3bec91e2..16d3514e1 100644
--- a/rma_put_away/tests/test_rma_put_away.py
+++ b/rma_put_away/tests/test_rma_put_away.py
@@ -84,6 +84,8 @@ def setUpClass(cls):
"put_away_location_id": cls.put_away_loc.id,
"in_route_id": cls.rma_route_cust.id,
"out_route_id": cls.rma_route_cust.id,
+ "out_force_same_lot": True,
+ "in_force_same_lot": True,
}
)
cls.operation_2 = cls.rma_op_obj.create(
@@ -97,6 +99,8 @@ def setUpClass(cls):
"put_away_location_id": cls.put_away_loc.id,
"in_route_id": cls.rma_route_cust.id,
"out_route_id": cls.rma_route_cust.id,
+ "out_force_same_lot": True,
+ "in_force_same_lot": True,
}
)