[REF] stock_account: valuation layer and not admin user

Carefully sudo when necessary.

task-2034044

closes odoo/odoo#34802

Signed-off-by: Simon Lejeune (sle) <sle@openerp.com>
This commit is contained in:
Simon Lejeune
2019-07-23 08:36:31 +00:00
parent f722ef0cb0
commit 7ef11e3c96
3 changed files with 69 additions and 15 deletions
+16 -10
View File
@@ -169,10 +169,11 @@ class ProductProduct(models.Model):
for product in self:
if product.cost_method not in ('standard', 'average'):
continue
if float_is_zero(product.quantity_svl, precision_rounding=product.uom_id.rounding):
quantity_svl = product.sudo().quantity_svl
if float_is_zero(quantity_svl, precision_rounding=product.uom_id.rounding):
continue
diff = new_price - product.standard_price
value = company_id.currency_id.round(product.quantity_svl * diff)
value = company_id.currency_id.round(quantity_svl * diff)
if company_id.currency_id.is_zero(value):
continue
@@ -184,7 +185,7 @@ class ProductProduct(models.Model):
'quantity': 0,
}
svl_vals_list.append(svl_vals)
stock_valuation_layers = self.env['stock.valuation.layer'].create(svl_vals_list)
stock_valuation_layers = self.env['stock.valuation.layer'].sudo().create(svl_vals_list)
# Handle account moves.
product_accounts = {product.id: product.product_tmpl_id.get_product_accounts() for product in self}
@@ -233,7 +234,7 @@ class ProductProduct(models.Model):
account_moves.post()
# Actually update the standard price.
self.write({'standard_price': new_price})
self.with_context(force_company=company_id.id).sudo().write({'standard_price': new_price})
def _run_fifo(self, quantity, company):
self.ensure_one()
@@ -291,16 +292,21 @@ class ProductProduct(models.Model):
}
return vals
def _run_fifo_vacuum(self):
def _run_fifo_vacuum(self, company=None):
"""Compensate layer valued at an estimated price with the price of future receipts
if any. If the estimated price is equals to the real price, no layer is created but
the original layer is marked as compensated.
:param company: recordset of `res.company` to limit the execution of the vacuum
"""
self.ensure_one()
svls_to_vacuum = self.env['stock.valuation.layer'].search([
if company is None:
company = self.env.company
svls_to_vacuum = self.env['stock.valuation.layer'].sudo().search([
('product_id', '=', self.id),
('remaining_qty', '<', 0),
('stock_move_id', '!=', False),
('company_id', '=', company.id),
])
for svl_to_vacuum in svls_to_vacuum:
domain = [
@@ -313,7 +319,7 @@ class ProductProduct(models.Model):
('create_date', '=', svl_to_vacuum.create_date),
('id', '>', svl_to_vacuum.id)
]
candidates = self.env['stock.valuation.layer'].search(domain)
candidates = self.env['stock.valuation.layer'].sudo().search(domain)
if not candidates:
continue
qty_to_take_on_candidates = abs(svl_to_vacuum.remaining_qty)
@@ -359,7 +365,7 @@ class ProductProduct(models.Model):
'company_id': move.company_id.id,
'description': 'Revaluation of %s (negative inventory)' % move.picking_id.name or move.name,
}
vacuum_svl = self.env['stock.valuation.layer'].create(vals)
vacuum_svl = self.env['stock.valuation.layer'].sudo().create(vals)
# Create the account move.
if self.valuation != 'real_time':
@@ -683,7 +689,7 @@ class ProductCategory(models.Model):
% (self.display_name, self.property_valuation, new_valuation)
out_svl_vals_list, products_orig_quantity_svl, products = Product\
._svl_empty_stock(description, product_category=product_category)
out_stock_valuation_layers = SVL.create(out_svl_vals_list)
out_stock_valuation_layers = SVL.sudo().create(out_svl_vals_list)
if product_category.property_valuation == 'real_time':
move_vals_list += Product._svl_empty_stock_am(out_stock_valuation_layers)
impacted_categories[product_category] = (products, description, products_orig_quantity_svl)
@@ -693,7 +699,7 @@ class ProductCategory(models.Model):
for product_category, (products, description, products_orig_quantity_svl) in impacted_categories.items():
# Replenish the stock with the new cost method.
in_svl_vals_list = products._svl_replenish_stock(description, products_orig_quantity_svl)
in_stock_valuation_layers = SVL.create(in_svl_vals_list)
in_stock_valuation_layers = SVL.sudo().create(in_svl_vals_list)
if product_category.property_valuation == 'real_time':
move_vals_list += Product._svl_replenish_stock_am(in_stock_valuation_layers)
+6 -5
View File
@@ -160,7 +160,7 @@ class StockMove(models.Model):
if forced_quantity:
svl_vals['description'] = 'Correction of %s (modification of past move)' % move.picking_id.name or move.name
svl_vals_list.append(svl_vals)
return self.env['stock.valuation.layer'].create(svl_vals_list)
return self.env['stock.valuation.layer'].sudo().create(svl_vals_list)
def _create_out_svl(self, forced_quantity=None):
"""Create a `stock.valuation.layer` from `self`.
@@ -179,7 +179,7 @@ class StockMove(models.Model):
if forced_quantity:
svl_vals['description'] = 'Correction of %s (modification of past move)' % move.picking_id.name or move.name
svl_vals_list.append(svl_vals)
return self.env['stock.valuation.layer'].create(svl_vals_list)
return self.env['stock.valuation.layer'].sudo().create(svl_vals_list)
def _create_dropshipped_svl(self, forced_quantity=None):
"""Create a `stock.valuation.layer` from `self`.
@@ -218,7 +218,7 @@ class StockMove(models.Model):
}
out_vals.update(common_vals)
svl_vals_list.append(out_vals)
return self.env['stock.valuation.layer'].create(svl_vals_list)
return self.env['stock.valuation.layer'].sudo().create(svl_vals_list)
def _create_dropshipped_returned_svl(self, forced_quantity=None):
"""Create a `stock.valuation.layer` from `self`.
@@ -242,7 +242,7 @@ class StockMove(models.Model):
res = super(StockMove, self)._action_done(cancel_backorder=cancel_backorder)
stock_valuation_layers = self.env['stock.valuation.layer']
stock_valuation_layers = self.env['stock.valuation.layer'].sudo()
# Create the valuation layers in batch by calling `moves._create_valued_type_svl`.
for valued_type in self._get_valued_types():
todo_valued_moves = valued_moves[valued_type]
@@ -260,8 +260,9 @@ class StockMove(models.Model):
# For every in move, run the vacuum for the linked product.
products_to_vacuum = valued_moves['in'].mapped('product_id')
company = valued_moves['in'].mapped('company_id') and valued_moves['in'].mapped('company_id')[0] or self.env.company
for product_to_vacuum in products_to_vacuum:
product_to_vacuum._run_fifo_vacuum()
product_to_vacuum._run_fifo_vacuum(company)
return res
@@ -29,6 +29,13 @@ class TestStockValuation(SavepointCase):
'type': 'product',
'categ_id': cls.env.ref('product.product_category_all').id,
})
cls.inventory_user = cls.env['res.users'].create({
'name': 'Pauline Poivraisselle',
'login': 'pauline',
'email': 'p.p@example.com',
'notification_type': 'inbox',
'groups_id': [(6, 0, [cls.env.ref('stock.group_stock_user').id])]
})
cls.product1.categ_id.property_valuation = 'real_time'
cls.product2.categ_id.property_valuation = 'real_time'
@@ -2674,6 +2681,46 @@ class TestStockValuation(SavepointCase):
self.assertAlmostEqual(self.product1.quantity_svl, 0.0)
self.assertAlmostEqual(self.product1.value_svl, 0.0)
def test_standard_manual_2(self):
"""Validate a receipt as a regular stock user."""
self.product1.categ_id.property_cost_method = 'standard'
self.product1.categ_id.property_valuation = 'manual_periodic'
self.product1.with_user(self.inventory_user)._change_standard_price(10)
move1 = self.env['stock.move'].with_user(self.inventory_user).create({
'name': 'IN 10 units',
'location_id': self.supplier_location.id,
'location_dest_id': self.stock_location.id,
'product_id': self.product1.id,
'product_uom': self.uom_unit.id,
'product_uom_qty': 10.0,
})
move1._action_confirm()
move1._action_assign()
move1.move_line_ids.qty_done = 10.0
move1._action_done()
def test_standard_perpetual_1(self):
"""Validate a receipt as a regular stock user."""
self.product1.categ_id.property_cost_method = 'standard'
self.product1.categ_id.property_valuation = 'real_time'
self.product1.with_user(self.inventory_user)._change_standard_price(10)
move1 = self.env['stock.move'].with_user(self.inventory_user).create({
'name': 'IN 10 units',
'location_id': self.supplier_location.id,
'location_dest_id': self.stock_location.id,
'product_id': self.product1.id,
'product_uom': self.uom_unit.id,
'product_uom_qty': 10.0,
})
move1._action_confirm()
move1._action_assign()
move1.move_line_ids.qty_done = 10.0
move1._action_done()
def test_change_cost_method_1(self):
""" Change the cost method from FIFO to AVCO.
"""