[FIX] purchase_stock: valuation layer wrong when different currency

To reproduce:
1. Create a storable product with ordered quantities policy for purchase and with a category set as FIFO automated
2. Create a purchase order in a different currency and set quantities for partial deliveries
3. Create a partial delivery
4. Fully invoice the purchase order
5. Create the delivery of the complementary units
6. Check the stock valuation layer
The valuation of backorder is wrong.

The value on valuation layer is in company's currency, while the value
on invoice line is in the PO's currency. When create valuation line for
backorder, we didn't convert them to same currency.

opw-3300266

closes odoo/odoo#125206

X-original-commit: c2de679fcba7f153201dde5b3aa989eb3f329910
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
Signed-off-by: Yuchen Huang (yhu) <yhu@odoo.com>
This commit is contained in:
yhu-odoo
2023-06-15 19:59:18 +02:00
parent 7d1959febc
commit 9955064415
2 changed files with 54 additions and 2 deletions
+9 -2
View File
@@ -45,13 +45,20 @@ class StockMove(models.Model):
if float_compare(line.qty_invoiced, received_qty, precision_rounding=line.product_uom.rounding) > 0:
move_layer = line.move_ids.stock_valuation_layer_ids
invoiced_layer = line.invoice_lines.stock_valuation_layer_ids
receipt_value = sum(move_layer.mapped('value')) + sum(invoiced_layer.mapped('value'))
# value on valuation layer is in company's currency, while value on invoice line is in order's currency
receipt_value = 0
if move_layer:
receipt_value += sum(move_layer.mapped(lambda l: l.currency_id._convert(
l.value, order.currency_id, order.company_id, l.account_move_id.date, round=False)))
if invoiced_layer:
receipt_value += sum(invoiced_layer.mapped(lambda l: l.currency_id._convert(
l.value, order.currency_id, order.company_id, l.account_move_id.date, round=False)))
invoiced_value = 0
invoiced_qty = 0
for invoice_line in line.invoice_lines:
if invoice_line.tax_ids:
invoiced_value += invoice_line.tax_ids.with_context(round=False).compute_all(
invoice_line.price_unit, currency=invoice_line.account_id.currency_id, quantity=invoice_line.quantity)['total_void']
invoice_line.price_unit, currency=invoice_line.currency_id, quantity=invoice_line.quantity)['total_void']
else:
invoiced_value += invoice_line.price_unit * invoice_line.quantity
invoiced_qty += invoice_line.product_uom_id._compute_quantity(invoice_line.quantity, line.product_id.uom_id)
@@ -1887,3 +1887,48 @@ class TestStockValuationWithCOA(AccountTestInvoicingCommon):
full_reconcile = input_amls[0].full_reconcile_id
self.assertTrue(full_reconcile)
self.assertTrue(all(aml.full_reconcile_id == full_reconcile for aml in input_amls))
def test_invoice_on_ordered_qty_with_backorder_and_different_currency(self):
"""Create a PO with currency different from the company currency. Set the
product to be invoiced on ordered quantities. Receive partially the products
and create a backorder. Create an invoice for the ordered quantity. Then
receive the backorder. Check if the valuation layer is correctly created.
"""
usd_currency = self.env.ref('base.USD')
self.env.company.currency_id = usd_currency.id
self.product1.categ_id.property_cost_method = 'fifo'
self.product1.purchase_method = 'purchase'
price_unit_EUR = 100
price_unit_USD = self.env.ref('base.EUR')._convert(price_unit_EUR, usd_currency, self.env.company, fields.Date.today(), round=False)
po = self.env['purchase.order'].create({
'partner_id': self.partner_id.id,
'currency_id': self.env.ref('base.EUR').id,
'order_line': [
(0, 0, {
'name': self.product1.name,
'product_id': self.product1.id,
'product_qty': 12.0,
'product_uom': self.product1.uom_po_id.id,
'price_unit': 100.0,
'date_planned': datetime.today().strftime(DEFAULT_SERVER_DATETIME_FORMAT),
}),
],
})
po.button_confirm()
picking = po.picking_ids[0]
move = picking.move_ids[0]
move.quantity_done = 10
res_dict = picking.button_validate()
self.assertEqual(res_dict['res_model'], 'stock.backorder.confirmation')
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
wizard.process()
self.assertAlmostEqual(move.stock_valuation_layer_ids.unit_cost, price_unit_USD)
po.action_create_invoice()
picking2 = po.picking_ids.filtered(lambda p: p.backorder_id)
move2 = picking2.move_ids[0]
move2.quantity_done = 2
picking2.button_validate()
self.assertAlmostEqual(move2.stock_valuation_layer_ids.unit_cost, price_unit_USD)