[FIX] stock_account: avoid negative values after revaluation
When performing a manual stock revaluation, the value difference is distributed equally among the available stock. This method breaks down however in case of a devaluation where some items in stock are already valued less than the unit cost difference: this results in a negative value. This commit will prevent such devaluations by raising a UserError whenever the remaining value of a stock.valuation.layer becomes negative. Additionally, after a revaluation, the standard_price field will now also be updated for fifo valued products. opw-3340298 closes odoo/odoo#143437 X-original-commit: a6db4b48f1d32f1020ee3ad242c77211aa10b3b2 Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
This commit is contained in:
committed by
Arnold Moyaux
parent
ee0b81b06d
commit
fee810535e
@@ -1061,3 +1061,8 @@ msgstr ""
|
||||
#: model_terms:ir.ui.view,arch_db:stock_account.stock_account_report_invoice_document
|
||||
msgid "units"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_account
|
||||
#: code:addons/stock_account/wizard/stock_valuation_layer_revaluation.py:0
|
||||
msgid "'The value of a stock valuation layer cannot be negative. Landed cost could be use to correct a specific transfer."
|
||||
msgstr ""
|
||||
|
||||
@@ -4004,3 +4004,46 @@ class TestStockValuation(TransactionCase):
|
||||
|
||||
self.product1.write({'standard_price': 7})
|
||||
self.assertEqual(self.product1.value_svl, 49)
|
||||
|
||||
def test_average_manual_revaluation(self):
|
||||
self.product1.categ_id.property_cost_method = 'average'
|
||||
|
||||
self._make_in_move(self.product1, 1, unit_cost=20)
|
||||
self._make_in_move(self.product1, 1, unit_cost=30)
|
||||
self.assertEqual(self.product1.standard_price, 25)
|
||||
|
||||
Form(self.env['stock.valuation.layer.revaluation'].with_context({
|
||||
'default_product_id': self.product1.id,
|
||||
'default_company_id': self.env.company.id,
|
||||
'default_account_id': self.stock_valuation_account,
|
||||
'default_added_value': -10.0,
|
||||
})).save().action_validate_revaluation()
|
||||
|
||||
self.assertEqual(self.product1.standard_price, 20)
|
||||
|
||||
def test_fifo_manual_revaluation(self):
|
||||
revaluation_vals = {
|
||||
'default_product_id': self.product1.id,
|
||||
'default_company_id': self.env.company.id,
|
||||
'default_account_id': self.stock_valuation_account,
|
||||
}
|
||||
self.product1.categ_id.property_cost_method = 'fifo'
|
||||
|
||||
self._make_in_move(self.product1, 1, unit_cost=15)
|
||||
self._make_in_move(self.product1, 1, unit_cost=30)
|
||||
self.assertEqual(self.product1.stock_valuation_layer_ids[0].remaining_value, 15)
|
||||
|
||||
Form(self.env['stock.valuation.layer.revaluation'].with_context({
|
||||
**revaluation_vals,
|
||||
'default_added_value': -10.0,
|
||||
})).save().action_validate_revaluation()
|
||||
|
||||
self.assertEqual(self.product1.stock_valuation_layer_ids[0].remaining_value, 10)
|
||||
|
||||
revaluation = Form(self.env['stock.valuation.layer.revaluation'].with_context({
|
||||
**revaluation_vals,
|
||||
'default_added_value': -25.0,
|
||||
})).save()
|
||||
|
||||
with self.assertRaises(UserError):
|
||||
revaluation.action_validate_revaluation()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tools import float_is_zero
|
||||
from odoo.tools import float_compare, float_is_zero
|
||||
|
||||
|
||||
class StockValuationLayerRevaluation(models.TransientModel):
|
||||
@@ -97,12 +97,15 @@ class StockValuationLayerRevaluation(models.TransientModel):
|
||||
remaining_value_unit_cost = self.currency_id.round(remaining_value / remaining_qty)
|
||||
for svl in remaining_svls:
|
||||
if float_is_zero(svl.remaining_qty - remaining_qty, precision_rounding=self.product_id.uom_id.rounding):
|
||||
svl.remaining_value += remaining_value
|
||||
taken_remaining_value = remaining_value
|
||||
else:
|
||||
taken_remaining_value = remaining_value_unit_cost * svl.remaining_qty
|
||||
svl.remaining_value += taken_remaining_value
|
||||
remaining_value -= taken_remaining_value
|
||||
remaining_qty -= svl.remaining_qty
|
||||
if float_compare(svl.remaining_value + taken_remaining_value, 0, precision_rounding=self.product_id.uom_id.rounding) < 0:
|
||||
raise UserError(_('The value of a stock valuation layer cannot be negative. Landed cost could be use to correct a specific transfer.'))
|
||||
|
||||
svl.remaining_value += taken_remaining_value
|
||||
remaining_value -= taken_remaining_value
|
||||
remaining_qty -= svl.remaining_qty
|
||||
|
||||
revaluation_svl = self.env['stock.valuation.layer'].create(revaluation_svl_vals)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user