diff --git a/addons/stock_account/data/product_data.xml b/addons/stock_account/data/product_data.xml index f1c3044dced..0d4e5602347 100644 --- a/addons/stock_account/data/product_data.xml +++ b/addons/stock_account/data/product_data.xml @@ -1,18 +1,6 @@ - - property_stock_account_output - - - - - - property_stock_account_input - - - - property_stock_account_output_categ_id diff --git a/addons/stock_account/data/stock_account_data.xml b/addons/stock_account/data/stock_account_data.xml index c71fee32837..45a9d817cde 100644 --- a/addons/stock_account/data/stock_account_data.xml +++ b/addons/stock_account/data/stock_account_data.xml @@ -1,18 +1,6 @@ - - Cost Method Property - - - selection - - - Valuation Property - - - selection - Cost Method Property diff --git a/addons/stock_account/models/product.py b/addons/stock_account/models/product.py index c95a3b3cd1f..3ecccb65beb 100644 --- a/addons/stock_account/models/product.py +++ b/addons/stock_account/models/product.py @@ -12,62 +12,11 @@ class ProductTemplate(models.Model): _name = 'product.template' _inherit = 'product.template' - property_valuation = fields.Selection([ - ('manual_periodic', 'Periodic (manual)'), - ('real_time', 'Perpetual (automated)')], string='Inventory Valuation', - company_dependent=True, copy=True, default='manual_periodic', - help="""Manual: The accounting entries to value the inventory are not posted automatically. - Automated: An accounting entry is automatically created to value the inventory when a product enters or leaves the company.""") - valuation = fields.Char(compute='_compute_valuation_type', inverse='_set_valuation_type') - property_cost_method = fields.Selection([ - ('standard', 'Standard Price'), - ('fifo', 'First In First Out (FIFO)'), - ('average', 'Average Cost (AVCO)')], string='Costing Method', - company_dependent=True, copy=True, - help="""Standard Price: The products are valued at their standard cost defined on the product. - Average Cost (AVCO): The products are valued at weighted average cost. - First In First Out (FIFO): The products are valued supposing those that enter the company first will also leave it first.""") - cost_method = fields.Char(compute='_compute_cost_method', inverse='_set_cost_method') - property_stock_account_input = fields.Many2one( - 'account.account', 'Stock Input Account', - company_dependent=True, domain=[('deprecated', '=', False)], - help="When doing real-time inventory valuation, counterpart journal items for all incoming stock moves will be posted in this account, unless " - "there is a specific valuation account set on the source location. When not set on the product, the one from the product category is used.") - property_stock_account_output = fields.Many2one( - 'account.account', 'Stock Output Account', - company_dependent=True, domain=[('deprecated', '=', False)], - help="When doing real-time inventory valuation, counterpart journal items for all outgoing stock moves will be posted in this account, unless " - "there is a specific valuation account set on the destination location. When not set on the product, the one from the product category is used.") - - @api.one - @api.depends('property_valuation', 'categ_id.property_valuation') - def _compute_valuation_type(self): - self.valuation = self.property_valuation or self.categ_id.property_valuation - - @api.one - def _set_valuation_type(self): - return self.write({'property_valuation': self.valuation}) - - @api.one - @api.depends('property_cost_method', 'categ_id.property_cost_method') - def _compute_cost_method(self): - self.cost_method = self.property_cost_method or self.categ_id.property_cost_method + cost_method = fields.Selection(related="categ_id.property_cost_method", readonly=True) + valuation = fields.Selection(related="categ_id.property_valuation", readonly=True) def _is_cost_method_standard(self): - return self.property_cost_method == 'standard' - - @api.one - def _set_cost_method(self): - # When going from FIFO to AVCO or to standard, we update the standard price with the - # average value in stock. - if self.property_cost_method == 'fifo' and self.cost_method in ['average', 'standard']: - # Cannot use the `stock_value` computed field as it's already invalidated when - # entering this method. - valuation = sum([variant._sum_remaining_values()[0] for variant in self.product_variant_ids]) - qty_available = self.with_context(company_owned=True).qty_available - if qty_available: - self.standard_price = valuation / qty_available - return self.write({'property_cost_method': self.cost_method}) + return self.categ_id.property_cost_method == 'standard' @api.multi def _get_product_accounts(self): @@ -77,8 +26,8 @@ class ProductTemplate(models.Model): accounts = super(ProductTemplate, self)._get_product_accounts() res = self._get_asset_accounts() accounts.update({ - 'stock_input': res['stock_input'] or self.property_stock_account_input or self.categ_id.property_stock_account_input_categ_id, - 'stock_output': res['stock_output'] or self.property_stock_account_output or self.categ_id.property_stock_account_output_categ_id, + 'stock_input': res['stock_input'] or self.categ_id.property_stock_account_input_categ_id, + 'stock_output': res['stock_output'] or self.categ_id.property_stock_account_output_categ_id, 'stock_valuation': self.categ_id.property_stock_valuation_account_id or False, }) return accounts @@ -177,7 +126,7 @@ class ProductProduct(models.Model): return sum(moves.mapped('remaining_value')), moves @api.multi - @api.depends('stock_move_ids.product_qty', 'stock_move_ids.state', 'stock_move_ids.remaining_value', 'product_tmpl_id.cost_method', 'product_tmpl_id.standard_price', 'product_tmpl_id.property_valuation', 'product_tmpl_id.categ_id.property_valuation') + @api.depends('stock_move_ids.product_qty', 'stock_move_ids.state', 'stock_move_ids.remaining_value', 'product_tmpl_id.cost_method', 'product_tmpl_id.standard_price', 'product_tmpl_id.categ_id.property_valuation') def _compute_stock_value(self): StockMove = self.env['stock.move'] to_date = self.env.context.get('to_date') @@ -402,6 +351,14 @@ class ProductCategory(models.Model): input_and_output_accounts = category.property_stock_account_input_categ_id | category.property_stock_account_output_categ_id if valuation_account and valuation_account in input_and_output_accounts: raise ValidationError(_('The Stock Input and/or Output accounts cannot be the same than the Stock Valuation account.')) + @api.multi + def write(self, vals): + # When going from FIFO to AVCO or to standard, we update the standard price with the + # average value in stock. + cost_method = vals.get('property_cost_method') + if cost_method and cost_method in ['average', 'standard']: + self._update_standard_price() + return super(ProductCategory, self).write(vals) @api.onchange('property_cost_method') def onchange_property_valuation(self): @@ -414,3 +371,12 @@ class ProductCategory(models.Model): 'message': _("Changing your cost method is an important change that will impact your inventory valuation. Are you sure you want to make that change?"), } } + + def _update_standard_price(self): + updated_categories = self.filtered(lambda x: x.property_cost_method == 'fifo') + templates = self.env['product.template'].search([('categ_id', 'in', updated_categories.ids)]) + for t in templates: + valuation = sum([variant._sum_remaining_values()[0] for variant in t.product_variant_ids]) + qty_available = t.with_context(company_owned=True).qty_available + if qty_available: + t.standard_price = valuation / qty_available diff --git a/addons/stock_account/models/stock.py b/addons/stock_account/models/stock.py index fc10fb468b9..c0d05ebbd0d 100644 --- a/addons/stock_account/models/stock.py +++ b/addons/stock_account/models/stock.py @@ -476,8 +476,6 @@ class StockMove(models.Model): def _run_fifo_vacuum(self): # Call `_fifo_vacuum` on concerned moves fifo_valued_products = self.env['product.product'] - fifo_valued_products |= self.env['product.template'].search([('property_cost_method', '=', 'fifo')]).mapped( - 'product_variant_ids') fifo_valued_categories = self.env['product.category'].search([('property_cost_method', '=', 'fifo')]) fifo_valued_products |= self.env['product.product'].search([('categ_id', 'child_of', fifo_valued_categories.ids)]) moves_to_vacuum = self.env['stock.move'] diff --git a/addons/stock_account/views/product_views.xml b/addons/stock_account/views/product_views.xml index 237a3862444..5a6326688fd 100644 --- a/addons/stock_account/views/product_views.xml +++ b/addons/stock_account/views/product_views.xml @@ -35,7 +35,6 @@ - - - - - - - -