mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
[FIX] various fixes as per peer review
This commit is contained in:
committed by
Jordi Ballester Alomar
parent
cad7b0eab7
commit
9c5ff301b8
@@ -12,14 +12,15 @@ class ProductCategory(models.Model):
|
||||
property_inventory_revaluation_increase_account_categ = fields.Many2one(
|
||||
'account.account', string='Valuation Increase Account',
|
||||
company_dependent=True,
|
||||
help="Define the G/L accounts to be used as the balancing account in "
|
||||
"the transaction created by the revaluation. The G/L Increase "
|
||||
"Account is used when the inventory value is increased due to "
|
||||
"the revaluation.")
|
||||
help="Define the Financial Accounts to be used as the balancing "
|
||||
"account in the transaction created by the revaluation. "
|
||||
"The Valuation Increase Account is used when the inventory value "
|
||||
"is increased due to the revaluation.")
|
||||
|
||||
property_inventory_revaluation_decrease_account_categ = fields.Many2one(
|
||||
'account.account', string='Valuation Decrease Account',
|
||||
company_dependent=True,
|
||||
help="Define the G/L accounts to be used as the balancing account in "
|
||||
"the transaction created by the revaluation. The G/L Decrease "
|
||||
"Account is used when the inventory value is decreased.")
|
||||
help="Define the Financial Accounts to be used as the balancing "
|
||||
"account in the transaction created by the revaluation. "
|
||||
"The Valuation Decrease Account is used when the inventory value "
|
||||
"is decreased.")
|
||||
|
||||
@@ -23,30 +23,35 @@ class StockInventoryRevaluation(models.Model):
|
||||
res = self.env['account.journal'].search([('type', '=', 'general')])
|
||||
return res and res[0] or False
|
||||
|
||||
@api.one
|
||||
@api.multi
|
||||
def _get_product_template_qty(self):
|
||||
self.qty_available = 0
|
||||
for prod_variant in self.product_template_id.product_variant_ids:
|
||||
self.qty_available += prod_variant.qty_available
|
||||
for revaluation in self:
|
||||
revaluation.qty_available = 0
|
||||
for prod_variant in \
|
||||
revaluation.product_template_id.product_variant_ids:
|
||||
revaluation.qty_available += prod_variant.qty_available
|
||||
|
||||
@api.one
|
||||
@api.multi
|
||||
def _calc_product_template_value(self):
|
||||
qty_available = 0
|
||||
current_value = 0.0
|
||||
quant_obj = self.env['stock.quant']
|
||||
for prod_variant in self.product_template_id.product_variant_ids:
|
||||
qty_available += prod_variant.qty_available
|
||||
if self.product_template_id.cost_method == 'real':
|
||||
quants = quant_obj.search([('product_id', '=',
|
||||
prod_variant.id),
|
||||
('location_id.usage', '=',
|
||||
'internal')])
|
||||
for quant in quants:
|
||||
current_value += quant.cost
|
||||
else:
|
||||
current_value = \
|
||||
self.product_template_id.standard_price * qty_available
|
||||
self.current_value = current_value
|
||||
for revaluation in self:
|
||||
qty_available = 0
|
||||
current_value = 0.0
|
||||
for prod_variant in \
|
||||
revaluation.product_template_id.product_variant_ids:
|
||||
qty_available += prod_variant.qty_available
|
||||
if revaluation.product_template_id.cost_method == 'real':
|
||||
quants = quant_obj.search([('product_id', '=',
|
||||
prod_variant.id),
|
||||
('location_id.usage', '=',
|
||||
'internal')])
|
||||
for quant in quants:
|
||||
current_value += quant.cost
|
||||
else:
|
||||
current_value = \
|
||||
revaluation.product_template_id.standard_price * \
|
||||
qty_available
|
||||
revaluation.current_value = current_value
|
||||
|
||||
name = fields.Char('Reference',
|
||||
help="Reference for the journal entry",
|
||||
@@ -167,26 +172,27 @@ class StockInventoryRevaluation(models.Model):
|
||||
"the transaction created by the revaluation. The Decrease "
|
||||
"Account is used when the inventory value is decreased.")
|
||||
|
||||
move_id = fields.Many2one('account.move', 'Account move', readonly=True,
|
||||
copy=False)
|
||||
account_move_id = fields.Many2one('account.move', 'Account move',
|
||||
readonly=True, copy=False)
|
||||
|
||||
reval_quant_ids = fields.One2many('stock.inventory.revaluation.quant',
|
||||
'revaluation_id',
|
||||
string='Revaluation line quants')
|
||||
|
||||
@api.one
|
||||
@api.multi
|
||||
@api.depends("product_template_id", "product_template_id.standard_price")
|
||||
def _calc_current_cost(self):
|
||||
self.current_cost = self.product_template_id.standard_price
|
||||
for revaluation in self:
|
||||
revaluation.current_cost = revaluation.product_template_id.standard_price
|
||||
|
||||
@api.one
|
||||
@api.multi
|
||||
@api.constrains('product_template_id', 'company_id')
|
||||
def _check_is_stockable(self):
|
||||
if self.product_template_id.type != 'product':
|
||||
raise UserError(_('Configuration error!\nThe product must be '
|
||||
'stockable.'))
|
||||
for revaluation in self:
|
||||
if revaluation.product_template_id.type != 'product':
|
||||
raise UserError(_('Configuration error!\nThe product must be '
|
||||
'stockable.'))
|
||||
|
||||
@api.one
|
||||
@api.onchange("product_template_id")
|
||||
def _onchange_product_template_id(self):
|
||||
if self.product_template_id:
|
||||
@@ -214,10 +220,10 @@ class StockInventoryRevaluation(models.Model):
|
||||
def _prepare_debit_move_line_data(self, amount, account_id, prod_id):
|
||||
return {
|
||||
'name': self.name,
|
||||
'date': self.move_id.date,
|
||||
'date': self.account_move_id.date,
|
||||
'product_id': prod_id,
|
||||
'account_id': account_id,
|
||||
'move_id': self.move_id.id,
|
||||
'move_id': self.account_move_id.id,
|
||||
'debit': amount
|
||||
}
|
||||
|
||||
@@ -225,10 +231,10 @@ class StockInventoryRevaluation(models.Model):
|
||||
def _prepare_credit_move_line_data(self, amount, account_id, prod_id):
|
||||
return {
|
||||
'name': self.name,
|
||||
'date': self.move_id.date,
|
||||
'date': self.account_move_id.date,
|
||||
'product_id': prod_id,
|
||||
'account_id': account_id,
|
||||
'move_id': self.move_id.id,
|
||||
'move_id': self.account_move_id.id,
|
||||
'credit': amount
|
||||
}
|
||||
|
||||
@@ -238,11 +244,11 @@ class StockInventoryRevaluation(models.Model):
|
||||
move_data = self._prepare_move_data(timenow)
|
||||
datas = self.env['product.template'].get_product_accounts(
|
||||
self.product_template_id.id)
|
||||
self.move_id = self.env['account.move'].create(move_data).id
|
||||
self.account_move_id = self.env['account.move'].create(move_data).id
|
||||
move_line_obj = self.env['account.move.line']
|
||||
|
||||
if not self.decrease_account_id or not self.increase_account_id:
|
||||
raise UserError(_("Please add a Increase Account and "
|
||||
raise UserError(_("Please add an Increase Account and "
|
||||
"a Decrease Account."))
|
||||
|
||||
for prod_variant in self.product_template_id.product_variant_ids:
|
||||
@@ -262,52 +268,56 @@ class StockInventoryRevaluation(models.Model):
|
||||
move_line_data = self._prepare_credit_move_line_data(
|
||||
abs(amount_diff), credit_account_id, prod_variant.id)
|
||||
move_line_obj.create(move_line_data)
|
||||
if self.move_id.journal_id.entry_posted:
|
||||
self.move_id.post()
|
||||
if self.account_move_id.journal_id.entry_posted:
|
||||
self.account_move_id.post()
|
||||
|
||||
@api.one
|
||||
@api.multi
|
||||
def post(self):
|
||||
for revaluation in self:
|
||||
amount_diff = 0.0
|
||||
if revaluation.product_template_id.cost_method == 'real':
|
||||
for reval_quant in revaluation.reval_quant_ids:
|
||||
amount_diff += reval_quant.get_total_value()
|
||||
reval_quant.write_new_cost()
|
||||
if amount_diff == 0.0:
|
||||
return True
|
||||
else:
|
||||
if revaluation.product_template_id.cost_method \
|
||||
in ['standard', 'average']:
|
||||
|
||||
amount_diff = 0.0
|
||||
if self.product_template_id.cost_method == 'real':
|
||||
for reval_quant in self.reval_quant_ids:
|
||||
amount_diff += reval_quant.get_total_value()
|
||||
reval_quant.write_new_cost()
|
||||
if amount_diff == 0.0:
|
||||
return True
|
||||
else:
|
||||
if self.product_template_id.cost_method in ['standard', 'average']:
|
||||
if revaluation.revaluation_type == 'price_change':
|
||||
diff = revaluation.current_cost - revaluation.new_cost
|
||||
amount_diff = revaluation.qty_available * diff
|
||||
else:
|
||||
amount_diff = \
|
||||
revaluation.current_value - revaluation.new_value
|
||||
if revaluation.new_value < 0:
|
||||
raise UserError(
|
||||
_("The new value for product %s cannot "
|
||||
"be negative" %
|
||||
revaluation.product_template_id.name))
|
||||
if revaluation.qty_available <= 0.0:
|
||||
raise UserError(
|
||||
_("Cannot do an inventory value change if the "
|
||||
"quantity available for product %s "
|
||||
"is 0 or negative" %
|
||||
revaluation.product_template_id.name))
|
||||
|
||||
if self.revaluation_type == 'price_change':
|
||||
diff = self.current_cost - self.new_cost
|
||||
amount_diff = self.qty_available * diff
|
||||
else:
|
||||
amount_diff = self.current_value - self.new_value
|
||||
if self.new_value < 0:
|
||||
raise UserError(_("The new value for product %s "
|
||||
"cannot be negative"
|
||||
% self.product_template_id.name))
|
||||
if self.qty_available <= 0.0:
|
||||
raise UserError(
|
||||
_("Cannot do an inventory value change if the "
|
||||
"quantity available for product %s "
|
||||
"is 0 or negative" %
|
||||
self.product_template_id.name))
|
||||
if revaluation.revaluation_type == 'price_change':
|
||||
revaluation.old_cost = revaluation.current_cost
|
||||
revaluation.product_template_id.write(
|
||||
{'standard_price': revaluation.new_cost})
|
||||
else:
|
||||
revaluation.old_cost = revaluation.current_cost
|
||||
revaluation.old_value = revaluation.current_value
|
||||
value_diff = revaluation.current_value - \
|
||||
revaluation.new_value
|
||||
new_cost = value_diff / revaluation.qty_available
|
||||
revaluation.product_template_id.write(
|
||||
{'standard_price': new_cost})
|
||||
|
||||
if self.revaluation_type == 'price_change':
|
||||
self.old_cost = self.current_cost
|
||||
self.product_template_id.write({'standard_price':
|
||||
self.new_cost})
|
||||
else:
|
||||
self.old_cost = self.current_cost
|
||||
self.old_value = self.current_value
|
||||
value_diff = self.current_value - self.new_value
|
||||
new_cost = value_diff / self.qty_available
|
||||
self.product_template_id.write({'standard_price':
|
||||
new_cost})
|
||||
|
||||
if self.product_template_id.valuation == 'real_time':
|
||||
self._create_accounting_entry(amount_diff)
|
||||
if revaluation.product_template_id.valuation == 'real_time':
|
||||
revaluation._create_accounting_entry(amount_diff)
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
@@ -330,18 +340,19 @@ class StockInventoryRevaluation(models.Model):
|
||||
@api.multi
|
||||
def button_cancel(self):
|
||||
moves = self.env['account.move']
|
||||
if self.move_id:
|
||||
moves += self.move_id
|
||||
for reval_quant in self.reval_quant_ids:
|
||||
reval_quant.quant_id.write({'cost': reval_quant.old_cost})
|
||||
if moves:
|
||||
# second, invalidate the move(s)
|
||||
moves.button_cancel()
|
||||
# delete the move this revaluation was pointing to
|
||||
# Note that the corresponding move_lines and move_reconciles
|
||||
# will be automatically deleted too
|
||||
moves.unlink()
|
||||
self.write({'state': 'cancel'})
|
||||
for revaluation in self:
|
||||
if revaluation.account_move_id:
|
||||
moves += revaluation.account_move_id
|
||||
for reval_quant in revaluation.reval_quant_ids:
|
||||
reval_quant.quant_id.write({'cost': reval_quant.old_cost})
|
||||
if moves:
|
||||
# second, invalidate the move(s)
|
||||
moves.button_cancel()
|
||||
# delete the move this revaluation was pointing to
|
||||
# Note that the corresponding move_lines and move_reconciles
|
||||
# will be automatically deleted too
|
||||
moves.unlink()
|
||||
revaluation.state = 'cancel'
|
||||
return True
|
||||
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ class TestStockInventoryRevaluation(TransactionCase):
|
||||
env['stock.inventory.revaluation.quant']
|
||||
self.get_quant_model = self.\
|
||||
env['stock.inventory.revaluation.get.quant']
|
||||
self.mass_post_model = self.\
|
||||
env['stock.inventory.revaluation.mass.post']
|
||||
self.stock_change_model = self.env['stock.change.product.qty']
|
||||
self.stock_lot_model = self.env['stock.production.lot']
|
||||
self.stock_location_model = self.env['stock.location']
|
||||
@@ -174,6 +176,21 @@ class TestStockInventoryRevaluation(TransactionCase):
|
||||
for reval_quant in revaluation.reval_quant_ids:
|
||||
reval_quant.new_cost = 8.0
|
||||
|
||||
def _mass_post(self, revaluations):
|
||||
"""Get Quants for Inventory Revaluation between the date supplied."""
|
||||
context = {
|
||||
'active_id': revaluations[0],
|
||||
'active_ids': [rev.id for rev in revaluations],
|
||||
'active_model': 'stock.inventory.revaluation',
|
||||
}
|
||||
mass_post_wiz = self.mass_post_model.with_context(context).create({})
|
||||
mass_post_wiz.process()
|
||||
return True
|
||||
|
||||
def test_defaults(self):
|
||||
"""Test default methods"""
|
||||
self.assertNotEqual(self.reval_model._default_journal(), False)
|
||||
|
||||
def test_inventory_revaluation_price_change_real(self):
|
||||
"""Test that the inventory is revaluated when the
|
||||
inventory price for a product managed under real costing method is
|
||||
@@ -194,16 +211,13 @@ class TestStockInventoryRevaluation(TransactionCase):
|
||||
|
||||
expected_result = (10.00 - 8.00) * 20.00
|
||||
|
||||
for move_line in invent_price_change_real.move_id.line_id:
|
||||
for move_line in invent_price_change_real.account_move_id.line_id:
|
||||
if move_line.debit:
|
||||
self.assertEqual(move_line.debit, expected_result,
|
||||
'Incorrect inventory revaluation for '
|
||||
'type Price Change.')
|
||||
|
||||
def test_inventory_revaluation_price_change_average(self):
|
||||
"""Test that the inventory is revaluated when the
|
||||
inventory price for a product managed under average costing method is
|
||||
changed."""
|
||||
def create_inventory_revaluation_price_change_average(self):
|
||||
revaluation_type = 'price_change'
|
||||
# Create an Inventory Revaluation for average cost product
|
||||
invent_price_change_average = self._create_inventory_revaluation(
|
||||
@@ -211,30 +225,61 @@ class TestStockInventoryRevaluation(TransactionCase):
|
||||
self.product_average.product_tmpl_id)
|
||||
# Post the inventory revaluation
|
||||
invent_price_change_average.new_cost = 8.00
|
||||
return invent_price_change_average
|
||||
|
||||
def test_inventory_revaluation_price_change_average(self):
|
||||
"""Test that the inventory is revaluated when the
|
||||
inventory price for a product managed under average costing method is
|
||||
changed."""
|
||||
invent_price_change_average = \
|
||||
self.create_inventory_revaluation_price_change_average()
|
||||
invent_price_change_average.button_post()
|
||||
expected_result = (10.00 - 8.00) * 20.00
|
||||
for move_line in invent_price_change_average.move_id.line_id:
|
||||
for move_line in invent_price_change_average.account_move_id.line_id:
|
||||
if move_line.debit:
|
||||
self.assertEqual(move_line.debit, expected_result,
|
||||
'Incorrect inventory revaluation for '
|
||||
'type Price Change.')
|
||||
|
||||
def test_inventory_revaluation_value_change(self):
|
||||
"""Test that the inventory is revaluated when the
|
||||
inventory price for any product is changed."""
|
||||
def create_inventory_revaluation_value_change(self):
|
||||
# Create an Inventory Revaluation for value change for average
|
||||
# cost product
|
||||
revaluation_type = 'inventory_value'
|
||||
invent_average = self._create_inventory_revaluation(
|
||||
invent_value_change = self._create_inventory_revaluation(
|
||||
self.journal, revaluation_type,
|
||||
self.product_average.product_tmpl_id)
|
||||
invent_average.new_value = 100.00
|
||||
invent_value_change.new_value = 100.00
|
||||
return invent_value_change
|
||||
|
||||
def test_inventory_revaluation_value_change(self):
|
||||
"""Test that the inventory is revaluated when the
|
||||
inventory price for any product is changed."""
|
||||
invent_value_change = self.create_inventory_revaluation_value_change()
|
||||
# Post the inventory revaluation
|
||||
invent_average.button_post()
|
||||
invent_value_change.button_post()
|
||||
|
||||
for move_line in invent_average.move_id.line_id:
|
||||
for move_line in invent_value_change.account_move_id.line_id:
|
||||
if move_line.debit:
|
||||
self.assertEqual(move_line.debit, 100.0,
|
||||
'Incorrect inventory revaluation for '
|
||||
'type Inventory Debit/Credit.')
|
||||
|
||||
def test_mass_post(self):
|
||||
"""Test mass post"""
|
||||
revaluations = []
|
||||
|
||||
# Create an Inventory Revaluation for average cost product
|
||||
invent_price_change_average = \
|
||||
self.create_inventory_revaluation_price_change_average()
|
||||
revaluations.append(invent_price_change_average)
|
||||
|
||||
# Create an Inventory Revaluation for real cost product
|
||||
invent_value_change = self.create_inventory_revaluation_value_change()
|
||||
revaluations.append(invent_value_change)
|
||||
|
||||
# Post the inventory revaluation using wizard
|
||||
self._mass_post(revaluations)
|
||||
|
||||
# Check that both inventory valuations are now posted
|
||||
self.assertEqual(invent_price_change_average.state, 'posted')
|
||||
self.assertEqual(invent_value_change.state, 'posted')
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
<group name="accounting">
|
||||
<field name="increase_account_id"/>
|
||||
<field name="decrease_account_id"/>
|
||||
<field name="move_id"/>
|
||||
<field name="account_move_id"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
@@ -119,7 +119,7 @@
|
||||
<field name="qty_available"/>
|
||||
<field name="increase_account_id"/>
|
||||
<field name="decrease_account_id"/>
|
||||
<field name="move_id"/>
|
||||
<field name="account_move_id"/>
|
||||
<field name="state"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</tree>
|
||||
|
||||
Reference in New Issue
Block a user