Stock Warehouse Flow

stock_warehouse_flow
REPOSITORY
REPOSITORYOCA/wms
GIT
GIThttps://github.com/OCA/wms.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/wms/tree/17.0/stock_warehouse_flow
VERSION
VERSION 1.0.0
CATEGORY
CATEGORYWarehouse Management
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOdoo Community Association (OCA), Camptocamp, BCIM
MAINTAINERS
MAINTAINERSOdoo Community Association (OCA), Camptocamp, BCIM
COMMITTERS
COMMITTERSWeblate, OCA-git-bot, oca-ci, Antoni Marroig Campomar
WEBSITE
WEBSITEhttps://github.com/OCA/wms
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 19:20:11
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/stock-logistics-workflow:
    - delivery_procurement_group_carrier
odoo/odoo:
    - stock
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - uom
    - barcodes_gs1_nomenclature
    - barcodes
    - digest
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - resource
    - delivery
    - sale
    - sales_team
    - account_payment
    - account
    - onboarding
    - analytic
    - payment
    - utm
    - sale_stock
    - stock_account
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION
This module introduces the concept of routing flows in order to manage
different delivery routes for a warehouse.

The default behavior of Odoo allows you to have only one delivery route
per warehouse (with one, two or three steps). With this module, you are
now able to manage multiple delivery routes (having their own rules and
operation types), the right one being selected automatically based on
some criterias, like the carrier and any attribute of the stock move to
process.

This allows you to define a delivery route based on the type of goods to
ship, for instance:

- whole pallet (pick + ship)
- cold chain goods
- dangerous goods

