Shopfloor

shopfloor
REPOSITORY
REPOSITORYOCA/stock-logistics-shopfloor
GIT
GIThttps://github.com/OCA/stock-logistics-shopfloor.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/stock-logistics-shopfloor/tree/18.0/shopfloor
VERSION
VERSION 0.16.1
CATEGORY
CATEGORYInventory
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONYes
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOdoo Community Association (OCA), Akretion, Camptocamp, BCIM
MAINTAINERS
MAINTAINERSOdoo Community Association (OCA), Akretion, Camptocamp, BCIM
COMMITTERS
COMMITTERSGitHub, Jacques-Etienne Baudoux, Akim Juillerat, Sébastien Alix, Thierry Ducrest, Weblate, OCA-git-bot, Simone Orsi, Michael Tietz, oca-ci, Henry Backman, Mmequignon, Rafael Lima
WEBSITE
WEBSITEhttps://github.com/OCA/stock-logistics-shopfloor
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 19:30:18
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/connector:
    - component
OCA/delivery-carrier:
    - stock_picking_delivery_link
OCA/product-attribute:
    - product_packaging_dimension
    - product_logistics_uom
    - product_manufacturer
    - product_packaging_level
OCA/rest-framework:
    - base_rest
OCA/server-tools:
    - jsonifier
OCA/shopfloor-app:
    - shopfloor_base
OCA/stock-logistics-tracking:
    - stock_quant_package_dimension
    - stock_quant_package_product_packaging
OCA/stock-logistics-warehouse:
    - stock_picking_completion_info
    - stock_move_common_dest
OCA/stock-logistics-workflow:
    - stock_move_line_change_lot
    - stock_picking_progress
    - stock_move_line_qty_picked
OCA/web-api:
    - endpoint_route_handler
odoo/odoo:
    - base
    - web
    - base_sparse_field
    - stock
    - product
    - mail
    - base_setup
    - bus
    - web_tour
    - html_editor
    - uom
    - barcodes_gs1_nomenclature
    - barcodes
    - digest
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - resource
    - stock_picking_batch
    - product_expiry
    - delivery
    - sale
    - sales_team
    - account_payment
    - account
    - onboarding
    - analytic
    - payment
    - utm
    - stock_delivery
    - sale_stock
    - stock_account
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES apispec
cerberus
parse-accept-language
pyquerystring
cachetools
openupgradelib
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION
Shopfloor is a barcode scanner application for internal warehouse
operations.

The application supports scenarios, to relate to Operation Types:

- Cluster Picking
- Zone Picking
- Checkout/Packing
- Delivery
- Location Content Transfer
- Single Pack Transfer

This module provides REST APIs to support the scenarios. It needs a
frontend to consume the backend APIs and provide screens for users on
barcode devices. A default front-end application is provided by
`shopfloor_mobile`.

