From f9c66ff20f2e7d8d35b9bc775486bb62abd4c367 Mon Sep 17 00:00:00 2001
From: "Hamza (hisl)" <hisl@odoo.com>
Date: Thu, 24 Aug 2023 14:11:15 +0300
Subject: [PATCH] [FIX] purchase: correct currency for purchase_order_line

If the currency_id and cost_currency_id is different for a product, the cost in the purchase order is wrong. The purchase order should use cost_currency_id instead of currency_id.

Steps to reproduce on runbot:
-Set the currency of main company as Dollars (USD).
-Choose in runbot the company "My Belgian Company" as its currency is Euro.
- Add the currency rate of today between EUR and USD
- Take a product and edit the cost to 100 EUR - as the cost field is linked with the currency of the company
make sure on the tab purchase there is no information - so the vendor pricelist is not present.
- Go inside the purchase module and start a request for a quotation
leave the currency as EUR
- Select the product to purchase

Current Behavior:
The unit price will be (100*currency rate). If you do the same but take the currency as USD the product unit price on the purchase order line will be 100

Expected Behavior:
The unit price should have been 100 Euros. And when dollar is chosen as currency, the exchange should have been applied.

OPW-3460551

closes odoo/odoo#133024

Signed-off-by: Tiffany Chang (tic) <tic@odoo.com>
---
 addons/purchase/models/purchase.py     |  2 +-
 addons/purchase/tests/test_purchase.py | 48 +++++++++++++++++++++++++-
 2 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/addons/purchase/models/purchase.py b/addons/purchase/models/purchase.py
index 2237a985de3e..482d177b19c6 100644
--- a/addons/purchase/models/purchase.py
+++ b/addons/purchase/models/purchase.py
@@ -1246,7 +1246,7 @@ class PurchaseOrderLine(models.Model):
                     line.taxes_id,
                     line.company_id,
                 )
-                price_unit = line.product_id.currency_id._convert(
+                price_unit = line.product_id.cost_currency_id._convert(
                     price_unit,
                     line.currency_id,
                     line.company_id,
diff --git a/addons/purchase/tests/test_purchase.py b/addons/purchase/tests/test_purchase.py
index 1977e2423bf8..5215dc9bfbcc 100644
--- a/addons/purchase/tests/test_purchase.py
+++ b/addons/purchase/tests/test_purchase.py
@@ -291,9 +291,12 @@ class TestPurchase(AccountTestInvoicingCommon):
         pol.product_qty += 1
         self.assertEqual(pol.name, "New custom description")
 
-    def test_unit_price_precision_multicurrency(self):
+    def test_purchase_multicurrency(self):
         """
         Purchase order lines should keep unit price precision of products
+        Also the products having prices in different currencies should be
+        correctly handled when creating a purchase order i-e product having a price of 100 usd
+        and when purchasing in EUR company the correct conversion should be applied
         """
         self.env['decimal.precision'].search([
             ('name', '=', 'Product Price'),
@@ -334,6 +337,49 @@ class TestPurchase(AccountTestInvoicingCommon):
         purchase_order_coco = po_form.save()
         self.assertEqual(purchase_order_coco.order_line.price_unit, currency_rate.rate * product.standard_price, "Value shouldn't be rounded 🍫")
 
+        #check if the correct currency is set on the purchase order by comparing the expected price and actual price
+
+        company_a = self.company_data['company']
+        company_b = self.company_data_2['company']
+
+        company_b.currency_id = currency
+
+        self.env['res.currency.rate'].create({
+            'name': '2023-01-01',
+            'rate': 2,
+            'currency_id': currency.id,
+            'company_id': company_b.id,
+        })
+
+        product_b = self.env['product.product'].with_company(company_a).create({
+            'name': 'product_2',
+            'uom_id': self.env.ref('uom.product_uom_unit').id,
+            'standard_price': 0.0,
+        })
+
+        self.assertEqual(product_b.cost_currency_id, company_a.currency_id, 'The cost currency should be the one set on'
+                                                                            ' the company')
+
+        product_b = product_b.with_company(company_b)
+
+        self.assertEqual(product_b.cost_currency_id, currency, 'The cost currency should be the one set on the company,'
+                                                               ' as the product is now opened in another company')
+
+        product_b.supplier_taxes_id = False
+        product_b.update({'standard_price': 10.0})
+
+        #create a purchase order with the product from company B
+        order_b = self.env['purchase.order'].with_company(company_b).create({
+            'partner_id': self.partner_a.id,
+            'order_line': [(0, 0, {
+                'product_id': product_b.id,
+                'product_qty': 1,
+                'product_uom': self.env.ref('uom.product_uom_unit').id,
+            })],
+        })
+
+        self.assertEqual(order_b.order_line.price_unit, 10.0, 'The price unit should be 10.0')
+
     def test_purchase_not_creating_useless_product_vendor(self):
         """ This test ensures that the product vendor is not created when the
         product is not set on the purchase order line.
-- 
GitLab