From 2c77efb05c9050663defe1bb997e489e4adb9b5f Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Sat, 11 May 2019 14:11:00 +0000 Subject: [PATCH] [ADD] stock_account: stock valuation layer This commit brings the model, views and compute method for the value and the quantity valued. An ir rule prevents to read the value of another company. Stat button are added on done picking to access the generated layers. Further commits will adapt one by one the cost method to actually use the stock valuation layer when As the goal is to move the valuation fields away from the stock move, we set the necessary fields on the layer. Note the absence of `remaining_value`. task-1875873 --- addons/stock_account/__manifest__.py | 1 + addons/stock_account/models/__init__.py | 2 + addons/stock_account/models/account_move.py | 2 + addons/stock_account/models/product.py | 20 ++++ addons/stock_account/models/stock_move.py | 1 + addons/stock_account/models/stock_picking.py | 15 +++ .../models/stock_valuation_layer.py | 27 ++++++ .../security/ir.model.access.csv | 1 + .../security/stock_account_security.xml | 7 ++ .../views/stock_valuation_layer_views.xml | 95 +++++++++++++++++++ 10 files changed, 171 insertions(+) create mode 100644 addons/stock_account/models/stock_picking.py create mode 100644 addons/stock_account/models/stock_valuation_layer.py create mode 100644 addons/stock_account/views/stock_valuation_layer_views.xml diff --git a/addons/stock_account/__manifest__.py b/addons/stock_account/__manifest__.py index ac9a54f1af0..e1fdfa3b079 100644 --- a/addons/stock_account/__manifest__.py +++ b/addons/stock_account/__manifest__.py @@ -31,6 +31,7 @@ Dashboard / Reports for Warehouse Management includes: 'views/res_config_settings_views.xml', 'data/product_data.xml', 'views/product_views.xml', + 'views/stock_valuation_layer_views.xml', ], 'test': [ ], diff --git a/addons/stock_account/models/__init__.py b/addons/stock_account/models/__init__.py index 134f11a2a47..9a0a869ef08 100644 --- a/addons/stock_account/models/__init__.py +++ b/addons/stock_account/models/__init__.py @@ -11,4 +11,6 @@ from . import stock_move from . import stock_inventory from . import stock_location from . import stock_move_line +from . import stock_picking +from . import stock_valuation_layer from . import res_config_settings diff --git a/addons/stock_account/models/account_move.py b/addons/stock_account/models/account_move.py index 97aebcdec29..be94260a407 100644 --- a/addons/stock_account/models/account_move.py +++ b/addons/stock_account/models/account_move.py @@ -10,3 +10,5 @@ class AccountMove(models.Model): _inherit = 'account.move' stock_move_id = fields.Many2one('stock.move', string='Stock Move') + stock_valuation_layer_ids = fields.One2many('stock.valuation.layer', 'account_move_id', string='Stock Valuation Layer') + diff --git a/addons/stock_account/models/product.py b/addons/stock_account/models/product.py index 8fb6a9ff916..b3c57626f97 100644 --- a/addons/stock_account/models/product.py +++ b/addons/stock_account/models/product.py @@ -60,6 +60,26 @@ class ProductProduct(models.Model): stock_fifo_manual_move_ids = fields.Many2many( 'stock.move', compute='_compute_stock_value') + value_svl = fields.Float(compute='_compute_value_svl') + quantity_svl = fields.Float(compute='_compute_value_svl') + stock_valuation_layer_ids = fields.One2many('stock.valuation.layer', 'product_id') + + @api.depends('stock_valuation_layer_ids') + def _compute_value_svl(self): + """Compute `value_svl` and `quantity_svl`.""" + domain = [ + ('product_id', 'in', self.ids), + ('company_id', '=', self.env.user.company_id.id) + ] + if self.env.context.get('to_date'): + to_date = fields.Datetime.to_datetime(self.env.context['to_date']) + domain.append(('create_date', '<=', to_date)) + groups = self.env['stock.valuation.layer'].read_group(domain, ['value:sum', 'quantity:sum'], ['product_id']) + for group in groups: + product = self.browse(group['product_id'][0]) + product.value_svl = group['value'] + product.quantity_svl = group['quantity'] + @api.multi def do_change_standard_price(self, new_price, account_id): """ Changes the Standard Price of Product and creates an account move accordingly.""" diff --git a/addons/stock_account/models/stock_move.py b/addons/stock_account/models/stock_move.py index 68ef562a79b..2d0ef85cb09 100644 --- a/addons/stock_account/models/stock_move.py +++ b/addons/stock_account/models/stock_move.py @@ -20,6 +20,7 @@ class StockMove(models.Model): remaining_qty = fields.Float(copy=False) remaining_value = fields.Float(copy=False) account_move_ids = fields.One2many('account.move', 'stock_move_id') + stock_valuation_layer_ids = fields.One2many('stock.valuation.layer', 'stock_move_id') @api.multi def action_get_account_moves(self): diff --git a/addons/stock_account/models/stock_picking.py b/addons/stock_account/models/stock_picking.py new file mode 100644 index 00000000000..cf3dba44314 --- /dev/null +++ b/addons/stock_account/models/stock_picking.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import models + + +class StockPicking(models.Model): + _inherit = 'stock.picking' + + def action_view_stock_valuation_layers(self): + self.ensure_one() + domain = [('id', 'in', self.move_lines.stock_valuation_layer_ids.ids)] + action = self.env.ref('stock_account.stock_valuation_layer_action').read()[0] + return dict(action, domain=domain) + diff --git a/addons/stock_account/models/stock_valuation_layer.py b/addons/stock_account/models/stock_valuation_layer.py new file mode 100644 index 00000000000..4eb6f5c86a8 --- /dev/null +++ b/addons/stock_account/models/stock_valuation_layer.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models + + +class StockValuationLayer(models.Model): + """Stock Valuation Layer""" + + _name = 'stock.valuation.layer' + _description = 'Stock Valuation Layer' + _order = 'create_date, id' + + _rec_name = 'product_id' + + company_id = fields.Many2one('res.company', 'Company', readonly=True, required=True) + product_id = fields.Many2one('product.product', 'Product', readonly=True, required=True) + quantity = fields.Float('Quantity', digits=0, help='Quantity', readonly=True) + uom_id = fields.Many2one(related='product_id.uom_id', readonly=True, required=True) + currency_id = fields.Many2one('res.currency', 'Currency', related='company_id.currency_id', readonly=True, required=True) + unit_cost = fields.Monetary('Unit Value', readonly=True) + value = fields.Monetary('Total Value', readonly=True) + remaining_qty = fields.Float(digits=0, readonly=True) + description = fields.Char('Description', readonly=True) + stock_move_id = fields.Many2one('stock.move', 'Stock Move', readonly=True) + account_move_id = fields.Many2one('account.move', 'Journal Entry', readonly=True) + diff --git a/addons/stock_account/security/ir.model.access.csv b/addons/stock_account/security/ir.model.access.csv index 3f44363eb0c..0a9ba71377d 100644 --- a/addons/stock_account/security/ir.model.access.csv +++ b/addons/stock_account/security/ir.model.access.csv @@ -2,3 +2,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_account_account_stock_manager,account.account stock manager,account.model_account_account,stock.group_stock_manager,1,0,0,0 access_stock_picking_invoicing_payments,stock.picking,stock.model_stock_picking,account.group_account_invoice,1,1,1,0 access_stock_move_invoicing_payments,stock.move,model_stock_move,account.group_account_invoice,1,1,1,0 +access_stock_valuation_layer,access_stock_valuation_layer,model_stock_valuation_layer,stock.group_stock_manager,1,1,1,0 diff --git a/addons/stock_account/security/stock_account_security.xml b/addons/stock_account/security/stock_account_security.xml index ea222a0fcc5..4a6f38ee61a 100644 --- a/addons/stock_account/security/stock_account_security.xml +++ b/addons/stock_account/security/stock_account_security.xml @@ -12,6 +12,13 @@ ['|',('company_id','=',False),('company_id', 'in', company_ids)] --> + + + Stock Valuation Layer Multicompany + + + [('company_id','=',user.company_id.id)] + diff --git a/addons/stock_account/views/stock_valuation_layer_views.xml b/addons/stock_account/views/stock_valuation_layer_views.xml new file mode 100644 index 00000000000..bbcbc1af797 --- /dev/null +++ b/addons/stock_account/views/stock_valuation_layer_views.xml @@ -0,0 +1,95 @@ + + + stock.valuation.layer.form + stock.valuation.layer + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + stock.valuation.layer.tree + stock.valuation.layer + + + + + + + + + + + + + + + stock.valuation.layer.tree + stock.valuation.layer + + + + + + + + + Stock Valuation + ir.actions.act_window + stock.valuation.layer + tree,form + form + + + {'search_default_group_by_product_id': 1} + +

+ There is no valuation layers. Valuation layers are created when some product moves should impact the valuation of the stock. +

+
+
+ + + stock.valuation.layer.picking + stock.picking + + + +