diff --git a/stock_inventory_revaluation/__openerp__.py b/stock_inventory_revaluation/__openerp__.py index 1f6389b8c..2ec2494cd 100644 --- a/stock_inventory_revaluation/__openerp__.py +++ b/stock_inventory_revaluation/__openerp__.py @@ -21,6 +21,7 @@ "views/stock_inventory_revaluation_view.xml", "views/product_view.xml", "data/stock_inventory_revaluation_data.xml", + "wizards/stock_inventory_revaluation_mass_post_view.xml", ], 'installable': True, } diff --git a/stock_inventory_revaluation/data/stock_inventory_revaluation_data.xml b/stock_inventory_revaluation/data/stock_inventory_revaluation_data.xml index 4ab5d3c02..75ecf2d13 100644 --- a/stock_inventory_revaluation/data/stock_inventory_revaluation_data.xml +++ b/stock_inventory_revaluation/data/stock_inventory_revaluation_data.xml @@ -12,7 +12,7 @@ Stock Inventory Revaluation stock.inventory.revaluation IR/ - 5 + 7 1 1 diff --git a/stock_inventory_revaluation/models/stock_inventory_revaluation.py b/stock_inventory_revaluation/models/stock_inventory_revaluation.py index 85675f1a6..31409d55d 100644 --- a/stock_inventory_revaluation/models/stock_inventory_revaluation.py +++ b/stock_inventory_revaluation/models/stock_inventory_revaluation.py @@ -23,6 +23,31 @@ class StockInventoryRevaluation(models.Model): res = self.env['account.journal'].search([('type', '=', 'general')]) return res and res[0] or False + @api.one + 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 + + @api.one + 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 + name = fields.Char('Reference', help="Reference for the journal entry", readonly=True, @@ -76,103 +101,6 @@ class StockInventoryRevaluation(models.Model): readonly=True, states={'draft': [('readonly', False)]}) - line_ids = fields.One2many('stock.inventory.revaluation.line', - 'revaluation_id', - string='Revaluation lines', - readonly=False, - states={'posted': [('readonly', True)]}) - - @api.model - def create(self, values): - sequence_obj = self.env['ir.sequence'] - if values.get('name', '/') == '/': - values['name'] = sequence_obj.get('stock.inventory.revaluation') - return super(StockInventoryRevaluation, self).create(values) - - @api.one - def post(self): - for line in self.line_ids: - if line.product_template_id.valuation != 'real_time': - continue - line.post() - return True - - @api.multi - def button_post(self): - self.post() - self.write({'state': 'posted'}) - return True - - @api.multi - def button_draft(self): - self.write({'state': 'draft'}) - return True - - @api.multi - def button_cancel(self): - moves = self.env['account.move'] - for line in self.line_ids: - if line.move_id: - moves += line.move_id - for line_quant in line.line_quant_ids: - if line_quant.move_id: - moves += line_quant.move_id - line_quant.quant_id.write({'cost': line_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'}) - return True - - -class StockInventoryRevaluationLine(models.Model): - - _name = 'stock.inventory.revaluation.line' - _description = 'Inventory revaluation line' - - @api.one - 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 - - @api.one - 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 - - @api.one - @api.depends("product_template_id", "product_template_id.standard_price") - def _calc_current_cost(self): - self.current_cost = self.product_template_id.standard_price - - revaluation_id = fields.Many2one('stock.inventory.revaluation', - 'Stock Inventory Revaluation', - required=True, - ondelete='cascade') - - state = fields.Selection(selection=_STATES, - string='UoM', readonly=True, - related="revaluation_id.state") - product_template_id = fields.Many2one('product.template', 'Product', required=True, domain=[('type', '=', 'product')]) @@ -239,26 +167,17 @@ class StockInventoryRevaluationLine(models.Model): "the transaction created by the revaluation. The Decrease " "Account is used when the inventory value is decreased.") - company_id = fields.Many2one( - comodel_name='res.company', string='Company', readonly=True, - related="revaluation_id.company_id") + move_id = fields.Many2one('account.move', 'Account move', readonly=True, + copy=False) - move_id = fields.Many2one('account.move', 'Account move', readonly=True) + reval_quant_ids = fields.One2many('stock.inventory.revaluation.quant', + 'revaluation_id', + string='Revaluation line quants') - revaluation_type = fields.Selection( - string="Revaluation Type", readonly=True, - related='revaluation_id.revaluation_type', - default='price_change') - - line_quant_ids = fields.One2many('stock.inventory.revaluation.line.quant', - 'line_id', - string='Revaluation line quants') - - _sql_constraints = [ - ('inv_valu_line_prod_temp_uniq', - 'unique (revaluation_id, product_template_id)', - _('Cannot enter the same product multiple times in the same ' - 'inventory valuation!'))] + @api.one + @api.depends("product_template_id", "product_template_id.standard_price") + def _calc_current_cost(self): + self.current_cost = self.product_template_id.standard_price @api.one @api.constrains('product_template_id', 'company_id') @@ -277,7 +196,6 @@ class StockInventoryRevaluationLine(models.Model): self.decrease_account_id = self.product_template_id.categ_id and \ self.product_template_id.categ_id.\ property_inventory_revaluation_decrease_account_categ - self.revaluation_type = self.revaluation_id.revaluation_type @api.model def _prepare_move_data(self, date_move): @@ -285,17 +203,17 @@ class StockInventoryRevaluationLine(models.Model): period = self.env['account.period'].find(date_move)[0] return { - 'narration': self.revaluation_id.remarks, + 'narration': self.remarks, 'date': date_move, - 'ref': self.revaluation_id.name, - 'journal_id': self.revaluation_id.journal_id.id, + 'ref': self.name, + 'journal_id': self.journal_id.id, 'period_id': period.id, } @api.model def _prepare_debit_move_line_data(self, amount, account_id, prod_id): return { - 'name': self.revaluation_id.name, + 'name': self.name, 'date': self.move_id.date, 'product_id': prod_id, 'account_id': account_id, @@ -306,7 +224,7 @@ class StockInventoryRevaluationLine(models.Model): @api.model def _prepare_credit_move_line_data(self, amount, account_id, prod_id): return { - 'name': self.revaluation_id.name, + 'name': self.name, 'date': self.move_id.date, 'product_id': prod_id, 'account_id': account_id, @@ -352,15 +270,15 @@ class StockInventoryRevaluationLine(models.Model): amount_diff = 0.0 if self.product_template_id.cost_method == 'real': - for line_quant in self.line_quant_ids: - amount_diff += line_quant.get_total_value() - line_quant.write_new_cost() + 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 self.revaluation_id.revaluation_type == 'price_change': + if self.revaluation_type == 'price_change': diff = self.current_cost - self.new_cost amount_diff = self.qty_available * diff else: @@ -376,7 +294,7 @@ class StockInventoryRevaluationLine(models.Model): "is 0 or negative" % self.product_template_id.name)) - if self.revaluation_id.revaluation_type == 'price_change': + if self.revaluation_type == 'price_change': self.old_cost = self.current_cost self.product_template_id.write({'standard_price': self.new_cost}) @@ -391,15 +309,50 @@ class StockInventoryRevaluationLine(models.Model): if self.product_template_id.valuation == 'real_time': self._create_accounting_entry(amount_diff) + @api.model + def create(self, values): + sequence_obj = self.env['ir.sequence'] + if values.get('name', '/') == '/': + values['name'] = sequence_obj.get('stock.inventory.revaluation') + return super(StockInventoryRevaluation, self).create(values) -class StockInventoryRevaluationLineQuant(models.Model): + @api.multi + def button_post(self): + self.post() + self.write({'state': 'posted'}) + return True - _name = 'stock.inventory.revaluation.line.quant' - _description = 'Inventory revaluation line quant' + @api.multi + def button_draft(self): + self.write({'state': 'draft'}) + return True - line_id = fields.Many2one('stock.inventory.revaluation.line', - 'Revaluation Line', required=True, - readonly=True) + @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'}) + return True + + +class StockInventoryRevaluationQuant(models.Model): + + _name = 'stock.inventory.revaluation.quant' + _description = 'Inventory revaluation quant' + + revaluation_id = fields.Many2one('stock.inventory.revaluation', + 'Revaluation', required=True, + readonly=True) quant_id = fields.Many2one('stock.quant', 'Quant', required=True, readonly=True, @@ -434,10 +387,14 @@ class StockInventoryRevaluationLineQuant(models.Model): digits=dp.get_precision('Product Price'), copy=False) + company_id = fields.Many2one( + comodel_name='res.company', string='Company', readonly=True, + related="revaluation_id.company_id") + def get_total_value(self): amount_diff = 0.0 if self.product_id.product_tmpl_id.cost_method == 'real': - if self.line_id.revaluation_id.revaluation_type != 'price_change': + if self.revaluation_id.revaluation_type != 'price_change': raise UserError(_("You can only post quant cost changes.")) else: diff = self.current_cost - self.new_cost diff --git a/stock_inventory_revaluation/security/ir.model.access.csv b/stock_inventory_revaluation/security/ir.model.access.csv index e397f0906..836d2f88d 100644 --- a/stock_inventory_revaluation/security/ir.model.access.csv +++ b/stock_inventory_revaluation/security/ir.model.access.csv @@ -1,4 +1,3 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_stock_inventory_revaluation,stock.inventory.revaluation,model_stock_inventory_revaluation,stock_account.group_inventory_valuation,1,1,1,1 -access_stock_inventory_revaluation_line,stock.inventory.revaluation.line,model_stock_inventory_revaluation_line,stock_account.group_inventory_valuation,1,1,1,1 -access_stock_inventory_revaluation_line_quant,stock.inventory.revaluation.line.quant,model_stock_inventory_revaluation_line_quant,stock_account.group_inventory_valuation,1,1,1,1 \ No newline at end of file +access_stock_inventory_revaluation_quant,stock.inventory.revaluation.quant,model_stock_inventory_revaluation_quant,stock_account.group_inventory_valuation,1,1,1,1 \ No newline at end of file diff --git a/stock_inventory_revaluation/security/stock_inventory_revaluation_security.xml b/stock_inventory_revaluation/security/stock_inventory_revaluation_security.xml index 1d59b4afa..6ea478999 100644 --- a/stock_inventory_revaluation/security/stock_inventory_revaluation_security.xml +++ b/stock_inventory_revaluation/security/stock_inventory_revaluation_security.xml @@ -10,9 +10,9 @@ ('company_id','child_of',[user.company_id.id])] - - Stock Inventory Revaluation line multi-company - + + Stock Inventory Revaluation quant multi-company + ['|',('company_id','=',False), ('company_id','child_of',[user.company_id.id])] diff --git a/stock_inventory_revaluation/tests/test_stock_inventory_revaluation.py b/stock_inventory_revaluation/tests/test_stock_inventory_revaluation.py index cb5626410..eb3dd08ae 100644 --- a/stock_inventory_revaluation/tests/test_stock_inventory_revaluation.py +++ b/stock_inventory_revaluation/tests/test_stock_inventory_revaluation.py @@ -18,13 +18,12 @@ class TestStockInventoryRevaluation(TransactionCase): self.product_model = self.env['product.product'] self.product_ctg_model = self.env['product.category'] self.reval_model = self.env['stock.inventory.revaluation'] - self.reval_line_model = self.env['stock.inventory.revaluation.line'] self.account_model = self.env['account.account'] self.acc_type_model = self.env['account.account.type'] - self.reval_line_quant_model = self.\ - env['stock.inventory.revaluation.line.quant'] + self.reval_quant_model = self.\ + env['stock.inventory.revaluation.quant'] self.get_quant_model = self.\ - env['stock.inventory.revaluation.line.get.quant'] + env['stock.inventory.revaluation.get.quant'] 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'] @@ -128,19 +127,9 @@ class TestStockInventoryRevaluation(TransactionCase): }) return product - def _create_inventory_revaluation(self, journal, revaluation_type): - """Create a Inventory Revaluation with revaluation_type set to - price_change to recalculate inventory value according to new price.""" - inventory = self.reval_model.create({ - 'name': 'test_inventory_revaluation', - 'document_date': datetime.today(), - 'revaluation_type': revaluation_type, - 'journal_id': journal.id, - }) - return inventory - - def _create_inventory_revaluation_line(self, revaluation, product): - """Create a Inventory Revaluation line by applying + def _create_inventory_revaluation(self, journal, revaluation_type, + product): + """Create a Inventory Revaluation by applying increase and decrease account to it.""" self.increase_account_id = product.categ_id and \ product.categ_id.\ @@ -149,13 +138,16 @@ class TestStockInventoryRevaluation(TransactionCase): product.categ_id.\ property_inventory_revaluation_decrease_account_categ - line = self.reval_line_model.create({ + reval = self.reval_model.create({ + 'name': 'test_inventory_revaluation', + 'document_date': datetime.today(), + 'revaluation_type': revaluation_type, + 'journal_id': journal.id, 'product_template_id': product.id, - 'revaluation_id': revaluation.id, 'increase_account_id': self.increase_account_id.id, 'decrease_account_id': self.decrease_account_id.id, }) - return line + return reval def _update_product_qty(self, product, location, quantity): """Update Product quantity.""" @@ -167,74 +159,82 @@ class TestStockInventoryRevaluation(TransactionCase): product_qty.change_product_qty() return product_qty - def _get_quant(self, date_from, line): + def _get_quant(self, date_from, revaluation): """Get Quants for Inventory Revaluation between the date supplied.""" quant = self.get_quant_model.create({ 'date_from': date_from, 'date_to': datetime.today(), }) line_context = { - 'active_id': line.id, - 'active_ids': line.ids, - 'active_model': 'stock.inventory.revaluation.line', + 'active_id': revaluation.id, + 'active_ids': revaluation.ids, + 'active_model': 'stock.inventory.revaluation', } quant.with_context(line_context).process() - for line_quant in line.line_quant_ids: - line_quant.new_cost = 8.0 + for reval_quant in revaluation.reval_quant_ids: + reval_quant.new_cost = 8.0 - def test_inventory_revaluation_price_change(self): + def test_inventory_revaluation_price_change_real(self): """Test that the inventory is revaluated when the - inventory price for any product is changed.""" + inventory price for a product managed under real costing method is + changed.""" - # Create an Inventory Revaluation + # Create an Inventory Revaluation for real cost product revaluation_type = 'price_change' - invent_price_change = self._create_inventory_revaluation( - self.journal, revaluation_type) - - # Create an Inventory Revaluation Line for real cost product - invent_line_real = \ - self._create_inventory_revaluation_line( - invent_price_change, self.product_real.product_tmpl_id) + invent_price_change_real = \ + self._create_inventory_revaluation( + self.journal, revaluation_type, + self.product_real.product_tmpl_id) # Create an Inventory Revaluation Line Quant date_from = date.today() - timedelta(1) - self._get_quant(date_from, invent_line_real) + self._get_quant(date_from, invent_price_change_real) - # Create an Inventory Revaluation Line for average cost product - invent_line_avg = self._create_inventory_revaluation_line( - invent_price_change, self.product_average.product_tmpl_id) - # Post the inventory revaluation - invent_line_avg.new_cost = 8.00 - - invent_price_change.button_post() + invent_price_change_real.button_post() expected_result = (10.00 - 8.00) * 20.00 - for line in invent_price_change.line_ids: - for move_line in line.move_id.line_id: - if move_line.debit: - self.assertEqual(move_line.debit, expected_result, - 'Incorrect inventory revaluation for ' - 'type Price Change.') + + for move_line in invent_price_change_real.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.""" + revaluation_type = 'price_change' + # Create an Inventory Revaluation for average cost product + invent_price_change_average = self._create_inventory_revaluation( + self.journal, revaluation_type, + self.product_average.product_tmpl_id) + # Post the inventory revaluation + invent_price_change_average.new_cost = 8.00 + 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: + 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.""" - # Create an Inventory Revaluation for value change + # Create an Inventory Revaluation for value change for average + # cost product revaluation_type = 'inventory_value' - invent_inventory_value = self._create_inventory_revaluation( - self.journal, revaluation_type) - - # Create an Inventory Revaluation Line for average cost product - invent_line_average = self._create_inventory_revaluation_line( - invent_inventory_value, self.product_average.product_tmpl_id) - invent_line_average.new_value = 100.00 + invent_average = self._create_inventory_revaluation( + self.journal, revaluation_type, + self.product_average.product_tmpl_id) + invent_average.new_value = 100.00 # Post the inventory revaluation - invent_inventory_value.button_post() + invent_average.button_post() - for line in invent_inventory_value.line_ids: - for move_line in line.move_id.line_id: - if move_line.debit: - self.assertEqual(move_line.debit, 100.0, - 'Incorrect inventory revaluation for ' - 'type Inventory Debit/Credit.') + for move_line in invent_average.move_id.line_id: + if move_line.debit: + self.assertEqual(move_line.debit, 100.0, + 'Incorrect inventory revaluation for ' + 'type Inventory Debit/Credit.') diff --git a/stock_inventory_revaluation/views/stock_inventory_revaluation_view.xml b/stock_inventory_revaluation/views/stock_inventory_revaluation_view.xml index c1b50c5ed..8cbc47506 100644 --- a/stock_inventory_revaluation/views/stock_inventory_revaluation_view.xml +++ b/stock_inventory_revaluation/views/stock_inventory_revaluation_view.xml @@ -42,101 +42,71 @@ - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - -