[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:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user