Repository
OCA/stock-logistics-putaway · module folder · Try on Runboat
Module version
1.6.2
Category
Warehouse Management
Folder size
0.42 MB
License
AGPL-3
Application
No
Auto-installable
No
Website
https://github.com/OCA/stock-logistics-putaway
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, Alexandre Fayolle, Sébastien Alix, Thierry Ducrest, Weblate, OCA-git-bot, oca-ci, Mmequignon
Odoo dependencies
Python dependencies
None
System dependencies
None
Required by
shopfloor_reception_package_dimension, stock_storage_type_buffer, stock_storage_type_move_line_qty_picked, stock_storage_type_putaway_abc, stock_vertical_lift_storage_type
Description
This module extends package types Odoo feature in order to better manage
stock moves with packages according to the packaging and stock location
properties (like height, weight or any customized conditions).

Moreover, this module implements "package type put-away strategy" in
order to compute a put-away location using package types.

The standard put-away strategy is applied *before* the package type
put-away strategy as the former relies on product or product category
and the latter relies on stock packages.

In other words, when a move is reserved, Odoo standard put-away strategy
will be applied to compute a new destination on the stock move lines,
according to the product. After this first "put-away computation", the
"package type" put-away strategy is applied, if the reserved quant is
linked to a package defining a package type.

Storage locations linked to the package type are processed sequentially,
if said storage location is a child of the move line's destination
location (i.e either the put-away location or the move's destination
location). For each location, their package type strategy is applied as
well as the restrictions defined on the storage category. If no suitable
location is found, the next location in the sequence will be searched
and so on.

For the package type putaway strategy "None", the location is considered
as is. For the "ordered children" strategy, children locations are
sorted by first by max height which is a physical constraint to respect,
then pack putaway sequence which allow to favor for example some level
or corridor, and finally by name.

At the end, if found location is not the same as the original
destination location, the putaway strategies are applied (e.g.: A "None"
pack putaway strategy is set on computed location and a putaway rule
exists on that one).

Code Analysis

Views touched (11)
XML IDNameModelTypeStatus
package_level_form_view_inherit Package Level Inherit (in stock_storage_type) stock.package_level form Inherits stock.package_level_form_view
package_level_tree_view_picking_inherit Package Level Tree Picking Inherit (in stock_storage_type) stock.package_level tree Inherits stock.package_level_tree_view_picking
package_storage_location_tree_view package.storage.location.list.view stock.storage.location.sequence list New
product_template_form_view_procurement_button_inherit product.template_procurement.inherit product.template form Inherits stock.product_template_form_view_procurement_button
stock_package_type_form stock.package.type.form (in stock_storage_type) stock.package.type form Inherits stock.stock_package_type_form
stock_storage_category_allow_new_product_cond_view_form stock.storage.category.allow_new_product.cond.form stock.storage.category.allow_new_product.cond form New
stock_storage_category_form stock.storage.category.form (in stock_storage_type) stock.storage.category form Inherits stock.stock_storage_category_form
stock_storage_location_sequence_cond_form_view stock.storage.location.sequence.cond.form (in stock_storage_type) stock.storage.location.sequence.cond form New
stock_storage_location_sequence_cond_tree_view stock.storage.location.sequence.cond.tree (in stock_storage_type) stock.storage.location.sequence.cond list New
view_location_form_inherit stock.location.form.inherit (in stock_storage_type) stock.location form Inherits stock.view_location_form
view_location_tree_inherit stock.location.tree.inherit (in stock_storage_type) stock.location tree Inherits stock.view_location_tree2
HTTP endpoints (0)

No HTTP endpoints found for this module.

Models touched (12)

