diff --git a/stock_picking_batch_extended/__manifest__.py b/stock_picking_batch_extended/__manifest__.py index 9b0006afe3a1..7e1c8df92348 100644 --- a/stock_picking_batch_extended/__manifest__.py +++ b/stock_picking_batch_extended/__manifest__.py @@ -5,12 +5,12 @@ { "name": "Stock batch picking extended", "summary": "Allows manage a lot of pickings in batch", - "version": "16.0.1.1.1", + "version": "18.0.1.0.0", "author": "Camptocamp, " "Tecnativa, " "Odoo Community Association (OCA)", "development_status": "Mature", "maintainers": ["gurneyalex", "carlosdauden", "i-vyshnevska"], "category": "Warehouse Management", - "depends": ["stock_picking_batch", "delivery"], + "depends": ["stock_picking_batch", "stock_delivery"], "website": "https://github.com/OCA/stock-logistics-workflow", "data": [ "security/ir.model.access.csv", diff --git a/stock_picking_batch_extended/hooks.py b/stock_picking_batch_extended/hooks.py index 7497bdd92e0e..82013d96f843 100644 --- a/stock_picking_batch_extended/hooks.py +++ b/stock_picking_batch_extended/hooks.py @@ -1,10 +1,6 @@ # Copyright 2019 Camptocamp - Iryna Vyshnevska # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). -from odoo import SUPERUSER_ID, api - - -def post_init_hook(cr, registry): - env = api.Environment(cr, SUPERUSER_ID, {}) +def post_init_hook(env): env["res.company"].search([]).write({"use_oca_batch_validation": True}) diff --git a/stock_picking_batch_extended/i18n/de.po b/stock_picking_batch_extended/i18n/de.po index 215ff6c374a7..10bb7d7d7ea3 100644 --- a/stock_picking_batch_extended/i18n/de.po +++ b/stock_picking_batch_extended/i18n/de.po @@ -336,7 +336,7 @@ msgid "Warehouse" msgstr "Warenlager" #. module: stock_picking_batch_extended -#: model:ir.model.fields,field_description:stock_picking_batch_extended.field_product_product__description_warehouse +#: model:ir.model.fields,field_description:stock_picking_batch_extended.field_product_product__description_picking #: model_terms:ir.ui.view,arch_db:stock_picking_batch_extended.product_normal_form_view msgid "Warehouse Description" msgstr "Warenlager-Beschreibung" diff --git a/stock_picking_batch_extended/i18n/es.po b/stock_picking_batch_extended/i18n/es.po index 6ebf211bd153..72d0b57e176e 100644 --- a/stock_picking_batch_extended/i18n/es.po +++ b/stock_picking_batch_extended/i18n/es.po @@ -332,7 +332,7 @@ msgid "Warehouse" msgstr "Almacén" #. module: stock_picking_batch_extended -#: model:ir.model.fields,field_description:stock_picking_batch_extended.field_product_product__description_warehouse +#: model:ir.model.fields,field_description:stock_picking_batch_extended.field_product_product__description_picking #: model_terms:ir.ui.view,arch_db:stock_picking_batch_extended.product_normal_form_view msgid "Warehouse Description" msgstr "Descripción del almacén" diff --git a/stock_picking_batch_extended/i18n/es_CL.po b/stock_picking_batch_extended/i18n/es_CL.po index 473e8b323766..8fd439c12b35 100644 --- a/stock_picking_batch_extended/i18n/es_CL.po +++ b/stock_picking_batch_extended/i18n/es_CL.po @@ -328,7 +328,7 @@ msgid "Warehouse" msgstr "Bodega" #. module: stock_picking_batch_extended -#: model:ir.model.fields,field_description:stock_picking_batch_extended.field_product_product__description_warehouse +#: model:ir.model.fields,field_description:stock_picking_batch_extended.field_product_product__description_picking #: model_terms:ir.ui.view,arch_db:stock_picking_batch_extended.product_normal_form_view msgid "Warehouse Description" msgstr "Descripción de Bodega" diff --git a/stock_picking_batch_extended/i18n/fr.po b/stock_picking_batch_extended/i18n/fr.po index ee27648b7306..df74da717f9c 100644 --- a/stock_picking_batch_extended/i18n/fr.po +++ b/stock_picking_batch_extended/i18n/fr.po @@ -335,7 +335,7 @@ msgid "Warehouse" msgstr "" #. module: stock_picking_batch_extended -#: model:ir.model.fields,field_description:stock_picking_batch_extended.field_product_product__description_warehouse +#: model:ir.model.fields,field_description:stock_picking_batch_extended.field_product_product__description_picking #: model_terms:ir.ui.view,arch_db:stock_picking_batch_extended.product_normal_form_view msgid "Warehouse Description" msgstr "Warehouse Description" diff --git a/stock_picking_batch_extended/i18n/it.po b/stock_picking_batch_extended/i18n/it.po index ed02e05496f3..9397f0af8e52 100644 --- a/stock_picking_batch_extended/i18n/it.po +++ b/stock_picking_batch_extended/i18n/it.po @@ -331,7 +331,7 @@ msgid "Warehouse" msgstr "Magazzino" #. module: stock_picking_batch_extended -#: model:ir.model.fields,field_description:stock_picking_batch_extended.field_product_product__description_warehouse +#: model:ir.model.fields,field_description:stock_picking_batch_extended.field_product_product__description_picking #: model_terms:ir.ui.view,arch_db:stock_picking_batch_extended.product_normal_form_view msgid "Warehouse Description" msgstr "Descrizione magazzino" diff --git a/stock_picking_batch_extended/i18n/pt_BR.po b/stock_picking_batch_extended/i18n/pt_BR.po index b81ac6820fbe..7a4b656bcfa8 100644 --- a/stock_picking_batch_extended/i18n/pt_BR.po +++ b/stock_picking_batch_extended/i18n/pt_BR.po @@ -332,7 +332,7 @@ msgid "Warehouse" msgstr "Armazém" #. module: stock_picking_batch_extended -#: model:ir.model.fields,field_description:stock_picking_batch_extended.field_product_product__description_warehouse +#: model:ir.model.fields,field_description:stock_picking_batch_extended.field_product_product__description_picking #: model_terms:ir.ui.view,arch_db:stock_picking_batch_extended.product_normal_form_view msgid "Warehouse Description" msgstr "Descrição do Armazém" diff --git a/stock_picking_batch_extended/i18n/sl.po b/stock_picking_batch_extended/i18n/sl.po index eaf383335ed9..390ee681924b 100644 --- a/stock_picking_batch_extended/i18n/sl.po +++ b/stock_picking_batch_extended/i18n/sl.po @@ -330,7 +330,7 @@ msgid "Warehouse" msgstr "Skladišče" #. module: stock_picking_batch_extended -#: model:ir.model.fields,field_description:stock_picking_batch_extended.field_product_product__description_warehouse +#: model:ir.model.fields,field_description:stock_picking_batch_extended.field_product_product__description_picking #: model_terms:ir.ui.view,arch_db:stock_picking_batch_extended.product_normal_form_view msgid "Warehouse Description" msgstr "Opis skladišča" diff --git a/stock_picking_batch_extended/i18n/stock_picking_batch_extended.pot b/stock_picking_batch_extended/i18n/stock_picking_batch_extended.pot index d0cde7ece4f8..87d245637763 100644 --- a/stock_picking_batch_extended/i18n/stock_picking_batch_extended.pot +++ b/stock_picking_batch_extended/i18n/stock_picking_batch_extended.pot @@ -322,7 +322,7 @@ msgid "Warehouse" msgstr "" #. module: stock_picking_batch_extended -#: model:ir.model.fields,field_description:stock_picking_batch_extended.field_product_product__description_warehouse +#: model:ir.model.fields,field_description:stock_picking_batch_extended.field_product_product__description_picking #: model_terms:ir.ui.view,arch_db:stock_picking_batch_extended.product_normal_form_view msgid "Warehouse Description" msgstr "" diff --git a/stock_picking_batch_extended/migrations/18.0.1.0.0/pre-migrate.py b/stock_picking_batch_extended/migrations/18.0.1.0.0/pre-migrate.py new file mode 100644 index 000000000000..fdce2e8c1854 --- /dev/null +++ b/stock_picking_batch_extended/migrations/18.0.1.0.0/pre-migrate.py @@ -0,0 +1,16 @@ +# Copyright 2025 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + + +def migrate(cr, version): + cr.execute(""" + UPDATE product_template + SET description_picking = + CASE + WHEN description_picking IS NOT NULL THEN + description_picking || '\n' || description_warehouse + ELSE + description_warehouse + END + WHERE description_warehouse IS NOT NULL; + """) diff --git a/stock_picking_batch_extended/models/__init__.py b/stock_picking_batch_extended/models/__init__.py index 4e8d47c13f5e..48a7e4b94eec 100644 --- a/stock_picking_batch_extended/models/__init__.py +++ b/stock_picking_batch_extended/models/__init__.py @@ -1,5 +1,6 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from . import res_company from . import res_config_settings from . import stock_batch_picking from . import product_product diff --git a/stock_picking_batch_extended/models/product_product.py b/stock_picking_batch_extended/models/product_product.py index 26c90107d369..fcac4a5125ce 100644 --- a/stock_picking_batch_extended/models/product_product.py +++ b/stock_picking_batch_extended/models/product_product.py @@ -4,7 +4,7 @@ from odoo import fields, models -class Product(models.Model): - _inherit = "product.product" - # TODO: Integrate in existent field - description_warehouse = fields.Text("Warehouse Description", translate=True) +class ProductTemplate(models.Model): + _inherit = "product.template" + + description_picking = fields.Text(string="Warehouse Description", translate=True) diff --git a/stock_picking_batch_extended/models/res_company.py b/stock_picking_batch_extended/models/res_company.py new file mode 100644 index 000000000000..4b4d10172ff3 --- /dev/null +++ b/stock_picking_batch_extended/models/res_company.py @@ -0,0 +1,10 @@ +# Copyright 2019 Camptocamp - Iryna Vyshnevska +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class Company(models.Model): + _inherit = "res.company" + + use_oca_batch_validation = fields.Boolean() diff --git a/stock_picking_batch_extended/models/res_config_settings.py b/stock_picking_batch_extended/models/res_config_settings.py index 6e9d015c020b..d395f0911287 100644 --- a/stock_picking_batch_extended/models/res_config_settings.py +++ b/stock_picking_batch_extended/models/res_config_settings.py @@ -12,9 +12,3 @@ class ResConfigSettings(models.TransientModel): related="company_id.use_oca_batch_validation", readonly=False, ) - - -class Company(models.Model): - _inherit = "res.company" - - use_oca_batch_validation = fields.Boolean() diff --git a/stock_picking_batch_extended/models/stock_batch_picking.py b/stock_picking_batch_extended/models/stock_batch_picking.py index b59ad3f52853..7b953751f0d4 100644 --- a/stock_picking_batch_extended/models/stock_batch_picking.py +++ b/stock_picking_batch_extended/models/stock_batch_picking.py @@ -1,7 +1,7 @@ # Copyright 2012-2014 Alexandre Fayolle, Camptocamp SA # Copyright 2018-2020 Tecnativa - Carlos Dauden # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import _, fields, models +from odoo import fields, models from odoo.exceptions import UserError @@ -12,13 +12,12 @@ class StockPickingBatch(models.Model): name = fields.Char( index=True, - states={"draft": [("readonly", False)]}, + readonly=False, # allow edition in draft state ) date = fields.Date( required=True, - readonly=True, + readonly=False, # allow edition in draft,in_progress state index=True, - states={"draft": [("readonly", False)], "in_progress": [("readonly", False)]}, default=fields.Date.context_today, help="date on which the batch picking is to be processed", ) @@ -66,7 +65,7 @@ def action_cancel(self): def action_print_picking(self): pickings = self.mapped("picking_ids") if not pickings: - raise UserError(_("Nothing to print.")) + raise UserError(self.env._("Nothing to print.")) return self.env.ref("stock.action_report_delivery").report_action( self.picking_ids ) diff --git a/stock_picking_batch_extended/report/batch_report.py b/stock_picking_batch_extended/report/batch_report.py index 7d3cf14a2644..53b119760ac3 100644 --- a/stock_picking_batch_extended/report/batch_report.py +++ b/stock_picking_batch_extended/report/batch_report.py @@ -22,7 +22,9 @@ def key_level_1(self, operation): @api.model def new_level_0(self, operation): - level_0_name = f"{operation.location_id.name_get()[0][1]} \u21e8 {operation.location_dest_id.name_get()[0][1]}" + location_name = operation.location_id.name_get()[0][1] + location_dest_name = operation.location_dest_id.name_get()[0][1] + level_0_name = f"{location_name} \u21e8 {location_dest_name}" return { "name": level_0_name, "location": operation.location_id, diff --git a/stock_picking_batch_extended/tests/test_batch.py b/stock_picking_batch_extended/tests/test_batch.py index f5ca7ecbdab1..bf7d7b7b82b5 100644 --- a/stock_picking_batch_extended/tests/test_batch.py +++ b/stock_picking_batch_extended/tests/test_batch.py @@ -1,11 +1,14 @@ # Copyright 2018 Tecnativa - Carlos Dauden +from odoo import Command from odoo.exceptions import UserError from odoo.tests import Form -from odoo.tests.common import TransactionCase, tagged +from odoo.tests.common import tagged + +from odoo.addons.base.tests.common import BaseCommon @tagged("post_install", "-at_install") -class TestBatchPicking(TransactionCase): +class TestBatchPicking(BaseCommon): @classmethod def _create_product(cls, name, product_type="consu"): return cls.env["product.product"].create({"name": name, "type": product_type}) @@ -13,8 +16,8 @@ def _create_product(cls, name, product_type="consu"): @classmethod def setUpClass(cls): super().setUpClass() - cls.stock_loc = cls.env.ref("stock.stock_location_stock") - cls.customer_loc = cls.env.ref("stock.stock_location_customers") + cls.stock_location = cls.env.ref("stock.stock_location_stock") + cls.customer_location = cls.env.ref("stock.stock_location_customers") cls.uom_unit = cls.env.ref("uom.product_uom_unit") cls.picking_type_out = cls.env.ref("stock.picking_type_out") cls.batch_model = cls.env["stock.picking.batch"] @@ -23,7 +26,9 @@ def setUpClass(cls): cls.picking_model = cls.env["stock.picking"] cls.product6 = cls._create_product("product_product_6") cls.product7 = cls._create_product("product_product_7") - cls.product8 = cls._create_product("product_product_8", "product") + cls.product8 = cls.env["product.product"].create( + {"name": "product_product_8", "is_storable": True} + ) cls.product9 = cls._create_product("product_product_9") cls.product10 = cls._create_product("product_product_10") cls.product11 = cls._create_product("product_product_11") @@ -35,7 +40,10 @@ def setUpClass(cls): { "user_id": cls.env.uid, "use_oca_batch_validation": True, - "picking_ids": [(4, cls.picking.id), (4, cls.picking2.id)], + "picking_ids": [ + Command.link(cls.picking.id), + Command.link(cls.picking2.id), + ], } ) @@ -46,19 +54,17 @@ def create_simple_picking(cls, product_ids, batch_id=False): return cls.picking_model.with_context(planned=True).create( { "picking_type_id": cls.picking_type_out.id, - "location_id": cls.stock_loc.id, - "location_dest_id": cls.customer_loc.id, + "location_id": cls.stock_location.id, + "location_dest_id": cls.customer_location.id, "batch_id": batch_id, "move_ids": [ - ( - 0, - 0, + Command.create( { "name": "Test move", "product_id": product_id, - "product_uom_qty": 1, - "location_id": cls.stock_loc.id, - "location_dest_id": cls.customer_loc.id, + "product_uom_qty": 10, + "location_id": cls.stock_location.id, + "location_dest_id": cls.customer_location.id, }, ) for product_id in product_ids @@ -229,15 +235,17 @@ def test_backorder(self): elif move.product_id == self.product7: move.product_uom_qty = 2 self.batch.action_assign() - # Mark product 6 as partially processed and 7 and 9 as fully processed. + # Mark product 6 and 10 as partially processed and 7 and 9 as fully processed. for operation in self.batch.move_line_ids: - # stock_move_line.qty_done + # stock_move_line.quantity if operation.product_id == self.product6: - operation.qty_done = 3 + operation.quantity = 3 elif operation.product_id == self.product7: - operation.qty_done = 2 + operation.quantity = 2 elif operation.product_id == self.product9: - operation.qty_done = 1 + operation.quantity = 10 + elif operation.product_id == self.product10: + operation.quantity = 9 # confirm transfer action creation self.batch.action_assign() context = self.batch.action_done().get("context") @@ -256,8 +264,7 @@ def test_backorder(self): self.assertEqual(self.product6, backorder.move_ids[0].product_id) self.assertEqual(2, backorder.move_ids[0].product_uom_qty) self.assertEqual(1, len(backorder.move_line_ids)) - self.assertEqual(2, backorder.move_line_ids[0].reserved_uom_qty) - self.assertEqual(0, backorder.move_line_ids[0].qty_done) + self.assertEqual(2, backorder.move_line_ids[0].quantity) backorder2 = self.picking_model.search( [("backorder_id", "=", self.picking2.id)] ) @@ -267,68 +274,63 @@ def test_backorder(self): self.assertEqual(self.product10, backorder2.move_ids.product_id) self.assertEqual(1, backorder2.move_ids.product_uom_qty) self.assertEqual(1, len(backorder2.move_line_ids)) - self.assertEqual(1, backorder2.move_line_ids.reserved_uom_qty) - self.assertEqual(0, backorder2.move_line_ids.qty_done) + self.assertEqual(1, backorder2.move_line_ids.quantity) def test_assign_draft_pick(self): - picking3 = self.create_simple_picking( + self.picking3 = self.create_simple_picking( self.product11.ids, batch_id=self.batch.id ) - self.assertEqual("draft", picking3.state) + self.assertEqual("draft", self.picking3.state) self.batch.action_assign() - context = self.batch.action_done().get("context") - Form( - self.env["stock.immediate.transfer"].with_context(**context) - ).save().process() + self.assertEqual(self.picking.state, "assigned", "Picking 1 should be ready") + self.assertEqual(self.picking2.state, "assigned", "Picking 2 should be ready") + self.assertEqual(self.picking3.state, "assigned", "Picking 3 should be ready") + self.picking.move_ids.write({"quantity": 5, "picked": True}) + self.picking2.move_ids.write({"quantity": 10, "picked": True}) + self.picking3.move_ids.write({"quantity": 5, "picked": True}) + # There should be a wizard asking to process picking without quantity done + back_order_wizard_dict = self.batch.action_done() + self.assertTrue(back_order_wizard_dict) + back_order_wizard = Form.from_action(self.env, back_order_wizard_dict).save() + self.assertEqual(len(back_order_wizard.pick_ids), 2) + back_order_wizard.process() self.assertEqual("done", self.batch.state) self.assertEqual("done", self.picking.state) self.assertEqual("done", self.picking2.state) - self.assertEqual("done", picking3.state) + self.assertEqual("done", self.picking3.state) def test_package(self): - warehouse = self.browse_ref("stock.warehouse0") - warehouse.delivery_steps = "pick_ship" - group = self.env["procurement.group"].create( - {"name": "Test", "move_type": "direct"} + # only do part of pickings + # + assign different destinations + # + try to pack (should get wizard to correct destination) + self.batch.move_line_ids.quantity = 5 + self.batch.move_line_ids[0].location_dest_id = self.stock_location.id + self.batch.move_ids.picked = True + wizard_values = self.batch.action_put_in_pack() + wizard = self.env[(wizard_values.get("res_model"))].browse( + wizard_values.get("res_id") ) - values = { - "company_id": warehouse.company_id, - "group_id": group, - "date_planned": "2018-11-13 12:12:59", - "warehouse_id": warehouse, - } - procurements = [ - self.env["procurement.group"].Procurement( - self.product11, - 1, - self.env.ref("uom.product_uom_unit"), - self.customer_loc, - "test", - "TEST", - warehouse.company_id, - values, - ) - ] - group.run(procurements) - pickings = self.picking_model.search([("group_id", "=", group.id)]) - self.assertEqual(2, len(pickings)) - picking = pickings.filtered(lambda p: p.state == "assigned") - picking.move_line_ids[0].qty_done = 1 - picking.action_put_in_pack() - other_picking = pickings.filtered(lambda p: p.id != picking.id) - picking._action_done() - self.assertEqual("assigned", other_picking.state) - # We add the 'package' picking in batch - other_picking.batch_id = self.batch - self.batch.action_assign() - context = self.batch.action_done().get("context") - Form( - self.env["stock.immediate.transfer"].with_context(**context) - ).save().process() + wizard.location_dest_id = self.customer_location.id + package = wizard.action_done() + + # a new package is made and done quantities should be in same package + self.assertTrue(package) + done_qty_move_lines = self.batch.move_line_ids.filtered( + lambda ml: ml.quantity == 5 + ) + self.assertEqual(done_qty_move_lines[0].result_package_id.id, package.id) + self.assertEqual(done_qty_move_lines[1].result_package_id.id, package.id) + + # confirm w/ backorder + back_order_wizard_dict = self.batch.action_done() + self.assertTrue(back_order_wizard_dict) + back_order_wizard = Form.from_action(self.env, back_order_wizard_dict).save() + self.assertEqual(len(back_order_wizard.pick_ids), 2) + back_order_wizard.process() + self.assertEqual("done", self.batch.state) self.assertEqual("done", self.picking.state) self.assertEqual("done", self.picking2.state) - self.assertEqual("done", other_picking.state) def test_remove_undone(self): self.picking2.action_cancel() @@ -342,21 +344,22 @@ def test_remove_undone(self): self.assertEqual(0, len(self.batch.picking_ids)) def test_partial_done(self): - # If user filled some quantity_done manually in operations tab, + # If user filled some quantity manually in operations tab, # we want only these qties to be processed. # So picking with no qties processed are release and backorder are # created for picking partially processed. self.batch.action_assign() self.assertEqual("assigned", self.picking.state) self.assertEqual("assigned", self.picking2.state) - self.picking.move_line_ids[0].qty_done = 1 - self.picking2.move_line_ids[0].qty_done = 1 - self.picking2.move_line_ids[1].qty_done = 1 - context = self.batch.action_done().get("context") - # Create backorder? action - Form( - self.env["stock.backorder.confirmation"].with_context(**context) - ).save().process() + self.picking.move_line_ids[0].write({"quantity": 10, "picked": True}) + self.picking2.move_line_ids[0].write({"quantity": 5, "picked": True}) + self.picking2.move_line_ids[1].write({"quantity": 10, "picked": True}) + # confirm w/ backorder + back_order_wizard_dict = self.batch.action_done() + self.assertTrue(back_order_wizard_dict) + back_order_wizard = Form.from_action(self.env, back_order_wizard_dict).save() + self.assertEqual(len(back_order_wizard.pick_ids), 2) + back_order_wizard.process() self.batch.remove_undone_pickings() self.assertEqual(len(self.batch.picking_ids), 2) self.assertEqual("done", self.picking.state) diff --git a/stock_picking_batch_extended/views/product_product.xml b/stock_picking_batch_extended/views/product_product.xml index 6a86d60b9c84..a523d23635e7 100644 --- a/stock_picking_batch_extended/views/product_product.xml +++ b/stock_picking_batch_extended/views/product_product.xml @@ -1,20 +1,15 @@ - product.normal.form product.product - - - - - - + + This note will show up on the batch picking printout. + 1 + diff --git a/stock_picking_batch_extended/views/report_batch_picking.xml b/stock_picking_batch_extended/views/report_batch_picking.xml index c05b2ecc6a67..d3fb402fa89b 100644 --- a/stock_picking_batch_extended/views/report_batch_picking.xml +++ b/stock_picking_batch_extended/views/report_batch_picking.xml @@ -108,12 +108,12 @@
                                                         
                                                     
diff --git a/stock_picking_batch_extended/views/res_config_settings_views.xml b/stock_picking_batch_extended/views/res_config_settings_views.xml index bf466a53a0dd..876e4e458bba 100644 --- a/stock_picking_batch_extended/views/res_config_settings_views.xml +++ b/stock_picking_batch_extended/views/res_config_settings_views.xml @@ -5,24 +5,15 @@ res.config.settings - -
+ - -
-
-
-
+ + +
diff --git a/stock_picking_batch_extended/views/stock_batch_picking.xml b/stock_picking_batch_extended/views/stock_batch_picking.xml index 8e992fae17c7..3d5f57705a7d 100644 --- a/stock_picking_batch_extended/views/stock_batch_picking.xml +++ b/stock_picking_batch_extended/views/stock_batch_picking.xml @@ -4,15 +4,18 @@ stock.picking.batch + + state != 'draft' + - +