diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index 44c1a961..e1f777e0 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -587,7 +587,19 @@ class RmaOrderLine(models.Model): self.reference_move_id = False return True + def _check_production_lot_assigned(self): + for rec in self: + if rec.product_id.tracking == "serial" and rec.product_qty != 1: + raise ValidationError( + _( + "Product %s has serial tracking configuration, " + "quantity to receive should be 1" + ) + % (rec.product_id.display_name) + ) + def action_rma_to_approve(self): + self._check_production_lot_assigned() self.write({"state": "to_approve"}) for rec in self: if rec.product_id.rma_approval_policy == "one_step": diff --git a/rma/models/stock.py b/rma/models/stock.py index 01d79647..2cab4bb3 100644 --- a/rma/models/stock.py +++ b/rma/models/stock.py @@ -60,3 +60,9 @@ class StockMove(models.Model): return self.move_dest_ids[0]._get_last_usage() else: return self.location_dest_id.usage + + def _should_bypass_reservation(self): + res = super(StockMove, self)._should_bypass_reservation() + if self.env.context.get("force_no_bypass_reservation"): + return False + return res diff --git a/rma/wizards/rma_add_stock_move.py b/rma/wizards/rma_add_stock_move.py index 8b1a3607..0352a1f3 100644 --- a/rma/wizards/rma_add_stock_move.py +++ b/rma/wizards/rma_add_stock_move.py @@ -36,6 +36,36 @@ class RmaAddStockMove(models.TransientModel): string="Stock Moves", domain="[('state', '=', 'done')]", ) + show_lot_filter = fields.Boolean( + string="Show lot filter?", compute="_compute_lot_domain", + ) + lot_domain_ids = fields.Many2many( + comodel_name="stock.production.lot", + string="Lots Domain", + compute="_compute_lot_domain", + ) + + @api.depends("move_ids.move_line_ids.lot_id") + def _compute_lot_domain(self): + for rec in self: + rec.lot_domain_ids = rec.mapped("move_ids.move_line_ids.lot_id").ids + rec.show_lot_filter = bool(rec.lot_domain_ids) + + lot_ids = fields.Many2many( + comodel_name="stock.production.lot", string="Lots/Serials selected" + ) + + def select_all(self): + self.ensure_one() + self.write({"lot_ids": [(6, 0, self.lot_domain_ids.ids)]}) + return { + "type": "ir.actions.act_window", + "name": _("Add from Stock Move"), + "view_mode": "form", + "res_model": self._name, + "res_id": self.id, + "target": "new", + } def _prepare_rma_line_from_stock_move(self, sm, lot=False): if self.env.context.get("customer"): @@ -74,6 +104,15 @@ class RmaAddStockMove(models.TransientModel): raise ValidationError( _("Please define a warehouse with a default RMA location") ) + product_qty = sm.product_uom_qty + if sm.product_id.tracking == "serial": + product_qty = 1 + elif sm.product_id.tracking == "lot": + product_qty = sum( + sm.move_line_ids.filtered(lambda x: x.lot_id.id == lot.id).mapped( + "qty_done" + ) + ) data = { "partner_id": self.partner_id.id, "reference_move_id": sm.id, @@ -82,7 +121,7 @@ class RmaAddStockMove(models.TransientModel): "origin": sm.picking_id.name or sm.name, "uom_id": sm.product_uom.id, "operation_id": operation.id, - "product_qty": sm.product_uom_qty, + "product_qty": product_qty, "delivery_address_id": sm.picking_id.partner_id.id, "rma_id": self.rma_id.id, "receipt_policy": operation.receipt_policy, @@ -110,16 +149,21 @@ class RmaAddStockMove(models.TransientModel): rma_line_obj = self.env["rma.order.line"] existing_stock_moves = self._get_existing_stock_moves() for sm in self.move_ids: - if sm not in existing_stock_moves: + tracking_move = sm.product_id.tracking in ("serial", "lot") + if sm not in existing_stock_moves or tracking_move: if sm.product_id.tracking == "none": data = self._prepare_rma_line_from_stock_move(sm, lot=False) rma_line_obj.with_context(default_rma_id=self.rma_id.id).create( data ) else: - lot_ids = [x.lot_id.id for x in sm.move_line_ids if x.lot_id] - data = self._prepare_rma_line_from_stock_move(sm, lot=lot_ids[0]) - rma_line_obj.with_context(default_rma_id=self.rma_id.id).create( - data - ) + for lot in sm.move_line_ids.mapped("lot_id").filtered( + lambda x: x.id in self.lot_ids.ids + ): + if lot.id in self.rma_id.rma_line_ids.mapped("lot_id").ids: + continue + data = self._prepare_rma_line_from_stock_move(sm, lot) + rma_line_obj.with_context(default_rma_id=self.rma_id.id).create( + data + ) return {"type": "ir.actions.act_window_close"} diff --git a/rma/wizards/rma_add_stock_move_view.xml b/rma/wizards/rma_add_stock_move_view.xml index e0b4cbc5..226b07c1 100644 --- a/rma/wizards/rma_add_stock_move_view.xml +++ b/rma/wizards/rma_add_stock_move_view.xml @@ -40,6 +40,35 @@ + + +
+ The creation of the RMA Lines will be separated according to the lots or serials selected +
+
+