![image_description](https://raw.githubusercontent.com/OCA/wms/14.0/stock_warehouse_flow/static/description/flow.png)

Code Analysis

Views touched (6)
XML IDNameModelTypeStatus
stock_location_route_tree stock.location.route.tree.inherit stock.route field Inherits stock.stock_location_route_tree
stock_warehouse_flow_view_form stock.warehouse.flow.form stock.warehouse.flow form New
stock_warehouse_flow_view_search stock.warehouse.flow.search stock.warehouse.flow search New
stock_warehouse_flow_view_tree stock.warehouse.flow.tree stock.warehouse.flow tree New
view_delivery_carrier_form delivery.carrier.form.inherit delivery.carrier div Inherits delivery.view_delivery_carrier_form
view_warehouse stock.warehouse.form.inherit stock.warehouse div Inherits stock.view_warehouse
Models touched (5)

New fields (1)
  • flow_ids Many2many → stock.warehouse.flow
    column1='delivery_carrier_id' column2='stock_warehouse_flow_id' comodel_name='stock.warehouse.flow' copy=False relation='delivery_carrier_stock_warehouse_flow_rel' string='Routing flows'
Public methods (1)
  • action_view_flows(self)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (2)
  • applicable_flow_ids One2many → stock.warehouse.flow
    comodel_name='stock.warehouse.flow' compute='_compute_applicable_flow_ids' string='Applicable Flows'
  • flow_id Many2one → stock.warehouse.flow
    comodel_name='stock.warehouse.flow' ondelete='set null' string='Routing Flow'
Public methods (0)

No public methods.

New fields (1)
  • flow_ids One2many → stock.warehouse.flow
    comodel_name='stock.warehouse.flow' inverse_name='warehouse_id' string='Flows'
Public methods (1)
  • action_view_all_flows(self)

New fields (26)
  • active Boolean
    default=True
  • carrier_ids Many2many → delivery.carrier
    column1='stock_warehouse_flow_id' column2='delivery_carrier_id' comodel_name='delivery.carrier' copy=False relation='delivery_carrier_stock_warehouse_flow_rel' string='With carriers'
  • company_id Many2one
    related='warehouse_id.company_id'
  • delivery_route_id Many2one → stock.route
    comodel_name='stock.route' copy=False index=True ondelete='set null' readonly=True string='Delivery Route'
  • delivery_steps Selection
    default='ship_only' help='Outgoing route to follow' required=True selection=[('ship_only', 'Deliver goods directly (1 step)'), ('pick_ship', 'Send goods in output and then deliver (2 steps)'), ('pick_pack_ship', 'Pack goods, send goods in output and then deliver (3 steps)')] string='Outgoing Shipments'
  • from_location_dest_id Many2one → stock.location
    comodel_name='stock.location' compute='_compute_from_location_dest_id'
  • from_location_src_id Many2one → stock.location
    comodel_name='stock.location' compute='_compute_from_location_src_id'
  • from_picking_type_id Many2one → stock.picking.type
    comodel_name='stock.picking.type' domain="[('code', '=', 'outgoing')]" index=True ondelete='restrict' required=True string='From operation type'
  • impacted_route_ids One2many → stock.route
    comodel_name='stock.route' compute='_compute_impacted_route_ids' string='Impacted Routes'
  • move_domain Char
    copy=False default=[] help='Domain based on Stock Moves, to define if the routing flow is applicable or not.' string='Source Routing Domain'
  • name Char
    required=True
  • out_type_id Many2one
    help="Same than 'To operation type' field, displayed here to get a global overview of the flow configuration." readonly=True related='to_picking_type_id' string='Out Type'
  • output_stock_loc_id Many2one
    help="Same than 'To output location' field, displayed here to get a global overview of the flow configuration." readonly=True related='to_output_stock_loc_id' string='Output Location'
  • pack_stock_loc_id Many2one → stock.location
    check_company=True args: 'stock.location', 'Packing Location'
  • pack_type_id Many2one → stock.picking.type
    check_company=True args: 'stock.picking.type', 'Pack Type'
  • pick_type_id Many2one → stock.picking.type
    check_company=True args: 'stock.picking.type', 'Pick Type'
  • qty Float
    default=0 help="If a qty is set the flow can be applied on moves where the move's qty >= the qty set on the flow\n"
  • rule_ids One2many
    related='delivery_route_id.rule_ids' string='Rules'
  • sequence Integer
    default=10
  • sequence_prefix Char
    help="Used to generate the default prefix of new operation types. (e.g. 'DG' => 'WH/OUT/DG/')"
  • split_method Selection
    help='Simple => move will be split by the qty of the flow or a multiple of it' args: [('simple', 'Simple')], 'Split method'
  • to_output_stock_loc_id Many2one → stock.location
    check_company=True comodel_name='stock.location' ondelete='restrict' string='To output location'
  • to_picking_type_id Many2one → stock.picking.type
    check_company=True comodel_name='stock.picking.type' domain="[('default_location_dest_id', '=', from_location_dest_id)]" ondelete='restrict' readonly=True string='To operation type'
  • uom_id Many2one → uom.uom
    default=<expr> args: 'uom.uom', 'Uom'
  • warehouse_id Many2one → stock.warehouse
    comodel_name='stock.warehouse' default=<expr> ondelete='restrict' required=True string='Warehouse'
  • warning Html
    compute='_compute_warning'
Public methods (6)
  • action_generate_route(self)
  • apply_on_move(self, move, assign_picking=True)
  • onchange_name(self)
    @api.onchange('name')
  • onchange_warehouse_id(self)
    @api.onchange('warehouse_id')
  • split_move(self, move)
  • write(self, vals)
REPOSITORY
REPOSITORYOCA/wms
GIT
GIThttps://github.com/OCA/wms.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/wms/tree/16.0/stock_warehouse_flow
VERSION
VERSION 1.1.0
CATEGORY
CATEGORYWarehouse Management
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOdoo Community Association (OCA), Camptocamp, BCIM
MAINTAINERS
MAINTAINERSOdoo Community Association (OCA), Camptocamp, BCIM
COMMITTERS
COMMITTERSSébastien Alix, Weblate, OCA-git-bot, Rodrigo, oca-ci, Mmequignon
WEBSITE
WEBSITEhttps://github.com/OCA/wms
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:53:59
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/stock-logistics-workflow:
    - delivery_procurement_group_carrier
odoo/odoo:
    - stock
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - uom
    - barcodes_gs1_nomenclature
    - barcodes
    - digest
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - resource
    - delivery
    - sale_stock
    - sale
    - sales_team
    - account_payment
    - account
    - analytic
    - payment
    - utm
    - stock_account
    - sale_management
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (7)
XML IDNameModelTypeStatus
stock_location_route_tree stock.location.route.tree.inherit stock.route field Inherits stock.stock_location_route_tree
stock_route_form_view stock.route.form.inherit stock.route xpath Inherits stock.stock_location_route_form_view
stock_warehouse_flow_view_form stock.warehouse.flow.form stock.warehouse.flow form New
stock_warehouse_flow_view_search stock.warehouse.flow.search stock.warehouse.flow search New
stock_warehouse_flow_view_tree stock.warehouse.flow.tree stock.warehouse.flow tree New
view_delivery_carrier_form delivery.carrier.form.inherit delivery.carrier div Inherits delivery.view_delivery_carrier_form
view_warehouse stock.warehouse.form.inherit stock.warehouse div Inherits stock.view_warehouse
Models touched (5)

New fields (1)
  • flow_ids Many2many → stock.warehouse.flow
    column1='delivery_carrier_id' column2='stock_warehouse_flow_id' comodel_name='stock.warehouse.flow' copy=False relation='delivery_carrier_stock_warehouse_flow_rel' string='Routing flows'
Public methods (1)
  • action_view_flows(self)

New fields (1)
  • default_picking_type_id Many2one → stock.picking.type
    help='Used as a backup to save picking type set by odoo, before a new flow is applied.' args: 'stock.picking.type'
Public methods (0)

No public methods.

New fields (3)
  • applicable_flow_ids One2many → stock.warehouse.flow
    comodel_name='stock.warehouse.flow' compute='_compute_applicable_flow_ids' string='Applicable Flows'
  • apply_flow_on Selection
    default='on_confirm' args: [('on_confirm', 'When move is confirmed')]
  • flow_id Many2one → stock.warehouse.flow
    comodel_name='stock.warehouse.flow' ondelete='set null' string='Routing Flow'
Public methods (0)

No public methods.

New fields (1)
  • flow_ids One2many → stock.warehouse.flow
    comodel_name='stock.warehouse.flow' inverse_name='warehouse_id' string='Flows'
Public methods (1)
  • action_view_all_flows(self)

New fields (26)
  • active Boolean
    default=True
  • carrier_ids Many2many → delivery.carrier
    column1='stock_warehouse_flow_id' column2='delivery_carrier_id' comodel_name='delivery.carrier' copy=False relation='delivery_carrier_stock_warehouse_flow_rel' string='With carriers'
  • company_id Many2one
    related='warehouse_id.company_id'
  • delivery_route_id Many2one → stock.route
    comodel_name='stock.route' copy=False index=True ondelete='set null' readonly=True string='Delivery Route'
  • delivery_steps Selection
    default='ship_only' help='Outgoing route to follow' required=True selection=[('ship_only', 'Deliver goods directly (1 step)'), ('pick_ship', 'Send goods in output and then deliver (2 steps)'), ('pick_pack_ship', 'Pack goods, send goods in output and then deliver (3 steps)')] string='Outgoing Shipments'
  • from_location_dest_id Many2one → stock.location
    comodel_name='stock.location' compute='_compute_from_location_dest_id'
  • from_location_src_id Many2one → stock.location
    comodel_name='stock.location' compute='_compute_from_location_src_id'
  • from_picking_type_id Many2one → stock.picking.type
    comodel_name='stock.picking.type' domain="[('code', '=', 'outgoing')]" index=True ondelete='restrict' required=True string='From operation type'
  • impacted_route_ids One2many → stock.route
    comodel_name='stock.route' compute='_compute_impacted_route_ids' string='Impacted Routes'
  • move_domain Char
    copy=False default=[] help='Domain based on Stock Moves, to define if the routing flow is applicable or not.' string='Source Routing Domain'
  • name Char
    required=True
  • out_type_id Many2one
    help="Same than 'To operation type' field, displayed here to get a global overview of the flow configuration." readonly=True related='to_picking_type_id' string='Out Type'
  • output_stock_loc_id Many2one
    help="Same than 'To output location' field, displayed here to get a global overview of the flow configuration." readonly=True related='to_output_stock_loc_id' string='Output Location'
  • pack_stock_loc_id Many2one → stock.location
    check_company=True args: 'stock.location', 'Packing Location'
  • pack_type_id Many2one → stock.picking.type
    check_company=True args: 'stock.picking.type', 'Pack Type'
  • pick_type_id Many2one → stock.picking.type
    check_company=True args: 'stock.picking.type', 'Pick Type'
  • qty Float
    default=0 help="If a qty is set the flow can be applied on moves where the move's qty >= the qty set on the flow\n"
  • rule_ids One2many
    related='delivery_route_id.rule_ids' string='Rules'
  • sequence Integer
    default=10
  • sequence_prefix Char
    help="Used to generate the default prefix of new operation types. (e.g. 'DG' => 'WH/OUT/DG/')"
  • split_method Selection
    help='Simple => move will be split by the qty of the flow or a multiple of it' args: [('simple', 'Simple')], 'Split method'
  • to_output_stock_loc_id Many2one → stock.location
    check_company=True comodel_name='stock.location' ondelete='restrict' string='To output location'
  • to_picking_type_id Many2one → stock.picking.type
    check_company=True comodel_name='stock.picking.type' domain="[('default_location_dest_id', '=', from_location_dest_id)]" ondelete='restrict' readonly=True string='To operation type'
  • uom_id Many2one → uom.uom
    default=<expr> args: 'uom.uom', 'Uom'
  • warehouse_id Many2one → stock.warehouse
    comodel_name='stock.warehouse' default=<expr> ondelete='restrict' required=True string='Warehouse'
  • warning Html
    compute='_compute_warning'
Public methods (6)
  • action_generate_route(self)
  • apply_on_move(self, move, assign_picking=True)
  • onchange_name(self)
    @api.onchange('name')
  • onchange_warehouse_id(self)
    @api.onchange('warehouse_id')
  • split_move(self, move)
  • write(self, vals)
REPOSITORY
REPOSITORYOCA/wms
GIT
GIThttps://github.com/OCA/wms.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/wms/tree/14.0/stock_warehouse_flow
VERSION
VERSION 2.1.1
CATEGORY
CATEGORYWarehouse Management
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOdoo Community Association (OCA), Camptocamp, BCIM
MAINTAINERS
MAINTAINERSOdoo Community Association (OCA), Camptocamp, BCIM
COMMITTERS
COMMITTERSJacques-Etienne Baudoux, Sébastien Alix, Thierry Ducrest, Weblate, OCA-git-bot, Michael Tietz, oca-ci, Ricardoalso, Mmequignon
WEBSITE
WEBSITEhttps://github.com/OCA/wms
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:41:12
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/stock-logistics-workflow:
    - delivery_procurement_group_carrier
odoo/odoo:
    - stock
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - uom
    - barcodes
    - digest
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - resource
    - delivery
    - sale_stock
    - sale
    - sales_team
    - payment
    - account
    - analytic
    - utm
    - stock_account
    - sale_management
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (7)
XML IDNameModelTypeStatus
stock_location_route_form_view stock.location.route.form.inherit stock.location.route field Inherits stock.stock_location_route_form_view
stock_location_route_tree stock.location.route.tree.inherit stock.location.route field Inherits stock.stock_location_route_tree
stock_warehouse_flow_view_form stock.warehouse.flow.form stock.warehouse.flow form New
stock_warehouse_flow_view_search stock.warehouse.flow.search stock.warehouse.flow search New
stock_warehouse_flow_view_tree stock.warehouse.flow.tree stock.warehouse.flow tree New
view_delivery_carrier_form delivery.carrier.form.inherit delivery.carrier div Inherits delivery.view_delivery_carrier_form
view_warehouse stock.warehouse.form.inherit stock.warehouse div Inherits stock.view_warehouse
Models touched (5)

New fields (1)
  • flow_ids Many2many → stock.warehouse.flow
    column1='delivery_carrier_id' column2='stock_warehouse_flow_id' comodel_name='stock.warehouse.flow' copy=False relation='delivery_carrier_stock_warehouse_flow_rel' string='Routing flows'
Public methods (1)
  • action_view_flows(self)

New fields (3)
  • applicable_flow_ids One2many → stock.warehouse.flow
    comodel_name='stock.warehouse.flow' compute='_compute_applicable_flow_ids' string='Applicable Flows'
  • apply_flow_on Selection
    default='on_confirm' args: [('on_confirm', 'When move is confirmed')]
  • flow_id Many2one → stock.warehouse.flow
    comodel_name='stock.warehouse.flow' ondelete='set null' string='Routing Flow'
Public methods (0)

No public methods.

New fields (1)
  • default_picking_type_id Many2one → stock.picking.type
    help='Used as a backup to save picking type set by odoo, before a new flow is applied.' args: 'stock.picking.type'
Public methods (0)

No public methods.

New fields (1)
  • flow_ids One2many → stock.warehouse.flow
    comodel_name='stock.warehouse.flow' inverse_name='warehouse_id' string='Flows'
Public methods (1)
  • action_view_all_flows(self)

New fields (26)
  • active Boolean
    default=True
  • carrier_ids Many2many → delivery.carrier
    column1='stock_warehouse_flow_id' column2='delivery_carrier_id' comodel_name='delivery.carrier' copy=False relation='delivery_carrier_stock_warehouse_flow_rel' string='With carriers'
  • company_id Many2one
    related='warehouse_id.company_id'
  • delivery_route_id Many2one → stock.location.route
    comodel_name='stock.location.route' copy=False index=True ondelete='set null' readonly=True string='Delivery Route'
  • delivery_steps Selection
    default='ship_only' help='Outgoing route to follow' required=True selection=[('ship_only', 'Deliver goods directly (1 step)'), ('pick_ship', 'Send goods in output and then deliver (2 steps)'), ('pick_pack_ship', 'Pack goods, send goods in output and then deliver (3 steps)')] string='Outgoing Shipments'
  • from_location_dest_id Many2one → stock.location
    comodel_name='stock.location' compute='_compute_from_location_dest_id'
  • from_location_src_id Many2one → stock.location
    comodel_name='stock.location' compute='_compute_from_location_src_id'
  • from_picking_type_id Many2one → stock.picking.type
    comodel_name='stock.picking.type' domain="[('code', '=', 'outgoing')]" index=True ondelete='restrict' required=True string='From operation type'
  • impacted_route_ids One2many → stock.location.route
    comodel_name='stock.location.route' compute='_compute_impacted_route_ids' string='Impacted Routes'
  • move_domain Char
    copy=False default=[] help='Domain based on Stock Moves, to define if the routing flow is applicable or not.' string='Source Routing Domain'
  • name Char
    required=True
  • out_type_id Many2one
    help="Same than 'To operation type' field, displayed here to get a global overview of the flow configuration." readonly=True related='to_picking_type_id' string='Out Type'
  • output_stock_loc_id Many2one
    help="Same than 'To output location' field, displayed here to get a global overview of the flow configuration." readonly=True related='to_output_stock_loc_id' string='Output Location'
  • pack_stock_loc_id Many2one → stock.location
    check_company=True args: 'stock.location', 'Packing Location'
  • pack_type_id Many2one → stock.picking.type
    check_company=True args: 'stock.picking.type', 'Pack Type'
  • pick_type_id Many2one → stock.picking.type
    check_company=True args: 'stock.picking.type', 'Pick Type'
  • qty Float
    default=0 help="If a qty is set the flow can be applied on moves where the move's qty >= the qty set on the flow\n" args: 'Qty'
  • rule_ids One2many
    related='delivery_route_id.rule_ids' string='Rules'
  • sequence Integer
    default=10
  • sequence_prefix Char
    help="Used to generate the default prefix of new operation types. (e.g. 'DG' => 'WH/OUT/DG/')"
  • split_method Selection
    help='Simple => move will be split by the qty of the flow or a multiple of it' args: [('simple', 'Simple')], 'Split method'
  • to_output_stock_loc_id Many2one → stock.location
    check_company=True comodel_name='stock.location' ondelete='restrict' string='To output location'
  • to_picking_type_id Many2one → stock.picking.type
    check_company=True comodel_name='stock.picking.type' domain="[('default_location_dest_id', '=', from_location_dest_id)]" ondelete='restrict' readonly=True string='To operation type'
  • uom_id Many2one → uom.uom
    default=<expr> args: 'uom.uom', 'Uom'
  • warehouse_id Many2one → stock.warehouse
    comodel_name='stock.warehouse' default=<expr> ondelete='restrict' required=True string='Warehouse'
  • warning Html
    compute='_compute_warning'
Public methods (6)
  • action_generate_route(self)
  • apply_on_move(self, move, assign_picking=True)
  • onchange_name(self)
    @api.onchange('name')
  • onchange_warehouse_id(self)
    @api.onchange('warehouse_id')
  • split_move(self, move)
  • write(self, vals)