diff --git a/purchase_split_by_route/README.rst b/purchase_split_by_route/README.rst new file mode 100644 index 00000000000..4079991c57b --- /dev/null +++ b/purchase_split_by_route/README.rst @@ -0,0 +1,85 @@ +==================== +Purchase Split Route +==================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:1679d1ffb6e608db2dac3887451673e17077113039e4bb701b2159d3bf55b06c + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fpurchase--workflow-lightgray.png?logo=github + :target: https://github.com/OCA/purchase-workflow/tree/16.0/purchase_split_by_route + :alt: OCA/purchase-workflow +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/purchase-workflow-16-0/purchase-workflow-16-0-purchase_split_by_route + :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/purchase-workflow&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows you to separate automatic purchases by sale order route + +**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 +~~~~~~~ + +* Akretion + +Contributors +~~~~~~~~~~~~ + +* `Akretion `_: + * Mathieu DELVA + +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. + +.. |maintainer-mathieudelva| image:: https://github.com/mathieudelva.png?size=40px + :target: https://github.com/mathieudelva + :alt: mathieudelva + +Current `maintainer `__: + +|maintainer-mathieudelva| + +This module is part of the `OCA/purchase-workflow `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/purchase_split_by_route/__init__.py b/purchase_split_by_route/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/purchase_split_by_route/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/purchase_split_by_route/__manifest__.py b/purchase_split_by_route/__manifest__.py new file mode 100644 index 00000000000..6c811d632f8 --- /dev/null +++ b/purchase_split_by_route/__manifest__.py @@ -0,0 +1,18 @@ +# Copyright 2024 Akretion France (http://www.akretion.com/) +# @author: Mathieu Delva +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Purchase Split Route", + "summary": """""", + "version": "16.0.1.0.0", + "license": "AGPL-3", + "maintainers": ["mathieudelva"], + "author": "Akretion,Odoo Community Association (OCA)", + "website": "https://github.com/OCA/purchase-workflow", + "depends": [ + "purchase_stock", + "sale_order_global_stock_route", + "stock_mts_mto_rule", + ], +} diff --git a/purchase_split_by_route/models/__init__.py b/purchase_split_by_route/models/__init__.py new file mode 100644 index 00000000000..7fefd289cf6 --- /dev/null +++ b/purchase_split_by_route/models/__init__.py @@ -0,0 +1,2 @@ +from . import purchase_order +from . import stock_rule diff --git a/purchase_split_by_route/models/purchase_order.py b/purchase_split_by_route/models/purchase_order.py new file mode 100644 index 00000000000..379e07967fa --- /dev/null +++ b/purchase_split_by_route/models/purchase_order.py @@ -0,0 +1,29 @@ +# Copyright 2024 Akretion France (http://www.akretion.com/) +# @author: Mathieu Delva +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class PurchaseOrder(models.Model): + _inherit = "purchase.order" + + default_route_id = fields.Many2one("stock.route", store=True) + + +class PurchaseOrderLine(models.Model): + _inherit = "purchase.order.line" + + @api.model + def _prepare_purchase_order_line_from_procurement( + self, product_id, product_qty, product_uom, company_id, values, po + ): + vals = super()._prepare_purchase_order_line_from_procurement( + product_id, product_qty, product_uom, company_id, values, po + ) + origin = values["move_dest_ids"].origin + order_id = self.env["sale.order"].search([("name", "=", origin)]) + if order_id: + po.default_route_id = order_id.route_id.id + + return vals diff --git a/purchase_split_by_route/models/stock_rule.py b/purchase_split_by_route/models/stock_rule.py new file mode 100644 index 00000000000..594fbaddbb0 --- /dev/null +++ b/purchase_split_by_route/models/stock_rule.py @@ -0,0 +1,38 @@ +# Copyright (C) 2024 Akretion (). +# @author Mathieu Delva +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import models + + +class StockRule(models.Model): + _inherit = "stock.rule" + + def _make_po_get_domain(self, company_id, values, partner): + """ """ + domain = super()._make_po_get_domain(company_id, values, partner) + if "move_dest_ids" in values: + origin = values["move_dest_ids"].origin + order_id = self.env["sale.order"].search([("name", "=", origin)]) + if order_id: + # import pdb + # pdb.set_trace() + values["group_id"] = False + default_route_id = order_id.route_id + domain = tuple(filter(lambda r: r[0] != "group_id", domain)) + domain += ( + ( + "default_route_id", + "=", + default_route_id.id, + ), + ) + # elif "orderpoint_id" in values: + # domain += ( + # ( + # "manufacturer_id", + # "=", + # values["orderpoint_id"].product_id.manufacturer_id.id, + # ), + # ) + return domain diff --git a/purchase_split_by_route/readme/CONTRIBUTORS.rst b/purchase_split_by_route/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000000..b2327a82951 --- /dev/null +++ b/purchase_split_by_route/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* `Akretion `_: + * Mathieu DELVA \ No newline at end of file diff --git a/purchase_split_by_route/readme/DESCRIPTION.rst b/purchase_split_by_route/readme/DESCRIPTION.rst new file mode 100644 index 00000000000..b08ac48f2de --- /dev/null +++ b/purchase_split_by_route/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module allows you to separate automatic purchases by sale order route \ No newline at end of file diff --git a/purchase_split_by_route/static/description/index.html b/purchase_split_by_route/static/description/index.html new file mode 100644 index 00000000000..3f3e74735b1 --- /dev/null +++ b/purchase_split_by_route/static/description/index.html @@ -0,0 +1,432 @@ + + + + + +Purchase Split Route + + + +
+

