Files
odoo_source/addons/stock_account/models/stock_quant.py
T
Tiffany Chang (tic) 06a2d3baaf [IMP] stock{_account}: update UX of valuation report
Note this is specific to the view shown when clicking on
"Reporting > Valuation", but this uses the same 'stock.quantity.history'
wizard and related custom js as "Configuration > Locations > Current Stock"

Minor UX updates to valuation report:
- don't default groupby product
- add filters incoming and outgoing (same logic as stock.move filters)
- replace "Inventory at Date" with "Valuation at Date" where appropriate
  (but leave location current stock view untouched)
- create separate view for the valuation report so remaining qty/value
  are displayed, but all other svl viewing actions (including the
  "Valuation at Date") will remain showing the original qty/value to
  support deeper analysis
- don't sum unit_cost when groupby is applied in list view since the
  value won't make sense
- add "reference" to svl which is = to stock.move.reference

"valuation" part of b2b task: 2882539

Part-of: odoo/odoo#97109
2022-08-29 23:46:35 +02:00

77 lines
3.8 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
from odoo.tools.float_utils import float_is_zero
from odoo.tools.misc import groupby
class StockQuant(models.Model):
_inherit = 'stock.quant'
value = fields.Monetary('Value', compute='_compute_value', groups='stock.group_stock_manager')
currency_id = fields.Many2one('res.currency', compute='_compute_value', groups='stock.group_stock_manager')
accounting_date = fields.Date(
'Accounting Date',
help="Date at which the accounting entries will be created"
" in case of automated inventory valuation."
" If empty, the inventory date will be used.")
cost_method = fields.Selection(related="product_categ_id.property_cost_method")
@api.depends('company_id', 'location_id', 'owner_id', 'product_id', 'quantity')
def _compute_value(self):
""" (Product.value_svl / Product.quantity_svl) * quant.quantity, i.e. average unit cost * on hand qty
"""
for quant in self:
quant.currency_id = quant.company_id.currency_id
if not quant.location_id or not quant.product_id or\
not quant.location_id._should_be_valued() or\
(quant.owner_id and quant.owner_id != quant.company_id.partner_id) or\
float_is_zero(quant.quantity, precision_rounding=quant.product_id.uom_id.rounding):
quant.value = 0
continue
quantity = quant.product_id.with_company(quant.company_id).quantity_svl
if float_is_zero(quantity, precision_rounding=quant.product_id.uom_id.rounding):
quant.value = 0.0
continue
quant.value = quant.quantity * quant.product_id.with_company(quant.company_id).value_svl / quantity
@api.model
def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):
""" This override is done in order for the grouped list view to display the total value of
the quants inside a location. This doesn't work out of the box because `value` is a computed
field.
"""
if 'value' not in fields:
return super(StockQuant, self).read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy)
res = super(StockQuant, self).read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy)
for group in res:
if group.get('__domain'):
quants = self.search(group['__domain'])
group['value'] = sum(quant.value for quant in quants)
return res
def _apply_inventory(self):
for accounting_date, inventory_ids in groupby(self, key=lambda q: q.accounting_date):
inventories = self.env['stock.quant'].concat(*inventory_ids)
if accounting_date:
super(StockQuant, inventories.with_context(force_period_date=accounting_date))._apply_inventory()
inventories.accounting_date = False
else:
super(StockQuant, inventories)._apply_inventory()
def _get_inventory_move_values(self, qty, location_id, location_dest_id, out=False):
res_move = super()._get_inventory_move_values(qty, location_id, location_dest_id, out)
if not self.env.context.get('inventory_name'):
force_period_date = self.env.context.get('force_period_date', False)
if force_period_date:
res_move['name'] += _(' [Accounted on %s]', force_period_date)
return res_move
@api.model
def _get_inventory_fields_write(self):
""" Returns a list of fields user can edit when editing a quant in `inventory_mode`."""
res = super()._get_inventory_fields_write()
res += ['accounting_date']
return res