From 86959e58650ae7f310da32a79c083865cab9ba8f Mon Sep 17 00:00:00 2001 From: MerlinGuillaume Date: Mon, 20 Jun 2022 07:21:01 +0000 Subject: [PATCH] [FIX] purchase_requisition_stock: alternative's RFQ delivery address When generating an alternative request for quotation from a dropship purchase, the delivery address is not copied Steps to reproduce: 1. Install Sales and stock_dropshipping module 2. Go to Settings > General Settings > Users > Manage Users, open user Mitchell Admin and in the Access Rights tab enable 'Manage Multiple Stock Locations' 3. Go to Settings > Sales > Quotations & Orders and enable Customer Addresses 4. Go to Settings > Purchase > Orders and enable Purchase Agreements 5. Go to Sales > Products > Products and edit a product (e.g. 'Acoustic Bloc Screens') - In the Inventory tab enable routes 'Buy' and 'Dropship' 6. Create a Sale Order for this product with a different Delivery Address then the Customer and confirm it 7. Go to the purchase order 8. In the Alternatives tab create an alternative 9. The Dropship Address is not repercuted on the new RFQ Solution: Add a method `_get_alternative_values` which sets the dest_address_id and is extended in `purchase_requisition_stock` to add the picking_type_id opw-2880042 closes odoo/odoo#94109 X-original-commit: a7ef5d93650c262497d3a02b934284829cfc5021 Signed-off-by: Adrien Widart Signed-off-by: Guillaume Merlin (megu) --- ...purchase_requisition_create_alternative.py | 19 +++++--- addons/purchase_requisition_stock/__init__.py | 1 + .../tests/test_purchase_requisition_stock.py | 48 +++++++++++++++++++ .../wizard/__init__.py | 1 + ...purchase_requisition_create_alternative.py | 13 +++++ 5 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 addons/purchase_requisition_stock/wizard/__init__.py create mode 100644 addons/purchase_requisition_stock/wizard/purchase_requisition_create_alternative.py diff --git a/addons/purchase_requisition/wizard/purchase_requisition_create_alternative.py b/addons/purchase_requisition/wizard/purchase_requisition_create_alternative.py index f4c0c93b78a..3a140744234 100644 --- a/addons/purchase_requisition/wizard/purchase_requisition_create_alternative.py +++ b/addons/purchase_requisition/wizard/purchase_requisition_create_alternative.py @@ -58,13 +58,7 @@ class PurchaseRequisitionCreateAlternative(models.TransientModel): _('The vendor you have selected or at least one of the products you are copying from the original ' 'order has a blocking warning on it and cannot be selected to create an alternative.') ) - vals = { - 'date_order': self.origin_po_id.date_order, - 'partner_id': self.partner_id.id, - 'user_id': self.origin_po_id.user_id.id, - } - if self.copy_products and self.origin_po_id: - vals['order_line'] = [Command.create({'product_id': line.product_id.id, 'product_qty': line.product_qty}) for line in self.origin_po_id.order_line] + vals = self._get_alternative_values() alt_po = self.env['purchase.order'].with_context(origin_po_id=self.origin_po_id.id).create(vals) return { 'type': 'ir.actions.act_window', @@ -75,3 +69,14 @@ class PurchaseRequisitionCreateAlternative(models.TransientModel): 'active_id': alt_po.id, }, } + + def _get_alternative_values(self): + vals = { + 'date_order': self.origin_po_id.date_order, + 'partner_id': self.partner_id.id, + 'user_id': self.origin_po_id.user_id.id, + 'dest_address_id': self.origin_po_id.dest_address_id.id, + } + if self.copy_products and self.origin_po_id: + vals['order_line'] = [Command.create({'product_id': line.product_id.id, 'product_qty': line.product_qty}) for line in self.origin_po_id.order_line] + return vals diff --git a/addons/purchase_requisition_stock/__init__.py b/addons/purchase_requisition_stock/__init__.py index d6210b1285d..33bbab569d0 100644 --- a/addons/purchase_requisition_stock/__init__.py +++ b/addons/purchase_requisition_stock/__init__.py @@ -1,3 +1,4 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from . import models +from . import wizard diff --git a/addons/purchase_requisition_stock/tests/test_purchase_requisition_stock.py b/addons/purchase_requisition_stock/tests/test_purchase_requisition_stock.py index 0cf2d7668b9..738eb40f651 100644 --- a/addons/purchase_requisition_stock/tests/test_purchase_requisition_stock.py +++ b/addons/purchase_requisition_stock/tests/test_purchase_requisition_stock.py @@ -2,6 +2,7 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo.addons.purchase_requisition.tests.common import TestPurchaseRequisitionCommon +from odoo.tests import Form class TestPurchaseRequisitionStock(TestPurchaseRequisitionCommon): @@ -195,3 +196,50 @@ class TestPurchaseRequisitionStock(TestPurchaseRequisitionCommon): ('product_qty', '=', 5.0), ]) self.assertEqual(order_line.price_unit, 50, 'The supplier info chosen should be the one without requisition id') + + def test_04_purchase_requisition_stock(self): + """Check that alt PO correctly copies the original PO values""" + # create original PO + orig_po = self.env['purchase.order'].create({ + 'partner_id': self.res_partner_1.id, + 'picking_type_id': self.env['stock.picking.type'].search([['code', '=', 'outgoing']], limit=1).id, + 'dest_address_id': self.env['res.partner'].create({'name': 'delivery_partner'}).id, + }) + unit_price = 50 + po_form = Form(orig_po) + with po_form.order_line.new() as line: + line.product_id = self.product_09 + line.product_qty = 5.0 + line.price_unit = unit_price + po_form.save() + + # create an alt PO + action = orig_po.action_create_alternative() + alt_po_wiz = Form(self.env['purchase.requisition.create.alternative'].with_context(**action['context'])) + alt_po_wiz.partner_id = self.res_partner_1 + alt_po_wiz.copy_products = True + alt_po_wiz = alt_po_wiz.save() + alt_po_wiz.action_create_alternative() + + # check alt PO was created with correct values + alt_po = orig_po.alternative_po_ids.filtered(lambda po: po.id != orig_po.id) + self.assertEqual(orig_po.picking_type_id, alt_po.picking_type_id, + "Alternative PO should have copied the picking type from original PO") + self.assertEqual(orig_po.dest_address_id, alt_po.dest_address_id, + "Alternative PO should have copied the destination address from original PO") + self.assertEqual(orig_po.order_line.product_id, alt_po.order_line.product_id, + "Alternative PO should have copied the product to purchase from original PO") + self.assertEqual(orig_po.order_line.product_qty, alt_po.order_line.product_qty, + "Alternative PO should have copied the qty to purchase from original PO") + self.assertEqual(len(alt_po.alternative_po_ids), 2, + "Newly created PO should be auto-linked to itself and original PO") + + # confirm the alt PO, original PO should be cancelled + action = alt_po.button_confirm() + warning_wiz = Form( + self.env['purchase.requisition.alternative.warning'].with_context(**action['context'])) + warning_wiz = warning_wiz.save() + self.assertEqual(warning_wiz.alternative_po_count, 1, + "POs not in a RFQ status should not be listed as possible to cancel") + warning_wiz.action_cancel_alternatives() + self.assertEqual(orig_po.state, 'cancel', "Original PO should have been cancelled") diff --git a/addons/purchase_requisition_stock/wizard/__init__.py b/addons/purchase_requisition_stock/wizard/__init__.py new file mode 100644 index 00000000000..0b9e53dd591 --- /dev/null +++ b/addons/purchase_requisition_stock/wizard/__init__.py @@ -0,0 +1 @@ +from . import purchase_requisition_create_alternative diff --git a/addons/purchase_requisition_stock/wizard/purchase_requisition_create_alternative.py b/addons/purchase_requisition_stock/wizard/purchase_requisition_create_alternative.py new file mode 100644 index 00000000000..cfb92ff9f44 --- /dev/null +++ b/addons/purchase_requisition_stock/wizard/purchase_requisition_create_alternative.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import models + + +class PurchaseRequisitionCreateAlternative(models.TransientModel): + _inherit = 'purchase.requisition.create.alternative' + + def _get_alternative_values(self): + vals = super(PurchaseRequisitionCreateAlternative, self)._get_alternative_values() + vals['picking_type_id'] = self.origin_po_id.picking_type_id.id + return vals