[16.0] stock_picking_report_valued_sale_mrp: kit component demanded quantity is doubled when a delivery is fully returned and then redelivered
Module
stock_picking_report_valued_sale_mrp – Odoo 16.0
Description
When a kit (phantom BOM) is delivered, fully returned, and then redelivered, the valued delivery reports Delivery Slip show twice the correct quantity and value for kit components.
The root cause is the method _get_components_per_kit() in models/stock_move.py, which incorrectly computes the demanded component quantity from the sale line when returns and redeliveries are present.
Current (wrong) behaviour
The method returns 80 components per kit instead of the correct 40 components per kit
Expected behaviour
A sale line demanding 2 kits must always show 40 components per kit in the report (80 units delivered / 2 kits ordered = 40), regardless of how many times the delivery was returned and redelivered).
Net effect: customer finally received 2 kits → component consumption must be valued for 2 kits only.
Real data example (anonymized but 100% representative)
| id | name | product_id | product_qty | product_uom_qty | move_dest_ids | move_orig_ids | picking_id | state | origin_returned_move_id | returned_move_ids | quantity_done | picking_code | sale_line_id |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| MV-01 | [BOX-01] | PRD-01 | 80 | 80 | MV-02 | PK-01, ALB/XXXX | PK-10 | done | false | MV-02 | 80 | outgoing | SO-2501524 |
| MV-02 | [BOX-01] | PRD-01 | 80 | 80 | MV-01 | PK-02, RET/XXXX | PK-11 | done | MV-01 (SO-2501524: Stock>Customers) | (none) | 80 | incoming | SO-2501524 |
| MV-03 | [BOX-01] | PRD-01 | 80 | 80 | PK-03, ALB/XXXX | (none) | PK-12 | done | false | (none) | 80 | outgoing | SO-2501524 |
Why the current code fails
Current implementation (lines 9–31):
component_demand = sum(
sale_line.move_ids.filtered(
lambda x: x.product_id == self.product_id
and not x.origin_returned_move_id # excludes only return moves
and ...
).mapped("product_uom_qty")
)
Result with the data above:
MV-01 → included (80)
MV-02 → correctly excluded (return)
MV-03 → included (80)
→ total = 160 → 160 / 2 kits ordered = 80 components per kit (doubled)
The original delivery quantity is never reduced by the quantity that was later returned, producing systematic over-valuation every time a return + replacement occurs.
### Buggy code (current)
https://github.com/OCA/stock-logistics-reporting/blob/56f7fc922cc9b4efd1100f6a51744871c1201704/stock_picking_report_valued_sale_mrp/models/stock_move.py#L9-L31
@pedrobaeza @chienandalu Hi! I’d be glad to submit a fix PR if you can give me a quick pointer. First: with the three stock moves in the example (original delivery → full return → replacement delivery, all linked to the same sale line), is this chain considered normal in Odoo 16, or is the data somehow corrupted/unexpected? Thanks!