Skip to content

Commit aba6ea3

Browse files
committed
[IMP] inventory: Improve stock info and UI in product form
This improvement refines the product template form view to offer better stock visibility and user control, particularly for users operating in multi-company environments. The default buttons such as Update Quantity On Hand and Print Labels are hidden to reduce UI clutter and avoid confusion for non-storable or consumable products. A computed field is_multicompany has been added to restrict direct editing of stock quantities when the user is linked to multiple companies helping maintain data consistency. Additionally, the form now displays the current available quantity alongside its unit of measure with a clear Update button, making it easier for users to quickly act on stock changes. The Forecasted button label has also been clarified with an inline quantity display. Visual decorations on the virtual_available field indicate when stock is low or negative, allowing users to identify stock issues at a glance. A custom server action has been added to open the product replenish wizard, providing a fast and user-friendly way to restock products. Overall, these changes streamline the inventory management workflow and enhance the clarity and usability of the product form.
1 parent fbf9ee9 commit aba6ea3

File tree

5 files changed

+101
-0
lines changed

5 files changed

+101
-0
lines changed

quantity_on_hand/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import models

quantity_on_hand/__manifest__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
'name': 'Quantity on hand',
3+
'version': '1.0',
4+
'depends': ['stock'],
5+
'installable': True,
6+
'data': [
7+
'views/product_template_views.xml',
8+
],
9+
'license': 'LGPL-3',
10+
}

quantity_on_hand/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import product_template
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from odoo import api, fields, models
2+
3+
4+
class ProductTemplate(models.Model):
5+
_inherit = 'product.template'
6+
7+
is_multicompany = fields.Boolean(compute="_compute_is_multicompany")
8+
9+
@api.depends('company_id')
10+
def _compute_is_multicompany(self):
11+
for record in self:
12+
user = self.env.user
13+
record.is_multicompany = len(user.company_ids) > 1
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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+
<xpath expr="//field[@name='product_tooltip']" position='attributes'>
54+
<attribute name='invisible'>type == 'consu'</attribute>
55+
</xpath>
56+
57+
<xpath expr="//field[@name='product_tooltip']" position="after">
58+
<label for="qty_available" invisible='not is_storable'>Quantity On Hand</label>
59+
<span class="d-flex gap-3">
60+
<field name="qty_available"
61+
readonly="is_multicompany"
62+
class="oe_inline"
63+
invisible='not is_storable'
64+
/>
65+
<field name="uom_name" class="oe_inline" invisible='not is_storable' />
66+
<button type="action"
67+
name="%(stock.action_product_stock_view)d"
68+
class="oe_stat_button oe_inline opacity-0 opacity-100-hover"
69+
invisible='not is_storable'>
70+
Update
71+
</button>
72+
</span>
73+
</xpath>
74+
</field>
75+
</record>
76+
</odoo>

0 commit comments

Comments
 (0)