diff --git a/setup/stock_picking_type_shipping_policy/odoo/addons/stock_picking_type_shipping_policy b/setup/stock_picking_type_shipping_policy/odoo/addons/stock_picking_type_shipping_policy new file mode 120000 index 0000000000..be8eeb87eb --- /dev/null +++ b/setup/stock_picking_type_shipping_policy/odoo/addons/stock_picking_type_shipping_policy @@ -0,0 +1 @@ +../../../../stock_picking_type_shipping_policy \ No newline at end of file diff --git a/setup/stock_picking_type_shipping_policy/setup.py b/setup/stock_picking_type_shipping_policy/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/stock_picking_type_shipping_policy/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/stock_picking_type_shipping_policy/__init__.py b/stock_picking_type_shipping_policy/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/stock_picking_type_shipping_policy/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/stock_picking_type_shipping_policy/__manifest__.py b/stock_picking_type_shipping_policy/__manifest__.py new file mode 100644 index 0000000000..4e6069ba45 --- /dev/null +++ b/stock_picking_type_shipping_policy/__manifest__.py @@ -0,0 +1,16 @@ +# Copyright 2020 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +{ + "name": "Stock Picking Type Shipping Policy", + "summary": "Define different shipping policies according to picking type", + "version": "13.0.1.0.0", + "development_status": "Alpha", + "category": "Warehouse Management", + "website": "https://github.com/OCA/wms", + "author": "Camptocamp, Odoo Community Association (OCA)", + "license": "AGPL-3", + "application": False, + "installable": True, + "depends": ["stock"], + "data": ["views/stock_picking_type.xml"], +} diff --git a/stock_picking_type_shipping_policy/models/__init__.py b/stock_picking_type_shipping_policy/models/__init__.py new file mode 100644 index 0000000000..90f60bebb8 --- /dev/null +++ b/stock_picking_type_shipping_policy/models/__init__.py @@ -0,0 +1,2 @@ +from . import stock_move +from . import stock_picking_type diff --git a/stock_picking_type_shipping_policy/models/stock_move.py b/stock_picking_type_shipping_policy/models/stock_move.py new file mode 100644 index 0000000000..8e249eb8ba --- /dev/null +++ b/stock_picking_type_shipping_policy/models/stock_move.py @@ -0,0 +1,17 @@ +# Copyright 2020 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +from odoo import models + + +class StockMove(models.Model): + + _inherit = "stock.move" + + def _get_new_picking_values(self): + res = super()._get_new_picking_values() + picking_type = self.mapped("picking_type_id") + if picking_type.shipping_policy == "force_as_soon_as_possible": + res["move_type"] = "direct" + elif picking_type.shipping_policy == "force_all_products_ready": + res["move_type"] = "one" + return res diff --git a/stock_picking_type_shipping_policy/models/stock_picking_type.py b/stock_picking_type_shipping_policy/models/stock_picking_type.py new file mode 100644 index 0000000000..5ff652ef09 --- /dev/null +++ b/stock_picking_type_shipping_policy/models/stock_picking_type.py @@ -0,0 +1,27 @@ +# Copyright 2020 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +from odoo import api, fields, models + + +class StockPickingType(models.Model): + + _inherit = "stock.picking.type" + + @api.model + def _default_shipping_policy(self): + return "procurement_group" + + @api.model + def _selection_shipping_policy(self): + return [ + ("procurement_group", "Take from procurement group"), + ("force_as_soon_as_possible", "Force to as soon as possible"), + ("force_all_products_ready", "Force to when all products are ready"), + ] + + shipping_policy = fields.Selection( + selection="_selection_shipping_policy", + default=lambda r: r._default_shipping_policy(), + help="Allows to force the shipping policy on pickings according to the" + " picking type.", + ) diff --git a/stock_picking_type_shipping_policy/readme/CONTRIBUTORS.rst b/stock_picking_type_shipping_policy/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..e31e2f0c4f --- /dev/null +++ b/stock_picking_type_shipping_policy/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Akim Juillerat diff --git a/stock_picking_type_shipping_policy/readme/DESCRIPTION.rst b/stock_picking_type_shipping_policy/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..12ee7d713b --- /dev/null +++ b/stock_picking_type_shipping_policy/readme/DESCRIPTION.rst @@ -0,0 +1,8 @@ +This module adds a Shipping Policy field on Operations Types in order to force +a specific Shipping Policy on Pickings according to their types. + +This is especially useful if you use a pick-pack-ship setup with the release +of operation (stock_available_to_promise_release) module along side with +the stock_routing_operation that may split operations by zone of the warehouse. +In that case, you want to be sure the pack operations will wait all different +picks to be processed before releasing the availability of the pack operation. diff --git a/stock_picking_type_shipping_policy/tests/__init__.py b/stock_picking_type_shipping_policy/tests/__init__.py new file mode 100644 index 0000000000..5437c31a2e --- /dev/null +++ b/stock_picking_type_shipping_policy/tests/__init__.py @@ -0,0 +1,2 @@ +# Copyright 2020 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) diff --git a/stock_picking_type_shipping_policy/tests/test_stock_picking_type_shipping_policy.py b/stock_picking_type_shipping_policy/tests/test_stock_picking_type_shipping_policy.py new file mode 100644 index 0000000000..5910bf3e62 --- /dev/null +++ b/stock_picking_type_shipping_policy/tests/test_stock_picking_type_shipping_policy.py @@ -0,0 +1,62 @@ +# Copyright 2020 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +from odoo.tests import SavepointCase + + +class TestPickingTypeShippingPolicy(SavepointCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) + ref = cls.env.ref + cls.warehouse = ref("stock.warehouse0") + # set pick-pack-ship on warehouse + cls.warehouse.delivery_steps = "pick_pack_ship" + cls.pick_type = cls.warehouse.pick_type_id + cls.pack_type = cls.warehouse.pack_type_id + cls.ship_type = cls.warehouse.out_type_id + + cls.customers_location = cls.env.ref("stock.stock_location_customers") + cls.output_location = cls.warehouse.wh_output_stock_loc_id + + cls.product = cls.env.ref("product.product_product_9") + # Create ir.default for procure_method as make_to_order in order to + # generate chained moves + cls.env["ir.default"].create( + { + "field_id": cls.env.ref("stock.field_stock_move__procure_method").id, + "json_value": '"make_to_order"', + } + ) + + def test_shipping_policy(self): + self.pack_type.shipping_policy = "force_all_products_ready" + self.pick_type.shipping_policy = "force_as_soon_as_possible" + # Create picking + out_picking = self.env["stock.picking"].create( + { + "picking_type_id": self.ship_type.id, + "location_id": self.output_location.id, + "location_dest_id": self.customers_location.id, + "move_lines": [ + ( + 0, + 0, + { + "name": self.product.name, + "product_id": self.product.id, + "product_uom_qty": 10.0, + "product_uom": self.product.uom_id.id, + }, + ) + ], + } + ) + out_picking.action_confirm() + + pack_picking = out_picking.move_lines.move_orig_ids.picking_id + pick_picking = pack_picking.move_lines.move_orig_ids.picking_id + self.assertEqual(pack_picking.picking_type_id, self.pack_type) + self.assertEqual(pack_picking.move_type, "one") + self.assertEqual(pick_picking.picking_type_id, self.pick_type) + self.assertEqual(pick_picking.move_type, "direct") diff --git a/stock_picking_type_shipping_policy/views/stock_picking_type.xml b/stock_picking_type_shipping_policy/views/stock_picking_type.xml new file mode 100644 index 0000000000..3cd080a747 --- /dev/null +++ b/stock_picking_type_shipping_policy/views/stock_picking_type.xml @@ -0,0 +1,13 @@ + + + + Operation Types inherit + stock.picking.type + + + + + + + +