From 2790372c7eb5da1137f6c9dd6367bd20d7c4ab7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Alix?= Date: Mon, 11 Jul 2022 14:17:23 +0200 Subject: [PATCH 01/35] Add 'stock_warehouse_flow' to configure routing flows New feature allowing to re-qualify the operation type of a stock move at confirmation. The main criteria to requalify a move is the carrier, as this one often implies a dedicated routing (we do not have the same flow, nor the same carrier, depending if we ship a pallet or a bunch of products for instance). This job was previously done by configuring the stock_dynamic_routing with a domain on the carrier, but the dynamic routing was applied on reservation, while we could already qualify moves at confirmation. --- stock_warehouse_flow/README.rst | 131 +++++ stock_warehouse_flow/__init__.py | 1 + stock_warehouse_flow/__manifest__.py | 32 ++ .../demo/stock_warehouse_flow.xml | 38 ++ .../i18n/stock_warehouse_flow.pot | 364 ++++++++++++++ .../migrations/14.0.1.0.1/pre-migrate.py | 23 + stock_warehouse_flow/models/__init__.py | 5 + .../models/delivery_carrier.py | 26 + .../models/stock_location_route.py | 29 ++ stock_warehouse_flow/models/stock_move.py | 21 + .../models/stock_warehouse.py | 23 + .../models/stock_warehouse_flow.py | 399 +++++++++++++++ stock_warehouse_flow/readme/CONFIGURE.rst | 18 + stock_warehouse_flow/readme/CONTRIBUTORS.rst | 2 + stock_warehouse_flow/readme/DESCRIPTION.rst | 18 + stock_warehouse_flow/readme/ROADMAP.rst | 2 + stock_warehouse_flow/readme/USAGE.rst | 2 + .../security/ir.model.access.csv | 4 + .../static/description/config.png | Bin 0 -> 62641 bytes .../static/description/flow.png | Bin 0 -> 36432 bytes .../static/description/icon.png | Bin 0 -> 7354 bytes .../static/description/index.html | 473 ++++++++++++++++++ stock_warehouse_flow/tests/__init__.py | 3 + stock_warehouse_flow/tests/common.py | 70 +++ .../tests/test_delivery_carrier.py | 12 + stock_warehouse_flow/tests/test_warehouse.py | 12 + .../tests/test_warehouse_flow.py | 94 ++++ .../views/delivery_carrier.xml | 25 + .../views/stock_location_route.xml | 17 + .../views/stock_warehouse.xml | 23 + .../views/stock_warehouse_flow.xml | 220 ++++++++ 31 files changed, 2087 insertions(+) create mode 100644 stock_warehouse_flow/README.rst create mode 100644 stock_warehouse_flow/__init__.py create mode 100644 stock_warehouse_flow/__manifest__.py create mode 100644 stock_warehouse_flow/demo/stock_warehouse_flow.xml create mode 100644 stock_warehouse_flow/i18n/stock_warehouse_flow.pot create mode 100644 stock_warehouse_flow/migrations/14.0.1.0.1/pre-migrate.py create mode 100644 stock_warehouse_flow/models/__init__.py create mode 100644 stock_warehouse_flow/models/delivery_carrier.py create mode 100644 stock_warehouse_flow/models/stock_location_route.py create mode 100644 stock_warehouse_flow/models/stock_move.py create mode 100644 stock_warehouse_flow/models/stock_warehouse.py create mode 100644 stock_warehouse_flow/models/stock_warehouse_flow.py create mode 100644 stock_warehouse_flow/readme/CONFIGURE.rst create mode 100644 stock_warehouse_flow/readme/CONTRIBUTORS.rst create mode 100644 stock_warehouse_flow/readme/DESCRIPTION.rst create mode 100644 stock_warehouse_flow/readme/ROADMAP.rst create mode 100644 stock_warehouse_flow/readme/USAGE.rst create mode 100644 stock_warehouse_flow/security/ir.model.access.csv create mode 100644 stock_warehouse_flow/static/description/config.png create mode 100644 stock_warehouse_flow/static/description/flow.png create mode 100644 stock_warehouse_flow/static/description/icon.png create mode 100644 stock_warehouse_flow/static/description/index.html create mode 100644 stock_warehouse_flow/tests/__init__.py create mode 100644 stock_warehouse_flow/tests/common.py create mode 100644 stock_warehouse_flow/tests/test_delivery_carrier.py create mode 100644 stock_warehouse_flow/tests/test_warehouse.py create mode 100644 stock_warehouse_flow/tests/test_warehouse_flow.py create mode 100644 stock_warehouse_flow/views/delivery_carrier.xml create mode 100644 stock_warehouse_flow/views/stock_location_route.xml create mode 100644 stock_warehouse_flow/views/stock_warehouse.xml create mode 100644 stock_warehouse_flow/views/stock_warehouse_flow.xml diff --git a/stock_warehouse_flow/README.rst b/stock_warehouse_flow/README.rst new file mode 100644 index 0000000000..da3bce23e1 --- /dev/null +++ b/stock_warehouse_flow/README.rst @@ -0,0 +1,131 @@ +==================== +Stock Warehouse Flow +==================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fwms-lightgray.png?logo=github + :target: https://github.com/OCA/wms/tree/14.0/stock_warehouse_flow + :alt: OCA/wms +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/wms-14-0/wms-14-0-stock_warehouse_flow + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/285/14.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module introduces the concept of routing flows in order to manage +different delivery routes for a warehouse. + +The default behavior of Odoo allows you to have only one delivery route per +warehouse (with one, two or three steps). +With this module, you are now able to manage multiple delivery routes (having +their own rules and operation types), the right one being selected automatically +based on some criterias, like the carrier and any attribute of the stock move +to process. + +This allows you to define a delivery route based on the type of goods to ship, +for instance: + +* whole pallet (pick + ship) +* cold chain goods +* dangerous goods + +.. image:: https://raw.githubusercontent.com/OCA/wms/14.0/stock_warehouse_flow/static/description/flow.png + +.. IMPORTANT:: + This is an alpha version, the data model and design can change at any time without warning. + Only for development or testing purpose, do not use in production. + `More details on development status `_ + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +Got to "Inventory > Settings > Routing Flows". + +A routing flow can be seen as a helper to generate a delivery route (like the +warehouse is doing automatically). The new route will get its own rules and +operation types that doesn't overlap with the default ones of the warehouse. + +A routing flow is responsible to change the warehouse delivery route of a move +by another one depending on some criterias: + +* the initial outgoing operation type (usually the default one) +* the carrier +* a custom domain (applied on the move) + +This way you are able to change the route a move will take depending on its +carrier and, for instance, the type or the packaging of the product +you want to ship. + +.. image:: https://raw.githubusercontent.com/OCA/wms/14.0/stock_warehouse_flow/static/description/config.png + +Usage +===== + +When a stock move is confirmed, if a flow is matching all the criteria then +the new delivery route will be automatically applied. + +Known issues / Roadmap +====================== + +Currently, the module supports only delivery routes, but it could improved to +support reception routes as well. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Camptocamp +* BCIM + +Contributors +~~~~~~~~~~~~ + +* Sébastien Alix +* Jacques-Etienne Baudoux + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/wms `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_warehouse_flow/__init__.py b/stock_warehouse_flow/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/stock_warehouse_flow/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/stock_warehouse_flow/__manifest__.py b/stock_warehouse_flow/__manifest__.py new file mode 100644 index 0000000000..7a2302a798 --- /dev/null +++ b/stock_warehouse_flow/__manifest__.py @@ -0,0 +1,32 @@ +# Copyright 2022 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) +{ + "name": "Stock Warehouse Flow", + "summary": "Configure routing flow for stock moves", + "author": "Camptocamp, BCIM, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/wms", + "category": "Warehouse Management", + "version": "14.0.1.0.1", + "license": "AGPL-3", + "depends": [ + # core + "stock", + "delivery", + # OCA/stock-logistics-workflow + "delivery_procurement_group_carrier", + # OCA/wms + "stock_available_to_promise_release", + ], + "demo": [ + "demo/stock_warehouse_flow.xml", + ], + "data": [ + "security/ir.model.access.csv", + "views/stock_location_route.xml", + "views/stock_warehouse_flow.xml", + "views/stock_warehouse.xml", + "views/delivery_carrier.xml", + ], + "installable": True, + "development_status": "Alpha", +} diff --git a/stock_warehouse_flow/demo/stock_warehouse_flow.xml b/stock_warehouse_flow/demo/stock_warehouse_flow.xml new file mode 100644 index 0000000000..0cb0792b49 --- /dev/null +++ b/stock_warehouse_flow/demo/stock_warehouse_flow.xml @@ -0,0 +1,38 @@ + + + + + + Delivery Ship Only + + + ship_only + DIRECT + + + + The Poste - Delivery Pick Ship + + + pick_ship + POST + + + + + Normal - Delivery Pick Pack Ship + + + pick_pack_ship + NORMAL + + + + diff --git a/stock_warehouse_flow/i18n/stock_warehouse_flow.pot b/stock_warehouse_flow/i18n/stock_warehouse_flow.pot new file mode 100644 index 0000000000..e5d3c3ec47 --- /dev/null +++ b/stock_warehouse_flow/i18n/stock_warehouse_flow.pot @@ -0,0 +1,364 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_warehouse_flow +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__active +msgid "Active" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_location_route__applicable_flow_ids +msgid "Applicable Flows" +msgstr "" + +#. module: stock_warehouse_flow +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.stock_warehouse_flow_view_form +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.stock_warehouse_flow_view_search +msgid "Archived" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__company_id +msgid "Company" +msgstr "" + +#. module: stock_warehouse_flow +#: model_terms:ir.actions.act_window,help:stock_warehouse_flow.stock_warehouse_flow_action +msgid "Create a new Routing Flow" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__create_uid +msgid "Created by" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__create_date +msgid "Created on" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields.selection,name:stock_warehouse_flow.selection__stock_warehouse_flow__delivery_steps__ship_only +msgid "Deliver goods directly (1 step)" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__delivery_route_id +msgid "Delivery Route" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_delivery_carrier__display_name +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_location_route__display_name +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_move__display_name +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse__display_name +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__display_name +msgid "Display Name" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,help:stock_warehouse_flow.field_stock_warehouse_flow__move_domain +msgid "" +"Domain based on Stock Moves, to define if the routing flow is applicable or " +"not." +msgstr "" + +#. module: stock_warehouse_flow +#: code:addons/stock_warehouse_flow/models/stock_warehouse_flow.py:0 +#, python-format +msgid "Existing flow '%s' already applies on these kind of moves." +msgstr "" + +#. module: stock_warehouse_flow +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.stock_warehouse_flow_view_form +msgid "Flow Name" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse__flow_ids +msgid "Flows" +msgstr "" + +#. module: stock_warehouse_flow +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.stock_warehouse_flow_view_form +msgid "From" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__from_location_dest_id +msgid "From Location Dest" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__from_location_src_id +msgid "From Location Src" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__from_picking_type_id +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.stock_warehouse_flow_view_search +msgid "From operation type" +msgstr "" + +#. module: stock_warehouse_flow +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.stock_warehouse_flow_view_form +msgid "Generate route" +msgstr "" + +#. module: stock_warehouse_flow +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.stock_warehouse_flow_view_search +msgid "Group by..." +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_delivery_carrier__id +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_location_route__id +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_move__id +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse__id +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__id +msgid "ID" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__impacted_route_ids +msgid "Impacted Routes" +msgstr "" + +#. module: stock_warehouse_flow +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.stock_warehouse_flow_view_form +msgid "Impacted routes" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model,name:stock_warehouse_flow.model_stock_location_route +msgid "Inventory Routes" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_delivery_carrier____last_update +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_location_route____last_update +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_move____last_update +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse____last_update +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow____last_update +msgid "Last Modified on" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__write_date +msgid "Last Updated on" +msgstr "" + +#. module: stock_warehouse_flow +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.stock_warehouse_flow_view_form +msgid "Locations" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__name +msgid "Name" +msgstr "" + +#. module: stock_warehouse_flow +#: code:addons/stock_warehouse_flow/models/stock_warehouse_flow.py:0 +#, python-format +msgid "" +"No rule corresponding to '%s' operation type has been found on delivery route '%s'.\n" +"Please check your configuration." +msgstr "" + +#. module: stock_warehouse_flow +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.stock_warehouse_flow_view_form +msgid "Operation Types" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__out_type_id +msgid "Out Type" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__delivery_steps +msgid "Outgoing Shipments" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,help:stock_warehouse_flow.field_stock_warehouse_flow__delivery_steps +msgid "Outgoing route to follow" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__output_stock_loc_id +msgid "Output Location" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__pack_type_id +msgid "Pack Type" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields.selection,name:stock_warehouse_flow.selection__stock_warehouse_flow__delivery_steps__pick_pack_ship +msgid "Pack goods, send goods in output and then deliver (3 steps)" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__pack_stock_loc_id +msgid "Packing Location" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__pick_type_id +msgid "Pick Type" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_location_route__flow_id +msgid "Routing Flow" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.actions.act_window,name:stock_warehouse_flow.stock_warehouse_flow_action +#: model:ir.ui.menu,name:stock_warehouse_flow.stock_warehouse_flow_menu +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.stock_warehouse_flow_view_search +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.stock_warehouse_flow_view_tree +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.view_delivery_carrier_form +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.view_warehouse +msgid "Routing Flows" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_delivery_carrier__flow_ids +msgid "Routing flows" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__rule_ids +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.stock_warehouse_flow_view_form +msgid "Rules" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,help:stock_warehouse_flow.field_stock_warehouse_flow__out_type_id +msgid "" +"Same than 'To operation type' field, displayed here to get a global overview" +" of the flow configuration." +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,help:stock_warehouse_flow.field_stock_warehouse_flow__output_stock_loc_id +msgid "" +"Same than 'To output location' field, displayed here to get a global " +"overview of the flow configuration." +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields.selection,name:stock_warehouse_flow.selection__stock_warehouse_flow__delivery_steps__pick_ship +msgid "Send goods in output and then deliver (2 steps)" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__sequence +msgid "Sequence" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__sequence_prefix +msgid "Sequence Prefix" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model,name:stock_warehouse_flow.model_delivery_carrier +msgid "Shipping Methods" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__move_domain +msgid "Source Routing Domain" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model,name:stock_warehouse_flow.model_stock_move +msgid "Stock Move" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model,name:stock_warehouse_flow.model_stock_warehouse_flow +msgid "Stock Warehouse Routing Flow" +msgstr "" + +#. module: stock_warehouse_flow +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.stock_warehouse_flow_view_form +msgid "Technical Information" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,help:stock_warehouse_flow.field_stock_warehouse_flow__company_id +msgid "The company is automatically set from your user preferences." +msgstr "" + +#. module: stock_warehouse_flow +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.stock_warehouse_flow_view_form +msgid "To" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__to_picking_type_id +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.stock_warehouse_flow_view_search +msgid "To operation type" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__to_output_stock_loc_id +msgid "To output location" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,help:stock_warehouse_flow.field_stock_warehouse_flow__sequence_prefix +msgid "" +"Used to generate the default prefix of new operation types. (e.g. 'DG' => " +"'WH/OUT/DG/')" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model,name:stock_warehouse_flow.model_stock_warehouse +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__warehouse_id +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.stock_warehouse_flow_view_search +msgid "Warehouse" +msgstr "" + +#. module: stock_warehouse_flow +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.stock_warehouse_flow_view_form +msgid "Warehouse Flow" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__warning +msgid "Warning" +msgstr "" + +#. module: stock_warehouse_flow +#: model:ir.model.fields,field_description:stock_warehouse_flow.field_stock_warehouse_flow__carrier_ids +msgid "With carriers" +msgstr "" + +#. module: stock_warehouse_flow +#: model_terms:ir.ui.view,arch_db:stock_warehouse_flow.stock_warehouse_flow_view_form +msgid "to" +msgstr "" diff --git a/stock_warehouse_flow/migrations/14.0.1.0.1/pre-migrate.py b/stock_warehouse_flow/migrations/14.0.1.0.1/pre-migrate.py new file mode 100644 index 0000000000..06e4a629fe --- /dev/null +++ b/stock_warehouse_flow/migrations/14.0.1.0.1/pre-migrate.py @@ -0,0 +1,23 @@ +# Copyright 2022 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + + +def migrate(cr, installed_version): + if not installed_version: + return + # 'output_stock_loc_id' became a related+readonly field and has been + # replaced by 'to_output_stock_loc_id' + queries = [ + """ + ALTER TABLE stock_warehouse_flow + ADD COLUMN to_output_stock_loc_id INT + REFERENCES stock_location(id) + ON DELETE RESTRICT; + """, + """ + UPDATE stock_warehouse_flow + SET to_output_stock_loc_id = output_stock_loc_id; + """, + ] + for query in queries: + cr.execute(query) diff --git a/stock_warehouse_flow/models/__init__.py b/stock_warehouse_flow/models/__init__.py new file mode 100644 index 0000000000..c99144f97d --- /dev/null +++ b/stock_warehouse_flow/models/__init__.py @@ -0,0 +1,5 @@ +from . import stock_warehouse_flow +from . import stock_warehouse +from . import stock_move +from . import stock_location_route +from . import delivery_carrier diff --git a/stock_warehouse_flow/models/delivery_carrier.py b/stock_warehouse_flow/models/delivery_carrier.py new file mode 100644 index 0000000000..675feb6269 --- /dev/null +++ b/stock_warehouse_flow/models/delivery_carrier.py @@ -0,0 +1,26 @@ +# Copyright 2022 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo import fields, models + + +class DeliveryCarrier(models.Model): + _inherit = "delivery.carrier" + + flow_ids = fields.Many2many( + comodel_name="stock.warehouse.flow", + relation="delivery_carrier_stock_warehouse_flow_rel", + column1="delivery_carrier_id", + column2="stock_warehouse_flow_id", + string="Routing flows", + copy=False, + ) + + def action_view_flows(self): + self.ensure_one() + action = self.env["ir.actions.actions"]._for_xml_id( + "stock_warehouse_flow.stock_warehouse_flow_action" + ) + action["domain"] = [("id", "in", self.flow_ids.ids)] + action["context"] = {"default_carrier_ids": [(6, 0, self.ids)]} + return action diff --git a/stock_warehouse_flow/models/stock_location_route.py b/stock_warehouse_flow/models/stock_location_route.py new file mode 100644 index 0000000000..859b705d8b --- /dev/null +++ b/stock_warehouse_flow/models/stock_location_route.py @@ -0,0 +1,29 @@ +# Copyright 2022 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo import api, fields, models + + +class StockLocationRoute(models.Model): + _inherit = "stock.location.route" + + flow_id = fields.Many2one( + comodel_name="stock.warehouse.flow", + ondelete="set null", + string="Routing Flow", + ) + applicable_flow_ids = fields.One2many( + comodel_name="stock.warehouse.flow", + compute="_compute_applicable_flow_ids", + string="Applicable Flows", + ) + + @api.depends("rule_ids.picking_type_id") + def _compute_applicable_flow_ids(self): + for route in self: + picking_types = route.rule_ids.picking_type_id + route.applicable_flow_ids = self.env["stock.warehouse.flow"].search( + [ + ("from_picking_type_id", "in", picking_types.ids), + ] + ) diff --git a/stock_warehouse_flow/models/stock_move.py b/stock_warehouse_flow/models/stock_move.py new file mode 100644 index 0000000000..4415668a89 --- /dev/null +++ b/stock_warehouse_flow/models/stock_move.py @@ -0,0 +1,21 @@ +# Copyright 2022 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo import models + + +class StockMove(models.Model): + _inherit = "stock.move" + + def _action_confirm(self, merge=True, merge_into=False): + # Apply the flow configuration on the move before it generates + # its chained moves (if any) + for move in self: + if not move._apply_flow_on_action_confirm(): + continue + flow = self.env["stock.warehouse.flow"]._search_for_move(move) + flow._apply_on_move(move) + return super()._action_confirm(merge=merge, merge_into=merge_into) + + def _apply_flow_on_action_confirm(self): + return self.picking_type_id.code == "outgoing" diff --git a/stock_warehouse_flow/models/stock_warehouse.py b/stock_warehouse_flow/models/stock_warehouse.py new file mode 100644 index 0000000000..5b58365aac --- /dev/null +++ b/stock_warehouse_flow/models/stock_warehouse.py @@ -0,0 +1,23 @@ +# Copyright 2022 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo import fields, models + + +class StockWarehouse(models.Model): + _inherit = "stock.warehouse" + + flow_ids = fields.One2many( + comodel_name="stock.warehouse.flow", + inverse_name="warehouse_id", + string="Flows", + ) + + def action_view_all_flows(self): + self.ensure_one() + action = self.env["ir.actions.actions"]._for_xml_id( + "stock_warehouse_flow.stock_warehouse_flow_action" + ) + action["domain"] = [("id", "in", self.flow_ids.ids)] + action["context"] = {"default_warehouse_id": self.id} + return action diff --git a/stock_warehouse_flow/models/stock_warehouse_flow.py b/stock_warehouse_flow/models/stock_warehouse_flow.py new file mode 100644 index 0000000000..9274247762 --- /dev/null +++ b/stock_warehouse_flow/models/stock_warehouse_flow.py @@ -0,0 +1,399 @@ +# Copyright 2022 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +import logging + +from odoo import _, api, fields, models +from odoo.exceptions import UserError +from odoo.tools.safe_eval import safe_eval + +logger = logging.getLogger(__name__) + + +class StockWarehouseFlow(models.Model): + _name = "stock.warehouse.flow" + _description = "Stock Warehouse Routing Flow" + _order = "sequence" + + name = fields.Char(required=True) + active = fields.Boolean(default=True) + sequence = fields.Integer(string="Sequence", default=10) + company_id = fields.Many2one(related="warehouse_id.company_id") + warehouse_id = fields.Many2one( + comodel_name="stock.warehouse", + ondelete="restrict", + string="Warehouse", + default=lambda o: o._default_warehouse_id(), + required=True, + ) + from_picking_type_id = fields.Many2one( + comodel_name="stock.picking.type", + ondelete="restrict", + string="From operation type", + required=True, + index=True, + domain="[('code', '=', 'outgoing')]", + ) + from_location_src_id = fields.Many2one( + comodel_name="stock.location", + compute="_compute_from_location_src_id", + ) + from_location_dest_id = fields.Many2one( + comodel_name="stock.location", + compute="_compute_from_location_dest_id", + ) + to_picking_type_id = fields.Many2one( + comodel_name="stock.picking.type", + ondelete="restrict", + string="To operation type", + readonly=True, + domain="[('default_location_dest_id', '=', from_location_dest_id)]", + check_company=True, + ) + to_output_stock_loc_id = fields.Many2one( + comodel_name="stock.location", + ondelete="restrict", + string="To output location", + check_company=True, + ) + carrier_ids = fields.Many2many( + comodel_name="delivery.carrier", + relation="delivery_carrier_stock_warehouse_flow_rel", + column1="stock_warehouse_flow_id", + column2="delivery_carrier_id", + string="With carriers", + copy=False, + ) + move_domain = fields.Char( + string="Source Routing Domain", + default=[], + copy=False, + help="Domain based on Stock Moves, to define if the " + "routing flow is applicable or not.", + ) + delivery_steps = fields.Selection( + selection=[ + ("ship_only", "Deliver goods directly (1 step)"), + ("pick_ship", "Send goods in output and then deliver (2 steps)"), + ( + "pick_pack_ship", + "Pack goods, send goods in output and then deliver (3 steps)", + ), + ], + string="Outgoing Shipments", + default="ship_only", + required=True, + help="Outgoing route to follow", + ) + sequence_prefix = fields.Char( + help=( + "Used to generate the default prefix of new operation types. " + "(e.g. 'DG' => 'WH/OUT/DG/')" + ) + ) + delivery_route_id = fields.Many2one( + comodel_name="stock.location.route", + string="Delivery Route", + ondelete="set null", + readonly=True, + index=True, + copy=False, + ) + rule_ids = fields.One2many( + related="delivery_route_id.rule_ids", + string="Rules", + ) + impacted_route_ids = fields.One2many( + comodel_name="stock.location.route", + compute="_compute_impacted_route_ids", + string="Impacted Routes", + ) + warning = fields.Html(compute="_compute_warning") + pack_stock_loc_id = fields.Many2one( + "stock.location", "Packing Location", check_company=True + ) + output_stock_loc_id = fields.Many2one( + related="to_output_stock_loc_id", + string="Output Location", + readonly=True, + help=( + "Same than 'To output location' field, displayed here to get a " + "global overview of the flow configuration." + ), + ) + pick_type_id = fields.Many2one( + "stock.picking.type", "Pick Type", check_company=True + ) + pack_type_id = fields.Many2one( + "stock.picking.type", "Pack Type", check_company=True + ) + out_type_id = fields.Many2one( + related="to_picking_type_id", + string="Out Type", + readonly=True, + help=( + "Same than 'To operation type' field, displayed here to get a " + "global overview of the flow configuration." + ), + ) + + def _default_warehouse_id(self): + warehouse = self.env["stock.warehouse"].search([]) + if len(warehouse) == 1: + return warehouse + + @api.depends("from_picking_type_id.default_location_src_id") + def _compute_from_location_src_id(self): + for record in self: + location = record.from_picking_type_id.default_location_src_id + if not location: + __, location = self.env["stock.warehouse"]._get_partner_locations() + record.from_location_src_id = location + + @api.depends("from_picking_type_id.default_location_dest_id") + def _compute_from_location_dest_id(self): + for record in self: + location = record.from_picking_type_id.default_location_dest_id + if not location: + location, __ = self.env["stock.warehouse"]._get_partner_locations() + record.from_location_dest_id = location + + def _compute_impacted_route_ids(self): + for flow in self: + rules = self.env["stock.rule"].search( + [ + ("picking_type_id", "=", flow.from_picking_type_id.id), + ("route_id.flow_id", "=", False), + ] + ) + flow.impacted_route_ids = rules.route_id + + def _compute_warning(self): + for flow in self: + flow.warning = False + try: + flow._get_rule_from_delivery_route(html_exc=True) + except UserError as exc: + flow.warning = str(exc) + + @api.constrains( + "warehouse_id", "from_picking_type_id", "carrier_ids", "move_domain" + ) + def _constrains_uniq(self): + args = [ + ("warehouse_id", "=", self.warehouse_id.id), + ("from_picking_type_id", "=", self.from_picking_type_id.id), + ] + flows = self.search(args) - self + for flow in flows: + if ( + self.carrier_ids & flow.carrier_ids + or not self.carrier_ids + and not flow.carrier_ids + ) and self.move_domain == flow.move_domain: + raise UserError( + _("Existing flow '%s' already applies on these kind of moves.") + % flow.name + ) + + @api.onchange("name") + def onchange_name(self): + self.sequence_prefix = "".join( + [w[0] for w in (self.name or "").split()] + ).upper() + + @api.onchange("warehouse_id") + def onchange_warehouse_id(self): + self.from_picking_type_id = self.warehouse_id.out_type_id + + def _generate_delivery_route(self): + self.ensure_one() + if self.delivery_route_id: + return False + # Re-generate the WH configuration with the chosen delivery steps in a + # savepoint to get a whole route+rules+picking types configured almost + # automatically (to not re-invent the wheel). + # Delivery route values are then copied to generate a new one. + # Copy some picking types with new sublocations first so the new + # delivery route will use them. + if not self.to_picking_type_id: + self.to_picking_type_id = self.warehouse_id.out_type_id.copy( + { + "name": ( + f"{self.warehouse_id.out_type_id.name} " + f"{self.sequence_prefix}" + ), + "active": True, + } + ) + self.to_picking_type_id.sequence_id.prefix += f"{self.sequence_prefix}/" + if "pick_" in self.delivery_steps: + if not self.pick_type_id: + self.pick_type_id = self.warehouse_id.pick_type_id.copy( + { + "name": ( + f"{self.warehouse_id.pick_type_id.name} " + f"{self.sequence_prefix}" + ), + "active": True, + } + ) + self.pick_type_id.sequence_id.prefix += f"{self.sequence_prefix}/" + # Create a dedicated 'Output/SUB' location + if not self.to_output_stock_loc_id: + self.to_output_stock_loc_id = ( + self.warehouse_id.wh_output_stock_loc_id.copy( + { + "name": self.sequence_prefix, + "location_id": self.warehouse_id.wh_output_stock_loc_id.id, + } + ) + ) + self.pick_type_id.default_location_dest_id = self.to_output_stock_loc_id + self.to_picking_type_id.default_location_src_id = ( + self.to_output_stock_loc_id + ) + if "pack_" in self.delivery_steps: + if not self.pack_type_id: + self.pack_type_id = self.warehouse_id.pack_type_id.copy( + { + "name": ( + f"{self.warehouse_id.pack_type_id.name} " + f"{self.sequence_prefix}" + ), + "active": True, + } + ) + self.pack_type_id.sequence_id.prefix += f"{self.sequence_prefix}/" + # Create a dedicated 'Packing Zone/SUB' location + if not self.pack_stock_loc_id: + self.pack_stock_loc_id = self.warehouse_id.wh_pack_stock_loc_id.copy( + { + "name": self.sequence_prefix, + "location_id": self.warehouse_id.wh_pack_stock_loc_id.id, + } + ) + self.pick_type_id.default_location_dest_id = self.pack_stock_loc_id + self.pack_type_id.default_location_src_id = self.pack_stock_loc_id + self.pack_type_id.default_location_dest_id = self.to_output_stock_loc_id + try: + with self.env.cr.savepoint(): + wh_vals = { + "delivery_steps": self.delivery_steps, + "out_type_id": self.to_picking_type_id.id, + } + if self.pick_type_id: + wh_vals.update( + { + "pick_type_id": self.pick_type_id.id, + "wh_output_stock_loc_id": self.to_output_stock_loc_id.id, + } + ) + if self.pack_type_id: + wh_vals.update( + { + "pack_type_id": self.pack_type_id.id, + "wh_pack_stock_loc_id": self.pack_stock_loc_id.id, + } + ) + wh_vals["out_type_id"] = self.to_picking_type_id.id + self.warehouse_id.write(wh_vals) + vals = self.warehouse_id.delivery_route_id.copy_data()[0] + raise Exception() + except Exception: + pass + vals.update( + { + "name": f"{self.warehouse_id.name}: {self.name}", + "active": True, + "flow_id": self.id, + # Give the priority to routes/rules not tied to a flow + # when the initial move is created by the procurement + "sequence": 1000, + } + ) + self.delivery_route_id = self.env["stock.location.route"].create(vals) + # Subscribe the route to the warehouse + if self.delivery_route_id.warehouse_selectable: + self.warehouse_id.route_ids |= self.delivery_route_id + + def action_generate_route(self): + for flow in self: + flow._generate_delivery_route() + return True + + def _search_for_move_domain(self, move): + domain = [ + ("from_picking_type_id", "=", move.picking_type_id.id), + ("delivery_route_id", "!=", False), + ] + if move.group_id.carrier_id: + domain.append(("carrier_ids", "in", move.group_id.carrier_id.ids)) + else: + domain.append(("carrier_ids", "=", False)) + return domain + + def _is_valid_for_move(self, move): + self.ensure_one() + if not self.move_domain: + return self + domain = safe_eval(self.move_domain or "[]") + if not domain: + return self + return move.filtered_domain(domain) + + @api.model + def _search_for_move(self, move): + """Return the first flow matching the move.""" + domain = self._search_for_move_domain(move) + for flow in self.search(domain): + if flow._is_valid_for_move(move): + return flow + return self.browse() + + def _get_rule_from_delivery_route(self, html_exc=False): + rule = self.delivery_route_id.rule_ids.filtered( + lambda r: r.picking_type_id == self.to_picking_type_id + ) + if self.delivery_route_id and not rule: + args = ( + self.to_picking_type_id.display_name, + self.delivery_route_id.display_name, + ) + if html_exc: + args = ( + f"{self.to_picking_type_id.display_name}", + f"{self.delivery_route_id.display_name}", + ) + raise UserError( + _( + "No rule corresponding to '%s' operation type " + "has been found on delivery route '%s'.\n" + "Please check your configuration." + ) + % args + ) + return rule + + def _apply_on_move(self, move): + """Apply the flow configuration on the move.""" + if not self: + return False + logger.info("Applying flow '%s' on '%s'", self.name, move) + rule = self._get_rule_from_delivery_route() + move.picking_id = False + move.picking_type_id = self.to_picking_type_id + move.location_id = ( + self.to_output_stock_loc_id + or self.to_picking_type_id.default_location_src_id + ) + move.procure_method = rule.procure_method + move.rule_id = rule + move._assign_picking() + + def write(self, vals): + res = super().write(vals) + # Sync 'active' field with underlying route + if "active" in vals: + self.delivery_route_id.write({"active": vals["active"]}) + return res diff --git a/stock_warehouse_flow/readme/CONFIGURE.rst b/stock_warehouse_flow/readme/CONFIGURE.rst new file mode 100644 index 0000000000..e809246565 --- /dev/null +++ b/stock_warehouse_flow/readme/CONFIGURE.rst @@ -0,0 +1,18 @@ +Got to "Inventory > Settings > Routing Flows". + +A routing flow can be seen as a helper to generate a delivery route (like the +warehouse is doing automatically). The new route will get its own rules and +operation types that doesn't overlap with the default ones of the warehouse. + +A routing flow is responsible to change the warehouse delivery route of a move +by another one depending on some criterias: + +* the initial outgoing operation type (usually the default one) +* the carrier +* a custom domain (applied on the move) + +This way you are able to change the route a move will take depending on its +carrier and, for instance, the type or the packaging of the product +you want to ship. + +.. image:: https://raw.githubusercontent.com/OCA/wms/14.0/stock_warehouse_flow/static/description/config.png diff --git a/stock_warehouse_flow/readme/CONTRIBUTORS.rst b/stock_warehouse_flow/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..025a237926 --- /dev/null +++ b/stock_warehouse_flow/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Sébastien Alix +* Jacques-Etienne Baudoux diff --git a/stock_warehouse_flow/readme/DESCRIPTION.rst b/stock_warehouse_flow/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..95ad69302b --- /dev/null +++ b/stock_warehouse_flow/readme/DESCRIPTION.rst @@ -0,0 +1,18 @@ +This module introduces the concept of routing flows in order to manage +different delivery routes for a warehouse. + +The default behavior of Odoo allows you to have only one delivery route per +warehouse (with one, two or three steps). +With this module, you are now able to manage multiple delivery routes (having +their own rules and operation types), the right one being selected automatically +based on some criterias, like the carrier and any attribute of the stock move +to process. + +This allows you to define a delivery route based on the type of goods to ship, +for instance: + +* whole pallet (pick + ship) +* cold chain goods +* dangerous goods + +.. image:: https://raw.githubusercontent.com/OCA/wms/14.0/stock_warehouse_flow/static/description/flow.png diff --git a/stock_warehouse_flow/readme/ROADMAP.rst b/stock_warehouse_flow/readme/ROADMAP.rst new file mode 100644 index 0000000000..6fcec940b9 --- /dev/null +++ b/stock_warehouse_flow/readme/ROADMAP.rst @@ -0,0 +1,2 @@ +Currently, the module supports only delivery routes, but it could improved to +support reception routes as well. diff --git a/stock_warehouse_flow/readme/USAGE.rst b/stock_warehouse_flow/readme/USAGE.rst new file mode 100644 index 0000000000..cd73d443fd --- /dev/null +++ b/stock_warehouse_flow/readme/USAGE.rst @@ -0,0 +1,2 @@ +When a stock move is confirmed, if a flow is matching all the criteria then +the new delivery route will be automatically applied. diff --git a/stock_warehouse_flow/security/ir.model.access.csv b/stock_warehouse_flow/security/ir.model.access.csv new file mode 100644 index 0000000000..4061d3a0a4 --- /dev/null +++ b/stock_warehouse_flow/security/ir.model.access.csv @@ -0,0 +1,4 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_stock_warehouse_flow_all,stock.warehouse.flow all users,model_stock_warehouse_flow,base.group_user,1,0,0,0 +access_stock_warehouse_flow_user,stock.warehouse.flow user,model_stock_warehouse_flow,stock.group_stock_user,1,0,0,0 +access_stock_warehouse_flow_manager,stock.warehouse.flow manager,model_stock_warehouse_flow,stock.group_stock_manager,1,1,1,1 diff --git a/stock_warehouse_flow/static/description/config.png b/stock_warehouse_flow/static/description/config.png new file mode 100644 index 0000000000000000000000000000000000000000..3f87ffc4fb350d06cda0eb913add8ed07312e400 GIT binary patch literal 62641 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 NqXW9@-Z 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 literal 0 HcmV?d00001 diff --git a/stock_warehouse_flow/static/description/flow.png b/stock_warehouse_flow/static/description/flow.png new file mode 100644 index 0000000000000000000000000000000000000000..05f4d83bc03241b40edb0e19f64076b96c11a9ee GIT binary patch literal 36432 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 literal 0 HcmV?d00001 diff --git a/stock_warehouse_flow/static/description/icon.png b/stock_warehouse_flow/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6feb17ab71a50fc2deec3990f9b3d798eed89820 GIT binary patch literal 7354 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 g_w{YqFc4hw|COULOw1pRa{vGU07*qoM6N<$f + + + + + +Stock Warehouse Flow + + + +
+

