From 07d0694daa1131ed8451871fc746b4b82229d429 Mon Sep 17 00:00:00 2001 From: Denis Roussel Date: Wed, 11 Dec 2024 14:05:50 +0100 Subject: [PATCH 1/2] [IMP] stock_split_picking: Add a common for tests --- stock_split_picking/tests/common.py | 45 +++++++++++++++++++ .../tests/test_stock_split_picking.py | 37 +-------------- 2 files changed, 47 insertions(+), 35 deletions(-) create mode 100644 stock_split_picking/tests/common.py diff --git a/stock_split_picking/tests/common.py b/stock_split_picking/tests/common.py new file mode 100644 index 000000000000..c7d5ad6e7163 --- /dev/null +++ b/stock_split_picking/tests/common.py @@ -0,0 +1,45 @@ +# Copyright 2017 Tecnativa - Vicent Cubells +# Copyright 2018 Camptocamp SA - Julien Coux +# Copyright 2024 ACSONE SA/NV +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo.tests.common import TransactionCase + +from odoo.addons.base.tests.common import DISABLED_MAIL_CONTEXT + + +class TestStockSplitPickingCase(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env(context=dict(cls.env.context, **DISABLED_MAIL_CONTEXT)) + cls.src_location = cls.env.ref("stock.stock_location_stock") + cls.dest_location = cls.env.ref("stock.stock_location_customers") + cls.product = cls.env["product.product"].create({"name": "Test product"}) + cls.product_2 = cls.env["product.product"].create({"name": "Test product 2"}) + cls.partner = cls.env["res.partner"].create({"name": "Test partner"}) + cls.picking = cls.env["stock.picking"].create( + { + "partner_id": cls.partner.id, + "picking_type_id": cls.env.ref("stock.picking_type_out").id, + "location_id": cls.src_location.id, + "location_dest_id": cls.dest_location.id, + } + ) + + cls.move = cls._create_stock_move(cls.product) + cls.move_2 = cls._create_stock_move(cls.product_2) + + @classmethod + def _create_stock_move(cls, product): + return cls.env["stock.move"].create( + { + "name": "/", + "picking_id": cls.picking.id, + "product_id": product.id, + "product_uom_qty": 10, + "product_uom": product.uom_id.id, + "location_id": cls.src_location.id, + "location_dest_id": cls.dest_location.id, + } + ) diff --git a/stock_split_picking/tests/test_stock_split_picking.py b/stock_split_picking/tests/test_stock_split_picking.py index 895889911440..96ff1779bfad 100644 --- a/stock_split_picking/tests/test_stock_split_picking.py +++ b/stock_split_picking/tests/test_stock_split_picking.py @@ -3,44 +3,11 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo.exceptions import UserError -from odoo.tests.common import TransactionCase +from .common import TestStockSplitPickingCase -class TestStockSplitPicking(TransactionCase): - @classmethod - def setUpClass(cls): - super(TestStockSplitPicking, cls).setUpClass() - - cls.src_location = cls.env.ref("stock.stock_location_stock") - cls.dest_location = cls.env.ref("stock.stock_location_customers") - cls.product = cls.env["product.product"].create({"name": "Test product"}) - cls.product_2 = cls.env["product.product"].create({"name": "Test product 2"}) - cls.partner = cls.env["res.partner"].create({"name": "Test partner"}) - cls.picking = cls.env["stock.picking"].create( - { - "partner_id": cls.partner.id, - "picking_type_id": cls.env.ref("stock.picking_type_out").id, - "location_id": cls.src_location.id, - "location_dest_id": cls.dest_location.id, - } - ) - - def _create_stock_move(product): - return cls.env["stock.move"].create( - { - "name": "/", - "picking_id": cls.picking.id, - "product_id": product.id, - "product_uom_qty": 10, - "product_uom": product.uom_id.id, - "location_id": cls.src_location.id, - "location_dest_id": cls.dest_location.id, - } - ) - - cls.move = _create_stock_move(cls.product) - cls.move_2 = _create_stock_move(cls.product_2) +class TestStockSplitPicking(TestStockSplitPickingCase): def test_stock_split_picking(self): # Picking state is draft self.assertEqual(self.picking.state, "draft") From c389b4424deecf390688b366950eb7f9918ed08e Mon Sep 17 00:00:00 2001 From: Denis Roussel Date: Wed, 11 Dec 2024 14:07:47 +0100 Subject: [PATCH 2/2] [IMP] stock_split_picking: Use specific exceptions --- stock_split_picking/__init__.py | 1 + stock_split_picking/exceptions.py | 33 +++++++++++++++++++++ stock_split_picking/models/stock_picking.py | 12 +++----- 3 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 stock_split_picking/exceptions.py diff --git a/stock_split_picking/__init__.py b/stock_split_picking/__init__.py index 917cba467fff..92c105146b52 100644 --- a/stock_split_picking/__init__.py +++ b/stock_split_picking/__init__.py @@ -3,3 +3,4 @@ from . import models from . import wizards +from . import exceptions diff --git a/stock_split_picking/exceptions.py b/stock_split_picking/exceptions.py new file mode 100644 index 000000000000..cef3e356f513 --- /dev/null +++ b/stock_split_picking/exceptions.py @@ -0,0 +1,33 @@ +# Copyright 2024 ACSONE SA/NV +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import _ +from odoo.exceptions import UserError + + +class SplitPickNotAllowedInStateError(UserError): + """ + Exception class to represent stock picking split error for picking wrong state + """ + + def __init__(self, env, picking): + self.env = env + super().__init__( + _( + "Cannot split picking %(name)s in state %(state)s", + name=picking.name, + state=picking.state, + ) + ) + + +class NotPossibleToSplitPickError(UserError): + """ + Exception class to represent stock picking split error for picking + """ + + def __init__(self, env, picking): + self.env = env + super().__init__( + _("Cannot split off all moves from picking %(name)s", name=picking.name) + ) diff --git a/stock_split_picking/models/stock_picking.py b/stock_split_picking/models/stock_picking.py index beb95edce90c..9e9f3fed3d7d 100644 --- a/stock_split_picking/models/stock_picking.py +++ b/stock_split_picking/models/stock_picking.py @@ -6,6 +6,8 @@ from odoo.exceptions import UserError from odoo.tools.float_utils import float_compare +from ..exceptions import NotPossibleToSplitPickError, SplitPickNotAllowedInStateError + class StockPicking(models.Model): """Adds picking split without done state.""" @@ -100,16 +102,10 @@ def _split_off_moves(self, moves): new_picking = self.env["stock.picking"] for this in self: if this.state in ("done", "cancel"): - raise UserError( - _("Cannot split picking {name} in state {state}").format( - name=this.name, state=this.state - ) - ) + raise SplitPickNotAllowedInStateError(self.env, this) new_picking = new_picking or this._create_split_backorder() if not this.move_ids - moves: - raise UserError( - _("Cannot split off all moves from picking %s") % this.name - ) + raise NotPossibleToSplitPickError(self.env, this) moves.write({"picking_id": new_picking.id}) moves.mapped("move_line_ids").write({"picking_id": new_picking.id}) return new_picking