[FIX] purchase_request: do not close allocations on locked orders - #3160
Conversation
_compute_open_product_qty treats a purchase order line in state done as a finished purchase and zeroes the open quantity. In Odoo that state means "Locked", a modification lock, not a completion: receipts still happen afterwards, and core creates and processes them for locked orders (_create_picking accepts both purchase and done). With po_lock = 'lock' the order reaches done at approval time, so the allocation is closed before any receipt can happen. As a consequence stock.move.line.allocate() never allocates the incoming quantity, the requester is never notified of the receipt, qty_done and qty_in_progress stay at 0 on the request line, and stock.move.copy_data carries no allocation over to backorders. Nothing fails and nothing is logged. This is a regression: the same one line change was requested by a maintainer in OCA#1419 and merged into 14.0 by OCA#1422, but the forward port to 15.0 brought back the version including done, and 15.0 up to 19.0 still carry it. cancel is the only state that really means nothing else will be allocated: once a receipt completes, allocated_product_qty reaches requested_product_uom_qty and the open quantity becomes 0 on its own. Add a test covering the locked order flow, which no test exercised because po_lock defaults to edit.
|
@StefanRijnhart you diagnosed this exact behaviour in #1419 and asked for the if rec.purchase_state == 'cancel': variant, which was merged into 14.0 by #1422. The forward port to 15.0 reverted it and 15.0 up to 19.0 still carry it, so this PR restores your fix on 18.0 with a test that pins it down. @HviorForgeFlow could you take a look? You have context on the allocation code. Thank you! |
|
/ocabot merge patch |
|
On my way to merge this fine PR! |
|
@les-adhoc do you mind moving the fix to all affected versions, thanks! |
|
Congratulations, your PR was merged at e59468a. Thanks a lot for contributing to OCA. ❤️ |
|
@HviorForgeFlow forwarded to the other affected versions:
19.0 is not affected. There the |
Problem
purchase.request.allocation._compute_open_product_qtyzeroes the open quantity when the purchase order line is in statedone. In Odoo that state is Locked — a modification lock — not a completion: receipts still happen afterwards, and core itself creates and processes them for locked orders (_create_pickingaccepts('purchase', 'done')).When the company has Lock Confirmed Orders enabled (
res.company.po_lock = 'lock'),button_approvemoves the order todoneat approval time. The allocation is therefore closed before any receipt can happen, and:stock.move.line.allocate()never allocates the incoming quantity, so no receipt message is posted and the requester is never notified;qty_doneandqty_in_progressstay at 0 on the request line, which then shows nothing received and everything still pending, forever;stock.move.copy_data()filters allocations onopen_product_qty, so backorders are created without allocations.For a database with that setting on, the allocation and notification feature is effectively dead. Nothing fails and nothing is logged.
This is a regression
The exact same one line change was already requested and merged once:
po_lock. A maintainer asked for theif rec.purchase_state == 'cancel':variant, and suggested mentioning thatdonedoes not indicate the delivery status.The forward port to 15.0 brought back the version including
done:_compute_open_product_qtyif rec.purchase_state == "cancel":if rec.purchase_state in ["cancel", "done"]:So 15.0 up to 19.0 all carry the bug again. This PR restores the 14.0 behaviour on 18.0; happy to port it to the other affected branches if you want them in the same batch.
For the record on why the check existed at all: it was introduced in 3927305 for service lines only, where the purchase order line is the only available signal, and extended to stock backed allocations by 587c260 while splitting the models into separate files.
Fix
cancelis the only state that really means nothing else will be allocated. Once a receipt completes,allocated_product_qtyreachesrequested_product_uom_qtyand the open quantity becomes 0 on its own, so no shortcut ondoneis needed. Keeping the open quantity positive on a locked order is also whatcopy_dataneeds in order to carry the remainder over to a backorder.Test plan
The new test covers the locked order flow, which no existing test exercised because
po_lockdefaults toedit. Before the change it fails:After it, the whole module suite passes on 18.0:
Out of scope
purchase_request_line._compute_purchase_stateand_purchase_request_line_checkreaddonethe same way, which is what raises "The purchase has already been completed" when generating a second RFQ for a request line of a locked order. That reading is asserted by an existing test, so changing it is a separate discussion and is deliberately left untouched here.