Stock Warehouse Flow

+ + +

Alpha License: AGPL-3 OCA/wms Translate me on Weblate Try me on Runbot

+

This module introduces the concept of routing flows in order to manage +different delivery routes for a warehouse.

+

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

+

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

+
    +
  • whole pallet (pick + ship)
  • +
  • cold chain goods
  • +
  • dangerous goods
  • +
+https://raw.githubusercontent.com/OCA/wms/14.0/stock_warehouse_flow/static/description/flow.png +
+

Important

+

This is an alpha version, the data model and design can change at any time without warning. +Only for development or testing purpose, do not use in production. +More details on development status

+
+

Table of contents

+ +
+

Configuration

+

Got to “Inventory > Settings > Routing Flows”.

+

A routing flow can be seen as a helper to generate a delivery route (like the +warehouse is doing automatically). The new route will get its own rules and +operation types that doesn’t overlap with the default ones of the warehouse.

+

A routing flow is responsible to change the warehouse delivery route of a move +by another one depending on some criterias:

+
    +
  • the initial outgoing operation type (usually the default one)
  • +
  • the carrier
  • +
  • a custom domain (applied on the move)
  • +
+

This way you are able to change the route a move will take depending on its +carrier and, for instance, the type or the packaging of the product +you want to ship.

+https://raw.githubusercontent.com/OCA/wms/14.0/stock_warehouse_flow/static/description/config.png +
+
+

