# Return validation rules

## Quantity caps

- For each return line, requested quantity **≤** `quantity_fulfilled − Σ(processed returns for that sales order line)`.
- **Over-return** (request above remaining returnable) is rejected at processing time with a dedicated violation code.

## Fulfillment reference

- Processing **requires** existing **stock_out** ledger rows for the sales order line (`reference_type = sales_order_line`, `movement_type = stock_out`), consumed in **FIFO order by movement id**.
- If the requested quantity cannot be matched to outstanding (not-yet-compensated) portions of those movements, processing fails (**trace missing**): the system must not invent inventory.

## Duplicate quantity / duplicate documents

- **Duplicate processing** of the same return document is prevented by **idempotent processing**: once status is `processed`, a second process attempt is a no-op at the business-effect level (still runs under locks for safety).
- Multiple **different** returns may reference the same order line as long as cumulative processed quantities respect the cap above.

## Tenant and order consistency

- Return header `tenant_id` must match the sales order and every line’s `sales_order_line_id` must belong to that order and tenant.
- Processing is **blocked** if the sales order is **cancelled** (integrity guard — reconcilers treat cancelled orders as closed for this flow).
