diff --git a/rma/models/rma_order_line.py b/rma/models/rma_order_line.py index fd53d9ae5..ea97ce6d8 100644 --- a/rma/models/rma_order_line.py +++ b/rma/models/rma_order_line.py @@ -125,11 +125,6 @@ def _get_rma_move_qty(self, states, direction="in"): ) ) for move in moves: - # If the move is part of a chain don't count it - if direction == "out" and move.move_orig_ids: - continue - elif direction == "in" and move.move_dest_ids: - continue qty += product_obj._compute_quantity(move.product_uom_qty, rec.uom_id) return qty @@ -184,7 +179,7 @@ def _compute_qty_received(self): def _compute_qty_outgoing(self): for rec in self: qty = rec._get_rma_move_qty( - ("draft", "confirmed", "assigned"), direction="out" + ("draft", "confirmed", "assigned", "waiting"), direction="out" ) rec.qty_outgoing = qty diff --git a/rma/tests/test_rma.py b/rma/tests/test_rma.py index 20c1caa46..489e4017a 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -78,6 +78,51 @@ def setUpClass(cls): cls.rma_supplier_id = cls._create_rma_from_move( products2move, "supplier", cls.env.ref("base.res_partner_2"), dropship=False ) + # create rules to have multi step reception/shipment, unactive by default + cls.test_rma_loc = cls.stock_rma_location.copy({"name": "rma loc shipping"}) + rma_route = cls.env.ref("rma.route_rma_customer") + cls.second_step_incoming_rule = cls.env["stock.rule"].create( + { + "name": "reception => rma loc shipping", + "action": "pull", + "picking_type_id": cls.wh.int_type_id.id, + "location_src_id": cls.wh.wh_input_stock_loc_id.id, + "location_dest_id": cls.test_rma_loc.id, + "procure_method": "make_to_stock", + "route_id": rma_route.id, + "warehouse_id": cls.wh.id, + "company_id": cls.wh.company_id.id, + "active": False, + "sequence": 0, + } + ) + cls.second_step_outgoing_rule = cls.env["stock.rule"].create( + { + "name": "rma => reception", + "action": "push", + "picking_type_id": cls.wh.int_type_id.id, + "location_src_id": cls.stock_rma_location.id, + "location_dest_id": cls.wh.wh_input_stock_loc_id.id, + "procure_method": "make_to_stock", + "route_id": rma_route.id, + "warehouse_id": cls.wh.id, + "company_id": cls.wh.company_id.id, + "active": False, + } + ) + + @classmethod + def _configure_2_steps_incoming_outgoing(cls): + cls.second_step_incoming_rule.write({"active": True}) + cls.second_step_outgoing_rule.write({"active": True}) + rma_customer_rule = cls.env.ref("rma.rule_rma_customer_out_pull") + rma_customer_rule.write( + { + "procure_method": "make_to_order", + "sequence": 0, + "location_src_id": cls.test_rma_loc.id, + } + ) @classmethod def _create_user(cls, login, groups, company): @@ -1096,37 +1141,7 @@ def test_09_rma_state(self): def test_10_rma_cancel_line(self): # configure a new rule to make reception and expedition in 2 steps - rma_route = self.env.ref("rma.route_rma_customer") - rma_loc = self.env.ref("rma.location_rma") - rma_loc2 = rma_loc.copy({"name": "rma loc shipping"}) - rma_customer_rule = self.env.ref("rma.rule_rma_customer_out_pull") - rma_customer_rule.write({"procure_method": "make_to_order", "sequence": 0}) - self.env["stock.rule"].create( - { - "name": "reception => rma loc shipping", - "action": "pull", - "picking_type_id": self.wh.int_type_id.id, - "location_src_id": self.wh.wh_input_stock_loc_id.id, - "location_dest_id": rma_loc2.id, - "procure_method": "make_to_stock", - "route_id": rma_route.id, - "warehouse_id": self.wh.id, - "company_id": self.wh.company_id.id, - } - ) - self.env["stock.rule"].create( - { - "name": "rma => reception", - "action": "push", - "picking_type_id": self.wh.int_type_id.id, - "location_src_id": rma_loc.id, - "location_dest_id": self.wh.wh_input_stock_loc_id.id, - "procure_method": "make_to_stock", - "route_id": rma_route.id, - "warehouse_id": self.wh.id, - "company_id": self.wh.company_id.id, - } - ) + self._configure_2_steps_incoming_outgoing() # Generate expedition for the rma group self.rma_customer_id.rma_line_ids.action_rma_to_approve() wizard = self.rma_make_picking.with_context( @@ -1138,13 +1153,12 @@ def test_10_rma_cancel_line(self): } ).create({}) wizard._create_picking() - self.rma_customer_id.rma_line_ids.action_view_in_shipments() # cancel first line and check it cancel the dest moves, but leave the picking # ongoing for the 2 other lines first_rma_line = self.rma_customer_id.rma_line_ids[0] second_rma_line = self.rma_customer_id.rma_line_ids[1] first_line_in_move = first_rma_line.move_ids.filtered( - lambda m: m.location_dest_id == rma_loc + lambda m: m.location_dest_id == self.stock_rma_location ) first_line_in_dest_move = first_line_in_move.move_dest_ids reception_picking = first_line_in_move.picking_id @@ -1154,7 +1168,7 @@ def test_10_rma_cancel_line(self): self.assertEqual(first_line_in_move.state, "cancel") self.assertEqual(reception_picking.state, "assigned") second_line_in_move = second_rma_line.move_ids.filtered( - lambda m: m.location_dest_id == rma_loc + lambda m: m.location_dest_id == self.stock_rma_location ) self.assertEqual(second_line_in_move.state, "assigned") @@ -1184,3 +1198,53 @@ def test_10_rma_cancel_line(self): self.assertEqual(second_rma_out_move_orig.state, "cancel") # check picking is not canceled because third line has not been yet. self.assertEqual(second_rma_out_move.picking_id.state, "waiting") + + def test_11_rma_received_shipped_quantities_multiple_step(self): + # configure a new rule to make reception and expedition in 2 steps + self._configure_2_steps_incoming_outgoing() + rma_customer = self._create_rma_from_move( + [(self.product_1, 3)], + "customer", + self.env.ref("base.res_partner_2"), + dropship=False, + ) + rma_customer.rma_line_ids.action_rma_to_approve() + # Generate reception for the rma group and check incoming quantities + rma_line = rma_customer.rma_line_ids + wizard = self.rma_make_picking.with_context( + **{ + "active_ids": rma_customer.rma_line_ids.ids, + "active_model": "rma.order.line", + "picking_type": "incoming", + "active_id": 1, + } + ).create({}) + wizard._create_picking() + in_pickings = rma_line._get_in_pickings() + first_in_picking = in_pickings.filtered(lambda p: p.state == "assigned") + self.assertEqual(rma_line.qty_incoming, 3.0) + self.assertEqual(rma_line.qty_received, 0.0) + for mv in first_in_picking.move_line_ids: + mv.qty_done = mv.reserved_uom_qty + first_in_picking._action_done() + self.assertEqual(rma_line.qty_incoming, 0.0) + self.assertEqual(rma_line.qty_received, 3.0) + + # generate 2 step expedition and check quantities + wizard = self.rma_make_picking.with_context( + **{ + "active_ids": rma_line.ids, + "active_model": "rma.order.line", + "picking_type": "outgoing", + "active_id": 1, + } + ).create({}) + wizard.with_context(test=True)._create_picking() + out_picking = rma_line._get_out_pickings() + self.assertEqual(rma_line.qty_outgoing, 3.0) + self.assertEqual(rma_line.qty_delivered, 0.0) + for mv in out_picking.move_ids: + mv.quantity_done = 3.0 + out_picking._action_done() + self.assertEqual(rma_line.qty_outgoing, 0.0) + self.assertEqual(rma_line.qty_delivered, 3.0)