Repository
OCA/stock-logistics-reservation · module folder · Try on Runboat
Module version
1.7.0
Category
Stock Management
Folder size
0.38 MB
License
LGPL-3
Application
No
Auto-installable
No
Website
https://github.com/OCA/stock-logistics-reservation
Last tracking update
2026-08-07 08:43:06
Authors
Camptocamp, Odoo Community Association (OCA), BCIM
Maintainers
Camptocamp, Odoo Community Association (OCA), BCIM
Committers
Jacques-Etienne Baudoux, Akim Juillerat, Sébastien Alix, Weblate, Ruchir Shukla, twalter-c2c, OCA-git-bot, oca-ci, Mmequignon, SIP
Odoo dependencies
Python dependencies
openupgradelib
System dependencies
None
Required by
sale_order_blanket_order_stock_prebook_release, sale_stock_available_to_promise_release, sale_stock_prebook_stock_available_to_promise_release, stock_available_to_promise_release_delivery, stock_available_to_promise_release_dynamic_routing, stock_available_to_promise_release_exclude_location, stock_release_channel, stock_release_channel_process_end_time
Description
Currently the reservation is performed by adding reserved quantities on
quants, which is fine as long as the reservation is made right after the
order confirmation. This way, the first arrived, first served principle
is always applied. But if you release warehouse operations in a chosen
order (through deliver round for example), then you need to be sure the
reservations are made in respect to the first arrived first served
principle and not driven by the order you choose to release your
operations.

Allow each delivery move to mark a quantity as virtually reserved.
Simple rule would be first ordered, first served. More complex rules
could be implemented.

When the reservation of a picking move occurs, the quantity that is
reserved is then based on the quantity that was promised to the customer
(available to promise):

- The moves can be reserved in any order, the right quantity is always
  reserved
- The removal strategy is computed only when the reservation occurs. If
  you reserve order 2 before order 1 (because you have/want to deliver
  order 2) you can apply correctly fifo/fefo.
  - For instance order 1 must be delivered in 1 month, order 2 must be
    delivered now.
  - Virtually lock quantities to be able to serve order 1
  - Reserve remaining quantity for order 2 and apply fefo
- Allow to limit the promised quantity in time. If a customer orders now
  for a planned delivery in 2 months, then allow to not lock this
  quantity as virtually reserved
- Allow to perform reservations jointly with your delivery rounds
  planning. Reserve only the quants you planned to deliver.

When move qty is not completely satisfied on release, the remaining qty
is split and attached to a new picking that can be released later.

Important: if the "Stock reservation horizon" is set, the qty is
calculated on moves which have an expected date not beyond \$today +
\$horizon (in days).

Important: Moves without a warehouse set are not supported. If the
warehouse is not set on the move, the "Ordered Available to Promise"
Quantity will always be 0. It will also not be considered as consuming
existing stock. The warehouse gets set by the Stock rule, if the Rule is
not assigned to a warehouse, also the move will not end up with a
warehouse.

Code Analysis

Views touched (13)
XML IDNameModelTypeStatus
product_normal_form_view product.product.move.release product.product form Inherits product.product_normal_form_view
res_config_settings_view_form_stock stock_available_to_promise_release res.config.settings form res.config.settings form Inherits stock.res_config_settings_view_form
stock_picking_type_form stock.picking.type.form stock.picking.type form Inherits stock.view_picking_type_form
stock_picking_type_kanban stock.picking.type.kanban stock.picking.type kanban Inherits stock.stock_picking_type_kanban
stock_route_form_view stock.route.form stock.route form Inherits stock.stock_location_route_form_view
view_move_release_form stock.move.release.form stock.move form Inherits stock.view_move_form
view_move_release_search stock.move.release.search stock.move search Inherits stock.view_move_search
view_move_release_tree Stock Moves Release stock.move tree Inherits stock.view_move_tree
view_picking_release_form stock.picking.release.form stock.picking form Inherits stock.view_picking_form
view_picking_release_search stock.picking.release.search stock.picking search Inherits stock.view_picking_internal_search
view_picking_release_tree stock.picking.release.tree stock.picking list New
view_stock_release_form Stock Allocations Release stock.release form New
view_stock_unrelease_form Stock Allocations Unrelease stock.unrelease form New
HTTP endpoints (0)

No HTTP endpoints found for this module.

Models touched (14)

New fields (0)

No new fields.

Public methods (1)
  • run_defer(self, procurements)

New fields (1)
  • move_need_release_count Integer
    compute='_compute_move_need_release_count' string='Moves Need Release'
Public methods (1)
  • action_open_move_need_release(self)

