From b2f535b479355b179edbe391f8577defb5abca76 Mon Sep 17 00:00:00 2001 From: Jordi Ballester Date: Mon, 28 Aug 2017 10:59:03 +0200 Subject: [PATCH] fixes permissions error when cancelling an inventory revaluation --- .../models/account_move.py | 6 +- .../models/stock_inventory_revaluation.py | 50 ++++++------ .../security/ir.model.access.csv | 3 + .../tests/test_stock_inventory_revaluation.py | 78 ++++++++++++++++--- 4 files changed, 100 insertions(+), 37 deletions(-) diff --git a/stock_inventory_revaluation/models/account_move.py b/stock_inventory_revaluation/models/account_move.py index 01144d4ba..a36202554 100644 --- a/stock_inventory_revaluation/models/account_move.py +++ b/stock_inventory_revaluation/models/account_move.py @@ -19,7 +19,8 @@ class AccountMove(models.Model): @api.multi def unlink(self): for rec in self: - if rec.stock_inventory_revaluation_id: + if rec.stock_inventory_revaluation_id and not \ + self.env.context.get('revaluation', False): raise exceptions.Warning( _("You cannot remove the journal item that is related " "to an inventory revaluation")) @@ -39,7 +40,8 @@ class AccountMoveLine(models.Model): @api.multi def unlink(self): for rec in self: - if rec.stock_inventory_revaluation_id: + if rec.stock_inventory_revaluation_id and 'revaluation' not in \ + self.env.context: raise exceptions.Warning( _("You cannot remove the journal item that is related " "to an inventory revaluation")) diff --git a/stock_inventory_revaluation/models/stock_inventory_revaluation.py b/stock_inventory_revaluation/models/stock_inventory_revaluation.py index e9b59843c..e7ca9a671 100644 --- a/stock_inventory_revaluation/models/stock_inventory_revaluation.py +++ b/stock_inventory_revaluation/models/stock_inventory_revaluation.py @@ -316,6 +316,7 @@ class StockInventoryRevaluation(models.Model): if revaluation.product_id.\ cost_method == 'real': for reval_quant in revaluation.reval_quant_ids: + reval_quant.old_cost = reval_quant.quant_id.cost reval_quant.write_new_cost() else: if revaluation.product_id.\ @@ -336,7 +337,9 @@ class StockInventoryRevaluation(models.Model): variant.name)) if revaluation.revaluation_type == 'price_change': revaluation.old_cost = revaluation.current_cost - revaluation.product_id.write( + revaluation.product_id.with_context( + force_company=revaluation.company_id.id + ).sudo().write( {'standard_price': revaluation.new_cost}) else: revaluation.old_cost = revaluation.current_cost @@ -344,16 +347,16 @@ class StockInventoryRevaluation(models.Model): value_diff = revaluation.current_value - \ revaluation.new_value new_cost = value_diff / revaluation.qty_available - revaluation.product_id.write( - {'standard_price': new_cost}) + revaluation.product_id.with_context( + force_company=revaluation.company_id.id + ).sudo().write({'standard_price': new_cost}) if revaluation.product_id.categ_id.\ property_valuation == 'real_time': - revaluation._create_accounting_entry() + revaluation.sudo()._create_accounting_entry() self.post_date = fields.Datetime.now() self.state = 'posted' amount_diff = 0.0 - diff = 0.0 if revaluation.product_id.\ cost_method == 'real': for reval_quant in revaluation.reval_quant_ids: @@ -364,23 +367,17 @@ class StockInventoryRevaluation(models.Model): else: if revaluation.product_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 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)) @api.model def create(self, values): @@ -404,14 +401,16 @@ class StockInventoryRevaluation(models.Model): def button_cancel(self): for revaluation in self: for reval_quant in revaluation.reval_quant_ids: - reval_quant.quant_id.write({'cost': reval_quant.old_cost}) + reval_quant.quant_id.sudo().write( + {'cost': reval_quant.old_cost}) if revaluation.account_move_ids: # second, invalidate the move(s) - revaluation.account_move_ids.button_cancel() + revaluation.account_move_ids.sudo().button_cancel() # delete the move this revaluation was pointing to # Note that the corresponding move_lines and move_reconciles # will be automatically deleted too - revaluation.account_move_ids.unlink() + revaluation.account_move_ids.sudo().with_context( + revaluation=True).unlink() revaluation.state = 'cancel' return True @@ -476,6 +475,5 @@ class StockInventoryRevaluationQuant(models.Model): @api.model def write_new_cost(self): - self.old_cost = self.current_cost self.quant_id.sudo().write({'cost': self.new_cost}) return True diff --git a/stock_inventory_revaluation/security/ir.model.access.csv b/stock_inventory_revaluation/security/ir.model.access.csv index ba416d40f..cbd785f32 100644 --- a/stock_inventory_revaluation/security/ir.model.access.csv +++ b/stock_inventory_revaluation/security/ir.model.access.csv @@ -2,3 +2,6 @@ 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_quant,stock.inventory.revaluation.quant,model_stock_inventory_revaluation_quant,stock_account.group_inventory_valuation,1,1,1,1 access_stock_inventory_revaluation_account_user,stock.inventory.revaluation.account.user,model_stock_inventory_revaluation,account.group_account_user,1,0,0,0 +access_stock_inventory_revaluation_account_journal,account.journal inventory revaluation,account.model_account_journal,stock_account.group_inventory_valuation,1,0,0,0 +access_stock_inventory_revaluation_account_move,account.move inventory revaluation,account.model_account_move,stock_account.group_inventory_valuation,1,0,0,0 +access_stock_inventory_revaluation_account_move_line inventory revaluation,account.move.line,account.model_account_move_line,stock_account.group_inventory_valuation,1,0,0,0 diff --git a/stock_inventory_revaluation/tests/test_stock_inventory_revaluation.py b/stock_inventory_revaluation/tests/test_stock_inventory_revaluation.py index a94aa6250..c9ecd6092 100644 --- a/stock_inventory_revaluation/tests/test_stock_inventory_revaluation.py +++ b/stock_inventory_revaluation/tests/test_stock_inventory_revaluation.py @@ -29,11 +29,18 @@ class TestStockInventoryRevaluation(TransactionCase): env['stock.inventory.revaluation.mass.post'] self.stock_change_model = self.env['stock.change.product.qty'] self.stock_location_model = self.env['stock.location'] + self.res_users_model = self.env['res.users'] # Get required Model data self.product_uom = self.env.ref('product.product_uom_unit') self.company = self.env.ref('base.main_company') + # groups + self.group_inventory_valuation = self.env.ref( + 'stock_account.group_inventory_valuation') + self.group_stock_user = self.env.ref( + 'stock.group_stock_user') + location = self.stock_location_model.search([('name', '=', 'WH')]) self.location = self.stock_location_model.search([('location_id', '=', location.id)]) @@ -73,6 +80,12 @@ class TestStockInventoryRevaluation(TransactionCase): # Create product category self.product_ctg = self._create_product_category() + # Create users + self.user1 = self._create_user('user_1', + [self.group_stock_user, + self.group_inventory_valuation], + self.company) + # Create a Product with real cost standard_price = 10.0 list_price = 20.0 @@ -103,13 +116,29 @@ class TestStockInventoryRevaluation(TransactionCase): self._update_product_qty(self.product_average_2, self.location, quantity) + def _create_user(self, login, groups, company): + """ Create a user.""" + group_ids = [group.id for group in groups] + user = \ + self.res_users_model.with_context( + {'no_reset_password': True}).create( + {'name': 'Test User', + 'login': login, + 'password': 'demo', + 'email': 'test@yourcompany.com', + 'company_id': company.id, + 'company_ids': [(4, company.id)], + 'groups_id': [(6, 0, group_ids)] + }) + return user + def _create_account(self, acc_type, name, code, company): """Create an account.""" account = self.account_model.create({ 'name': name, 'code': code, 'user_type_id': acc_type.id, - 'company_id': company.id + 'company_id': company.id, }) return account @@ -121,7 +150,7 @@ class TestStockInventoryRevaluation(TransactionCase): self.account_revaluation.id, 'property_inventory_revaluation_decrease_account_categ': self.account_revaluation.id, - 'property_valuation': 'real_time' + 'property_valuation': 'real_time', }) return product_ctg @@ -137,7 +166,7 @@ class TestStockInventoryRevaluation(TransactionCase): 'valuation': 'real_time', 'cost_method': cost_method, 'property_stock_account_input': self.account_grni.id, - 'property_stock_account_output': self.account_cogs.id + 'property_stock_account_output': self.account_cogs.id, }) return template.product_variant_ids[0] product = self.product_model.create( @@ -156,7 +185,7 @@ class TestStockInventoryRevaluation(TransactionCase): product.categ_id.\ property_inventory_revaluation_decrease_account_categ - reval = self.reval_model.create({ + reval = self.reval_model.sudo(self.user1).create({ 'name': 'test_inventory_revaluation', 'document_date': datetime.today(), 'revaluation_type': revaluation_type, @@ -198,7 +227,8 @@ class TestStockInventoryRevaluation(TransactionCase): '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 = self.mass_post_model.sudo(self.user1).with_context( + context).create({}) mass_post_wiz.process() return True @@ -221,7 +251,7 @@ class TestStockInventoryRevaluation(TransactionCase): date_from = date.today() - timedelta(1) self._get_quant(date_from, invent_price_change_real) - invent_price_change_real.button_post() + invent_price_change_real.sudo(self.user1).button_post() expected_result = (10.00 - 8.00) * 10.00 self.assertEqual(len( @@ -316,16 +346,16 @@ class TestStockInventoryRevaluation(TransactionCase): def test_mass_post(self): """Test mass post""" - revaluations = [] + revaluations = self.env['stock.inventory.revaluation'] # 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) + revaluations += 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) + revaluations += invent_value_change # Post the inventory revaluation using wizard self._mass_post(revaluations) @@ -333,3 +363,33 @@ class TestStockInventoryRevaluation(TransactionCase): # Check that both inventory valuations are now posted self.assertEqual(invent_price_change_average.state, 'posted') self.assertEqual(invent_value_change.state, 'posted') + + def test_cancel(self): + """Test cancel""" + # Create an Inventory Revaluation for real cost product + revaluation_type = 'price_change' + invent_price_change_real = \ + self._create_inventory_revaluation( + revaluation_type, + self.product_real_1) + + # Create an Inventory Revaluation Line Quant + date_from = date.today() - timedelta(1) + self._get_quant(date_from, invent_price_change_real) + + invent_price_change_real.sudo(self.user1).button_post() + + # Allow cancelling journal entries + invent_price_change_real.journal_id.sudo().update_posted = True + + # Cancel the inventory revaluation + invent_price_change_real.sudo(self.user1).button_cancel() + + for reval_quant in invent_price_change_real.reval_quant_ids: + self.assertEqual(reval_quant.quant_id.cost, 10.0, + 'Cancelling a revaluation does not restore the ' + 'original quant cost.') + + self.assertEqual(len( + invent_price_change_real.account_move_ids), 0, + 'Accounting entries have not been removed after cancel')