[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
This commit is contained in:
Tiffany Chang (tic)
2022-08-29 23:46:35 +02:00
parent 0d826efeb3
commit 06a2d3baaf
9 changed files with 100 additions and 9 deletions
@@ -31,7 +31,7 @@ var InventoryReportListController = ListController.extend({
// -------------------------------------------------------------------------
/**
* Handler called when the user clicked on the 'Inventory at Date' button.
* Handler called when the user clicked on the 'Valuation at Date' button.
* Opens wizard to display, at choice, the products inventory or a computed
* inventory at a given date.
*/
@@ -4,7 +4,9 @@
<t t-extend="ListView.buttons" t-name="StockInventoryReport.Buttons">
<t t-jquery="button.o_list_button_discard" t-operation="after">
<button class="btn btn-primary o_button_at_date me-2" type="button">
Inventory at Date
<t t-if="widget.modelName == 'stock.quant'">
Inventory at Date
</t>
</button>
</t>
</t>
+6
View File
@@ -35,10 +35,16 @@ Dashboard / Reports for Warehouse Management includes:
'views/stock_quant_views.xml',
'wizard/stock_request_count.xml',
'wizard/stock_valuation_layer_revaluation_views.xml',
'wizard/stock_quantity_history.xml',
'report/report_stock_forecasted.xml',
],
'installable': True,
'auto_install': True,
'post_init_hook': '_configure_journals',
'assets': {
'web.assets_qweb': [
'stock_account/static/src/xml/inventory_report.xml',
],
},
'license': 'LGPL-3',
}
@@ -16,6 +16,7 @@ class StockQuant(models.Model):
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):
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models, tools
from odoo import api, fields, models, tools
class StockValuationLayer(models.Model):
@@ -29,6 +29,7 @@ class StockValuationLayer(models.Model):
stock_valuation_layer_ids = fields.One2many('stock.valuation.layer', 'stock_valuation_layer_id')
stock_move_id = fields.Many2one('stock.move', 'Stock Move', readonly=True, check_company=True, index=True)
account_move_id = fields.Many2one('account.move', 'Journal Entry', readonly=True, check_company=True)
reference = fields.Char(related='stock_move_id.reference')
def init(self):
tools.create_index(
@@ -55,3 +56,9 @@ class StockValuationLayer(models.Model):
def _validate_analytic_accounting_entries(self):
for svl in self:
svl.stock_move_id._account_analytic_entry_move()
@api.model
def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):
if 'unit_cost' in fields:
fields.remove('unit_cost')
return super().read_group(domain, fields, groupby, offset, limit, orderby, lazy)
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<templates id="template" xml:space="preserve">
<t t-extend="StockInventoryReport.Buttons">
<t t-jquery="button.o_button_at_date" t-operation="append">
<t t-if="widget.modelName == 'stock.valuation.layer'">
Valuation at Date
</t>
</t>
</t>
</templates>
@@ -19,8 +19,14 @@
<field name="arch" type="xml">
<xpath expr="//field[@name='product_uom_id']" position="after">
<field name="currency_id" invisible="1"/>
<field name="cost_method" invisible="1"/>
<field name="value" optional="hidden" sum="Total Value"/>
<button name="%(stock_valuation_layer_action)d" title="Stock Valuation" type="action" class="btn-link" icon="fa-bar-chart" context="{'search_default_product_id': product_id}"/>
</xpath>
<xpath expr="//button[@name='action_view_orderpoints']" position="after">
<button name="%(stock_valuation_layer_report_action)d" title="Stock Valuation"
string="Valuation" type="action" class="btn-link" icon="fa-bar-chart"
context="{'search_default_product_id': product_id}"
attrs="{'invisible': [('cost_method', '!=', 'fifo')]}"/>
</xpath>
</field>
</record>
@@ -44,12 +44,14 @@
<tree default_order="create_date desc, id desc" create="0"
import="0" js_class="inventory_report_list">
<field name="create_date" string="Date" />
<field name="reference"/>
<field name="product_id" />
<field name="quantity" />
<field name="company_id" groups="base.group_multi_company"/>
<field name="quantity" string="Moved Quantity"/>
<field name="unit_cost" />
<field name="uom_id" groups="uom.group_uom" />
<field name="currency_id" invisible="1" />
<field name="value" sum="Total Value"/>
<field name="company_id" groups="base.group_multi_company" />
<groupby name="product_id">
<field name="cost_method" invisible="1"/>
<field name="quantity_svl" invisible="1"/>
@@ -77,11 +79,10 @@
<field name="view_mode">tree,form,pivot</field>
<field name="view_id" ref="stock_valuation_layer_tree"/>
<field name="domain">[('product_id.type', '=', 'product')]</field>
<field name="context">{'search_default_group_by_product_id': 1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face"/>
<p>
There is no valuation layers. Valuation layers are created when some product moves should impact the valuation of the stock.
There are no valuation layers. Valuation layers are created when there are product moves that impact the valuation of the stock.
</p>
</field>
</record>
@@ -95,6 +96,10 @@
<field name="categ_id" />
<field name="product_tmpl_id" />
<separator/>
<filter string="Incoming" name="incoming" domain="[('stock_move_id.location_id.usage', 'not in', ('internal', 'transit')), ('stock_move_id.location_dest_id.usage', 'in', ('internal', 'transit'))]"/>
<filter string="Outgoing" name="outgoing" domain="[('stock_move_id.location_id.usage', 'in', ('internal', 'transit')), ('stock_move_id.location_dest_id.usage', 'not in', ('internal', 'transit'))]"/>
<separator/>
<filter string="Has Remaining Qty" name="has_remaining_qty" domain="[('remaining_qty', '>', 0)]"/>
<group expand='0' string='Group by...'>
<filter string='Product' name="group_by_product_id" context="{'group_by': 'product_id'}"/>
</group>
@@ -102,7 +107,38 @@
</field>
</record>
<menuitem id="menu_valuation" name="Valuation" parent="stock.menu_warehouse_report" sequence="250" action="stock_valuation_layer_action" groups="base.group_no_one"/>
<!-- reporting view -->
<record id="stock_valuation_layer_report_tree" model="ir.ui.view">
<field name="name">stock.valuation.layer.report.tree</field>
<field name="model">stock.valuation.layer</field>
<field name="inherit_id" ref="stock_valuation_layer_tree"/>
<field name="mode">primary</field>
<field name="arch" type="xml">
<field name="unit_cost" position="after">
<field name="remaining_qty" sum="Total Remaining Quantity"/>
</field>
<field name="value" position="replace">
<field name="remaining_value" sum="Total Remaining Value"/>
</field>
</field>
</record>
<record id="stock_valuation_layer_report_action" model="ir.actions.act_window">
<field name="name">Stock Valuation</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">stock.valuation.layer</field>
<field name="view_mode">tree,form,pivot</field>
<field name="view_id" ref="stock_valuation_layer_report_tree"/>
<field name="context">{'search_default_has_remaining_qty': 1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face"/>
<p>
There are no valuation layers. Valuation layers are created when there are product moves that impact the valuation of the stock.
</p>
</field>
</record>
<menuitem id="menu_valuation" name="Valuation" parent="stock.menu_warehouse_report" sequence="250" action="stock_valuation_layer_report_action" groups="base.group_no_one"/>
<record id="stock_valuation_layer_picking" model="ir.ui.view">
<field name="name">stock.valuation.layer.picking</field>
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_stock_quantity_history_inherit_stock_account" model="ir.ui.view">
<field name="name">Valuation Report at Date</field>
<field name="model">stock.quantity.history</field>
<field name="inherit_id" ref="stock.view_stock_quantity_history"></field>
<field name="arch" type="xml">
<!-- ensure string/description matches the model we're looking at the history of -->
<field name="inventory_datetime" position="attributes">
<attribute name="invisible">
context.get('active_model') != 'stock.quant'
</attribute>
</field>
<field name="inventory_datetime" position="after">
<field name="inventory_datetime" string="Valuation at Date"
help="Choose a date to get the valuation at that date"
invisible="context.get('active_model') != 'stock.valuation.layer'"/>
</field>
</field>
</record>
</odoo>