Repository navigation
Conversation
When: * using a 3 steps delivery * creating and confirming a sale order * opening the transfer using the "Deliveries" button on the sale order * clicking on the "Release" button The pickings generated by the release are incorrect. This is because the smart button of the sale order view adds several "default_" fields that are then interpreted during the creation of the chained pickings. Clean these fields from the context.
When stock moves have been released, their 'need_release' flag must be set to False. Due to a coding mistake, they were not. The most visible effect was the "Release" button still visible on transfers and moves, but other vicious effects can't be excluded. The issue come from an inversion in the order of the list comprehension, added up to the fact that the 'procurement' variable name was recycled from the code above: 'procurement' was always equal to the latest procurement used in the loop before the list comprehension.
To reproduce * Order 100x [E-COM10] * Update quantities in stock to have 70 [E-COM10] in Stock/Shelf 1 * Release the moves Actual result: 2 transfer, the backorder for the waiting 30 [E-COM10] has no backorder link with the original transfer Expected result: 2 transfer, the backorder for the waiting 30 [E-COM10] has a backorder link with the original transfer
Current behavior: When we release an OUT stock move, the OUT transfer is set to printed. The origin transfers (e.g. Pick+Pack) are not. Expected behavior: When we release an OUT stock move, all the origin transfer (e.g. Pick+Pack) are set to printed. Reason: The original reason for setting "printed" to True, is that when "_assign_picking()" is called on a stock.move, the stock.move can be added only in a stock.picking which is not printed yet. In other terms, "printed" means the transfer has been started and shouldn't be modified. When we "release" moves, we actually planify the work to be done, and if we release again new moves, we don't expect transfers of the 2 waves of releases to be merged together. If we set the flag "printed" on the Out transfer only, we can end up with one Packing transfer leading to 2 Out transfers, which generally doesn't make sense.
* When a new picking was created in the "super" call, it would get the carrier of the sale order (default implementation of `_get_new_picking_values` in delivery). * Modify the way to upgrade the groups and carriers during release: * filter moves without available quantity or which do not need a release, it prevents assigning a carrier on a picking with nothing available or for which we already set the carrier * as soon as a picking is assigned a new carrier, push it in a new group * the new group has the delivery method in the name, to prevent confusion with identical group names (default is the SO name) * after "super", new picking could have been created for the remaining, search them and assign them back to the old group and carrier
Previous behavior: * If we use the "release" action on a move partially available, the remaining will be moved to a backorder picking * When we "release" a move, it stays in the same transfer as the "unreleased" ones (wether they are available or not), so the "unreleased" ones are now in a picking with the "printed flag" Examples of OUT transfer: * 20 product A, 20 allocated * 10 product B, 0 allocated 1. If I use the "release" on the 20 product A: both lines stays in the same transfer, which has the "printed" flag 2. If I use the "release" on both lines: a backorder is created for 10 products B, the backorder has no "printed" flag * 20 product A, 18 allocated * 10 product B, 0 allocated 1. If I use the "release" on the 18 product A: both lines stays in the same transfer, which has the "printed" flag, a backorder is created for 2 product A (without print flag) 2. If I use the "release" on both lines: a backorder is created for 10 products B, the backorder has no "printed" flag Expected behavior: * If we use the "release" action on a move partially available, the remaining will be moved to a backorder picking * When we "release" a move, the unreleased moves are put in a backorder (with the unavailable part of the released move if any) (and they are not "printed")
Add a module with tests to check a release of moves with dynamic routing correctly sets the "printed" flag on all the chain. When we release moves, we set the "printed" flag on the released transfers, so we do not include any new moves (like a "wave" of release). As the dynamic routing is applied when we assign the moves, new moves and transfers may be created after the "assign". We therefore have to set the printed flag after it.
When we have thousands of moves, the screen becomes hardly usable. Make the comptutation faster. * Compute the available quantity directly from quants with a read group (the qty_available computed field is too slow as it computes other quantities, and even much slower because of "mrp" overrides) * The computation of the quantity promised to previous moves is very slow because it runs one query per move. Use a SQL query with LATERAL JOIN in order to run a single query for *all* the moves. As I changed the computation, I went through it and improved / fixed some things: * Show a "previous_promised_qty" field which contains the result of the new query that returns the promised qty of previous moves. It is shown only with debug mode. * Do no longer filter on the "previous moves" of the same warehouse: moves do not always have a "warehouse_id" set. Instead, all the quantities are computed on the same basis: in the view locations of all the warehouses, assuming that if we have the quantity anywhere in the stock, we can release (then make internal transfers). * Compute both uom and real "ordered available to promise" quantity in the same compute method, the uom one being displayed to the user, while the real one is used during the release * When both the priority and the date_priority of previous moves were equal, the previous quantity could be indeterministic, in this case, order by id in last resort * Add tests for search methods
split realease_ready and release_ready_count as the first is used for often and the second is more expensive to compute
…cation The warehouse is used for computing available stock. Allow to view if the warehouse is set.
Do not unrelease when 2 released moves are merged and do not send pre-released move to a backorder.
…nsfers This can happen with stock_dynamic_routing installed that split/cancel pick transfers.
Move "Transfers Allocations" inside "Transfers" section
When a move partially available is released, a new move is created for the remaining quantity. If the released move gets a new picking type, he cannot loose it's priority in favor of the remaining quantity move. Revert of OCA/wms#441
Add support to send released moves to a split order. Always force a new picking on assignation. The condition is already checked before calling action_assign. Improve backorder link with origin and posted message. Call hookable before_release before sending remaining moves to backorder as the hook could manage the way backorders are created (see carrier alternative).
Currently translated at 100.0% (87 of 87 strings) Translation: stock-logistics-reservation-18.0/stock-logistics-reservation-18.0-stock_available_to_promise_release Translate-URL: https://translation.odoo-community.org/projects/stock-logistics-reservation-18-0/stock-logistics-reservation-18-0-stock_available_to_promise_release/it/
Fix migration to v18.0
Fix loop, do not override function argument on first iteration
Currently translated at 100.0% (90 of 90 strings) Translation: stock-logistics-reservation-18.0/stock-logistics-reservation-18.0-stock_available_to_promise_release Translate-URL: https://translation.odoo-community.org/projects/stock-logistics-reservation-18-0/stock-logistics-reservation-18-0-stock_available_to_promise_release/it/
When the rule is configured for a fixed procurement group, a procurement group must be provided
- Fix query for horizon - Fix split of move, ensure need_release is propagated
The procure_method is propagated since odoo v15.0. This is now obsolete.
Ensure released moves are not marked anymore as need_release before defer is called
On run_defer, _action_confirm already calls _action_assign, no need to run it a second time
Currently translated at 100.0% (90 of 90 strings) Translation: stock-logistics-reservation-18.0/stock-logistics-reservation-18.0-stock_available_to_promise_release Translate-URL: https://translation.odoo-community.org/projects/stock-logistics-reservation-18-0/stock-logistics-reservation-18-0-stock_available_to_promise_release/it/
vvrossem
force-pushed
the
19.0-mig-stock_available_to_promise_release
branch
from
October 19, 2026 13:27
3f22ec8 to
2f3625f
Compare
vvrossem
force-pushed
the
19.0-mig-stock_available_to_promise_release
branch
3 times, most recently
from
October 20, 2026 10:39
60c3f06 to
06d902f
Compare
vvrossem
marked this pull request as ready for review
October 20, 2026 10:41
ivantodorovich
approved these changes
Oct 26, 2026
| "=": py_operator.eq, | ||
| "!=": py_operator.ne, | ||
| "in": lambda qty, values: qty in values, | ||
| "not in": lambda qty, values: qty not in values, |
Author
There was a problem hiding this comment.
In 19.0 the ORM turns =/!= into in/not in before calling a search method (fields.py#L145-L150). It only falls back to =/!= when the method returns NotImplemented for in/not in (domains.py#L1038-L1043), which this one doesn't.
In odoo shell:
Move = env.registry["stock.move"]
orig = Move._search_ordered_available_to_promise_uom_qty
def spy(self, operator, value):
print(operator, value)
return orig(self, operator, value)
Move._search_ordered_available_to_promise_uom_qty = spy
env["stock.move"].search([("ordered_available_to_promise_uom_qty", "=", 5)])
env["stock.move"].search([("ordered_available_to_promise_uom_qty", "!=", 5)])in OrderedSet([5])
not in OrderedSet([5])
| "move_name": move.name, | ||
| "done_move_names": ", ".join(done_moves.mapped("name")), | ||
| "move_name": move.product_id.display_name, | ||
| "done_move_names": done_moves.mapped("reference"), |
There was a problem hiding this comment.
", ".join is lost from done_move_names, and it made sense to properly display multiple values.. no?
Author
There was a problem hiding this comment.
env._ formats list arguments itself, with the language's separators (translate.py#L440-L448).
In odoo shell:
msg = "You cannot unrelease the move %(move_name)s because some origin moves %(done_move_names)s are done"
env._(msg, move_name="Desk", done_move_names=["WH/PICK/00001", "WH/PICK/00002"])You cannot unrelease the move Desk because some origin moves WH/PICK/00001 and WH/PICK/00002 are done
In French the list becomes WH/PICK/00001 et WH/PICK/00002.
vvrossem
force-pushed
the
19.0-mig-stock_available_to_promise_release
branch
from
October 26, 2026 13:27
06d902f to
f35aecd
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Migration of
stock_available_to_promise_releaseto 19.0.Depends on OCA/stock-logistics-warehouse#2677 (
stock_warehouse_out_pull), pulled in by the[DO NOT MERGE] test-requirements.txtcommit.Most changes come from
procurement.groupbeing removed in 19.0.Release policy
release_policyused to be taken from the procurement group'smove_typewhen the picking was created. In 19.0, sale_stock computes the picking'smove_typefrom the SO lines, so it is only known once the moves are linked. The module now setsrelease_policyfor new pickings in_assign_picking_post_process. It stays a plain field, as in 18.0:release_policymove_type: SO shipping policy, else the operation type'sThe install hook fills existing pickings from
move_type.Other
procurement.groupchangesrun_defermoves tostock.rule.stock.referenceinstead of groups. The "fixed" group on the pick rule is gone, so tests that relied on it to gather the pick moves of two deliveries in one transfer use a_merge_pickingshelper.19.0 API
in/not in, which 19.0 passes instead of=/!=(boolean fields andordered_available_to_promise_uom_qty), and returnNotImplementedfor other operators.grouped("picking_id")replacesitertools.groupby, which split moves of the same picking when they weren't consecutive._read_group,Domain,models.Constraint,group_ids,stock.package,fields.first,stock.move.name.