[ADD] stock_move_manual_quantity: a hand-typed quantity is the picked one

An operator weighing a basket types 0.87 kg where the member ordered 1 kg,
and a few hours later the line is back at 1 kg. Raising the quantity never
reverts. The asymmetry is the reservation engine: below the demand the move
goes back to `partially_available` (`_recompute_state`), which is exactly
the state `_action_assign` looks for, while above it stays `assigned` and
matches no domain.

Two things call `_action_assign` on their own: the `Procurement: run
scheduler` cron, and `_trigger_assign`, which runs every time another
transfer of the same product is validated -- the second explains the "a few
hours" better than a daily cron. Both respect one flag only, `picked`, and
nobody was setting it: the checkbox is `optional="hide"` on the transfer
form and absent from the detailed operation lists.

So an onchange on `quantity` marks the record as picked. Onchanges only run
from the interface, never from the reservation engine, so a manual edit is
told apart from a reservation without guessing at contexts, and if the
onchange ever stops firing the behaviour degrades to today's instead of
freezing reservations across the system. `picked` also keeps
`_free_reservation` from stealing the quantity when stock runs short
elsewhere. The three lists where a quantity can be typed now load the field,
since the client only sends back what the arch declares.

When the typed quantity is below the demand, the demand follows it down. The
move stays `assigned` and no backorder is asked for a weight that will never
be completed. Only downwards: above the demand nothing needs adjusting. A
line left at zero keeps its demand, so a transfer still offers its usual
backorder choice for what was not delivered, and chained moves are only
frozen -- lowering their demand would leave the next step of the route
asking for more than this one delivers.

`_pre_action_done_hook` needs the counterpart. Core auto-picks a transfer
only when *no* move is picked yet, so freezing one weighed line would push
the untouched ones to a backorder, or cancel them if the user answers "no
backorder", with the goods already in the basket. Picking everything that
carries a quantity keeps validation exactly as operators know it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
GitHub Copilot 2026-08-27 13:26:44 +02:00
parent cb32fb6c0d
commit d433e50f2f
15 changed files with 436 additions and 0 deletions

View file

@ -0,0 +1,23 @@
Nothing to configure: the behaviour applies to every transfer as soon as the
module is installed.
**Weighing a line**
#. Open the transfer (or the batch operator view) and type the real quantity,
for example 0.87 instead of the demanded 1.
#. The move is marked as picked and, because 0.87 is below the demand, the
demand becomes 0.87 too. The move stays *Ready*.
#. Neither the scheduler nor the validation of another transfer of the same
product will change that quantity again.
**Notes**
* The demand is only ever lowered, never raised: above the demand the move is
already fully reserved and nothing needs to be adjusted.
* A line left at zero keeps the standard behaviour, so the transfer still
offers its usual backorder choice for what was not delivered.
* Chained moves (multi-step routes) are only frozen, their demand is left
untouched so the next step of the route stays consistent.
* Lowering the demand is logged in the transfer chatter, and it is what the
sale order uses to know how much is still to deliver while the transfer is
not validated.