[FIX] purchase_stock: get_price_unit with manual valuation

layer.account_move_id may not be defined on 'manual' valuation.
Use layer.create_date instead which is equal to layer.account_move_id.date.

# HOW TO REPRODUCE:
- Create a product P, storable in AVCO !! MANUAL !!
- Set 'Control Policy' under Purchase to 'Ordered Quantity'
- Create a PO for 10 units of P with for $1 each.
- Create Vendor Bill -> Confirm
- Receive 5 unit of P: Create backorder
- Validate backorder
==>> Traceback

OPW-3383833

closes odoo/odoo#127218

X-original-commit: b1351ee348207283dcdf7118440b31c03f0d0b4b
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
Signed-off-by: David Fesquet (dafr) <dafr@odoo.com>
This commit is contained in:
David (dafr)
2023-07-04 12:47:12 +02:00
parent b1d75b0134
commit 343f6143d7
2 changed files with 92 additions and 47 deletions
+2 -2
View File
@@ -50,10 +50,10 @@ class StockMove(models.Model):
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)))
l.value, order.currency_id, order.company_id, l.create_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)))
l.value, order.currency_id, order.company_id, l.create_date, round=False)))
invoiced_value = 0
invoiced_qty = 0
for invoice_line in line.invoice_lines:
@@ -1942,51 +1942,6 @@ class TestStockValuationWithCOA(AccountTestInvoicingCommon):
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)
def test_pdiff_and_credit_notes(self):
"""
Auto FIFO
@@ -2484,3 +2439,93 @@ class TestStockValuationWithCOA(AccountTestInvoicingCommon):
svls = self.product1.stock_valuation_layer_ids
self.assertEqual(svls.mapped('remaining_value'), [13.0, 12.0, 0.0, 0.0, 0.0, 0.0])
self.assertEqual(svls.mapped('value'), [10.0, 10.0, 1.0, 2.0, -1.0, 3.0])
def test_invoice_on_ordered_qty_with_backorder_and_different_currency_automated(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.categ_id.property_valuation = 'real_time'
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)
def test_invoice_on_ordered_qty_with_backorder_and_different_currency_manual(self):
"""Same test as test_invoice_on_ordered_qty_with_backorder_and_different_currency_automated with manual_periodic valuation
Ensure that the absence of account_move_id on the layers does not generate an Exception
"""
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.categ_id.property_valuation = 'manual_periodic'
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)