[FIX] purchase_stock, stock_landed_costs: bill after LC
1. Create a product with a category AVCO + Automated and set a price
difference account
2. Create a Purchase Order for 1 unit at a value of 1000,
3. Stock entry at receipt
D C
Stock interim received 1000
Stock valuation 1000
4. Create a vendor bill for a Landed cost, post it
D C
Stock interim received 100
5. Create the landed cost from the bill and apply it on the receipt of
point 3
D C
Stock valuation 100
Stock interim received 100
6. Create the vendor bill for the initial PO
Current entry is not correct:
D C
Stock interim received 1000
Price difference account 100 --> Shouldn't take place
Stock interim received 100 --> Shouldn't take place
This happens because the valuation layers of the landed cost are taken
into account when computing the unit price of the product.
This shouldn't be the case: when computing the price difference between
the invoice price and the stock move price, LC should be filtered out.
opw-2183511
closes odoo/odoo#47804
X-original-commit: 9bd3feb7f8778ba65e1974ef012ca3a4608878b1
Signed-off-by: Nicolas Martinelli (nim) <nim@odoo.com>
This commit is contained in:
@@ -74,8 +74,9 @@ class AccountMove(models.Model):
|
||||
# In case val_stock_move is a return move, its valuation entries have been made with the
|
||||
# currency rate corresponding to the original stock move
|
||||
valuation_date = val_stock_move.origin_returned_move_id.date or val_stock_move.date
|
||||
layers_qty = sum(val_stock_move.mapped('stock_valuation_layer_ids.quantity'))
|
||||
layers_values = sum(val_stock_move.mapped('stock_valuation_layer_ids.value'))
|
||||
svl = val_stock_move.mapped('stock_valuation_layer_ids').filtered(lambda l: l.quantity)
|
||||
layers_qty = sum(svl.mapped('quantity'))
|
||||
layers_values = sum(svl.mapped('value'))
|
||||
valuation_price_unit_total += line.company_currency_id._convert(
|
||||
layers_values, move.currency_id,
|
||||
move.company_id, valuation_date, round=False,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
import unittest
|
||||
from odoo.addons.stock_landed_costs.tests.common import TestStockLandedCostsCommon
|
||||
from odoo.addons.stock_landed_costs.tests.test_stockvaluationlayer import TestStockValuationLCCommon
|
||||
from odoo.addons.stock_account.tests.test_stockvaluation import _create_accounting_data
|
||||
|
||||
from odoo.tests import tagged, Form
|
||||
@@ -300,3 +301,73 @@ class TestLandedCosts(TestStockLandedCostsCommon):
|
||||
|
||||
def _error_message(self, actucal_cost, computed_cost):
|
||||
return 'Additional Landed Cost should be %s instead of %s' % (actucal_cost, computed_cost)
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestLandedCostsWithPurchaseAndInv(TestStockValuationLCCommon):
|
||||
def test_invoice_after_lc(self):
|
||||
self.env.company.anglo_saxon_accounting = True
|
||||
self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo'
|
||||
self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time'
|
||||
self.product1.product_tmpl_id.invoice_policy = 'delivery'
|
||||
self.price_diff_account = self.env['account.account'].create({
|
||||
'name': 'price diff account',
|
||||
'code': 'price diff account',
|
||||
'user_type_id': self.env.ref('account.data_account_type_current_assets').id,
|
||||
})
|
||||
self.product1.property_account_creditor_price_difference = self.price_diff_account
|
||||
|
||||
# Create PO
|
||||
po_form = Form(self.env['purchase.order'])
|
||||
po_form.partner_id = self.env['res.partner'].create({'name': 'vendor'})
|
||||
with po_form.order_line.new() as po_line:
|
||||
po_line.product_id = self.product1
|
||||
po_line.product_qty = 1
|
||||
po_line.price_unit = 455.0
|
||||
order = po_form.save()
|
||||
order.button_confirm()
|
||||
|
||||
# Receive the goods
|
||||
receipt = order.picking_ids[0]
|
||||
receipt.move_lines.quantity_done = 1
|
||||
receipt.button_validate()
|
||||
|
||||
# Check SVL and AML
|
||||
svl = self.env['stock.valuation.layer'].search([('stock_move_id', '=', receipt.move_lines.id)])
|
||||
self.assertAlmostEqual(svl.value, 455)
|
||||
aml = self.env['account.move.line'].search([('account_id', '=', self.stock_valuation_account.id)])
|
||||
self.assertAlmostEqual(aml.debit, 455)
|
||||
|
||||
# Create and validate LC
|
||||
lc = self.env['stock.landed.cost'].create(dict(
|
||||
picking_ids=[(6, 0, [receipt.id])],
|
||||
account_journal_id=self.stock_journal.id,
|
||||
cost_lines=[
|
||||
(0, 0, {
|
||||
'name': 'equal split',
|
||||
'split_method': 'equal',
|
||||
'price_unit': 99,
|
||||
'product_id': self.productlc1.id,
|
||||
}),
|
||||
],
|
||||
))
|
||||
lc.compute_landed_cost()
|
||||
lc.button_validate()
|
||||
|
||||
# Check LC, SVL and AML
|
||||
self.assertAlmostEqual(lc.valuation_adjustment_lines.final_cost, 554)
|
||||
svl = self.env['stock.valuation.layer'].search([('stock_move_id', '=', receipt.move_lines.id)], order='id desc', limit=1)
|
||||
self.assertAlmostEqual(svl.value, 99)
|
||||
aml = self.env['account.move.line'].search([('account_id', '=', self.stock_valuation_account.id)], order='id desc', limit=1)
|
||||
self.assertAlmostEqual(aml.debit, 99)
|
||||
|
||||
# Create an invoice with the same price
|
||||
move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
|
||||
move_form.partner_id = order.partner_id
|
||||
move_form.purchase_id = order
|
||||
move = move_form.save()
|
||||
move.post()
|
||||
|
||||
# Check nothing was posted in the price difference account
|
||||
price_diff_aml = self.env['account.move.line'].search([('account_id','=', self.price_diff_account.id), ('move_id', '=', move.id)])
|
||||
self.assertEqual(len(price_diff_aml), 0, "No line should have been generated in the price difference account.")
|
||||
|
||||
Reference in New Issue
Block a user