New fields (2)
  • stock_release_max_prep_time Integer
    default=180.0 help='When your release transfers, their scheduled date is rescheduled to now + this preparation time (in minutes). Their scheduled date represents the latest the transfers should be done, and therefore, past this timestamp, considered late.' string='Transfer Releases Max Prep. Time'
  • stock_reservation_horizon Integer
    default=0 help='Compute promised quantities for order planned to be shipped until this number of days from today.'
Public methods (0)

No public methods.

New fields (2)
  • stock_release_max_prep_time Integer
    readonly=False related='company_id.stock_release_max_prep_time'
  • stock_reservation_horizon Integer
    readonly=False related='company_id.stock_reservation_horizon'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (7)
  • date_priority Datetime
    default=fields.Datetime.now help='Date/time used to sort moves to deliver first. Used to calculate the ordered available to promise.' index=True string='Priority Date'
  • need_release Boolean
    index=True
  • ordered_available_to_promise_qty Float
    compute='_compute_ordered_available_to_promise' digits='Product Unit of Measure' help='Available to Promise quantity minus quantities promised to moves with higher priority (in default UoM of the product).' string='Ordered Available to Promise (Real Qty)'
  • ordered_available_to_promise_uom_qty Float
    compute='_compute_ordered_available_to_promise' digits='Product Unit of Measure' help="Available to Promise quantity minus quantities promised to moves with higher priority (in initial demand's UoM)." search='_search_ordered_available_to_promise_uom_qty' string='Ordered Available to Promise'
  • previous_promised_qty Float
    compute='_compute_previous_promised_qty' digits='Product Unit of Measure' help='Quantities promised to moves with higher priority than this move (in default UoM of the product).' string='Quantity Promised before this move'
  • release_ready Boolean
    compute='_compute_release_ready' search='_search_release_ready'
  • unrelease_allowed Boolean
    compute='_compute_unrelease_allowed'
Public methods (3)
  • release_available_to_promise(self)
  • unrelease(self, safe_unrelease=False)
    Unrelease unreleasable moves If safe_unrelease is True, the unreleasaable moves for which the processing has already started will be ignored
  • write(self, vals)

New fields (7)
  • date_priority Datetime
    compute='_compute_date_priority' help='Date/time used to sort moves to deliver first. Used to calculate the ordered available to promise.' string='Priority Date'
  • last_release_date Datetime
    copy=False
  • need_release Boolean
    compute='_compute_need_release' search='_search_need_release'
  • need_release_count Integer
    compute='_compute_need_release' string='# of need release moves'
  • release_policy Selection
    default='direct' help='It specifies how to release a transfer partially or all at once' required=True args: [('direct', 'As soon as possible'), ('one', 'When all products are ready')]
  • release_ready Boolean
    compute='_compute_release_ready' search='_search_release_ready'
  • release_ready_count Integer
    compute='_compute_release_ready_count' string='# of moves ready'
Public methods (3)
  • action_open_move_need_release(self)
  • release_available_to_promise(self)
  • unrelease(self, safe_unrelease=False)
    Unrelease the moves of the picking. If safe_unrelease is True, the unreleasable moves for which the processing has already started will be ignored

New fields (3)
  • count_picking_need_release Integer
    compute='_compute_picking_count'
  • prevent_new_move_after_release Boolean
    help='If checked, once a delivery picking has been released, no more moves will be added to it. For example, if you add lines in the origin sales order, the new moves will be added to a new delivery.' string='Prevent new move after release'
  • unrelease_on_backorder Boolean
    help='If checked, when a backorder is created (i.e. at the validation of the delivery), the moves into the backorder are unreleased as long as they came from a route configured to manually release moves. This means that the moves that were not delivered are put back in need for release and the unprocessed internal pulled moves are canceled.' string='Unrelease on backorder'
Public methods (1)
  • get_action_picking_tree_need_release(self)

New fields (0)

No new fields.

Public methods (1)
  • release(self)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (3)
  • allow_unrelease_return_done_move Boolean
    default=False help="If checked, unreleasing the delivery may create a new inverse internal operation on the last done pulled transfer. Otherwise, you won't be able to unrelease as soon as one of the pulled transfer is done" string='Reverse done transfer on cancellation'
  • available_to_promise_defer_pull Boolean
    default=False help='Do not create chained moved automatically for delivery. Transfers must be released manually when they have enough available to promise.' string='Release based on Available to Promise'
  • no_backorder_at_release Boolean
    default=False help='When releasing a transfer, do not create a backorder for the moves created for the unavailable quantities.' string='No backorder at release'
Public methods (0)

No public methods.

New fields (3)
  • allow_unrelease_return_done_move Boolean
    related='route_id.allow_unrelease_return_done_move' store=True
  • available_to_promise_defer_pull Boolean
    related='route_id.available_to_promise_defer_pull' store=True
  • no_backorder_at_release Boolean
    related='route_id.no_backorder_at_release' store=True
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (1)
  • unrelease(self)

Loading…

Loading…

Loading…

Loading…