Repository
OCA/stock-logistics-shopfloor · module folder · Try on Runboat
Module version
0.18.1
Category
Inventory
Folder size
2.63 MB
License
AGPL-3
Application
Yes
Auto-installable
No
Website
https://github.com/OCA/stock-logistics-shopfloor
Last tracking update
2026-08-07 08:42:52
Authors
Camptocamp, Akretion, Odoo Community Association (OCA), BCIM
Maintainers
Camptocamp, Akretion, Odoo Community Association (OCA), BCIM
Committers
Simone Orsi, Jacques-Etienne Baudoux, GitHub, Laurent Mignon (ACSONE), Akim Juillerat, Sébastien Alix, Thierry Ducrest, Michael Tietz, Henry Backman, Weblate, OCA-git-bot, oca-ci, Mmequignon, Rafael Lima
Odoo dependencies
Python dependencies
apispec, cerberus, parse-accept-language, pyquerystring, cachetools, openupgradelib
System dependencies
None
Required by
shopfloor_batch_automatic_creation, shopfloor_checkout_sync, shopfloor_cluster_picking_repack, shopfloor_dangerous_goods, shopfloor_delivery_shipment, shopfloor_gs1, shopfloor_mobile, shopfloor_reception, shopfloor_single_product_transfer, shopfloor_vendor_packaging
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 form Inherits shopfloor_base.shopfloor_menu_form_view
shopfloor_menu_search_view shopfloor.menu search Inherits shopfloor_base.shopfloor_menu_search_view
shopfloor_menu_tree_view shopfloor.menu tree Inherits shopfloor_base.shopfloor_menu_tree_view
view_location_form Shopfloor stock.location form stock.location form Inherits stock.view_location_form
view_picking_type_form Operation Types stock.picking.type form Inherits stock.view_picking_type_form
view_stock_move_line_detailed_operation_tree shopfloor stock_move_line_detailed_operation_tree stock.move.line tree Inherits stock.view_stock_move_line_detailed_operation_tree
view_stock_move_line_operation_tree shopfloor stock.move.line.operations.tree stock.move.line tree Inherits stock.view_stock_move_line_operation_tree
HTTP endpoints (0)

No HTTP endpoints found for this module.

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 (4)
  • 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.
  • has_quantity_reserved(self)
    @property
  • 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 (4)
  • has_quantity_reserved(self)
    @property
  • is_fully_picked(self)
    @property
    :return: True if the quantity picked >= quantity reserved.
  • 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.

Loading…

Loading…

Loading…

Loading…