Skip to content

Conversation

@sbejaoui
Copy link
Contributor

In many business flows, a returned product must be linked back to the original sale in order to validate warranty conditions, refunds or exchanges.

Manually searching the correct sale order for each RMA is error-prone and time consuming, especially when:

  • the customer has multiple past orders
  • the product was delivered in several partial shipments
  • the return period depends on the type of RMA operation (refund, warranty, lifetime, etc.)

This module introduces an automatic matching engine that links RMA records to the correct delivery moves of the original sale order, based on delivered quantities and eligibility period.

It avoids manual reconciliation and provides a deterministic, auditable match.

refs: #473

@sbejaoui sbejaoui added this to the 18.0 milestone Oct 31, 2025
@sbejaoui sbejaoui force-pushed the 18.0-rma_sale_auto_detect-sbj branch 2 times, most recently from f78ae8a to 73097d6 Compare November 3, 2025 11:08
def _filter_sale_lines_by_delivery_move(self, sale_lines):
"""get sale line only if the move is not linked"""
return sale_lines.filtered(
lambda sol: any(m.state == "done" and not m.rma_ids for m in sol.move_ids)
Copy link
Contributor

@marielejeune marielejeune Nov 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you only consider delivery moves that arrive to the customer here?

If my delivery is in 2 steps: Stock -> Pack -> Customer, and if the product has been picked but isn't packed yet, won't this method possibly return the related SOL, although the customer hasn't received the product yet?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sol.move_ids refer only to the delivery moves, the preparation moves are not directly linked to the sale order line, but to the delivery moves through move_orig_ids
the filter on state == 'done' ensures that we ignore cancelled deliveries and deliveries that have not yet been validated

Comment on lines +15 to +52
def action_link_rma_to_sale_line(self):
"""automatically link RMAs to the most relevant sale order lines"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with how the code is written and organized. However I find it quite difficult to understand the logic when reading it.

I've seen the description in the README, but I don't know, shouldn't we add a bit more explanation here in the code? I'm open to discussion

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding the eligibility period to the RMA simplified the code significantly, take another look and let me know what you think now

Comment on lines +196 to +200
def test_10(self):
"""When user suggest the sale order and there is multiple delivery moves
the rma is split"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a test "When user suggest the sale order and there are multiple sale order lines" or is this covered with the multiple delivery moves case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, it is already covered by the other tests:

  • If no sale line is found, the rma is flagged as having a linking issue
  • If multiple sale lines are found, the process iterates line by line until the full rma quantity is satisfied

@sbejaoui sbejaoui force-pushed the 18.0-rma_sale_auto_detect-sbj branch from 73097d6 to 59618af Compare November 3, 2025 13:32
Copy link
Contributor

@marielejeune marielejeune left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (code review). Functional tests planned soon.

@sbejaoui sbejaoui force-pushed the 18.0-rma_sale_auto_detect-sbj branch from 798b5b6 to b29852a Compare November 13, 2025 13:45
Comment on lines +200 to +227
def action_confirm(self):
precision = self.env["decimal.precision"].precision_get(
"Product Unit of Measure"
)

for rec in self:
if rec.move_id and (
float_compare(
rec.move_id.rma_returnable_uom_qty,
0,
precision_digits=precision,
)
< 0
):
raise ValidationError(
_(
"The quantity to return exceeds the remaining returnable "
"quantity for this delivery."
)
)

return super().action_confirm()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a feature we want to keep in rma_sale_auto_detect? Shouldn't it be interesting in a more generic addon?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, this can be in base module

In many business flows, a returned product must be linked back to the original
sale in order to validate warranty conditions, refunds or exchanges.

Manually searching the correct sale order for each RMA is error-prone and time
consuming, especially when:

- the customer has multiple past orders
- the product was delivered in several partial shipments
- the return period depends on the type of RMA operation (refund, warranty, lifetime, etc.)

This module introduces an **automatic matching engine** that links RMA records
to the correct delivery moves of the original sale order, based on delivered
quantities and eligibility period.

It avoids manual reconciliation and provides a deterministic, auditable match.

refs: OCA#473

[IMP] rma_sale_auto_detect: allow user to suggest the sale order in order to compute the sale line
@sbejaoui sbejaoui force-pushed the 18.0-rma_sale_auto_detect-sbj branch from 5668780 to f2444a1 Compare November 20, 2025 10:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants