From c053ed14effe2a25e4e300213f2cdb19f58ac4b1 Mon Sep 17 00:00:00 2001 From: Marina Alapont Date: Tue, 9 Apr 2024 11:19:00 +0200 Subject: [PATCH] [ADD] stock_move_location_purchase_uom --- .../addons/stock_move_location_purchase_uom | 1 + .../stock_move_location_purchase_uom/setup.py | 6 + stock_move_location_purchase_uom/README.rst | 79 ++++ stock_move_location_purchase_uom/__init__.py | 1 + .../__manifest__.py | 16 + .../readme/CONTRIBUTORS.rst | 1 + .../readme/DESCRIPTION.rst | 4 + .../static/description/index.html | 425 ++++++++++++++++++ .../tests/__init__.py | 1 + .../tests/test_move_location_purchase_uom.py | 122 +++++ .../wizard/__init__.py | 4 + .../wizard/stock_move_location.py | 53 +++ 12 files changed, 713 insertions(+) create mode 120000 setup/stock_move_location_purchase_uom/odoo/addons/stock_move_location_purchase_uom create mode 100644 setup/stock_move_location_purchase_uom/setup.py create mode 100644 stock_move_location_purchase_uom/README.rst create mode 100644 stock_move_location_purchase_uom/__init__.py create mode 100644 stock_move_location_purchase_uom/__manifest__.py create mode 100644 stock_move_location_purchase_uom/readme/CONTRIBUTORS.rst create mode 100644 stock_move_location_purchase_uom/readme/DESCRIPTION.rst create mode 100644 stock_move_location_purchase_uom/static/description/index.html create mode 100644 stock_move_location_purchase_uom/tests/__init__.py create mode 100644 stock_move_location_purchase_uom/tests/test_move_location_purchase_uom.py create mode 100644 stock_move_location_purchase_uom/wizard/__init__.py create mode 100644 stock_move_location_purchase_uom/wizard/stock_move_location.py diff --git a/setup/stock_move_location_purchase_uom/odoo/addons/stock_move_location_purchase_uom b/setup/stock_move_location_purchase_uom/odoo/addons/stock_move_location_purchase_uom new file mode 120000 index 000000000000..17db3493b613 --- /dev/null +++ b/setup/stock_move_location_purchase_uom/odoo/addons/stock_move_location_purchase_uom @@ -0,0 +1 @@ +../../../../stock_move_location_purchase_uom \ No newline at end of file diff --git a/setup/stock_move_location_purchase_uom/setup.py b/setup/stock_move_location_purchase_uom/setup.py new file mode 100644 index 000000000000..28c57bb64031 --- /dev/null +++ b/setup/stock_move_location_purchase_uom/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/stock_move_location_purchase_uom/README.rst b/stock_move_location_purchase_uom/README.rst new file mode 100644 index 000000000000..e9388e8db916 --- /dev/null +++ b/stock_move_location_purchase_uom/README.rst @@ -0,0 +1,79 @@ +================================ +Move Stock Location Purchase UoM +================================ + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:cbb3ddaaf3f033fa78193497c0e75c1dd22033897a89e39f04124f5e5b12cb3d + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |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%2Fstock--logistics--warehouse-lightgray.png?logo=github + :target: https://github.com/OCA/stock-logistics-warehouse/tree/15.0/stock_move_location_purchase_uom + :alt: OCA/stock-logistics-warehouse +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/stock-logistics-warehouse-15-0/stock-logistics-warehouse-15-0-stock_move_location_purchase_uom + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/stock-logistics-warehouse&target_branch=15.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module is a 'glue' module for the modules stock_move_location and stock_move_purchase_uom. +If an operation type has the option "use purchase uom" enabled, when creating a transfer for that +operation using the "Move to location" button, the uom of the products in the transfer will be set +to the purchase uom of the products. + +**Table of contents** + +.. contents:: + :local: + +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 to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* ForgeFlow + +Contributors +~~~~~~~~~~~~ + + * Marina Alapont + +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/stock-logistics-warehouse `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_move_location_purchase_uom/__init__.py b/stock_move_location_purchase_uom/__init__.py new file mode 100644 index 000000000000..40272379f721 --- /dev/null +++ b/stock_move_location_purchase_uom/__init__.py @@ -0,0 +1 @@ +from . import wizard diff --git a/stock_move_location_purchase_uom/__manifest__.py b/stock_move_location_purchase_uom/__manifest__.py new file mode 100644 index 000000000000..47e3b3775263 --- /dev/null +++ b/stock_move_location_purchase_uom/__manifest__.py @@ -0,0 +1,16 @@ +# Copyright 2024 ForgeFlow S.L. (https://www.forgeflow.com) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +{ + "name": "Move Stock Location Purchase UoM", + "version": "15.0.1.0.0", + "author": "ForgeFlow, Odoo Community Association (OCA)", + "summary": "This module 'glues' the modules stock_move_location" + " and stock_move_purchase_uom.", + "website": "https://github.com/OCA/stock-logistics-warehouse", + "license": "AGPL-3", + "depends": ["stock_move_location", "stock_move_purchase_uom"], + "category": "Stock", + "data": [], + "installable": True, +} diff --git a/stock_move_location_purchase_uom/readme/CONTRIBUTORS.rst b/stock_move_location_purchase_uom/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000000..45857503aff0 --- /dev/null +++ b/stock_move_location_purchase_uom/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ + * Marina Alapont diff --git a/stock_move_location_purchase_uom/readme/DESCRIPTION.rst b/stock_move_location_purchase_uom/readme/DESCRIPTION.rst new file mode 100644 index 000000000000..df7f6cca208f --- /dev/null +++ b/stock_move_location_purchase_uom/readme/DESCRIPTION.rst @@ -0,0 +1,4 @@ +This module is a 'glue' module for the modules stock_move_location and stock_move_purchase_uom. +If an operation type has the option "use purchase uom" enabled, when creating a transfer for that +operation using the "Move to location" button, the uom of the products in the transfer will be set +to the purchase uom of the products. diff --git a/stock_move_location_purchase_uom/static/description/index.html b/stock_move_location_purchase_uom/static/description/index.html new file mode 100644 index 000000000000..e7147b616567 --- /dev/null +++ b/stock_move_location_purchase_uom/static/description/index.html @@ -0,0 +1,425 @@ + + + + + +Move Stock Location Purchase UoM + + + +
+