Note: if you want to enable a new scenario on an existing application,
you must trigger the registry sync on the shopfloor.app in a
post_init_hook or a post-migrate script.  
See an example
[here](https://github.com/OCA/wms/pull/520/commits/bccdfd445a9bc943998c4848f183a076e8459a98).


**WARNING v18**

Scenario will be migrated one by one.

Current availability status:

- [ ] checkout
- [ ] cluster picking
- [ ] zone picking
- [ ] delivery
- [ ] location content transfer
- [ ] single pack transfer (to be discarded in favor of shopfloor_single_product_transfer)
- [ ] zone picking

Code Analysis

Views touched (7)
XML IDNameModelTypeStatus
shopfloor_menu_form_view shopfloor.menu field Inherits shopfloor_base.shopfloor_menu_form_view
shopfloor_menu_search_view shopfloor.menu field Inherits shopfloor_base.shopfloor_menu_search_view
shopfloor_menu_tree_view shopfloor.menu field Inherits shopfloor_base.shopfloor_menu_tree_view
view_location_form Shopfloor stock.location form stock.location xpath Inherits stock.view_location_form
view_picking_type_form Operation Types stock.picking.type xpath Inherits stock.view_picking_type_form
view_stock_move_line_detailed_operation_tree shopfloor stock_move_line_detailed_operation_tree stock.move.line field Inherits stock.view_stock_move_line_detailed_operation_tree
view_stock_move_line_operation_tree shopfloor stock.move.line.operations.tree stock.move.line field Inherits stock.view_stock_move_line_operation_tree
Models touched (12)

New fields (1)
  • category Selection
    selection_add=[('wms', 'WMS')]
Public methods (0)

No public methods.

New fields (45)
  • allow_alternative_destination Boolean
    default=False help='When enabled the user will have the option to scan destination locations other than the expected ones (ask for confirmation).' string='Allow to scan alternative destination locations'
  • allow_alternative_destination_is_possible Boolean
    compute='_compute_allow_alternative_destination_is_possible'
  • allow_alternative_destination_package Boolean
    default=False help=ALLOW_ALTERNATIVE_DESTINATION_PACKAGE_HELP string='Allow to change the destination package'
  • allow_alternative_destination_package_is_possible Boolean
    compute='_compute_allow_alternative_destination_package_is_possible'
  • allow_force_reservation Boolean
    default=False string='Force stock reservation'
  • allow_force_reservation_is_possible Boolean
    compute='_compute_allow_force_reservation_is_possible'
  • allow_get_work Boolean
    default=False help='When enabled the user will have the option to ask for a task to work on.' string='Show Get Work on start'
  • allow_get_work_is_possible Boolean
    compute='_compute_allow_get_work_is_possible'
  • allow_move_create Boolean
    default=False help='Some scenario may create move(s) when a product or package is scanned and no move already exists. Any new move is created in the selected operation type, so it can be active only when one type is selected.' string='Allow Move Creation'
  • allow_prepackaged_product Boolean
    default=False help="When active, what you scan (typically a product packaging EAN) will be ship 'as-is' and the operation will be validated triggering a backorder creation with the remaining lines." string='Process as pre-packaged'
  • allow_return Boolean
    default=False help=RETURN_HELP string='Allow create returns'
  • allow_return_is_possible Boolean
    compute='_compute_allow_return_is_possible'
  • allow_unreserve_other_moves Boolean
    default=False help='If you tick this box, this scenario will allow operator to move goods even if a reservation is made by a different operation type.' string='Allow to process reserved quantities'
  • auto_post_line Boolean
    default=False help=AUTO_POST_LINE_HELP string='Automatically post line'
  • auto_post_line_is_possible Boolean
    compute='_compute_auto_post_line_is_possible'
  • disable_full_bin_action Boolean
    default=False help='When picking, prevent unloading the whole bin when full.' string='Disable full bin action'
  • disable_full_bin_action_is_possible Boolean
    compute='_compute_disable_full_bin_action_is_possible'
  • ignore_no_putaway_available Boolean
    default=False help="If you tick this box, the transfer is reserved only if the put-away can find a sublocation (when putaway destination is different from the operation type's destination)." string='Ignore transfers when no put-away is available'
  • ignore_no_putaway_available_is_possible Boolean
    compute='_compute_ignore_no_putaway_available_is_possible'
  • move_create_is_possible Boolean
    compute='_compute_move_create_is_possible'
  • move_line_processing_sort_order Selection
    default='location' help=MOVE_LINE_PROCESSING_SORT_ORDER_HELP required=True selection=[('location', 'Location'), ('location_grouped_product', 'Location Grouping products'), ('custom_code', 'Custom code')] string='Sort method used when processing move lines'
  • move_line_processing_sort_order_custom_code Text
    default=CUSTOM_CODE_DEFAULT help='Python code to sort processing move lines.'
  • move_line_processing_sort_order_is_possible Boolean
    compute='_compute_move_line_processing_sort_order_is_possible'
  • move_line_search_additional_domain Char
    string='Additional domain used when searching move lines'
  • move_line_search_additional_domain_is_possible Boolean
    compute='_compute_move_line_search_additional_domain_is_possible'
  • move_line_search_sort_order Selection
    default='priority' selection=[('priority', 'Priority'), ('location', 'Location'), ('custom_code', 'Custom code')] string='Sort method used when searching move lines'
  • move_line_search_sort_order_custom_code Text
    help='Python code to sort move lines on search. '
  • move_line_search_sort_order_is_possible Boolean
    compute='_compute_move_line_search_sort_order_is_possible'
  • multiple_move_single_pack Boolean
    default=False help=MULTIPLE_MOVE_SINGLE_PACK_HELP string='Collect multiple moves on a same destination package'
  • multiple_move_single_pack_is_possible Boolean
    compute='_compute_multiple_move_single_pack_is_possible'
  • no_prefill_qty Boolean
    default=False help=NO_PREFILL_QTY_HELP string='Do not pre-fill quantity to pick'
  • no_prefill_qty_is_possible Boolean
    compute='_compute_no_prefill_qty_is_possible'
  • pick_pack_same_time Boolean
    default=False help=PICK_PACK_SAME_TIME_HELP string='Pick and pack at the same time'
  • pick_pack_same_time_is_possible Boolean
    compute='_compute_pick_pack_same_time_is_possible'
  • picking_type_ids Many2many → stock.picking.type
    comodel_name='stock.picking.type' required=True string='Operation Types'
  • prepackaged_product_is_possible Boolean
    compute='_compute_prepackaged_product_is_possible'
  • require_destination_package Boolean
    default=True help='If set, the user will have to scan only the source location and the destination location to process a line. The unload step will be skipped.' string='Destination package required'
  • require_destination_package_is_possible Boolean
    compute='_compute_require_destination_package_is_possible'
  • scan_location_or_pack_first Boolean
    help='When checked, the user will be restricted by the type of object barcode that he can scan to select the document/transfer/move line to work on.' string='Restrict scannable barcode at work selection'
  • scan_location_or_pack_first_is_possible Boolean
    compute='_compute_scan_location_or_pack_first_is_possible'
  • show_oneline_package_content Boolean
    default=False help='Display the content of package if it contains 1 line only' string='Show one-line package content'
  • show_oneline_package_content_is_possible Boolean
    compute='_compute_show_oneline_package_content_is_possible'
  • unload_package_at_destination Boolean
    default=False help=UNLOAD_PACK_AT_DEST_HELP string='Unload package at destination'
  • unload_package_at_destination_is_possible Boolean
    compute='_compute_unload_package_at_dest_is_possible'
  • unreserve_other_moves_is_possible Boolean
    compute='_compute_unreserve_other_moves_is_possible'
Public methods (5)
  • create(self, vals_list)
    @api.model_create_multi
  • onchange_ignore_no_putaway_available_is_possible(self)
    @api.onchange('ignore_no_putaway_available_is_possible')
  • onchange_move_create_is_possible(self)
    @api.onchange('move_create_is_possible')
  • onchange_unreserve_other_moves_is_possible(self)
    @api.onchange('unreserve_other_moves_is_possible')
  • write(self, vals)

New fields (2)
  • shopfloor_postponed Boolean
    copy=False help='Technical field. Indicates if the operation has been postponed in a barcode scenario.'
  • shopfloor_priority Integer
    copy=False default=<expr> help='Technical field. Overrides operation priority in barcode scenario.'
Public methods (1)
  • shopfloor_postpone(self, *recordsets)
    Postpone the record and update its priority based on other records. The method accepts several recordsets as parameter (to be able to get the current max priority from different types of records).

New fields (3)
  • reserved_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' compute='_compute_reserved_move_lines'
  • shopfloor_picking_sequence Char
    help="The picking done in Shopfloor scenarios will respect this order. The sequence is a char so it can be composed of fields such as 'corridor-rack-side-level'. Pay attention to the padding ('09' is before '19', '9' is not). It is recommended to use an Export then an Import to populate this field using a spreadsheet."
  • source_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' inverse_name='location_id' readonly=True
Public methods (2)
  • planned_qty_in_location_is_empty(self, move_lines=None)
    Return if a location will be empty when move lines will be confirmed Used for the "zero check". We need to know if a location is empty, but since we set the move lines to "done" only at the end of the unload workflow, we have to look at the picked quantity of the move lines from this location. With `move_lines` we can force the use of the given move lines for the check. This allows to know that the location will be empty if we process only these move lines.
  • should_bypass_reservation(self)

New fields (1)
  • quantity_picked Float
    compute='_compute_quantity_picked'
Public methods (3)
  • extract_and_action_done(self)
    Extract the moves in a separate transfer and validate them. You can combine this method with `split_other_move_lines` method to first extract some move lines in a separate move, then validate it with this method.
  • split_other_move_lines(self, move_lines, intersection=False)
    Substract `move_lines` from `move.move_line_ids`, put the result in a new move and returns it. If `intersection` is set to `True`, this is the common lines between `move_lines` and `move.move_line_ids` which will be put in a new move.
  • split_unavailable_qty(self)
    Put unavailable qty of a partially available move in their own move (which will be 'confirmed').

New fields (9)
  • date_planned Datetime
    index=True related='move_id.date' store=True
  • is_shopfloor_created Boolean
  • location_id Many2one
    index=True
  • package_id Many2one
    index=True
  • picking_id Many2one
    auto_join=True
  • result_package_id Many2one
    index=True
  • shopfloor_checkout_done Boolean
    default=False
  • shopfloor_unloaded Boolean
    default=False
  • shopfloor_user_id Many2one → res.users
    comodel_name='res.users' index=True
Public methods (2)
  • replace_package(self, new_package)
    Replace a package on an assigned move line
  • shopfloor_postpone(self, *recordsets)
    Specific behavior for move lines. As we need to reset the quantity picked.

New fields (2)
  • package_id Many2one
    index=True
  • picking_id Many2one
    auto_join=True
Public methods (1)
  • explode_package(self)
    Unlink but keep the moves. Original motivation: A package level has a relation to "move_lines" only when the package level was created first from the UI and it created its move. When we unlink a package level, it deletes the move it created. But in some cases, we want to keep the move, e.g.: * create a package level from the UI to move a package * it generates a move for the matching product quantity * we use a barcode scenario such as cluster or zone picking * we use the "replace package" button * when replacing the package, we have to delete the package level, but we still have the same need in term of "I want X products", so we have to keep the move * another case is when we "dismiss" the package level in the location content transfer scenario, we want to keep the "need" in moves, but we are no longer moving the entire package level Commit https://github.com/odoo/odoo/commit/b33e72d0bf027fb2c789b1b9476f7edf1a40b0a6 introduced the handling of pkg level deletion which is doing what was done by this method. Moreover it has been fixed here https://github.com/odoo/odoo/pull/66517. Hence, we keep this method to unify the action of "exploding a package" especially to avoid to refactor many places every time the core changes.

New fields (5)
  • bulk_line_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of move lines without package included.'
  • is_shopfloor_created Boolean
  • move_line_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of move lines included.'
  • package_level_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of package_level included.'
  • total_weight Float
    compute='_compute_picking_info' help='Technical field. Indicates total weight of transfers included.'
Public methods (1)
  • split_assigned_move_lines(self, move_lines=None)
    Put all reserved quantities (move lines) in their own moves and transfer. As a result, the current transfer will contain only confirmed moves.

New fields (3)
  • move_line_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of move lines included.'
  • picking_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of transfers included.'
  • total_weight Float
    compute='_compute_picking_info' help='Technical field. Indicates total weight of transfers included.'
Public methods (0)

No public methods.

New fields (2)
  • shopfloor_menu_ids Many2many → shopfloor.menu
    comodel_name='shopfloor.menu' readonly=True string='Shopfloor Menus'
  • shopfloor_zero_check Boolean
    help='For Shopfloor scenarios using it (Cluster Picking, Zone Picking, Discrete order Picking), the zero check step will be activated when a location becomes empty after a move.' string='Activate Zero Check'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (1)
  • user_has_groups(self, groups)

New fields (4)
  • move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' help='Technical field. Move lines moving this package.' inverse_name='package_id' readonly=True
  • planned_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' domain=[('state', 'not in', ('done', 'cancel'))] help='Technical field. Move lines for which destination is this package.' inverse_name='result_package_id' readonly=True
  • reserved_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' compute='_compute_reserved_move_lines'
  • shopfloor_weight Float
    compute='_compute_shopfloor_weight' digits='Product Unit of Measure' help='Real pack weight or the estimated one.' args: 'Shopfloor weight (kg)'
Public methods (1)
  • move_package_to_location(self, dest_location)
    Create inventories to move a package to a different location It should be called when the package is - in real life - already in the destination. It creates an inventory to remove the package from the source location and a second inventory to place the package in the destination (to reflect the reality). The source location is the current location of the package.
REPOSITORY
REPOSITORYOCA/wms
GIT
GIThttps://github.com/OCA/wms.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/wms/tree/16.0/shopfloor
VERSION
VERSION 2.20.1
CATEGORY
CATEGORYInventory
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONYes
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOdoo Community Association (OCA), Akretion, Camptocamp, BCIM
MAINTAINERS
MAINTAINERSOdoo Community Association (OCA), Akretion, Camptocamp, BCIM
COMMITTERS
COMMITTERSJacques-Etienne Baudoux, Laurent Mignon (ACSONE), Denis Roussel, sbejaoui, Sébastien Alix, Weblate, OCA-git-bot, Simone Orsi, Michael Tietz, oca-ci, Mmequignon, Nicolas Delbovier, Laurent Mignonn (ACSONE)
WEBSITE
WEBSITEhttps://github.com/OCA/wms
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:53:59
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/connector:
    - component
OCA/delivery-carrier:
    - stock_picking_delivery_link
OCA/product-attribute:
    - product_packaging_dimension
    - product_logistics_uom
    - product_manufacturer
    - product_packaging_level
OCA/rest-framework:
    - base_rest
OCA/server-tools:
    - jsonifier
    - base_partition
OCA/stock-logistics-warehouse:
    - stock_helper
    - stock_move_common_dest
    - stock_location_fill_state
    - stock_location_pending_move
    - stock_storage_category_capacity_name
OCA/stock-logistics-workflow:
    - stock_move_line_change_lot
    - stock_quant_package_dimension
    - stock_quant_package_product_packaging
    - stock_picking_progress
    - stock_move_line_reserved_quant
    - stock_putaway_hook
OCA/web-api:
    - endpoint_route_handler
OCA/wms:
    - shopfloor_base
    - stock_picking_completion_info
    - stock_storage_type
odoo/odoo:
    - base
    - web
    - base_sparse_field
    - stock
    - product
    - mail
    - base_setup
    - bus
    - web_tour
    - uom
    - barcodes_gs1_nomenclature
    - barcodes
    - digest
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - resource
    - stock_picking_batch
    - product_expiry
    - delivery
    - sale_stock
    - sale
    - sales_team
    - account_payment
    - account
    - analytic
    - payment
    - utm
    - stock_account
    - sale_management
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES apispec
cerberus
parse-accept-language
pyquerystring
cachetools
openupgradelib
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (7)
XML IDNameModelTypeStatus
shopfloor_menu_form_view shopfloor.menu field Inherits shopfloor_base.shopfloor_menu_form_view
shopfloor_menu_search_view shopfloor.menu field Inherits shopfloor_base.shopfloor_menu_search_view
shopfloor_menu_tree_view shopfloor.menu field Inherits shopfloor_base.shopfloor_menu_tree_view
view_location_form Shopfloor stock.location form stock.location xpath Inherits stock.view_location_form
view_picking_type_form Operation Types stock.picking.type xpath Inherits stock.view_picking_type_form
view_stock_move_line_detailed_operation_tree shopfloor stock_move_line_detailed_operation_tree stock.move.line field Inherits stock.view_stock_move_line_detailed_operation_tree
view_stock_move_line_operation_tree shopfloor stock.move.line.operations.tree stock.move.line field Inherits stock.view_stock_move_line_operation_tree
Models touched (12)

New fields (1)
  • category Selection
    selection_add=[('wms', 'WMS')]
Public methods (0)

No public methods.

New fields (44)
  • allow_alternative_destination Boolean
    default=False help='When enabled the user will have the option to scan destination locations other than the expected ones (ask for confirmation).' string='Allow to scan alternative destination locations'
  • allow_alternative_destination_is_possible Boolean
    compute='_compute_allow_alternative_destination_is_possible'
  • allow_alternative_destination_package Boolean
    default=False help=ALLOW_ALTERNATIVE_DESTINATION_PACKAGE_HELP string='Allow to change the destination package'
  • allow_alternative_destination_package_is_possible Boolean
    compute='_compute_allow_alternative_destination_package_is_possible'
  • allow_force_reservation Boolean
    default=False string='Force stock reservation'
  • allow_force_reservation_is_possible Boolean
    compute='_compute_allow_force_reservation_is_possible'
  • allow_get_work Boolean
    default=False help='When enabled the user will have the option to ask for a task to work on.' string='Show Get Work on start'
  • allow_get_work_is_possible Boolean
    compute='_compute_allow_get_work_is_possible'
  • allow_move_create Boolean
    default=False help='Some scenario may create move(s) when a product or package is scanned and no move already exists. Any new move is created in the selected operation type, so it can be active only when one type is selected.' string='Allow Move Creation'
  • allow_prepackaged_product Boolean
    default=False help="When active, what you scan (typically a product packaging EAN) will be ship 'as-is' and the operation will be validated triggering a backorder creation with the remaining lines." string='Process as pre-packaged'
  • allow_quantity_exceeding_demand Boolean
    help='If True, prevents shopfloor error in case you process more qty than planned.'
  • allow_quantity_exceeding_demand_is_possible Boolean
    compute='_compute_allow_quantity_exceeding_demand_is_possible'
  • allow_return Boolean
    default=False help=RETURN_HELP string='Allow create returns'
  • allow_return_is_possible Boolean
    compute='_compute_allow_return_is_possible'
  • allow_unreserve_other_moves Boolean
    default=False help='If you tick this box, this scenario will allow operator to move goods even if a reservation is made by a different operation type.' string='Allow to process reserved quantities'
  • auto_post_line Boolean
    default=False help=AUTO_POST_LINE_HELP string='Automatically post line'
  • auto_post_line_is_possible Boolean
    compute='_compute_auto_post_line_is_possible'
  • disable_full_bin_action Boolean
    default=False help='When picking, prevent unloading the whole bin when full.' string='Disable full bin action'
  • disable_full_bin_action_is_possible Boolean
    compute='_compute_disable_full_bin_action_is_possible'
  • ignore_no_putaway_available Boolean
    default=False help="If you tick this box, the transfer is reserved only if the put-away can find a sublocation (when putaway destination is different from the operation type's destination)." string='Ignore transfers when no put-away is available'
  • ignore_no_putaway_available_is_possible Boolean
    compute='_compute_ignore_no_putaway_available_is_possible'
  • move_create_is_possible Boolean
    compute='_compute_move_create_is_possible'
  • move_line_search_additional_domain Char
    string='Additional domain used when searching move lines'
  • move_line_search_additional_domain_is_possible Boolean
    compute='_compute_move_line_search_additional_domain_is_possible'
  • move_line_search_sort_order Selection
    default='priority' selection=[('priority', 'Priority'), ('location', 'Location'), ('custom_code', 'Custom code')] string='Sort method used when searching move lines'
  • move_line_search_sort_order_custom_code Text
    help='Python code to sort move lines. ' string='Custom sort key code'
  • move_line_search_sort_order_is_possible Boolean
    compute='_compute_move_line_search_sort_order_is_possible'
  • multiple_move_single_pack Boolean
    default=False help=MULTIPLE_MOVE_SINGLE_PACK_HELP string='Collect multiple moves on a same destination package'
  • multiple_move_single_pack_is_possible Boolean
    compute='_compute_multiple_move_single_pack_is_possible'
  • no_prefill_qty Boolean
    default=False help=NO_PREFILL_QTY_HELP string='Do not pre-fill quantity to pick'
  • no_prefill_qty_is_possible Boolean
    compute='_compute_no_prefill_qty_is_possible'
  • pick_pack_same_time Boolean
    default=False help=PICK_PACK_SAME_TIME_HELP string='Pick and pack at the same time'
  • pick_pack_same_time_is_possible Boolean
    compute='_compute_pick_pack_same_time_is_possible'
  • picking_type_ids Many2many → stock.picking.type
    comodel_name='stock.picking.type' required=True string='Operation Types'
  • prepackaged_product_is_possible Boolean
    compute='_compute_prepackaged_product_is_possible'
  • require_destination_package Boolean
    default=True help='If set, the user will have to scan only the source location and the destination location to process a line. The unload step will be skipped.' string='Destination package required'
  • require_destination_package_is_possible Boolean
    compute='_compute_require_destination_package_is_possible'
  • scan_location_or_pack_first Boolean
    help='When checked, the user will be restricted by the type of object barcode that he can scan to select the document/transfer/move line to work on.' string='Restrict scannable barcode at work selection'
  • scan_location_or_pack_first_is_possible Boolean
    compute='_compute_scan_location_or_pack_first_is_possible'
  • show_oneline_package_content Boolean
    default=False help='Display the content of package if it contains 1 line only' string='Show one-line package content'
  • show_oneline_package_content_is_possible Boolean
    compute='_compute_show_oneline_package_content_is_possible'
  • unload_package_at_destination Boolean
    default=False help=UNLOAD_PACK_AT_DEST_HELP string='Unload package at destination'
  • unload_package_at_destination_is_possible Boolean
    compute='_compute_unload_package_at_dest_is_possible'
  • unreserve_other_moves_is_possible Boolean
    compute='_compute_unreserve_other_moves_is_possible'
Public methods (5)
  • create(self, vals_list)
    @api.model_create_multi
  • onchange_ignore_no_putaway_available_is_possible(self)
    @api.onchange('ignore_no_putaway_available_is_possible')
  • onchange_move_create_is_possible(self)
    @api.onchange('move_create_is_possible')
  • onchange_unreserve_other_moves_is_possible(self)
    @api.onchange('unreserve_other_moves_is_possible')
  • write(self, vals)

New fields (2)
  • shopfloor_postponed Boolean
    copy=False help='Technical field. Indicates if the operation has been postponed in a barcode scenario.'
  • shopfloor_priority Integer
    copy=False default=<expr> help='Technical field. Overrides operation priority in barcode scenario.'
Public methods (1)
  • shopfloor_postpone(self, *recordsets)
    Postpone the record and update its priority based on other records. The method accepts several recordsets as parameter (to be able to get the current max priority from different types of records).

New fields (3)
  • reserved_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' compute='_compute_reserved_move_lines'
  • shopfloor_picking_sequence Char
    help="The picking done in Shopfloor scenarios will respect this order. The sequence is a char so it can be composed of fields such as 'corridor-rack-side-level'. Pay attention to the padding ('09' is before '19', '9' is not). It is recommended to use an Export then an Import to populate this field using a spreadsheet."
  • source_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' inverse_name='location_id' readonly=True
Public methods (2)
  • planned_qty_in_location_is_empty(self, move_lines=None)
    Return if a location will be empty when move lines will be confirmed Used for the "zero check". We need to know if a location is empty, but since we set the move lines to "done" only at the end of the unload workflow, we have to look at the qty_done of the move lines from this location. With `move_lines` we can force the use of the given move lines for the check. This allows to know that the location will be empty if we process only these move lines.
  • should_bypass_reservation(self)

New fields (0)

No new fields.

Public methods (3)
  • extract_and_action_done(self)
    Extract the moves in a separate transfer and validate them. You can combine this method with `split_other_move_lines` method to first extract some move lines in a separate move, then validate it with this method.
  • split_other_move_lines(self, move_lines, intersection=False)
    Substract `move_lines` from `move.move_line_ids`, put the result in a new move and returns it. If `intersection` is set to `True`, this is the common lines between `move_lines` and `move.move_line_ids` which will be put in a new move.
  • split_unavailable_qty(self)
    Put unavailable qty of a partially available move in their own move (which will be 'confirmed').

New fields (8)
  • date_planned Datetime
    index=True related='move_id.date' store=True
  • location_id Many2one
    index=True
  • package_id Many2one
    index=True
  • picking_id Many2one
    auto_join=True
  • result_package_id Many2one
    index=True
  • shopfloor_checkout_done Boolean
    default=False
  • shopfloor_unloaded Boolean
    default=False
  • shopfloor_user_id Many2one → res.users
    comodel_name='res.users' index=True
Public methods (2)
  • replace_package(self, new_package)
    Replace a package on an assigned move line
  • shopfloor_postpone(self, *recordsets)
    Specific behavior for move lines. As we need to reset qty_done.

New fields (2)
  • package_id Many2one
    index=True
  • picking_id Many2one
    auto_join=True
Public methods (1)
  • explode_package(self)
    Unlink but keep the moves. Original motivation: A package level has a relation to "move_lines" only when the package level was created first from the UI and it created its move. When we unlink a package level, it deletes the move it created. But in some cases, we want to keep the move, e.g.: * create a package level from the UI to move a package * it generates a move for the matching product quantity * we use a barcode scenario such as cluster or zone picking * we use the "replace package" button * when replacing the package, we have to delete the package level, but we still have the same need in term of "I want X products", so we have to keep the move * another case is when we "dismiss" the package level in the location content transfer scenario, we want to keep the "need" in moves, but we are no longer moving the entire package level Commit https://github.com/odoo/odoo/commit/b33e72d0bf027fb2c789b1b9476f7edf1a40b0a6 introduced the handling of pkg level deletion which is doing what was done by this method. Moreover it has been fixed here https://github.com/odoo/odoo/pull/66517. Hence, we keep this method to unify the action of "exploding a package" especially to avoid to refactor many places every time the core changes.

New fields (5)
  • bulk_line_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of move lines without package included.'
  • is_shopfloor_created Boolean
  • move_line_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of move lines included.'
  • package_level_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of package_level included.'
  • total_weight Float
    compute='_compute_picking_info' help='Technical field. Indicates total weight of transfers included.'
Public methods (1)
  • split_assigned_move_lines(self, move_lines=None)
    Put all reserved quantities (move lines) in their own moves and transfer. As a result, the current transfer will contain only confirmed moves.

New fields (3)
  • move_line_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of move lines included.'
  • picking_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of transfers included.'
  • total_weight Float
    compute='_compute_picking_info' help='Technical field. Indicates total weight of transfers included.'
Public methods (0)

No public methods.

New fields (2)
  • shopfloor_menu_ids Many2many → shopfloor.menu
    comodel_name='shopfloor.menu' readonly=True string='Shopfloor Menus'
  • shopfloor_zero_check Boolean
    help='For Shopfloor scenarios using it (Cluster Picking, Zone Picking, Discrete order Picking), the zero check step will be activated when a location becomes empty after a move.' string='Activate Zero Check'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (1)
  • user_has_groups(self, groups)

New fields (4)
  • move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' help='Technical field. Move lines moving this package.' inverse_name='package_id' readonly=True
  • planned_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' domain=[('state', 'not in', ('done', 'cancel'))] help='Technical field. Move lines for which destination is this package.' inverse_name='result_package_id' readonly=True
  • reserved_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' compute='_compute_reserved_move_lines'
  • shopfloor_weight Float
    compute='_compute_shopfloor_weight' digits='Product Unit of Measure' help='Real pack weight or the estimated one.' args: 'Shopfloor weight (kg)'
Public methods (1)
  • move_package_to_location(self, dest_location)
    Create inventories to move a package to a different location It should be called when the package is - in real life - already in the destination. It creates an inventory to remove the package from the source location and a second inventory to place the package in the destination (to reflect the reality). The source location is the current location of the package.
REPOSITORY
REPOSITORYOCA/wms
GIT
GIThttps://github.com/OCA/wms.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/wms/tree/14.0/shopfloor
VERSION
VERSION 4.19.0
CATEGORY
CATEGORYInventory
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONYes
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOdoo Community Association (OCA), Akretion, Camptocamp, BCIM
MAINTAINERS
MAINTAINERSOdoo Community Association (OCA), Akretion, Camptocamp, BCIM
COMMITTERS
COMMITTERSGitHub, Jacques-Etienne Baudoux, OCA Transbot, Sébastien Alix, Thierry Ducrest, Sébastien BEAU, oca-travis, Weblate, OCA-git-bot, Simone Orsi, hparfr, Michael Tietz, oca-ci, Matthieu Méquignon, JuMiSanAr, Mmequignon
WEBSITE
WEBSITEhttps://github.com/OCA/wms
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:41:12
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/connector:
    - component
OCA/delivery-carrier:
    - stock_picking_delivery_link
OCA/product-attribute:
    - product_packaging_dimension
    - product_logistics_uom
    - product_manufacturer
    - product_packaging_type
OCA/rest-framework:
    - base_rest
OCA/server-tools:
    - jsonifier
    - base_m2m_custom_field
OCA/stock-logistics-warehouse:
    - stock_helper
    - stock_move_common_dest
OCA/stock-logistics-workflow:
    - stock_quant_package_dimension
    - stock_quant_package_product_packaging
    - stock_picking_progress
    - stock_putaway_hook
OCA/web:
    - web_domain_field
OCA/web-api:
    - endpoint_route_handler
OCA/wms:
    - shopfloor_base
    - stock_picking_completion_info
    - stock_storage_type
odoo/odoo:
    - base
    - base_sparse_field
    - stock
    - product
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - uom
    - barcodes
    - digest
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - resource
    - stock_picking_batch
    - product_expiry
    - delivery
    - sale_stock
    - sale
    - sales_team
    - payment
    - account
    - analytic
    - utm
    - stock_account
    - sale_management
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES apispec
cerberus
parse-accept-language
pyquerystring
cachetools
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (7)
XML IDNameModelTypeStatus
shopfloor_menu_form_view shopfloor.menu field Inherits shopfloor_base.shopfloor_menu_form_view
shopfloor_menu_search_view shopfloor.menu field Inherits shopfloor_base.shopfloor_menu_search_view
shopfloor_menu_tree_view shopfloor.menu field Inherits shopfloor_base.shopfloor_menu_tree_view
view_location_form Shopfloor stock.location form stock.location xpath Inherits stock.view_location_form
view_picking_type_form Operation Types stock.picking.type xpath Inherits stock.view_picking_type_form
view_stock_move_line_detailed_operation_tree shopfloor stock_move_line_detailed_operation_tree stock.move.line field Inherits stock.view_stock_move_line_detailed_operation_tree
view_stock_move_line_operation_tree shopfloor stock.move.line.operations.tree stock.move.line field Inherits stock.view_stock_move_line_operation_tree
Models touched (13)

New fields (1)
  • category Selection
    selection_add=[('wms', 'WMS')]
Public methods (0)

No public methods.

New fields (35)
  • allow_alternative_destination Boolean
    default=False help='When enabled the user will have the option to scan destination locations other than the expected ones (ask for confirmation).' string='Allow to scan alternative destination locations'
  • allow_alternative_destination_is_possible Boolean
    compute='_compute_allow_alternative_destination_is_possible'
  • allow_alternative_destination_package Boolean
    default=False help=ALLOW_ALTERNATIVE_DESTINATION_PACKAGE_HELP string='Allow to change the destination package'
  • allow_alternative_destination_package_is_possible Boolean
    compute='_compute_allow_alternative_destination_package_is_possible'
  • allow_force_reservation Boolean
    default=False string='Force stock reservation'
  • allow_force_reservation_is_possible Boolean
    compute='_compute_allow_force_reservation_is_possible'
  • allow_get_work Boolean
    default=False help='When enabled the user will have the option to ask for a task to work on.' string='Show Get Work on start'
  • allow_get_work_is_possible Boolean
    compute='_compute_allow_get_work_is_possible'
  • allow_move_create Boolean
    default=False help='Some scenario may create move(s) when a product or package is scanned and no move already exists. Any new move is created in the selected operation type, so it can be active only when one type is selected.' string='Allow Move Creation'
  • allow_prepackaged_product Boolean
    default=False help="When active, what you scan (typically a product packaging EAN) will be ship 'as-is' and the operation will be validated triggering a backorder creation with the remaining lines." string='Process as pre-packaged'
  • allow_return Boolean
    default=False help=RETURN_HELP string='Allow create returns'
  • allow_return_is_possible Boolean
    compute='_compute_allow_return_is_possible'
  • allow_unreserve_other_moves Boolean
    default=False help='If you tick this box, this scenario will allow operator to move goods even if a reservation is made by a different operation type.' string='Allow to process reserved quantities'
  • auto_post_line Boolean
    default=False help=AUTO_POST_LINE_HELP string='Automatically post line'
  • auto_post_line_is_possible Boolean
    compute='_compute_auto_post_line_is_possible'
  • disable_full_bin_action Boolean
    default=False help='When picking, prevent unloading the whole bin when full.' string='Disable full bin action'
  • disable_full_bin_action_is_possible Boolean
    compute='_compute_disable_full_bin_action_is_possible'
  • ignore_no_putaway_available Boolean
    default=False help="If you tick this box, the transfer is reserved only if the put-away can find a sublocation (when putaway destination is different from the operation type's destination)." string='Ignore transfers when no put-away is available'
  • ignore_no_putaway_available_is_possible Boolean
    compute='_compute_ignore_no_putaway_available_is_possible'
  • move_create_is_possible Boolean
    compute='_compute_move_create_is_possible'
  • multiple_move_single_pack Boolean
    default=False help=MULTIPLE_MOVE_SINGLE_PACK_HELP string='Collect multiple moves on a same destination package'
  • multiple_move_single_pack_is_possible Boolean
    compute='_compute_multiple_move_single_pack_is_possible'
  • no_prefill_qty Boolean
    default=False help=NO_PREFILL_QTY_HELP string='Do not pre-fill quantity to pick'
  • no_prefill_qty_is_possible Boolean
    compute='_compute_no_prefill_qty_is_possible'
  • pick_pack_same_time Boolean
    default=False help=PICK_PACK_SAME_TIME_HELP string='Pick and pack at the same time'
  • pick_pack_same_time_is_possible Boolean
    compute='_compute_pick_pack_same_time_is_possible'
  • picking_type_ids Many2many → stock.picking.type
    comodel_name='stock.picking.type' required=True string='Operation Types'
  • prepackaged_product_is_possible Boolean
    compute='_compute_prepackaged_product_is_possible'
  • scan_location_or_pack_first Boolean
    help='When checked, the user will be restricted by the type of object barcode that he can scan to select the document/transfer/move line to work on.' string='Restrict scannable barcode at work selection'
  • scan_location_or_pack_first_is_possible Boolean
    compute='_compute_scan_location_or_pack_first_is_possible'
  • show_oneline_package_content Boolean
    default=False help='Display the content of package if it contains 1 line only' string='Show one-line package content'
  • show_oneline_package_content_is_possible Boolean
    compute='_compute_show_oneline_package_content_is_possible'
  • unload_package_at_destination Boolean
    default=False help=UNLOAD_PACK_AT_DEST_HELP string='Unload package at destination'
  • unload_package_at_destination_is_possible Boolean
    compute='_compute_unload_package_at_dest_is_possible'
  • unreserve_other_moves_is_possible Boolean
    compute='_compute_unreserve_other_moves_is_possible'
Public methods (3)
  • onchange_ignore_no_putaway_available_is_possible(self)
    @api.onchange('ignore_no_putaway_available_is_possible')
  • onchange_move_create_is_possible(self)
    @api.onchange('move_create_is_possible')
  • onchange_unreserve_other_moves_is_possible(self)
    @api.onchange('unreserve_other_moves_is_possible')

New fields (2)
  • shopfloor_postponed Boolean
    copy=False help='Technical field. Indicates if the operation has been postponed in a barcode scenario.'
  • shopfloor_priority Integer
    copy=False default=<expr> help='Technical field. Overrides operation priority in barcode scenario.'
Public methods (1)
  • shopfloor_postpone(self, *recordsets)
    Postpone the record and update its priority based on other records. The method accepts several recordsets as parameter (to be able to get the current max priority from different types of records).

New fields (0)

No new fields.

Public methods (1)
  • user_has_groups(self, groups)

New fields (3)
  • reserved_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' compute='_compute_reserved_move_lines'
  • shopfloor_picking_sequence Char
    help="The picking done in Shopfloor scenarios will respect this order. The sequence is a char so it can be composed of fields such as 'corridor-rack-side-level'. Pay attention to the padding ('09' is before '19', '9' is not). It is recommended to use an Export then an Import to populate this field using a spreadsheet." string='Shopfloor Picking Sequence'
  • source_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' inverse_name='location_id' readonly=True
Public methods (2)
  • planned_qty_in_location_is_empty(self, move_lines=None)
    Return if a location will be empty when move lines will be confirmed Used for the "zero check". We need to know if a location is empty, but since we set the move lines to "done" only at the end of the unload workflow, we have to look at the qty_done of the move lines from this location. With `move_lines` we can force the use of the given move lines for the check. This allows to know that the location will be empty if we process only these move lines.
  • should_bypass_reservation(self)

New fields (0)

No new fields.

Public methods (3)
  • extract_and_action_done(self)
    Extract the moves in a separate transfer and validate them. You can combine this method with `split_other_move_lines` method to first extract some move lines in a separate move, then validate it with this method.
  • split_other_move_lines(self, move_lines, intersection=False)
    Substract `move_lines` from `move.move_line_ids`, put the result in a new move and returns it. If `intersection` is set to `True`, this is the common lines between `move_lines` and `move.move_line_ids` which will be put in a new move.
  • split_unavailable_qty(self)
    Put unavailable qty of a partially available move in their own move (which will be 'confirmed').

New fields (8)
  • date_planned Datetime
    index=True related='move_id.date' store=True
  • location_id Many2one
    index=True
  • package_id Many2one
    index=True
  • picking_id Many2one
    auto_join=True
  • result_package_id Many2one
    index=True
  • shopfloor_checkout_done Boolean
    default=False
  • shopfloor_unloaded Boolean
    default=False
  • shopfloor_user_id Many2one → res.users
    comodel_name='res.users' index=True
Public methods (1)
  • replace_package(self, new_package)
    Replace a package on an assigned move line

New fields (2)
  • package_id Many2one
    index=True
  • picking_id Many2one
    auto_join=True
Public methods (1)
  • explode_package(self)
    Unlink but keep the moves. Original motivation: A package level has a relation to "move_ids" only when the package level was created first from the UI and it created its move. When we unlink a package level, it deletes the move it created. But in some cases, we want to keep the move, e.g.: * create a package level from the UI to move a package * it generates a move for the matching product quantity * we use a barcode scenario such as cluster or zone picking * we use the "replace package" button * when replacing the package, we have to delete the package level, but we still have the same need in term of "I want X products", so we have to keep the move * another case is when we "dismiss" the package level in the location content transfer scenario, we want to keep the "need" in moves, but we are no longer moving the entire package level Commit https://github.com/odoo/odoo/commit/b33e72d0bf027fb2c789b1b9476f7edf1a40b0a6 introduced the handling of pkg level deletion which is doing what was done by this method. Moreover it has been fixed here https://github.com/odoo/odoo/pull/66517. Hence, we keep this method to unify the action of "exploding a package" especially to avoid to refactor many places every time the core changes.

New fields (5)
  • bulk_line_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of move lines without package included.'
  • is_shopfloor_created Boolean
  • move_line_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of move lines included.'
  • package_level_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of package_level included.'
  • total_weight Float
    compute='_compute_picking_info' help='Technical field. Indicates total weight of transfers included.'
Public methods (1)
  • split_assigned_move_lines(self, move_lines=None)
    Put all reserved quantities (move lines) in their own moves and transfer. As a result, the current transfer will contain only confirmed moves.

New fields (3)
  • move_line_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of move lines included.'
  • picking_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of transfers included.'
  • total_weight Float
    compute='_compute_picking_info' help='Technical field. Indicates total weight of transfers included.'
Public methods (0)

No public methods.

New fields (2)
  • shopfloor_menu_ids Many2many → shopfloor.menu
    comodel_name='shopfloor.menu' readonly=True string='Shopfloor Menus'
  • shopfloor_zero_check Boolean
    help='For Shopfloor scenarios using it (Cluster Picking, Zone Picking, Discrete order Picking), the zero check step will be activated when a location becomes empty after a move.' string='Activate Zero Check'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (4)
  • move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' help='Technical field. Move lines moving this package.' inverse_name='package_id' readonly=True
  • planned_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' domain=[('state', 'not in', ('done', 'cancel'))] help='Technical field. Move lines for which destination is this package.' inverse_name='result_package_id' readonly=True
  • reserved_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' compute='_compute_reserved_move_lines'
  • shopfloor_weight Float
    compute='_compute_shopfloor_weight' digits='Product Unit of Measure' help='Real pack weight or the estimated one.' args: 'Shopfloor weight (kg)'
Public methods (1)
  • move_package_to_location(self, dest_location)
    Create inventories to move a package to a different location It should be called when the package is - in real life - already in the destination. It creates an inventory to remove the package from the source location and a second inventory to place the package in the destination (to reflect the reality). The source location is the current location of the package.
REPOSITORY
REPOSITORYOCA/wms
GIT
GIThttps://github.com/OCA/wms.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/wms/tree/13.0/shopfloor
VERSION
VERSION 4.13.1
CATEGORY
CATEGORYInventory
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONYes
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOdoo Community Association (OCA), Akretion, Camptocamp, BCIM
MAINTAINERS
MAINTAINERSOdoo Community Association (OCA), Akretion, Camptocamp, BCIM
COMMITTERS
COMMITTERSGuewen Baconnier, Alexandre Fayolle, GitHub, Jacques-Etienne Baudoux, sebalix, OCA Transbot, Sébastien Alix, Thierry Ducrest, oca-travis, Weblate, OCA-git-bot, Benoit, Simone Orsi, Carlos Serra-Toro, Matthieu Méquignon
WEBSITE
WEBSITEhttps://github.com/OCA/wms
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:34:20
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/connector:
    - component
OCA/delivery-carrier:
    - stock_picking_delivery_link
OCA/product-attribute:
    - product_packaging_dimension
    - product_manufacturer
    - product_packaging_type
OCA/rest-framework:
    - base_rest
OCA/server-auth:
    - auth_api_key
OCA/server-env:
    - server_environment
OCA/server-tools:
    - base_jsonify
    - base_m2m_custom_field
OCA/stock-logistics-warehouse:
    - stock_helper
    - stock_picking_completion_info
    - stock_move_common_dest
OCA/stock-logistics-workflow:
    - stock_quant_package_product_packaging
    - stock_quant_package_dimension
    - stock_putaway_hook
OCA/web:
    - web_domain_field
OCA/wms:
    - shopfloor_base
    - stock_storage_type
odoo/odoo:
    - base
    - base_sparse_field
    - stock
    - product
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - uom
    - barcodes
    - stock_picking_batch
    - product_expiry
    - delivery
    - sale_stock
    - sale
    - sales_team
    - payment
    - account
    - analytic
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - digest
    - resource
    - utm
    - stock_account
    - sale_management
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES apispec
cerberus
parse-accept-language
pyquerystring
cachetools
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (6)
XML IDNameModelTypeStatus
shopfloor_menu_form_view shopfloor.menu field Inherits shopfloor_base.shopfloor_menu_form_view
shopfloor_menu_search_view shopfloor.menu field Inherits shopfloor_base.shopfloor_menu_search_view
shopfloor_menu_tree_view shopfloor.menu field Inherits shopfloor_base.shopfloor_menu_tree_view
view_location_form Shopfloor stock.location form stock.location xpath Inherits stock.view_location_form
view_picking_type_form Operation Types stock.picking.type xpath Inherits stock.view_picking_type_form
view_stock_move_line_detailed_operation_tree shopfloor stock_move_line_detailed_operation_tree stock.move.line field Inherits stock.view_stock_move_line_detailed_operation_tree
Models touched (12)

New fields (9)
  • allow_move_create Boolean
    default=False help='Some scenario may create move(s) when a product or package is scanned and no move already exists. Any new move is created in the selected operation type, so it can be active only when one type is selected.' string='Allow Move Creation'
  • allow_unreserve_other_moves Boolean
    default=False help='If you tick this box, this scenario will allow operator to move goods even if a reservation is made by a different operation type.' string='Allow to process reserved quantities'
  • ignore_no_putaway_available Boolean
    default=False help="If you tick this box, the transfer is reserved only if the put-away can find a sublocation (when putaway destination is different from the operation type's destination)." string='Ignore transfers when no put-away is available'
  • ignore_no_putaway_available_is_possible Boolean
    compute='_compute_ignore_no_putaway_available_is_possible'
  • move_create_is_possible Boolean
    compute='_compute_move_create_is_possible'
  • pick_pack_same_time Boolean
    default=False help=PICK_PACK_SAME_TIME_HELP string='Pick and pack at the same time'
  • pick_pack_same_time_is_possible Boolean
    compute='_compute_pick_pack_same_time_is_possible'
  • picking_type_ids Many2many → stock.picking.type
    comodel_name='stock.picking.type' required=True string='Operation Types'
  • unreserve_other_moves_is_possible Boolean
    compute='_compute_unreserve_other_moves_is_possible'
Public methods (3)
  • onchange_ignore_no_putaway_available_is_possible(self)
    @api.onchange('ignore_no_putaway_available_is_possible')
  • onchange_move_create_is_possible(self)
    @api.onchange('move_create_is_possible')
  • onchange_unreserve_other_moves_is_possible(self)
    @api.onchange('unreserve_other_moves_is_possible')

New fields (2)
  • shopfloor_postponed Boolean
    copy=False help='Technical field. Indicates if the operation has been postponed in a barcode scenario.'
  • shopfloor_priority Integer
    copy=False default=<expr> help='Technical field. Overrides operation priority in barcode scenario.'
Public methods (1)
  • shopfloor_postpone(self, *recordsets)
    Postpone the record and update its priority based on other records. The method accepts several recordsets as parameter (to be able to get the current max priority from different types of records).

New fields (0)

No new fields.

Public methods (1)
  • user_has_groups(self, groups)

New fields (3)
  • reserved_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' compute='_compute_reserved_move_lines'
  • shopfloor_picking_sequence Char
    help="The picking done in Shopfloor scenarios will respect this order. The sequence is a char so it can be composed of fields such as 'corridor-rack-side-level'. Pay attention to the padding ('09' is before '19', '9' is not). It is recommended to use an Export then an Import to populate this field using a spreadsheet." string='Shopfloor Picking Sequence'
  • source_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' inverse_name='location_id' readonly=True
Public methods (1)
  • planned_qty_in_location_is_empty(self, move_lines=None)
    Return if a location will be empty when move lines will be confirmed Used for the "zero check". We need to know if a location is empty, but since we set the move lines to "done" only at the end of the unload workflow, we have to look at the qty_done of the move lines from this location. With `move_lines` we can force the use of the given move lines for the check. This allows to know that the location will be empty if we process only these move lines.

New fields (0)

No new fields.

Public methods (3)
  • extract_and_action_done(self)
    Extract the moves in a separate transfer and validate them. You can combine this method with `split_other_move_lines` method to first extract some move lines in a separate move, then validate it with this method.
  • split_other_move_lines(self, move_lines, intersection=False)
    Substract `move_lines` from `move.move_line_ids`, put the result in a new move and returns it. If `intersection` is set to `True`, this is the common lines between `move_lines` and `move.move_line_ids` which will be put in a new move.
  • split_unavailable_qty(self)
    Put unavailable qty of a partially available move in their own move (which will be 'confirmed').

New fields (6)
  • location_id Many2one
    index=True
  • package_id Many2one
    index=True
  • picking_id Many2one
    auto_join=True
  • shopfloor_checkout_done Boolean
    default=False
  • shopfloor_unloaded Boolean
    default=False
  • shopfloor_user_id Many2one → res.users
    comodel_name='res.users' index=True
Public methods (1)
  • replace_package(self, new_package)
    Replace a package on an assigned move line

New fields (2)
  • package_id Many2one
    index=True
  • picking_id Many2one
    auto_join=True
Public methods (1)
  • explode_package(self)
    Unlink but keep the moves. Original motivation: A package level has a relation to "move_ids" only when the package level was created first from the UI and it created its move. When we unlink a package level, it deletes the move it created. But in some cases, we want to keep the move, e.g.: * create a package level from the UI to move a package * it generates a move for the matching product quantity * we use a barcode scenario such as cluster or zone picking * we use the "replace package" button * when replacing the package, we have to delete the package level, but we still have the same need in term of "I want X products", so we have to keep the move * another case is when we "dismiss" the package level in the location content transfer scenario, we want to keep the "need" in moves, but we are no longer moving the entire package level Commit https://github.com/odoo/odoo/commit/b33e72d0bf027fb2c789b1b9476f7edf1a40b0a6 introduced the handling of pkg level deletion which is doing what was done by this method. Moreover it has been fixed here https://github.com/odoo/odoo/pull/66517. Hence, we keep this method to unify the action of "exploding a package" especially to avoid to refactor many places every time the core changes.

New fields (4)
  • bulk_line_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of move lines without package included.'
  • move_line_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of move lines included.'
  • package_level_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of package_level included.'
  • total_weight Float
    compute='_compute_picking_info' help='Technical field. Indicates total weight of transfers included.'
Public methods (1)
  • split_assigned_move_lines(self, move_lines=None)
    Put all reserved quantities (move lines) in their own moves and transfer. As a result, the current transfer will contain only confirmed moves.

New fields (3)
  • move_line_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of move lines included.'
  • picking_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of transfers included.'
  • total_weight Float
    compute='_compute_picking_info' help='Technical field. Indicates total weight of transfers included.'
Public methods (0)

No public methods.

New fields (2)
  • shopfloor_menu_ids Many2many → shopfloor.menu
    comodel_name='shopfloor.menu' readonly=True string='Shopfloor Menus'
  • shopfloor_zero_check Boolean
    help='For Shopfloor scenarios using it (Cluster Picking, Zone Picking, Discrete order Picking), the zero check step will be activated when a location becomes empty after a move.' string='Activate Zero Check'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (4)
  • move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' help='Technical field. Move lines moving this package.' inverse_name='package_id' readonly=True
  • planned_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' help='Technical field. Move lines for which destination is this package.' inverse_name='result_package_id' readonly=True
  • reserved_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' compute='_compute_reserved_move_lines'
  • shopfloor_weight Float
    compute='_compute_shopfloor_weight' digits='Product Unit of Measure' help='Real pack weight or the estimated one.' args: 'Shopfloor weight (kg)'
Public methods (1)
  • move_package_to_location(self, dest_location)
    Create inventories to move a package to a different location It should be called when the package is - in real life - already in the destination. It creates an inventory to remove the package from the source location and a second inventory to place the package in the destination (to reflect the reality). The source location is the current location of the package.
REPOSITORY
REPOSITORYOCA/wms
GIT
GIThttps://github.com/OCA/wms.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/wms/tree/10.0/shopfloor
VERSION
VERSION 1.3.7
CATEGORY
CATEGORYInventory
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONYes
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSOdoo Community Association (OCA), Akretion, Camptocamp, BCIM
MAINTAINERS
MAINTAINERSOdoo Community Association (OCA), Akretion, Camptocamp, BCIM
COMMITTERS
COMMITTERSGuewen Baconnier, Alexandre Fayolle, GitHub, sebalix, Laurent Mignon (ACSONE), Sébastien Alix, oca-travis, OCA-git-bot, Benoit, Simone Orsi
WEBSITE
WEBSITEhttps://github.com/OCA/wms
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:20:03
ODOO DEPENDENCIES
ODOO DEPENDENCIES OCA/connector:
    - component
OCA/product-attribute:
    - product_manufacturer
OCA/rest-framework:
    - base_rest
OCA/server-auth:
    - auth_api_key
OCA/server-tools:
    - base_jsonify
    - server_environment
OCA/stock-logistics-warehouse:
    - stock_picking_completion_info
    - stock_move_common_dest
OCA/stock-logistics-workflow:
    - stock_quant_package_product_packaging
OCA/web:
    - web_domain_field
OCA/wms:
    - stock_storage_type
odoo/odoo:
    - stock
    - product
    - base
    - decimal_precision
    - mail
    - base_setup
    - web_kanban
    - web
    - bus
    - web_tour
    - report
    - procurement
    - barcodes
    - web_planner
    - product_expiry
    - delivery
    - sale_stock
    - sale
    - sales_team
    - account
    - analytic
    - stock_account
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES accept_language
cerberus
pyquerystring
cachetools
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (14)
XML IDNameModelTypeStatus
res_partner_shopfloor_form partner.shopfloor.form res.partner xpath Inherits base.view_partner_form
shopfloor_log_form_view shopfloor.log form shopfloor.log form New
shopfloor_log_search_view shopfloor.log search shopfloor.log search New
shopfloor_log_tree_view shopfloor.log tree shopfloor.log tree New
shopfloor_menu_form_view shopfloor menu form shopfloor.menu form New
shopfloor_menu_search_view shopfloor menu search shopfloor.menu search New
shopfloor_menu_tree_view shopfloor menu tree shopfloor.menu tree New
shopfloor_profile_form_view shopfloor.profile form shopfloor.profile form New
shopfloor_profile_search_view shopfloor.profile search shopfloor.profile search New
shopfloor_profile_tree_view shopfloor.profile tree shopfloor.profile tree New
view_location_form Shopfloor stock.location form stock.location xpath Inherits stock.view_location_form
view_picking_shopfloor_form stock.picking.shopfloor.form stock.picking xpath Inherits stock.view_picking_form
view_picking_type_form Operation Types stock.picking.type xpath Inherits stock.view_picking_type_form
view_stock_move_line_detailed_operation_tree shopfloor stock_move_line_detailed_operation_tree stock.move.line field Inherits stock.view_stock_move_line_detailed_operation_tree
Models touched (15)

New fields (1)
  • shopfloor_packing_info Text
    string='Checkout Packing Information'
Public methods (0)

No public methods.

New fields (10)
  • error Text
    readonly=True
  • exception_message Text
    readonly=True
  • exception_name Char
    readonly=True string='Exception'
  • headers Text
    readonly=True
  • params Text
    readonly=True
  • request_method Char
    readonly=True
  • request_url Char
    readonly=True string='Request URL'
  • result Text
    readonly=True
  • severity Selection
    compute='_compute_severity' readonly=False selection=[('functional', 'Functional'), ('warning', 'Warning'), ('severe', 'Severe')] store=True
  • state Selection
    readonly=True selection=[('success', 'Success'), ('failed', 'Failed')]
Public methods (2)
  • autovacuum(self)
    Delete logs which have exceeded their retention duration Called from a cron.
  • logging_active(self)

New fields (12)
  • active Boolean
    default=True
  • allow_move_create Boolean
    default=False help='Some scenario may create move(s) when a product or package is scanned and no move already exists. Any new move is created in the selected operation type, so it can be active only when one type is selected.' string='Allow Move Creation'
  • allow_unreserve_other_moves Boolean
    default=False help='If you tick this box, this scenario will allow operator to move goods even if a reservation is made by a different operation type.' string='Allow to process reserved quantities'
  • ignore_no_putaway_available Boolean
    default=False help="If you tick this box, the transfer is reserved only if the put-away can find a sublocation (when putaway destination is different from the operation type's destination)." string='Ignore transfers when no put-away is available'
  • ignore_no_putaway_available_is_possible Boolean
    compute='_compute_ignore_no_putaway_available_is_possible'
  • move_create_is_possible Boolean
    compute='_compute_move_create_is_possible'
  • name Char
    translate=True
  • picking_type_ids Many2many → stock.picking.type
    comodel_name='stock.picking.type' required=True string='Operation Types'
  • profile_ids Many2many → shopfloor.profile
    help='Visible for these profiles' string='Profiles' args: 'shopfloor.profile'
  • scenario Selection
    required=True selection='_selection_scenario'
  • sequence Integer
  • unreserve_other_moves_is_possible Boolean
    compute='_compute_unreserve_other_moves_is_possible'
Public methods (3)
  • onchange_ignore_no_putaway_available_is_possible(self)
    @api.onchange('ignore_no_putaway_available_is_possible')
  • onchange_move_create_is_possible(self)
    @api.onchange('move_create_is_possible')
  • onchange_unreserve_other_moves_is_possible(self)
    @api.onchange('unreserve_other_moves_is_possible')

New fields (2)
  • shopfloor_postponed Boolean
    compute='_compute_shopfloor_postponed' help='Technical field. Indicates if the operation has been postponed in a barcode scenario.' inverse='_inverse_shopfloor_postponed'
  • shopfloor_priority Integer
    copy=False default=<expr> help='Technical field. Overrides operation priority in barcode scenario.'
Public methods (0)

No public methods.

New fields (4)
  • active Boolean
    default=True
  • menu_ids Many2many → shopfloor.menu
    help='Menus visible for this profile' string='Menus' args: 'shopfloor.menu'
  • name Char
    required=True
  • warehouse_id Many2one → stock.warehouse
    default=<expr> required=True args: 'stock.warehouse'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (1)
  • user_has_groups(self, groups)

New fields (3)
  • reserved_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' compute='_compute_reserved_move_lines'
  • shopfloor_picking_sequence Char
    help="The picking done in Shopfloor scenarios will respect this order. The sequence is a char so it can be composed of fields such as 'corridor-rack-side-level'. Pay attention to the padding ('09' is before '19', '9' is not). It is recommended to use an Export then an Import to populate this field using a spreadsheet." string='Shopfloor Picking Sequence'
  • source_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' inverse_name='location_id' readonly=True
Public methods (2)
  • is_sublocation_of(self, others, func=any)
    Return True if self is a sublocation of others (or equal) By default, it return True if any other is a parent or equal. ``all`` can be passed to ``func`` to require all the other locations to be parent or equal to be True.
  • planned_qty_in_location_is_empty(self, move_lines=None)
    Return if a location will be empty when move lines will be confirmed Used for the "zero check". We need to know if a location is empty, but since we set the move lines to "done" only at the end of the unload workflow, we have to look at the qty_done of the move lines from this location. With `move_lines` we can force the use of the given move lines for the check. This allows to know that the location will be empty if we process only these move lines.

New fields (0)

No new fields.

Public methods (2)
  • extract_and_action_done(self)
    Extract the moves in a separate transfer and validate them. You can combine this method with `split_other_move_lines` method to first extract some move lines in a separate move, then validate it with this method.
  • split_other_move_lines(self, move_lines, intersection=False)
    Substract `move_lines` from `move.move_line_ids`, put the result in a new move and returns it. If `intersection` is set to `True`, this is the common lines between `move_lines` and `move.move_line_ids` which will be put in a new move.

New fields (6)
  • location_id Many2one
    index=True
  • package_id Many2one
    index=True
  • picking_id Many2one
    auto_join=True
  • shopfloor_checkout_done Boolean
    default=False
  • shopfloor_unloaded Boolean
    default=False
  • shopfloor_user_id Many2one → res.users
    comodel_name='res.users' index=True
Public methods (1)
  • replace_package(self, new_package)
    Replace a package on an assigned move line

New fields (0)

No new fields.

Public methods (2)
  • explode_package(self)
  • shallow_unlink(self)
    Unlink but keep the moves A package level has a relation to "move_ids" only when the package level was created first from the UI and it created its move. When we unlink a package level, it deletes the move it created. But in some cases, we want to keep the move, e.g.: * create a package level from the UI to move a package * it generates a move for the matching product quantity * we use a barcode scenario such as cluster or zone picking * we use the "replace package" button * when replacing the package, we have to delete the package level, but we still have the same need in term of "I want X products", so we have to keep the move * another case is when we "dismiss" the package level in the location content transfer scenario, we want to keep the "need" in moves, but we are no longer moving the entire package level

New fields (4)
  • move_line_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of move lines included.'
  • shopfloor_display_packing_info Boolean
    related='picking_type_id.shopfloor_display_packing_info'
  • shopfloor_packing_info Text
    related='partner_id.shopfloor_packing_info' string='Packing information'
  • total_weight Float
    compute='_compute_picking_info' help='Technical field. Indicates total weight of transfers included.'
Public methods (0)

No public methods.

New fields (3)
  • move_line_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of move lines included.'
  • picking_count Integer
    compute='_compute_picking_info' help='Technical field. Indicates number of transfers included.'
  • total_weight Float
    compute='_compute_picking_info' help='Technical field. Indicates total weight of transfers included.'
Public methods (0)

No public methods.

New fields (3)
  • shopfloor_display_packing_info Boolean
    help='For the Shopfloor Checkout/Packing scenarios to display the customer packing info.' string='Display customer packing info'
  • shopfloor_menu_ids Many2many → shopfloor.menu
    comodel_name='shopfloor.menu' readonly=True string='Shopfloor Menus'
  • shopfloor_zero_check Boolean
    help='For Shopfloor scenarios using it (Cluster Picking, Zone Picking, Discrete order Picking), the zero check step will be activated when a location becomes empty after a move.' string='Activate Zero Check'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (3)
  • move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' help='Technical field. Move lines moving this package.' inverse_name='package_id' readonly=True
  • planned_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' help='Technical field. Move lines for which destination is this package.' inverse_name='result_package_id' readonly=True
  • reserved_move_line_ids One2many → stock.move.line
    comodel_name='stock.move.line' compute='_compute_reserved_move_lines'
Public methods (1)
  • move_package_to_location(self, dest_location)
    Create inventories to move a package to a different location It should be called when the package is - in real life - already in the destination. It creates an inventory to remove the package from the source location and a second inventory to place the package in the destination (to reflect the reality). The source location is the current location of the package.