Skip to content

Commit d3164e9

Browse files
committed
[ADD] inventory: Improve stock info and UI in product form
Before: Users could easily get confused or make mistakes when managing stock, especially in multi-company environments. Important actions like updating quantity on hand were hard to find, and the interface didn’t clearly guide safe workflows. After: The interface now better supports new users by reducing confusion and make stock workflows safer. Risky actions are hidden if not appropriate, visual clarity helps users avoid errors and understand inventory status more easily. task-4965098
1 parent fbf9ee9 commit d3164e9

File tree

5 files changed

+118
-0
lines changed

5 files changed

+118
-0
lines changed

quantity_on_hand/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Part of Odoo. See LICENSE file for full copyright and licensing details.
2+
3+
from . import models

quantity_on_hand/__manifest__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Part of Odoo. See LICENSE file for full copyright and licensing details.
2+
3+
{
4+
'name': 'Quantity on hand',
5+
'version': '1.0',
6+
'depends': ['stock'],
7+
'installable': True,
8+
'author': 'arkp',
9+
'data': [
10+
'views/product_template_views.xml',
11+
],
12+
'license': 'LGPL-3',
13+
}

quantity_on_hand/models/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Part of Odoo. See LICENSE file for full copyright and licensing details.
2+
3+
from . import product_template
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Part of Odoo. See LICENSE file for full copyright and licensing details.
2+
3+
from odoo import api, fields, models
4+
5+
6+
class ProductTemplate(models.Model):
7+
_inherit = 'product.template'
8+
9+
is_multilocation = fields.Boolean(compute="_compute_is_multilocation")
10+
11+
@api.depends('product_variant_ids.stock_quant_ids.location_id')
12+
def _compute_is_multilocation(self):
13+
for record in self:
14+
internal_location_ids = {
15+
loc.id
16+
for loc in record.mapped(
17+
'product_variant_ids.stock_quant_ids.location_id'
18+
)
19+
if loc.usage == 'internal'
20+
}
21+
record.is_multilocation = len(internal_location_ids) > 1
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<odoo>
3+
<record id="view_product_template_form_inherited" model="ir.ui.view">
4+
<field name="name">product.template.form.custom.inherit</field>
5+
<field name="model">product.template</field>
6+
<field name="inherit_id" ref="product.product_template_only_form_view" />
7+
<field name="arch" type="xml">
8+
9+
<xpath expr="//button[@name='action_update_quantity_on_hand']" position="attributes">
10+
<attribute name="invisible">1</attribute>
11+
</xpath>
12+
13+
<xpath expr="//button[@invisible='not show_on_hand_qty_status_button']"
14+
position="attributes">
15+
<attribute name="invisible">1</attribute>
16+
</xpath>
17+
18+
<xpath expr="//field[@name='virtual_available']"
19+
position='attributes'>
20+
<attribute name='decoration-danger'>virtual_available &lt; 0</attribute>
21+
<attribute name='decoration-primary'>virtual_available == 0</attribute>
22+
</xpath>
23+
24+
<xpath
25+
expr="//button[@name='action_product_tmpl_forecast_report']/div/span[hasclass('o_stat_value', 'd-flex', 'gap-1')]/field[@name='uom_name']"
26+
position='replace'>
27+
<span>Forecasted</span>
28+
</xpath>
29+
30+
<xpath
31+
expr="//button[@name='action_product_tmpl_forecast_report']/div/span[hasclass('o_stat_value', 'd-flex', 'gap-1')]"
32+
position='before'>
33+
<span class="o_stat_value d-flex gap-1">
34+
<field name="qty_available" nolabel="1" class="oe_inline" />
35+
<field name="uom_name" class="oe_inline" />
36+
</span>
37+
</xpath>
38+
39+
<xpath
40+
expr="//button[@name='action_product_tmpl_forecast_report']/div/span[hasclass('o_stat_text')]"
41+
position='attributes'>
42+
<attribute name='invisible'>1</attribute>
43+
</xpath>
44+
45+
</field>
46+
</record>
47+
48+
<record id="product_template_form_view_inherit" model="ir.ui.view">
49+
<field name="name">product.template.common.form.inherit</field>
50+
<field name="model">product.template</field>
51+
<field name="inherit_id" ref="product.product_template_form_view" />
52+
<field name="arch" type="xml">
53+
54+
<xpath expr="//field[@name='product_tooltip']" position='attributes'>
55+
<attribute name='invisible'>type == 'consu'</attribute>
56+
</xpath>
57+
58+
<xpath expr="//field[@name='product_tooltip']" position="after">
59+
<label for="qty_available" invisible='not is_storable'>Quantity On Hand</label>
60+
<span class="d-flex gap-3">
61+
<field name="qty_available"
62+
readonly="is_multilocation"
63+
class="oe_inline"
64+
invisible='not is_storable'
65+
/>
66+
<field name="uom_name" class="oe_inline" invisible='not is_storable' />
67+
<button type="action"
68+
name="%(stock.action_product_stock_view)d"
69+
class="oe_stat_button oe_inline opacity-0 opacity-100-hover"
70+
invisible="not is_storable">
71+
Update
72+
</button>
73+
</span>
74+
</xpath>
75+
76+
</field>
77+
</record>
78+
</odoo>

0 commit comments

Comments
 (0)