Usage

+

When a stock move is confirmed, if a flow is matching all the criteria then +the new delivery route will be automatically applied.

+
+
+

Known issues / Roadmap

+

Currently, the module supports only delivery routes, but it could improved to +support reception routes as well.

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Camptocamp
  • +
  • BCIM
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/wms project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/stock_warehouse_flow/tests/__init__.py b/stock_warehouse_flow/tests/__init__.py new file mode 100644 index 0000000000..e37a702088 --- /dev/null +++ b/stock_warehouse_flow/tests/__init__.py @@ -0,0 +1,3 @@ +from . import test_delivery_carrier +from . import test_warehouse +from . import test_warehouse_flow diff --git a/stock_warehouse_flow/tests/common.py b/stock_warehouse_flow/tests/common.py new file mode 100644 index 0000000000..b90bde2899 --- /dev/null +++ b/stock_warehouse_flow/tests/common.py @@ -0,0 +1,70 @@ +# Copyright 2022 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo import fields +from odoo.tests.common import SavepointCase + + +class CommonFlow(SavepointCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) + ref = cls.env.ref + cls.wh = ref("stock.warehouse0") + cls.company = cls.wh.company_id + cls.loc_stock = cls.wh.lot_stock_id + cls.loc_customer = cls.env.ref("stock.stock_location_customers") + cls.product = ref("product.product_product_9") + cls._update_qty_in_location(cls.loc_stock, cls.product, 10) + cls.env["stock.warehouse.flow"].search([]).action_generate_route() + + def _get_flow(self, delivery_steps): + return self.env.ref( + f"stock_warehouse_flow.stock_warehouse_flow_delivery_{delivery_steps}" + ) + + @classmethod + def _update_qty_in_location( + cls, location, product, quantity, package=None, lot=None + ): + quants = cls.env["stock.quant"]._gather( + product, location, lot_id=lot, package_id=package, strict=True + ) + # this method adds the quantity to the current quantity, so remove it + quantity -= sum(quants.mapped("quantity")) + cls.env["stock.quant"]._update_available_quantity( + product, location, quantity, package_id=package, lot_id=lot + ) + + def _run_procurement(self, product, qty, carrier=None): + proc_group = self.env["procurement.group"] + uom = product.uom_id + proc_qty, proc_uom = uom._adjust_uom_quantities(qty, uom) + today = fields.Date.today() + proc_group = self.env["procurement.group"].create( + {"carrier_id": carrier.id if carrier else False} + ) + values = { + "group_id": proc_group, + "date_planned": today, + "date_deadline": today, + "warehouse_id": self.wh or False, + "company_id": self.company, + } + procurement = proc_group.Procurement( + product, + proc_qty, + proc_uom, + self.loc_customer, + product.name, + "PROC TEST", + self.company, + values, + ) + proc_group.run([procurement]) + + def _validate_picking(self, picking): + for move_line in picking.move_line_ids: + move_line.qty_done = move_line.product_uom_qty + picking._action_done() diff --git a/stock_warehouse_flow/tests/test_delivery_carrier.py b/stock_warehouse_flow/tests/test_delivery_carrier.py new file mode 100644 index 0000000000..287e49b99f --- /dev/null +++ b/stock_warehouse_flow/tests/test_delivery_carrier.py @@ -0,0 +1,12 @@ +# Copyright 2022 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + + +from . import common + + +class TestDeliveryCarrier(common.CommonFlow): + def test_action_view_flows(self): + flow = self._get_flow("pick_ship") + action = flow.carrier_ids.action_view_flows() + self.assertEqual(action["domain"][0][2], flow.ids) diff --git a/stock_warehouse_flow/tests/test_warehouse.py b/stock_warehouse_flow/tests/test_warehouse.py new file mode 100644 index 0000000000..1a4b0c4743 --- /dev/null +++ b/stock_warehouse_flow/tests/test_warehouse.py @@ -0,0 +1,12 @@ +# Copyright 2022 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + + +from . import common + + +class TestWarehouse(common.CommonFlow): + def test_action_view_all_flows(self): + action = self.wh.action_view_all_flows() + self.assertTrue(self.wh.flow_ids) + self.assertEqual(action["domain"][0][2], self.wh.flow_ids.ids) diff --git a/stock_warehouse_flow/tests/test_warehouse_flow.py b/stock_warehouse_flow/tests/test_warehouse_flow.py new file mode 100644 index 0000000000..22a438144b --- /dev/null +++ b/stock_warehouse_flow/tests/test_warehouse_flow.py @@ -0,0 +1,94 @@ +# Copyright 2022 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo.exceptions import UserError + +from . import common + + +class TestWarehouseFlow(common.CommonFlow): + def test_flow_ship_only(self): + """Replace the initial move by a 'ship_only' move.""" + # NOTE: use the recorder when migrating to 15.0 to catch created moves + moves_before = self.env["stock.move"].search([]) + flow = self._get_flow("ship_only") + self._run_procurement(self.product, 10, flow.carrier_ids) + moves_after = self.env["stock.move"].search([]) + moves = moves_after - moves_before + # Check we got pick+ship moves instead of one ship_only move + move_ship = moves.filtered(lambda m: m.picking_type_id.code == "outgoing") + to_picking_type = flow.to_picking_type_id + self.assertRecordValues( + move_ship, + [ + { + "picking_type_id": to_picking_type.id, + "location_id": to_picking_type.default_location_src_id.id, + "location_dest_id": self.loc_customer.id, + }, + ], + ) + self.assertIn(flow.sequence_prefix, move_ship.picking_id.name) + move_ship.picking_id.action_assign() + self.assertEqual(move_ship.state, "assigned") + self._validate_picking(move_ship.picking_id) + + def test_flow_pick_ship(self): + """Replace the initial move by pick+ship chained moves.""" + # NOTE: use the recorder when migrating to 15.0 to catch created moves + moves_before = self.env["stock.move"].search([]) + flow = self._get_flow("pick_ship") + self._run_procurement(self.product, 10, flow.carrier_ids) + moves_after = self.env["stock.move"].search([]) + moves = moves_after - moves_before + # Check we got pick+ship moves instead of one ship_only move + move_ship = moves.filtered(lambda m: m.picking_type_id.code == "outgoing") + to_picking_type = flow.to_picking_type_id + self.assertRecordValues( + move_ship, + [ + { + "picking_type_id": to_picking_type.id, + "location_id": to_picking_type.default_location_src_id.id, + "location_dest_id": self.loc_customer.id, + }, + ], + ) + self.assertIn(flow.sequence_prefix, move_ship.picking_id.name) + move_pick = move_ship.move_orig_ids + self.assertTrue(move_pick) + move_pick.picking_id.action_assign() + self.assertEqual(move_pick.state, "assigned") + self._validate_picking(move_pick.picking_id) + self.assertEqual(move_pick.state, "done") + self.assertEqual(move_ship.state, "assigned") + self._validate_picking(move_ship.picking_id) + + def test_no_rule_found_on_delivery_route(self): + flow = self._get_flow("pick_ship") + # Remove the rule + self.assertFalse(flow.warning) + rule = flow._get_rule_from_delivery_route() + rule.unlink() + # Check the warning message + self.assertTrue(flow.warning) + # Check that an error is raised when processing the move + exception_msg = ( + "No rule corresponding to .*%s.* operation type " + "has been found on delivery route .*%s.*.\n" + "Please check your configuration." + ) % ( + flow.to_picking_type_id.display_name, + flow.delivery_route_id.display_name, + ) + with self.assertRaisesRegex(UserError, exception_msg): + self._run_procurement(self.product, 10, flow.carrier_ids) + + def test_flow_uniq_constraint(self): + flow = self._get_flow("pick_ship") + vals = flow.copy_data()[0] + with self.assertRaises(UserError): + vals["carrier_ids"] = [ + (6, 0, self.env.ref("delivery.delivery_carrier").ids) + ] + self.env["stock.warehouse.flow"].create(vals) diff --git a/stock_warehouse_flow/views/delivery_carrier.xml b/stock_warehouse_flow/views/delivery_carrier.xml new file mode 100644 index 0000000000..03d07955e5 --- /dev/null +++ b/stock_warehouse_flow/views/delivery_carrier.xml @@ -0,0 +1,25 @@ + + + + + + delivery.carrier.form.inherit + delivery.carrier + + +
+ +
+
+
+ +
diff --git a/stock_warehouse_flow/views/stock_location_route.xml b/stock_warehouse_flow/views/stock_location_route.xml new file mode 100644 index 0000000000..e32f8edfc9 --- /dev/null +++ b/stock_warehouse_flow/views/stock_location_route.xml @@ -0,0 +1,17 @@ + + + + + + stock.location.route.tree.inherit + stock.location.route + + + + + + + + + diff --git a/stock_warehouse_flow/views/stock_warehouse.xml b/stock_warehouse_flow/views/stock_warehouse.xml new file mode 100644 index 0000000000..acf6d6009a --- /dev/null +++ b/stock_warehouse_flow/views/stock_warehouse.xml @@ -0,0 +1,23 @@ + + + + + + stock.warehouse.form.inherit + stock.warehouse + + +
+
+
+
+ +
diff --git a/stock_warehouse_flow/views/stock_warehouse_flow.xml b/stock_warehouse_flow/views/stock_warehouse_flow.xml new file mode 100644 index 0000000000..091e7106de --- /dev/null +++ b/stock_warehouse_flow/views/stock_warehouse_flow.xml @@ -0,0 +1,220 @@ + + + + + + stock.warehouse.flow.form + stock.warehouse.flow + +
+ + +
+
+ + + + + + + + + +
+ + => + + to + +
+ + +
+ + + + + + + +