[IMP] various: improve product form usability

This commit is contained in:
Kirti Choudhary
2018-08-08 14:51:11 +02:00
committed by RomainLibert
parent 10b9d06689
commit c1f7987f49
20 changed files with 179 additions and 172 deletions
+3
View File
@@ -7,6 +7,9 @@
<field name="priority">5</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='purchase']" position="attributes">
<attribute name="invisible">0</attribute>
</xpath>
<page name="inventory" position="after">
<page string="Accounting" name="invoicing" groups="account.group_account_user">
<group name="properties">
@@ -6,9 +6,11 @@
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="arch" type="xml">
<field name="categ_id" position="after">
<field name="hs_code"/>
</field>
<xpath expr="//group[@name='accounting']" position="inside">
<group string="GST" name="gst">
<field name="hs_code"/>
</group>
</xpath>
</field>
</record>
+2 -1
View File
@@ -260,7 +260,7 @@
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="arch" type="xml">
<div name="options" position="inside">
<div attrs="{'invisible': [('type','not in', ['consu', 'service'])]}">
<div>
<field name="can_be_expensed"/>
<label for="can_be_expensed"/>
</div>
@@ -310,6 +310,7 @@
<group string="Accounting">
<field name="property_account_expense_id" groups="account.group_account_user"/>
<field name="supplier_taxes_id" widget="many2many_tags"/>
<field name="taxes_id" widget="many2many_tags"/>
</group>
</group>
</sheet>
+1 -1
View File
@@ -7,7 +7,7 @@ from odoo.exceptions import UserError
class ProductTemplate(models.Model):
_inherit = 'product.template'
available_in_pos = fields.Boolean(string='Available in Point of Sale', help='Check if you want this product to appear in the Point of Sale', default=False)
available_in_pos = fields.Boolean(string='Available in POS', help='Check if you want this product to appear in the Point of Sale', default=False)
to_weight = fields.Boolean(string='To Weigh With Scale', help="Check if the product should be weighted using the hardware scale integration")
pos_categ_id = fields.Many2one(
'pos.category', string='Point of Sale Category',
+11 -7
View File
@@ -52,13 +52,17 @@
<field name="model">product.template</field>
<field name="inherit_id" ref="stock.view_template_property_form"/>
<field name="arch" type="xml">
<group name="email_template_and_project" position="before">
<group name="pos" string="Point of Sale">
<field name="available_in_pos"/>
<field name="pos_categ_id" attrs="{'invisible': [('available_in_pos', '=', False)]}" string="PoS Category"/>
<field name="to_weight" attrs="{'invisible': [('available_in_pos', '=', False)]}"/>
</group>
</group>
<xpath expr="//page[@name='sales']" position="after">
<page name="pos" string="Point of Sale" attrs="{'invisible': [('sale_ok','=',False)]}">
<group name="pos">
<group>
<field name="available_in_pos"/>
<field name="pos_categ_id" attrs="{'invisible': [('available_in_pos', '=', False)]}" string="Category"/>
<field name="to_weight" attrs="{'invisible': [('available_in_pos', '=', False)]}"/>
</group>
</group>
</page>
</xpath>
</field>
</record>
+34 -35
View File
@@ -60,7 +60,40 @@
<field name="currency_id" invisible="1"/>
<field name="product_variant_id" invisible="1"/>
</group>
<group name="group_lots_and_weight" attrs="{'invisible':[('type', 'not in', ['product', 'consu'])]}">
</group>
<group string="Internal Notes">
<field name="description" nolabel="1" placeholder="This note is only for internal purposes."/>
</group>
</page>
<page string="Sales" attrs="{'invisible':[('sale_ok','=',False)]}" name="sales" invisible="1">
<group name="sale">
<div name="pricelist_item" groups="product.group_product_pricelist">
<separator string="Pricing"/>
<field name="item_ids" nolabel="1" context="{'default_base':'list_price', 'default_applied_on' :'1_product'}">
<tree string="Pricelist Items" editable="bottom">
<field name="pricelist_id" string="Pricelist" required='1'/>
<field name="fixed_price" string="Price" required='1'/>
<field name="min_quantity"/>
<field name="date_start"/>
<field name="date_end"/>
<field name="applied_on" invisible="1"/>
</tree>
</field>
</div>
<group name="email_template_and_project" invisible="1"/>
</group>
<group string="Description for Customers" name="description">
<field name="description_sale" nolabel="1" placeholder="This note will show up on sales orders &amp; invoices."/>
</group>
</page>
<page string="Purchase" name="purchase" attrs="{'invisible': [('purchase_ok','=',False)]}" invisible="1">
<group name="purchase">
<group string="Vendor Bills" name="bill"/>
</group>
</page>
<page string="Inventory" name="inventory" groups="stock.group_stock_user,product.group_stock_packaging" attrs="{'invisible':[('type', '=', 'service')]}">
<group name="inventory">
<group name="group_lots_and_weight" string="Logistics" attrs="{'invisible': [('type', 'not in', ['product', 'consu'])]}">
<label for="weight"/>
<div class="o_row" name="weight">
<field name="weight"/>
@@ -72,41 +105,7 @@
<span>m³</span>
</div>
</group>
<group name="description_internal">
<group string="Description for Internal">
<field name="description" nolabel="1" placeholder="This note is only for internal purposes."/>
</group>
</group>
</group>
</page>
<page string="Sales" attrs="{'invisible':[('sale_ok','=',False)]}" name="sales">
<div name="pricelist_item" groups="product.group_product_pricelist">
<separator string="Pricing"/>
<field name="item_ids" nolabel="1" context="{'default_base':'list_price', 'default_applied_on' :'1_product'}">
<tree string="Pricelist Items" editable="bottom">
<field name="pricelist_id" string="Pricelist" required='1'/>
<field name="fixed_price" string="Price" required='1'/>
<field name="min_quantity"/>
<field name="date_start"/>
<field name="date_end"/>
<field name="applied_on" invisible="1"/>
</tree>
</field>
</div>
<group name="sale">
<group name="email_template_and_project"
attrs="{'invisible':[('type', '!=', 'service')]}"/>
</group>
<group string="Description for Customers" name="description">
<field name="description_sale" nolabel="1" placeholder="This note will show up on sales orders &amp; invoices."/>
</group>
</page>
<page string="Purchase" name="purchase" attrs="{'invisible': [('purchase_ok','=',False)]}">
<group name="purchase">
<group string="Vendor Bills" name="bill"/>
</group>
</page>
<page string="Inventory" name="inventory" groups="stock.group_stock_user,product.group_stock_packaging" attrs="{'invisible':[('type', '=', 'service')]}">
<group name="packaging" string="Packaging"
colspan="4"
attrs="{'invisible':['|', ('type', 'not in', ['product', 'consu']), ('product_variant_count', '>', 1)]}"
@@ -5,11 +5,11 @@
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="arch" type="xml">
<group name="email_template_and_project" position="attributes">
<attribute name="string">Email</attribute>
<attribute name="attrs"></attribute>
</group>
<group name="email_template_and_project" position="inside">
<xpath expr="//group[@name='email_template_and_project']" position="attributes">
<attribute name="string">Automatic Email at Invoice</attribute>
<attribute name="invisible">0</attribute>
</xpath>
<xpath expr="//group[@name='email_template_and_project']" position="inside">
<field name="email_template_id" string="Email Template" help="Send a product-specific email once the invoice is paid"
domain="[('model','=','product.template')]"
context="{
@@ -18,7 +18,7 @@
'default_subject': name,
'default_name': name,
}"/>
</group>
</xpath>
</field>
</record>
</odoo>
+3
View File
@@ -8,6 +8,9 @@
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='purchase']" position="attributes">
<attribute name="invisible">0</attribute>
</xpath>
<group name="purchase" position="before">
<group string="Vendors" name="vendors" attrs="{'invisible': [('product_variant_count','&gt;',1)]}">
<field name="seller_ids" context="{'default_product_tmpl_id':context.get('product_tmpl_id',active_id), 'product_template_invisible_variant': True}" nolabel="1"/>
+22 -10
View File
@@ -18,7 +18,28 @@ class ProductTemplate(models.Model):
expense_policy = fields.Selection(
[('no', 'No'), ('cost', 'At cost'), ('sales_price', 'Sales price')],
string='Re-Invoice Policy',
default='no')
default='no',
help="Expenses registered in Expense app or in a vendor bill (with an analytic account set) "
"can be automatically re-invoiced to the customer. This is useful for customer projects. "
"With this option activated, the validated expense is added to the sales order linked to the "
"analytic account, in order to be invoiced. With Project Management, such an analytic account "
"can be automatically generated at the order confirmation, if set on the Service Tracking "
"option of one product item.")
sales_count = fields.Float(compute='_compute_sales_count', string='Sold')
hide_expense_policy = fields.Boolean(compute='_compute_hide_expense_policy')
invoice_policy = fields.Selection(
[('order', 'Ordered quantities'),
('delivery', 'Delivered quantities'),
], string='Invoicing Policy',
help='Ordered Quantity: Invoice based on the quantity the customer ordered.\n'
'Delivered Quantity: Invoiced based on the quantity the vendor delivered (time or deliveries).',
default='order')
@api.multi
def _compute_hide_expense_policy(self):
hide_expense_policy = self.user_has_groups('!analytic.group_analytic_accounting,!project.group_project_user,!hr_expense.group_hr_expense_user')
for template in self:
template.hide_expense_policy = hide_expense_policy
@api.multi
@api.depends('product_variant_ids.sales_count')
@@ -44,15 +65,6 @@ class ProductTemplate(models.Model):
'domain': [('state', 'in', ['sale', 'done']), ('product_id.product_tmpl_id', '=', self.id)],
}
sales_count = fields.Integer(compute='_sales_count', string='# Sales')
invoice_policy = fields.Selection(
[('order', 'Ordered quantities'),
('delivery', 'Delivered quantities'),
], string='Invoicing Policy',
help='Ordered Quantity: Invoice based on the quantity the customer ordered.\n'
'Delivered Quantity: Invoiced based on the quantity the vendor delivered (time or deliveries).',
default='order')
@api.onchange('type')
def _onchange_type(self):
""" Force values to stay consistent with integrity constraints """
+4 -7
View File
@@ -929,17 +929,14 @@
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="arch" type="xml">
<group name="sale" position="inside">
<xpath expr="//group[@name='email_template_and_project']" position="before">
<group string="Invoicing" name="invoicing">
<field name="invoice_policy" widget="radio"/>
<field name="service_type" widget="radio" invisible="True"/>
<field name="hide_expense_policy" invisible="1"/>
<field name="expense_policy" widget="radio" attrs="{'invisible': [('hide_expense_policy', '=', True)]}"/>
</group>
</group>
<group name="purchase" position="inside">
<group string="Invoicing" name="invoicing">
<field name="expense_policy" widget="radio"/>
</group>
</group>
</xpath>
</field>
</record>
@@ -12,6 +12,12 @@
<field name="expense_policy"/>
</group>
</xpath>
<xpath expr="//field[@name='list_price']" position="replace">
<field name="list_price" attrs="{'invisible':[('expense_policy', '!=', 'sales_price')]}"/>
</xpath>
<xpath expr="//field[@name='taxes_id']" position="replace">
<field name="taxes_id" widget="many2many_tags" attrs="{'invisible':[('expense_policy', '=', 'no')]}"/>
</xpath>
</field>
</record>
@@ -100,4 +100,15 @@
</field>
</record>
<record model="ir.ui.view" id="product_template_sale_form_view">
<field name="name">product.template.sales</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='sales']" position="attributes">
<attribute name="invisible">0</attribute>
</xpath>
</field>
</record>
</odoo>
-1
View File
@@ -33,7 +33,6 @@ You can choose flexible invoicing methods:
'views/res_config_settings_views.xml',
'views/account_invoice_views.xml',
'views/sale_stock_portal_template.xml',
'views/product_template_views.xml',
'views/res_users_views.xml',
'views/stock_production_lot_views.xml',
'report/sale_order_report_templates.xml',
@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="product_template_view_form_view_inherit_invoice_policy" model="ir.ui.view">
<field name="name">product.template.form.expense.policy.inherit</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="sale.product_template_form_view_invoice_policy"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='expense_policy']" position="attributes">
<attribute name="attrs">{'invisible': [('type','=', 'product')]}</attribute>
</xpath>
</field>
</record>
</odoo>
+1 -1
View File
@@ -12,7 +12,7 @@ class ProductTemplate(models.Model):
('ordered_timesheet', 'Ordered quantities'),
('delivered_timesheet', 'Timesheets on tasks'),
('delivered_manual', 'Milestones (manually set quantities on order)')
], string="Invoice based on", compute='_compute_service_policy', inverse='_inverse_service_policy')
], string="Service Invoicing Policy", compute='_compute_service_policy', inverse='_inverse_service_policy')
service_type = fields.Selection(selection_add=[
('timesheet', 'Timesheets on project (one fare per SO/Project)'),
])
@@ -18,20 +18,6 @@
</field>
</record>
<record id="product_template_search_view_sale_timesheet" model="ir.ui.view">
<field name="name">product.template.search.timesheet</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_search_view"/>
<field name="arch" type="xml">
<xpath expr="//filter[@name='consumable']" position="after">
<separator/>
<filter string="Time-based services" name="product_time_based" domain="[('type', '=', 'service'), ('invoice_policy', '=', 'delivery'), ('service_type', '=', 'timesheet')]"/>
<filter string="Fixed price services" name="product_service_fixed" domain="[('type', '=', 'service'), ('invoice_policy', '=', 'order'), ('service_type', '=', 'timesheet')]"/>
<filter string="Milestone services" name="product_service_milestone" domain="[('type', '=', 'service'), ('invoice_policy', '=', 'delivery'), ('service_type', '=', 'manual')]"/>
</xpath>
</field>
</record>
<record id="product_template_action_time_based" model="ir.actions.act_window">
<field name="name">Products</field>
<field name="res_model">product.template</field>
+19 -21
View File
@@ -62,17 +62,17 @@
<record id="product_template_search_form_view_stock" model="ir.ui.view">
<field name="name">product.template.search.stock.form</field>
<field name="model">product.template</field>
<field name="mode">primary</field>
<field name="inherit_id" ref="product.product_template_search_view"/>
<field name="arch" type="xml">
<field name="pricelist_id" position="after">
<xpath expr="//field[@name='pricelist_id']" position="after">
<separator/>
<field name="location_id" widget="selection" context="{'location': self}"/>
<field name="warehouse_id" widget="selection" context="{'warehouse': self}"/>
<separator/>
<filter name="real_stock_available" string="Available Products" domain="[('qty_available','&gt;',0)]"/>
<filter name="real_stock_exhausted" string="Exhausted Stock" domain="[('qty_available','&lt;=',0),('type','not in',('service', 'consu'))]"/>
<filter name="real_stock_negative" string="Negative Stock" domain="[('qty_available','&lt;',0)]"/>
</field>
<filter name="real_stock_negative" string="Negative Forecasted Quantity" domain="[('virtual_available','&lt;',0)]"/>
</xpath>
</field>
</record>
@@ -82,23 +82,21 @@
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="arch" type="xml">
<xpath expr="//group[@name='packaging']" position="before">
<group name="inventory">
<group string="Operations" name="operations">
<field name="route_ids" widget="many2many_checkboxes" attrs="{'invisible':[('type', 'in', ['service', 'digital'])]}"/>
<field name="route_from_categ_ids" widget="many2many_tags" readonly="1" attrs="{'invisible':[('route_from_categ_ids', '=', [])]}"/>
<label for="sale_delay"/>
<div>
<field name="sale_delay" attrs="{'readonly':[('sale_ok','=',False)]}" class="oe_inline" style="vertical-align:baseline"/> days
</div>
</group>
<group string="Traceability" name="traceability" groups="stock.group_production_lot">
<field name="tracking" widget="radio" attrs="{'invisible':[('type', 'in', ['service', 'digital'])]}"/>
</group>
<group string="Counterpart Locations" name="stock_property" groups="base.group_no_one">
<field name="property_stock_production" domain="[('usage','=','production')]"/>
<field name="property_stock_inventory" domain="[('usage','=','inventory')]"/>
</group>
<xpath expr="//group[@name='group_lots_and_weight']" position="before">
<group string="Operations" name="operations">
<field name="route_ids" widget="many2many_checkboxes" attrs="{'invisible': [('type', 'in', ['service', 'digital'])]}"/>
<field name="route_from_categ_ids" widget="many2many_tags" readonly="1" attrs="{'invisible': [('route_from_categ_ids', '=', [])]}"/>
<label for="sale_delay" attrs="{'invisible': [('sale_ok', '=', False)]}"/>
<div attrs="{'invisible': [('sale_ok', '=', False)]}">
<field name="sale_delay" class="oe_inline" style="vertical-align:baseline"/> days
</div>
</group>
<group string="Traceability" name="traceability" groups="stock.group_production_lot">
<field name="tracking" widget="radio" attrs="{'invisible': [('type', 'in', ['service', 'digital'])]}"/>
</group>
<group string="Counterpart Locations" name="stock_property" groups="base.group_no_one">
<field name="property_stock_production" domain="[('usage', '=', 'production')]"/>
<field name="property_stock_inventory" domain="[('usage', '=', 'inventory')]"/>
</group>
</xpath>
<page name="inventory" position="inside">
+46 -45
View File
@@ -73,58 +73,59 @@
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="arch" type="xml">
<!-- add state field in header -->
<group name="email_template_and_project" position="before">
<group name="website" string="eCommerce" >
<field name="website_url" invisible="1"/>
<field name="public_categ_ids" widget="many2many_tags" string="eCommerce Categories"/>
<field name="alternative_product_ids" widget="many2many_tags"/>
<field name="accessory_product_ids" widget="many2many_tags"/>
<field name="website_style_ids" widget="many2many_tags" groups="base.group_no_one"/>
</group>
</group>
<button name="toggle_active" position="before">
<xpath expr="//button[@name='toggle_active']" position="before">
<button class="oe_stat_button" name="website_publish_button"
type="object" icon="fa-globe" attrs="{'invisible': [('sale_ok','=',False)]}">
<field name="website_published" widget="website_button"/>
</button>
</button>
<xpath expr="//notebook[last()]" position="inside">
<page string="Images">
<field name="product_image_ids" class="o_website_sale_image_list" context="{'default_name': name, 'default_product_tmpl_id': active_id}">
<kanban string="Product Images" class="o_attachments_previews">
<field name="name"/>
<field name="image"/>
<templates>
<t t-name="kanban-box">
<div class="o_attachment oe_kanban_global_click o_website_sale_image_card">
<div class="o_attachment_wrap">
<div class="o_image_box">
<div class="o_attachment_image" t-att-style="'background-image:url(data:image/png;base64,'+record.image.raw_value +')'"/>
<div t-attf-class="o_image_overlay" t-att-title="record.name.value"/>
<div class="o_website_sale_image_card_title" t-att-title="record.name.value">
<field name="name"/>
</xpath>
<xpath expr="//page[@name='sales']" position="after">
<page name="shop" string="eCommerce" attrs="{'invisible': [('sale_ok','=',False)]}">
<group name="shop">
<group string="Shop">
<field name="website_url" invisible="1"/>
<field name="public_categ_ids" widget="many2many_tags" string="Categories"/>
<field name="alternative_product_ids" widget="many2many_tags"/>
<field name="accessory_product_ids" widget="many2many_tags"/>
<field name="website_style_ids" widget="many2many_tags" groups="base.group_no_one"/>
</group>
</group>
<group name="extra_images" string="Extra Images">
<field name="product_image_ids" class="o_website_sale_image_list" context="{'default_name': name, 'default_product_tmpl_id': active_id}" nolabel="1">
<kanban string="Product Images" class="o_attachments_previews">
<field name="name"/>
<field name="image"/>
<templates>
<t t-name="kanban-box">
<div class="o_attachment oe_kanban_global_click o_website_sale_image_card">
<div class="o_attachment_wrap">
<div class="o_image_box">
<div class="o_attachment_image" t-att-style="'background-image:url(data:image/png;base64,'+record.image.raw_value +')'"/>
<div t-attf-class="o_image_overlay" t-att-title="record.name.value"/>
<div class="o_website_sale_image_card_title" t-att-title="record.name.value">
<field name="name"/>
</div>
</div>
<t t-set="size" t-value="[record.image.value][0]"/>
<t t-set="size_status" t-value="'normal'" t-if="size.indexOf('Bytes') !== -1 or ( size.indexOf('Kb') !== -1 and size[2]=='.')"/>
<t t-set="size_status" t-value="'warning'" t-elif="( size.indexOf('Kb') !== -1 and size[3]=='.')"/>
<t t-set="size_status" t-value="'danger'" t-else=""/>
<t t-set="message" t-value="'Acceptable file size'" t-if="size_status == 'normal'"></t>
<t t-set="message" t-value="'Huge file size. The image should be optimized/reduced.'" t-elif="size_status == 'warning'"></t>
<t t-set="message" t-value="'Optimization required! Reduce the image size or increase your compression settings.'" t-else=""></t>
<span t-attf-class="o_website_sale_image_card_size badge badge-#{size_status}" t-att-title="message">
<t t-esc="record.image.value"/>
</span>
<a role="button" t-if="!read_only_mode" type="delete" class="btn btn-sm btn-secondary o_website_sale_image_card_remove" aria-label="Remove" title="Remove"><i class="fa fa-trash"/></a>
</div>
<t t-set="size" t-value="[record.image.value][0]"/>
<t t-set="size_status" t-value="'normal'" t-if="size.indexOf('Bytes') !== -1 or ( size.indexOf('Kb') !== -1 and size[2]=='.')"/>
<t t-set="size_status" t-value="'warning'" t-elif="( size.indexOf('Kb') !== -1 and size[3]=='.')"/>
<t t-set="size_status" t-value="'danger'" t-else=""/>
<t t-set="message" t-value="'Acceptable file size'" t-if="size_status == 'normal'"></t>
<t t-set="message" t-value="'Huge file size. The image should be optimized/reduced.'" t-elif="size_status == 'warning'"></t>
<t t-set="message" t-value="'Optimization required! Reduce the image size or increase your compression settings.'" t-else=""></t>
<span t-attf-class="o_website_sale_image_card_size badge badge-#{size_status}" t-att-title="message">
<t t-esc="record.image.value"/>
</span>
<a role="button" t-if="!read_only_mode" type="delete" class="btn btn-sm btn-secondary o_website_sale_image_card_remove" aria-label="Remove" title="Remove"><i class="fa fa-trash"/></a>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</t>
</templates>
</kanban>
</field>
</group>
</page>
</xpath>
</field>
@@ -7,7 +7,7 @@
<field name="arch" type="xml">
<button name="toggle_active" position="before">
<button class="oe_stat_button" name="action_open_attachments" type="object" icon="fa-file">
<field string="Portal Files" name="attachment_count" widget="statinfo" />
<field string="Digital Files" name="attachment_count" widget="statinfo" />
</button>
</button>
</field>
@@ -20,7 +20,7 @@
<field name="arch" type="xml">
<button name="toggle_active" position="before">
<button class="oe_stat_button" name="action_open_attachments" type="object" icon="fa-file">
<field string="Portal Files" name="attachment_count" widget="statinfo" />
<field string="Digital Files" name="attachment_count" widget="statinfo" />
</button>
</button>
</field>
@@ -5,11 +5,11 @@
<field name="model">product.template</field>
<field name="inherit_id" ref="website_sale.product_template_form_view" />
<field name="arch" type="xml">
<field name="website_style_ids" position="before">
<field name="inventory_availability" string="Inventory" widget="selection" attrs="{'invisible':[('type', 'in', ['service', 'consu'])]}"/>
<xpath expr="//field[@name='public_categ_ids']" position="after">
<field name="inventory_availability" string="Availability" widget="selection" attrs="{'invisible': [('type', 'in', ['service', 'consu'])]}"/>
<field name="available_threshold" attrs="{'invisible': ['|', ('type', 'in', ['service', 'consu']), ('inventory_availability', '!=', 'threshold')], 'required': [('inventory_availability', '=', 'threshold'), ('type', '=', 'product')]}"/>
<field name="custom_message" attrs="{'invisible': ['|', ('type', 'in', ['service', 'consu']), ('inventory_availability', '!=', 'custom')]}"/>
</field>
</xpath>
</field>
</record>
</odoo>