Move Stock Location Purchase UoM

+ + +

Beta License: AGPL-3 OCA/stock-logistics-warehouse Translate me on Weblate Try me on Runboat

+

This module is a ‘glue’ module for the modules stock_move_location and stock_move_purchase_uom. +If an operation type has the option “use purchase uom” enabled, when creating a transfer for that +operation using the “Move to location” button, the uom of the products in the transfer will be set +to the purchase uom of the products.

+

Table of contents

+ +
+

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 to smash it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • ForgeFlow
  • +
+
+
+

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/stock-logistics-warehouse project on GitHub.

+

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

+
+
+
+ + diff --git a/stock_move_location_purchase_uom/tests/__init__.py b/stock_move_location_purchase_uom/tests/__init__.py new file mode 100644 index 000000000000..df479e4c7cd1 --- /dev/null +++ b/stock_move_location_purchase_uom/tests/__init__.py @@ -0,0 +1 @@ +from . import test_move_location_purchase_uom diff --git a/stock_move_location_purchase_uom/tests/test_move_location_purchase_uom.py b/stock_move_location_purchase_uom/tests/test_move_location_purchase_uom.py new file mode 100644 index 000000000000..f03762d57c9b --- /dev/null +++ b/stock_move_location_purchase_uom/tests/test_move_location_purchase_uom.py @@ -0,0 +1,122 @@ +# Copyright 2024 ForgeFlow S.L. (https://www.forgeflow.com) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo.tests import common + + +class TestMoveLocationPurchaseUom(common.TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.location_obj = cls.env["stock.location"] + product_obj = cls.env["product.product"] + cls.wizard_obj = cls.env["wiz.stock.move.location"] + cls.quant_obj = cls.env["stock.quant"] + cls.company = cls.env.ref("base.main_company") + cls.partner = cls.env.ref("base.res_partner_category_0") + + cls.internal_loc_1 = cls.location_obj.create( + { + "name": "INT_1", + "usage": "internal", + "active": True, + "company_id": cls.company.id, + } + ) + cls.internal_loc_2 = cls.location_obj.create( + { + "name": "INT_2", + "usage": "internal", + "active": True, + "company_id": cls.company.id, + } + ) + cls.stock_picking_type = cls.env["stock.picking.type"].create( + { + "name": "Internal transfer 2", + "code": "internal", + "sequence_code": "INT2", + "use_purchase_uom": True, + } + ) + cls.uom_unit = cls.env.ref("uom.product_uom_unit") + cls.product = product_obj.create( + { + "name": "Test", + "type": "product", + } + ) + + cls.set_product_amount(cls.product, cls.internal_loc_1, 70) + + @classmethod + def set_product_amount( + cls, product, location, amount, lot_id=None, package_id=None, owner_id=None + ): + cls.env["stock.quant"]._update_available_quantity( + product, + location, + amount, + lot_id=lot_id, + package_id=package_id, + owner_id=owner_id, + ) + + @classmethod + def _create_wizard(cls, origin_location, destination_location): + move_location_wizard = cls.env["wiz.stock.move.location"] + return move_location_wizard.create( + { + "origin_location_id": origin_location.id, + "destination_location_id": destination_location.id, + } + ) + + def test_move_location_purchase_uom(self): + wizard = self._create_wizard(self.internal_loc_1, self.internal_loc_2) + wizard.onchange_origin_location() + self.assertEqual(len(wizard.stock_move_location_line_ids), 1) + line = wizard.stock_move_location_line_ids[0] + self.assertEqual(line.product_uom_id, self.product.uom_id) + original_picking_type = wizard.picking_type_id + + # Change the picking type to one that must use purchase uom + wizard.picking_type_id = self.stock_picking_type + wizard._onchange_picking_type_id() + + # Check that the uom and quantities have changed + original_uom = line.product_uom_id + original_move_qty = line.move_quantity + original_max_qty = line.max_quantity + original_reserved_qty = line.reserved_quantity + expected_move_quantity = original_uom._compute_quantity( + original_move_qty, self.product.uom_po_id + ) + expected_max_quantity = original_uom._compute_quantity( + original_max_qty, self.product.uom_po_id + ) + expected_reserved_quantity = original_uom._compute_quantity( + original_reserved_qty, self.product.uom_po_id + ) + self.assertEqual(line.product_uom_id, self.product.uom_po_id) + self.assertEqual(line.move_quantity, expected_move_quantity) + self.assertEqual(line.max_quantity, expected_max_quantity) + self.assertEqual(line.reserved_quantity, expected_reserved_quantity) + + # Change again to the first picking type that does not use purchase uom + wizard.picking_type_id = original_picking_type + wizard._onchange_picking_type_id() + self.assertEqual(line.product_uom_id, self.product.uom_id) + self.assertEqual(line.move_quantity, original_move_qty) + self.assertEqual(line.max_quantity, original_max_qty) + self.assertEqual(line.reserved_quantity, original_reserved_qty) + + # Check the creation of the move with a picking type using purchase uom + wizard.picking_type_id = self.stock_picking_type + wizard._onchange_picking_type_id() + wizard.action_move_location() + picking = wizard.picking_id + self.assertEqual(len(picking.move_line_ids), 1) + picking_line = picking.move_line_ids[0] + self.assertEqual(picking_line.product_uom_id, self.product.uom_po_id) + self.assertEqual(picking_line.qty_done, expected_move_quantity) diff --git a/stock_move_location_purchase_uom/wizard/__init__.py b/stock_move_location_purchase_uom/wizard/__init__.py new file mode 100644 index 000000000000..b8affa0eadad --- /dev/null +++ b/stock_move_location_purchase_uom/wizard/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2024 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from . import stock_move_location diff --git a/stock_move_location_purchase_uom/wizard/stock_move_location.py b/stock_move_location_purchase_uom/wizard/stock_move_location.py new file mode 100644 index 000000000000..65b559ea8d22 --- /dev/null +++ b/stock_move_location_purchase_uom/wizard/stock_move_location.py @@ -0,0 +1,53 @@ +# Copyright 2024 ForgeFlow S.L. (https://www.forgeflow.com) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo import api, models + + +class StockMoveLocationWizard(models.TransientModel): + _inherit = "wiz.stock.move.location" + + @api.onchange("picking_type_id") + def _onchange_picking_type_id(self): + for line in self.stock_move_location_line_ids: + product_uom = line.product_id.uom_id + purchase_uom = line.product_id.uom_po_id + original_uom = line.product_uom_id + + # If the picking type has the 'use_purchase_uom' enabled, + # set the uom to the product purchase one + if self.picking_type_id.use_purchase_uom: + new_uom = purchase_uom + # Else, set the uom to the product uom again + else: + new_uom = product_uom + + if original_uom != new_uom: + line.move_quantity = original_uom._compute_quantity( + line.move_quantity, new_uom + ) + line.max_quantity = original_uom._compute_quantity( + line.max_quantity, new_uom + ) + line.reserved_quantity = original_uom._compute_quantity( + line.reserved_quantity, new_uom + ) + line.product_uom_id = new_uom + + def _get_move_values(self, picking, lines): + res = super()._get_move_values(picking, lines) + picking_id = res["picking_id"] + picking = self.env["stock.picking"].search([("id", "=", picking_id)]) + if picking.picking_type_id.use_purchase_uom: + original_uom_id = res["product_uom"] + original_uom = self.env["uom.uom"].search([("id", "=", original_uom_id)]) + original_qty = res["product_uom_qty"] + product_id = res["product_id"] + product = self.env["product.product"].search([("id", "=", product_id)]) + + new_uom = product.uom_po_id + new_qty = original_uom._compute_quantity(original_qty, new_uom) + res["product_uom_qty"] = new_qty + res["product_uom"] = new_uom.id + + return res