Purchase Split Route

+ + +

Beta License: AGPL-3 OCA/purchase-workflow Translate me on Weblate Try me on Runboat

+

This module allows you to separate automatic purchases by sale order route

+

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

+
    +
  • Akretion
  • +
+
+
+

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.

+

Current maintainer:

+

mathieudelva

+

This module is part of the OCA/purchase-workflow project on GitHub.

+

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

+
+
+
+ + diff --git a/purchase_split_by_route/tests/__init__.py b/purchase_split_by_route/tests/__init__.py new file mode 100644 index 00000000000..e68736b91f5 --- /dev/null +++ b/purchase_split_by_route/tests/__init__.py @@ -0,0 +1 @@ +from . import test_purchase_route diff --git a/purchase_split_by_route/tests/test_purchase_route.py b/purchase_split_by_route/tests/test_purchase_route.py new file mode 100644 index 00000000000..bd8818350c3 --- /dev/null +++ b/purchase_split_by_route/tests/test_purchase_route.py @@ -0,0 +1,132 @@ +# Copyright 2024 Akretion France (http://www.akretion.com/) +# @author: Mathieu Delva +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.tests.common import TransactionCase + + +class TestPurchasePackaging(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) + cls.line_obj = cls.env["purchase.order.line"] + cls.partner = cls.env.ref("base.res_partner_12") + cls.product = cls.env.ref("product.product_product_9") + cls.env.user.groups_id += cls.env.ref("stock.group_adv_location") + cls.warehouse = cls.env.ref("stock.warehouse0") + cls.warehouse.mto_mts_management = True + cls.route1 = cls.env.ref("stock_mts_mto_rule.route_mto_mts") + cls.route2 = cls.env.ref("purchase_stock.route_warehouse0_buy") + cls.sale_route1 = cls.env["stock.route"].create({"name": "Sale Route1"}) + cls.sale_route2 = cls.env["stock.route"].create({"name": "Sale Route2"}) + cls.vendor_id = cls.env.ref("base.res_partner_12") + cls.currency_id = cls.env.ref("base.EUR") + cls.product_id = cls.env["product.template"].create( + { + "name": "Test Packaging", + "sale_ok": True, + "purchase_ok": True, + "detailed_type": "product", + "route_ids": [(6, 0, [cls.route1.id, cls.route2.id])], + "seller_ids": [ + ( + 0, + 0, + { + "partner_id": cls.vendor_id.id, + "price": 10, + "currency_id": cls.currency_id.id, + "delay": 1, + }, + ) + ], + } + ) + cls.env["res.config.settings"].create( + { + "group_stock_adv_location": True, + "group_stock_multi_locations": True, + "group_stock_packaging": True, + } + ).execute() + + def test_sale_order_with_multiple_route(self): + product_variant_id = self.product_id.product_variant_id + sale_order1 = self.env["sale.order"].create( + { + "partner_id": self.partner.id, + "route_id": self.sale_route1.id, + "order_line": [ + ( + 0, + 0, + { + "product_id": product_variant_id.id, + "product_uom_qty": 5, + }, + ), + ], + } + ) + sale_order1.action_confirm() + sale_order2 = self.env["sale.order"].create( + { + "partner_id": self.partner.id, + "route_id": self.sale_route2.id, + "order_line": [ + ( + 0, + 0, + { + "product_id": product_variant_id.id, + "product_uom_qty": 5, + }, + ), + ], + } + ) + sale_order2.action_confirm() + purchase_ids1 = sale_order1._get_purchase_orders() + purchase_ids2 = sale_order2._get_purchase_orders() + self.assertNotEqual(purchase_ids1.id, purchase_ids2.id) + + def test_sale_order_with_same_route(self): + product_variant_id = self.product_id.product_variant_id + sale_order1 = self.env["sale.order"].create( + { + "partner_id": self.partner.id, + "route_id": self.sale_route1.id, + "order_line": [ + ( + 0, + 0, + { + "product_id": product_variant_id.id, + "product_uom_qty": 5, + }, + ), + ], + } + ) + sale_order1.action_confirm() + sale_order2 = self.env["sale.order"].create( + { + "partner_id": self.partner.id, + "route_id": self.sale_route1.id, + "order_line": [ + ( + 0, + 0, + { + "product_id": product_variant_id.id, + "product_uom_qty": 5, + }, + ), + ], + } + ) + sale_order2.action_confirm() + purchase_ids1 = sale_order1._get_purchase_orders() + purchase_ids2 = sale_order2._get_purchase_orders() + self.assertEqual(purchase_ids1.id, purchase_ids2.id) diff --git a/setup/purchase_split_by_route/odoo/addons/purchase_split_by_route b/setup/purchase_split_by_route/odoo/addons/purchase_split_by_route new file mode 120000 index 00000000000..033c6c8960e --- /dev/null +++ b/setup/purchase_split_by_route/odoo/addons/purchase_split_by_route @@ -0,0 +1 @@ +../../../../purchase_split_by_route \ No newline at end of file diff --git a/setup/purchase_split_by_route/setup.py b/setup/purchase_split_by_route/setup.py new file mode 100644 index 00000000000..28c57bb6403 --- /dev/null +++ b/setup/purchase_split_by_route/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)