New fields (16)
  • computed_storage_capacity_ids One2many
    related='computed_storage_category_id.capacity_ids'
  • computed_storage_category_id Many2one → stock.storage.category
    comodel_name='stock.storage.category' compute='_compute_computed_storage_category_id' help='This represents the Storage Category that will be used. It depends either on the category set on the location or on one of its parent.' index='btree_not_null' recursive=True store=True string='Computed Storage Category'
  • do_not_mix_lots Boolean
    compute='_compute_do_not_mix_lots' recursive=True store=True
  • do_not_mix_products Boolean
    compute='_compute_do_not_mix_products' recursive=True store=True
  • has_potential_lot_mix_exception Boolean
    compute='_compute_has_potential_lot_mix_exception' help='This will represent a situation where several moves are pointingto the location for different product lots and the location doesnot allow mixed lots.' index=True store=True
  • has_potential_product_mix_exception Boolean
    compute='_compute_has_potential_product_mix_exception' help='This will represent a situation where several moves are pointingto the location for different products and the location doesnot allow mixed products.' index=True store=True
  • leaf_child_location_ids Many2many → stock.location
    compute='_compute_leaf_location_ids' help='technical field: all the leaves sub-locations' recursive=True args: 'stock.location'
  • leaf_location_ids Many2many → stock.location
    compute='_compute_leaf_location_ids' help='technical field: all the leaves locations' recursive=True args: 'stock.location'
  • location_will_contain_lot_ids Many2many → stock.lot
    compute='_compute_location_will_contain_lot_ids' help='technical field: list of stock.lots in the location, either now or in pending operations' store=True args: 'stock.lot'
  • location_will_contain_product_ids Many2many → product.product
    compute='_compute_location_will_contain_product_ids' help='technical field: list of products in the location, either now or in pending operations' store=True args: 'product.product'
  • max_height Float
    recursive=True related='computed_storage_category_id.max_height' store=True
  • max_height_in_m Float
    recursive=True related='computed_storage_category_id.max_height_in_m' store=True
  • only_empty Boolean
    compute='_compute_only_empty' recursive=True store=True
  • pack_putaway_strategy Selection
    default='none' help='This defines the storage strategy based on package type to use when a product or package is put away in this location.\nNone: when moved to this location, it will not be put away any further.\nOrdered Children Locations: when moved to this location, a suitable location will be searched in its children locations according to the restrictions defined on their respective storage category.' required=True selection=[('none', 'None'), ('ordered_locations', 'Ordered Children Locations')] string='Put-Away Strategy'
  • package_type_putaway_sequence Integer
    help='Allow to sort the valid locations by sequence for the storage strategy based on package type' string='Putaway Sequence'
  • storage_location_sequence_ids One2many → stock.storage.location.sequence
    string='Storage locations sequences' args: 'stock.storage.location.sequence', 'location_id'
Public methods (4)
  • get_storage_locations(self, products=None)
  • init(self)
  • select_allowed_locations(self, package_type, quants, products, limit=None)
    Filter allowed locations for a package type. ``self`` contains locations already ordered according to the putaway strategy, so beware of the return that must keep the same order
  • select_first_allowed_location(self, package_type, quants, products)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (6)
  • active Boolean
    default=True
  • barcode Char
    copy=False
  • height_required Boolean
    default=False help='Height is mandatory for packages configured with this package type.' string='Height required for packages'
  • product_packaging_ids One2many → product.packaging
    args: 'product.packaging', 'package_type_id'
  • storage_location_sequence_ids One2many → stock.storage.location.sequence
    string='Put-Away sequence' args: 'stock.storage.location.sequence', 'package_type_id'
  • storage_type_message Html
    compute='_compute_storage_type_message'
Public methods (1)
  • action_view_storage_locations(self)

New fields (1)
  • allowed_location_dest_ids Many2many → stock.location
    comodel_name='stock.location' compute='_compute_allowed_location_dest_ids' string='Allowed Destinations'
Public methods (1)
  • recompute_pack_putaway(self)

New fields (0)

No new fields.

Public methods (2)
  • create(self, vals_list)
    @api.model_create_multi
  • write(self, vals)

