From 9cf0b2890b85a884cc8fd3beb37c99150178e58e Mon Sep 17 00:00:00 2001 From: Marie Lejeune Date: Tue, 25 Feb 2025 10:20:49 +0100 Subject: [PATCH] [IMP] sale_purchase_force_vendor: propagate on stock rules --- sale_purchase_force_vendor/README.rst | 5 +- sale_purchase_force_vendor/__manifest__.py | 5 +- .../models/stock_move.py | 9 ++- .../readme/CONTRIBUTORS.md | 2 + sale_purchase_force_vendor/readme/USAGE.md | 2 +- .../static/description/index.html | 4 +- .../tests/test_sale_purchase_force_vendor.py | 55 +++++++++++++++++++ 7 files changed, 75 insertions(+), 7 deletions(-) diff --git a/sale_purchase_force_vendor/README.rst b/sale_purchase_force_vendor/README.rst index 34589163fc7..1520b510fb4 100644 --- a/sale_purchase_force_vendor/README.rst +++ b/sale_purchase_force_vendor/README.rst @@ -61,7 +61,8 @@ Usage 1. Go to *Sale -> Orders -> Quotations* and create a new Quotation. 2. Create a new line with the following options: - - \`Route\`: MTO. + - \`Route\`: Any MTO-like route, i.e. a route that will trigger a buy + rule. - \`Vendor\`: Vendor B. 3. Confirm sale order. @@ -96,6 +97,8 @@ Contributors - Víctor Martínez - Pedro M. Baeza +- Marie Lejeune marie.lejeune@acsone.eu + Maintainers ----------- diff --git a/sale_purchase_force_vendor/__manifest__.py b/sale_purchase_force_vendor/__manifest__.py index b67c4caa0f6..7b6f36af7ee 100644 --- a/sale_purchase_force_vendor/__manifest__.py +++ b/sale_purchase_force_vendor/__manifest__.py @@ -7,7 +7,10 @@ "website": "https://github.com/OCA/purchase-workflow", "author": "Tecnativa, Odoo Community Association (OCA)", "license": "AGPL-3", - "depends": ["sale_purchase_stock"], + "depends": [ + "sale_order_line_chained_move", + "sale_purchase_stock", + ], "installable": True, "data": [ "views/res_config_settings_view.xml", diff --git a/sale_purchase_force_vendor/models/stock_move.py b/sale_purchase_force_vendor/models/stock_move.py index 84a38e72dfa..803a1018502 100644 --- a/sale_purchase_force_vendor/models/stock_move.py +++ b/sale_purchase_force_vendor/models/stock_move.py @@ -13,9 +13,12 @@ def _prepare_procurement_values(self): res = super()._prepare_procurement_values() # Get all chained moves to get sale line moves = self.browse(list(self._rollup_move_dests({self.id}))) - move_sale = moves.filtered("sale_line_id")[:1] - if move_sale.sale_line_id.vendor_id: - res_order_line = move_sale.sale_line_id._prepare_procurement_values( + move_sale = moves.filtered(lambda x: x.sale_line_id or x.related_sale_line_id)[ + :1 + ] + related_sale = move_sale.sale_line_id or move_sale.related_sale_line_id + if related_sale.vendor_id: + res_order_line = related_sale._prepare_procurement_values( group_id=move_sale.group_id ) res.update({"supplierinfo_id": res_order_line["supplierinfo_id"]}) diff --git a/sale_purchase_force_vendor/readme/CONTRIBUTORS.md b/sale_purchase_force_vendor/readme/CONTRIBUTORS.md index 5fee3904270..f109b10a09c 100644 --- a/sale_purchase_force_vendor/readme/CONTRIBUTORS.md +++ b/sale_purchase_force_vendor/readme/CONTRIBUTORS.md @@ -1,3 +1,5 @@ - [Tecnativa](https://www.tecnativa.com): - Víctor Martínez - Pedro M. Baeza + +- Marie Lejeune diff --git a/sale_purchase_force_vendor/readme/USAGE.md b/sale_purchase_force_vendor/readme/USAGE.md index de8a7174de0..69affc08fff 100644 --- a/sale_purchase_force_vendor/readme/USAGE.md +++ b/sale_purchase_force_vendor/readme/USAGE.md @@ -1,6 +1,6 @@ 1. Go to *Sale -\> Orders -\> Quotations* and create a new Quotation. 2. Create a new line with the following options: - - \`Route\`: MTO. + - \`Route\`: Any MTO-like route, i.e. a route that will trigger a buy rule. - \`Vendor\`: Vendor B. 3. Confirm sale order. 4. A new purchase order will have been created to Vendor B. diff --git a/sale_purchase_force_vendor/static/description/index.html b/sale_purchase_force_vendor/static/description/index.html index 62da99afece..6f362e83d36 100644 --- a/sale_purchase_force_vendor/static/description/index.html +++ b/sale_purchase_force_vendor/static/description/index.html @@ -411,7 +411,8 @@

Usage

  1. Go to Sale -> Orders -> Quotations and create a new Quotation.
  2. Create a new line with the following options:
      -
    • `Route`: MTO.
    • +
    • `Route`: Any MTO-like route, i.e. a route that will trigger a buy +rule.
    • `Vendor`: Vendor B.
  3. @@ -446,6 +447,7 @@

    Contributors

  4. Pedro M. Baeza
  5. +
  6. Marie Lejeune marie.lejeune@acsone.eu
  7. diff --git a/sale_purchase_force_vendor/tests/test_sale_purchase_force_vendor.py b/sale_purchase_force_vendor/tests/test_sale_purchase_force_vendor.py index 9e414f0b96d..1ae1c454c98 100644 --- a/sale_purchase_force_vendor/tests/test_sale_purchase_force_vendor.py +++ b/sale_purchase_force_vendor/tests/test_sale_purchase_force_vendor.py @@ -1,6 +1,10 @@ # Copyright 2022 Tecnativa - Víctor Martínez # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo.addons.sale_order_line_chained_move.tests.test_chained_move import ( + TestSaleChainedMove as TestSaleOrderLineChainedMoveBase, +) + from .common import TestSalePurchaseForceVendorBase @@ -31,3 +35,54 @@ def test_misc_not_force_vendor_restrict(self): self.sale_order.action_confirm() self.assertEqual(self.sol_a.vendor_id_domain, []) self.assertEqual(self.sol_b.vendor_id_domain, []) + + +class TestSalePurchaseForceVendorChainedMove(TestSaleOrderLineChainedMoveBase): + """ + This class makes a test with another route than the default Odoo MTO route. + It uses the route defined in sale_order_line_chained_move, which is a + 3-steps delivery: Pick/Pack/Ship. + """ + + def test_force_vendor_on_mto_like_route(self): + """ + Test that the vendor is correctly forced on a PO even on a more + complicated MTO-like route. + We configure the rules of the route as following: + Out -> Customer: pull; make_to_order + Pack -> Out: pull; make_to_order + Stock -> Pack: pull; make_to_order + In Stock: buy route + The 3 first rules are defined in sale_order_line_chained_move test class. + We add the buy route in this test. + """ + self.stock_out_rule.procure_method = "make_to_order" + self.env["stock.rule"].create( + { + "name": "Buy", + "route_id": self.route.id, + "action": "buy", + "location_dest_id": self.env.ref("stock.stock_location_stock").id, + "picking_type_id": self.env.ref("stock.picking_type_in").id, + } + ) + vendor_a = self.env["res.partner"].create({"name": "Test Vendor A"}) + vendor_b = self.env["res.partner"].create({"name": "Test Vendor B"}) + self.product1.seller_ids = [ + (0, 0, {"partner_id": vendor_a.id, "min_qty": 1, "price": 10}), + (0, 0, {"partner_id": vendor_b.id, "min_qty": 1, "price": 20}), + ] + so = self.env["sale.order"].create( + { + "partner_id": self.env["res.partner"] + .create({"name": "Test Customer"}) + .id, + "order_line": [ + (0, 0, {"product_id": self.product1.id, "vendor_id": vendor_b.id}) + ], + } + ) + so.action_confirm() + po = so._get_purchase_orders() + self.assertEqual(len(po), 1, "A purchase order should have been created") + self.assertEqual(po.partner_id, vendor_b)