New fields (3)
  • height Float
    compute='_compute_height' readonly=False store=True
  • height_in_m Float
    compute='_compute_height_in_m' help='Technical field, to speed up comparaisons' store=True
  • pack_weight_in_kg Float
    compute='_compute_pack_weight_in_kg' help='Technical field, to speed up comparaisons' store=True
Public methods (0)

No public methods.

New fields (10)
  • allow_new_product Selection
    ondelete={'same_lot': 'cascade'} selection_add=[('same_lot', 'If lots are all the same')]
  • allow_new_product_ids One2many → stock.storage.category.allow_new_product
    comodel_name='stock.storage.category.allow_new_product' inverse_name='storage_category_id' string='Allow New Product Rules'
  • computed_location_ids One2many → stock.location
    comodel_name='stock.location' inverse_name='computed_storage_category_id'
  • has_restrictions Boolean
    compute='_compute_has_restrictions' help='Technical: This is used to check if we need to display warning message'
  • length_uom_id Many2one → uom.uom
    default=<expr> domain=<expr> args: 'uom.uom', 'Max height Unit of Measure'
  • max_height Float
    help='The max height supported for this storage category.' string='Max height (mm)'
  • max_height_in_m Float
    compute='_compute_max_height_in_m' help='Technical field, to speed up comparaisons' store=True
  • max_weight_in_kg Float
    compute='_compute_max_weight_in_kg' help='Technical field, to speed up comparaisons' store=True
  • weight_uom_id Many2one → uom.uom
    compute=False default=<expr> domain=<expr> help='Weight Unit of Measure' string='Weight Units of Measure' args: 'uom.uom'
  • weight_uom_name Char
    readonly=True related='weight_uom_id.name' string='Weight unit of measure label'
Public methods (1)
  • get_allow_new_product(self, product, package_type=None, package=None, quants=None)
    Return the `allow_new_product` option value. It first evaluates the conditions based on different criteria, and if no value can be found among them it fallbacks on the category option value.

New fields (4)
  • allow_new_product Selection
    default='mixed' required=True selection=_selection_allow_new_product
  • condition_ids Many2many → stock.storage.category.allow_new_product.cond
    comodel_name='stock.storage.category.allow_new_product.cond' help='All conditions have to match to apply the Allow New Product policy.' relation='stock_storage_category_allow_new_product_cond_rel' required=True string='Conditions'
  • sequence Integer
    index=True
  • storage_category_id Many2one → stock.storage.category
    comodel_name='stock.storage.category' index=True ondelete='cascade' required=True
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (1)
  • evaluate(self, storage_category, product, package_type, package, quants)

New fields (5)
  • active Boolean
    default=True
  • code_snippet Text
    required=True
  • code_snippet_docs Text
    compute='_compute_code_snippet_docs' default=<expr>
  • condition_type Selection
    default='code' required=True selection=[('code', 'Execute code')]
  • name Char
    required=True
Public methods (1)
  • evaluate(self, *args, **kwargs)
    Evaluate and return the result of the condition.

New fields (5)
  • location_id Many2one → stock.location
    required=True args: 'stock.location'
  • location_putaway_strategy Selection
    related='location_id.pack_putaway_strategy'
  • location_sequence_cond_ids Many2many → stock.storage.location.sequence.cond
    comodel_name='stock.storage.location.sequence.cond' help='All conditions have to match to apply the put-away strategy.' relation='stock_location_sequence_cond_rel' string='Conditions'
  • package_type_id Many2one → stock.package.type
    ondelete='cascade' required=True args: 'stock.package.type'
  • sequence Integer
    required=True
Public methods (2)
  • button_show_locations(self)
  • can_be_applied(self, putaway_location, quant, product)
    Check if conditions are met.

New fields (0)

No new fields.

Public methods (1)
  • evaluate(self, storage_location_sequence, putaway_location, quant, product)

Loading…

Loading…

Loading…

Loading…

Loading…