diff options
| author | Thibault Delavallée <tde@openerp.com> | 2014-01-21 10:38:32 +0100 |
|---|---|---|
| committer | Thibault Delavallée <tde@openerp.com> | 2014-01-21 10:38:32 +0100 |
| commit | 28eaa636f0bfbf497e616edcfbc64d8a720e788d (patch) | |
| tree | 7898a40b6f11d96f64f973347619b2442f6e62f2 /addons/product | |
| parent | 3b1fec32208879a4655a37180e2ea4296728e6ed (diff) | |
| parent | 9ce241349f3f35b6c75a2aaf9cf7c1ce0006cd7e (diff) | |
[MERGE] Merged DKA's branch about product variants in the CMS. Review is coming.
bzr revid: tde@openerp.com-20140121093832-yp3jl36nsuho74vk
Diffstat (limited to 'addons/product')
| -rw-r--r-- | addons/product/product.py | 81 | ||||
| -rw-r--r-- | addons/product/product_view.xml | 222 | ||||
| -rw-r--r-- | addons/product/security/product_security.xml | 2 |
3 files changed, 208 insertions, 97 deletions
diff --git a/addons/product/product.py b/addons/product/product.py index 163785459b4..2e7eb3c499d 100644 --- a/addons/product/product.py +++ b/addons/product/product.py @@ -23,8 +23,10 @@ import math import re from _common import rounding -from openerp import SUPERUSER_ID +from lxml import etree +from openerp.osv.orm import setup_modifiers +from openerp import SUPERUSER_ID from openerp import tools from openerp.osv import osv, fields from openerp.tools.translate import _ @@ -391,7 +393,7 @@ class product_template(osv.osv): 'categ_id': fields.many2one('product.category','Category', required=True, change_default=True, domain="[('type','=','normal')]" ,help="Select category for the current product"), 'public_categ_id': fields.many2one('product.public.category','Public Category', help="Those categories are used to group similar products for public sales (eg.: point of sale, e-commerce)."), 'list_price': fields.float('Sale Price', digits_compute=dp.get_precision('Product Price'), help="Base price to compute the customer price. Sometimes called the catalog price."), - 'standard_price': fields.float('Cost', digits_compute=dp.get_precision('Product Price'), help="Cost price of the product used for standard stock valuation in accounting and used as a base price on purchase orders.", groups="base.group_user"), + 'standard_price': fields.float('Cost Price', digits_compute=dp.get_precision('Product Price'), help="Cost price of the product template used for standard stock valuation in accounting and used as a base price on purchase orders.", groups="base.group_user"), 'volume': fields.float('Volume', help="The volume in m3."), 'weight': fields.float('Gross Weight', digits_compute=dp.get_precision('Stock Weight'), help="The gross weight in Kg."), 'weight_net': fields.float('Net Weight', digits_compute=dp.get_precision('Stock Weight'), help="The net weight in Kg."), @@ -468,6 +470,15 @@ class product_template(osv.osv): raise osv.except_osv(_('Unit of Measure categories Mismatch!'), _("New Unit of Measure '%s' must belong to same Unit of Measure category '%s' as of old Unit of Measure '%s'. If you need to change the unit of measure, you may deactivate this product from the 'Procurements' tab and create a new one.") % (new_uom.name, old_uom.category_id.name, old_uom.name,)) return super(product_template, self).write(cr, uid, ids, vals, context=context) + def copy(self, cr, uid, id, default=None, context=None): + if default is None: + default = {} + #TOFIX: it should be pass default={'name': _("%s (copy)") % (template['name'])}. + template = self.read(cr, uid, id, ['name'], context=context) + res = super(product_template, self).copy(cr, uid, id, default=default, context=context) + self.write(cr, uid, res, {'name': _("%s (copy)") % (template['name'])}, context=context) + return res + _defaults = { 'company_id': lambda s,cr,uid,c: s.pool.get('res.company')._company_default_get(cr, uid, 'product.template', context=c), 'list_price': 1, @@ -574,6 +585,7 @@ class product_product(osv.osv): list_price = (field_value - product.price_extra) / (product.price_margin or 1.0) return self.write(cr, uid, [product_id], {'list_price': list_price}, context=context) + def _get_partner_code_name(self, cr, uid, ids, product, partner_id, context=None): for supinfo in product.seller_ids: if supinfo.name.id == partner_id: @@ -664,12 +676,12 @@ class product_product(osv.osv): 'partner_ref' : fields.function(_product_partner_ref, type='char', string='Customer ref'), 'default_code' : fields.char('Internal Reference', size=64, select=True), 'active': fields.boolean('Active', help="If unchecked, it will allow you to hide the product without removing it."), - 'variants': fields.char('Variants', size=64), + 'variants': fields.char('Variants', size=64, translate=True), 'product_tmpl_id': fields.many2one('product.template', 'Product Template', required=True, ondelete="cascade", select=True), 'ean13': fields.char('EAN13 Barcode', size=13, help="International Article Number used for product identification."), 'packaging' : fields.one2many('product.packaging', 'product_id', 'Logistical Units', help="Gives the different ways to package the same product. This has no impact on the picking order and is mainly used if you use the EDI module."), - 'price_extra': fields.float('Variant Price Extra', digits_compute=dp.get_precision('Product Price')), - 'price_margin': fields.float('Variant Price Margin', digits_compute=dp.get_precision('Product Price')), + 'price_extra': fields.float('Variant Price Extra', digits_compute=dp.get_precision('Product Price'), help="Price Extra: Extra price for the variant on sale price. eg. 200 price extra, 1000 + 200 = 1200."), + 'price_margin': fields.float('Variant Price Margin', digits_compute=dp.get_precision('Product Price'), help="Price Margin: Margin in percentage amount on sale price for the variant. eg. 10 price margin, 1000 * 1.1 = 1100."), 'pricelist_id': fields.dummy(string='Pricelist', relation='product.pricelist', type='many2one'), 'name_template': fields.related('product_tmpl_id', 'name', string="Template Name", type='char', size=128, store={ 'product.template': (_get_name_template_ids, ['name'], 10), @@ -682,20 +694,28 @@ class product_product(osv.osv): 'seller_qty': fields.function(_calc_seller, type='float', string='Supplier Quantity', multi="seller_info", help="This is minimum quantity to purchase from Main Supplier."), 'seller_id': fields.function(_calc_seller, type='many2one', relation="res.partner", string='Main Supplier', help="Main Supplier who has highest priority in Supplier List.", multi="seller_info"), } - def unlink(self, cr, uid, ids, context=None): - unlink_ids = [] - unlink_product_tmpl_ids = [] - for product in self.browse(cr, uid, ids, context=context): - tmpl_id = product.product_tmpl_id.id - # Check if the product is last product of this template - other_product_ids = self.search(cr, uid, [('product_tmpl_id', '=', tmpl_id), ('id', '!=', product.id)], context=context) - if not other_product_ids: - unlink_product_tmpl_ids.append(tmpl_id) - unlink_ids.append(product.id) - res = super(product_product, self).unlink(cr, uid, unlink_ids, context=context) - # delete templates after calling super, as deleting template could lead to deleting - # products due to ondelete='cascade' - self.pool.get('product.template').unlink(cr, uid, unlink_product_tmpl_ids, context=context) + + + def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): + #override of fields_view_get in order to replace the name field to product template + if context is None: + context = {} + res = super(product_product, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu) + #check the current user in group_product_variant + if view_type == 'form': + doc = etree.XML(res['arch']) + if self.pool['res.users'].has_group(cr, uid, 'product.group_product_variant'): + for node in doc.xpath("//field[@name='name']"): + node.set('invisible', '1') + node.set('required', '0') + setup_modifiers(node, res['fields']['name']) + for node in doc.xpath("//label[@name='label_name']"): + node.set('string','Product Template') + else: + for node in doc.xpath("//field[@name='product_tmpl_id']"): + node.set('required', '0') + setup_modifiers(node, res['fields']['name']) + res['arch'] = etree.tostring(doc) return res def onchange_uom(self, cursor, user, ids, uom_id, uom_po_id): @@ -707,6 +727,16 @@ class product_product(osv.osv): return {'value': {'uom_po_id': uom_id}} return False + def onchange_product_tmpl_id(self, cr, uid, ids, template_id, context=None): + res = {} + if template_id: + template = self.pool.get('product.template').browse(cr, uid, template_id, context=context) + res['value'] = { + 'name': template.name, + 'lst_price': template.list_price, + } + return res + def _check_ean_key(self, cr, uid, ids, context=None): for product in self.read(cr, uid, ids, ['ean13'], context=context): res = check_ean(product['ean13']) @@ -776,7 +806,7 @@ class product_product(osv.osv): # OR operator (and given the fact that the 'name' lookup results come from the ir.translation table # Performing a quick memory merge of ids in Python will give much better performance ids = set() - ids.update(self.search(cr, user, args + [('default_code',operator,name)], limit=limit, context=context)) + ids.update(self.search(cr, user, args + ['|',('default_code',operator,name),('variants',operator,name)], limit=limit, context=context)) if not limit or len(ids) < limit: # we may underrun the limit because of dupes in the results, that's fine ids.update(self.search(cr, user, args + [('name',operator,name)], limit=(limit and (limit-len(ids)) or False) , context=context)) @@ -838,9 +868,12 @@ class product_product(osv.osv): # will do the other languages). context_wo_lang = context.copy() context_wo_lang.pop('lang', None) - product = self.read(cr, uid, id, ['name'], context=context_wo_lang) + product = self.read(cr, uid, id, ['name', 'list_price', 'standard_price', 'categ_id', 'variants', 'product_tmpl_id'], context=context_wo_lang) default = default.copy() - default.update(name=_("%s (copy)") % (product['name'])) + if product['variants']: + default.update(variants=_("%s (copy)") % (product['variants']), product_tmpl_id=product['product_tmpl_id'][0]) + else: + default.update(name=_("%s (copy)") % (product['name']), list_price=product['list_price'], standard_price=product['standard_price'], categ_id=product['categ_id'][0], product_tmpl_id=None) if context.get('variant',False): fields = ['product_tmpl_id', 'active', 'variants', 'default_code', @@ -858,7 +891,9 @@ class product_product(osv.osv): context=context) def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False): - if context and context.get('search_default_categ_id'): + if context is None: + context = {} + if context.get('search_default_categ_id'): args.append((('categ_id', 'child_of', context['search_default_categ_id']))) return super(product_product, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count) diff --git a/addons/product/product_view.xml b/addons/product/product_view.xml index 1ea85cc96d4..4c315dfe221 100644 --- a/addons/product/product_view.xml +++ b/addons/product/product_view.xml @@ -8,7 +8,7 @@ <field name="model">product.product</field> <field name="arch" type="xml"> <search string="Product"> - <field name="name" string="Product" filter_domain="['|',('name','ilike',self),('default_code','ilike',self)]"/> + <field name="name" string="Product" filter_domain="['|','|',('name','ilike',self),('default_code','ilike',self),('variants','ilike',self)]"/> <filter string="Services" icon="terp-accessories-archiver" domain="[('type','=','service')]"/> <filter string="Consumable" name="consumable" icon="terp-accessories-archiver" domain="[('type','=','consu')]" help="Consumable products"/> <separator/> @@ -23,6 +23,7 @@ <filter string='Default Unit of Measure' icon="terp-mrp" domain="[]" context="{'group_by' : 'uom_id'}"/> <filter string='Type' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'type'}"/> <filter string='Company' icon="terp-go-home" domain="[]" context="{'group_by' : 'company_id'}" groups="base.group_multi_company"/> + <filter string='Template' name="template_id" domain="[]" context="{'group_by' : 'product_tmpl_id'}" groups="product.group_product_variant"/> </group> </search> </field> @@ -36,6 +37,7 @@ <tree colors="red:virtual_available<0;blue:virtual_available>=0 and state in ('draft', 'end', 'obsolete');black:virtual_available>=0 and state not in ('draft', 'end', 'obsolete')" string="Products"> <field name="default_code"/> <field name="name"/> + <field name="variants" groups="product.group_product_variant"/> <field name="categ_id" invisible="1"/> <field name="type" invisible="1"/> <field name="uom_id" string="Unit of Measure" groups="product.group_uom"/> @@ -46,6 +48,7 @@ <field name="standard_price" invisible="1"/> <field name="state"/> <field name="company_id" groups="base.group_multi_company" invisible="1"/> + <field name="product_tmpl_id" invisible="1"/> </tree> </field> </record> @@ -60,10 +63,13 @@ <field name="image_medium" widget="image" class="oe_avatar oe_left"/> <div class="oe_title"> <div class="oe_edit_only"> - <label for="name" string="Product Name"/> + <label for="name" name='label_name' string="Product Name"/> </div> <h1> - <field name="name"/> + <field name="name" class="oe_inline"/> + <field name="product_tmpl_id" groups="product.group_product_variant" on_change="onchange_product_tmpl_id(product_tmpl_id)" class="oe_inline"/> + <span attrs="{'invisible':[('variants','=',False)]}" groups="product.group_product_variant"> - </span> + <field name="variants" placeholder="Variant Name" groups="product.group_product_variant" class="oe_inline" readonly="0"/> </h1> <label for="categ_id" class="oe_edit_only"/> <h2><field name="categ_id"/></h2> @@ -82,7 +88,7 @@ <group> <field name="type"/> <field name="uom_id" on_change="onchange_uom(uom_id,uom_po_id)" groups="product.group_uom"/> - <field name="list_price"/> + <field name="lst_price" string="Public Sale Price"/> </group> <group> <field name="default_code"/> @@ -189,7 +195,7 @@ <div class="oe_kanban_details"> <h4> <a type="open"> - <t t-if="record.code.raw_value">[<field name="code"/>]</t> <field name="name"/> + <t t-if="record.code.raw_value">[<field name="code"/>]</t> <field name="name"/> <t t-if="record.variants.raw_value">(<field name="variants"/>)</t> </a> </h4> <div name="tags"/> @@ -222,7 +228,7 @@ </field> </record> <record id="product_normal_action_sell" model="ir.actions.act_window"> - <field name="name">Products</field> + <field name="name">All Products</field> <field name="type">ir.actions.act_window</field> <field name="res_model">product.product</field> <field name="view_mode">kanban,tree,form</field> @@ -364,7 +370,7 @@ action="product_category_action" id="product.menu_products_category" parent="base.menu_product" - sequence="0" groups="base.group_no_one"/> + sequence="2" groups="base.group_no_one"/> <record id="product_category_action_form" model="ir.actions.act_window"> <field name="name">Product Categories</field> <field name="type">ir.actions.act_window</field> @@ -578,7 +584,7 @@ </field> </record> <menuitem - action="product_ul_form_action" groups="product.group_stock_packaging" id="menu_product_ul_form_action" parent="prod_config_main" sequence="3"/> + action="product_ul_form_action" groups="product.group_stock_packaging" id="menu_product_ul_form_action" parent="prod_config_main" sequence="5"/> <record id="product_packaging_tree_view" model="ir.ui.view"> <field name="name">product.packaging.tree.view</field> @@ -668,6 +674,19 @@ </record> <!-- Variants --> + <record id="product_variant_search_form_view" model="ir.ui.view"> + <field name="name">product.variant.search.form</field> + <field name="model">product.product</field> + <field name="arch" type="xml"> + <search string="Product Variant"> + <field name="product_tmpl_id"/> + <field name="name" string="Product" filter_domain="['|','|',('name','ilike',self),('default_code','ilike',self),('variants','ilike',self)]"/> + <group expand='0' string='Group by...'> + <filter string='Template' name="template_id" domain="[]" context="{'group_by' : 'product_tmpl_id'}"/> + </group> + </search> + </field> + </record> <record id="product_variant_form_view" model="ir.ui.view"> <field name="name">product.variant.form</field> <field name="model">product.product</field> @@ -704,12 +723,12 @@ <record id="product_variant_action" model="ir.actions.act_window"> <field name="name">Product Variants</field> <field name="type">ir.actions.act_window</field> - <!--<field name="domain">[('variants','<>', False)]</field>--> + <field name="domain">[('variants','!=', '')]</field> <field name="res_model">product.product</field> <field name="view_type">form</field> <field name="view_mode">tree,form,kanban</field> <field name="view_id" ref="product_variant_tree_view"/> - <field name="search_view_id" ref="product_search_form_view"/> + <field name="search_view_id" ref="product_variant_search_form_view"/> <field name="help" type="html"> <p class="oe_view_nocontent_create"> Click to define a new variant of product. @@ -728,9 +747,30 @@ <field name="view_id" ref="product_variant_form_view"/> <field name="act_window_id" ref="product_variant_action"/> </record> - <menuitem action="product.product_variant_action" id="product.menu_variant_product" parent="base.menu_product" sequence="100" groups="product.group_product_variant"/> + <menuitem action="product.product_variant_action" id="product.menu_variant_product" parent="prod_config_main" sequence="4" groups="product.group_product_variant"/> <!-- templates --> + + <record id="product_template_search_view" model="ir.ui.view"> + <field name="name">product.template.search</field> + <field name="model">product.template</field> + <field name="arch" type="xml"> + <search string="Product Template"> + <field name="name" string="Product"/> + <filter string="Services" icon="terp-accessories-archiver" domain="[('type','=','service')]"/> + <filter string="Consumable" name="consumable" icon="terp-accessories-archiver" domain="[('type','=','consu')]" help="Consumable products"/> + <separator/> + <filter string="Can be Sold" name="filter_to_sell" icon="terp-accessories-archiver-minus" domain="[('sale_ok','=',1)]"/> + <field name="categ_id"/> + <group expand='0' string='Group by...'> + <filter string='Category' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'categ_id'}"/> + <filter string='Default Unit of Measure' icon="terp-mrp" domain="[]" context="{'group_by' : 'uom_id'}"/> + <filter string='Type' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'type'}"/> + </group> + </search> + </field> + </record> + <record id="product_template_tree_view" model="ir.ui.view"> <field name="name">product.template.product.tree</field> <field name="model">product.template</field> @@ -740,6 +780,7 @@ <field name="categ_id"/> <field name="type"/> <field name="state"/> + <field name="uom_id" invisible="1"/> </tree> </field> </record> @@ -762,81 +803,85 @@ <h2><field name="categ_id"/></h2> <label for="public_categ_id" class="oe_edit_only"/> <h3><field name="public_categ_id"/></h3> + <div name="options" groups="base.group_user"> + <field name="sale_ok"/> + <label for="sale_ok"/> + </div> </div> <notebook> <page string="Information"> - <group> - <group string="Product Type"> - <field name="sale_ok"/> - </group> - <group string="Procurement"> + <group colspan="4"> + <group> <field name="type"/> - </group> - - <group string="Base Prices"> + <field name="uom_id" on_change="onchange_uom(uom_id,uom_po_id)" groups="product.group_uom"/> <field name="list_price"/> + </group> + <group> + <field name="company_id" groups="base.group_multi_company" widget="selection"/> + </group> + </group> + <group colspan="4" string="Product Variants" groups="product.group_product_variant"> + <field colspan="4" name="product_variant_ids" nolabel="1" > + <tree string="Product Variants" editable="bottom"> + <field name="variants" required="1"/> + <field name="price_margin" string="Variant Price Margin"/> + <field name="price_extra"/> + <field name="lst_price" string="Sale Price" readonly="1"/> + </tree> + </field> + </group> + <field name="description" placeholder="describe the product characteristics..."/> + </page> + <page string="Procurements" groups="base.group_user"> + <group name="procurement"> + <group name="general"> + <field name="cost_method" groups="product.group_costing_method"/> <field name="standard_price" attrs="{'readonly':[('cost_method','=','average')]}"/> - <field name="cost_method"/> </group> - - <group string="Weights"> - <field digits="(14, 3)" name="volume" attrs="{'readonly':[('type','=','service')]}"/> - <field digits="(14, 3)" name="weight" attrs="{'readonly':[('type','=','service')]}"/> - <field digits="(14, 3)" name="weight_net" attrs="{'readonly':[('type','=','service')]}"/> - </group> - - <group name="status" string="Status"> - <field name="categ_id"/> - <field name="state"/> - <field name="product_manager" context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'base.group_sale_manager']}"/> + <group name="delay" string="Delays"> + <label for="produce_delay"/> + <div> + <field name="produce_delay" class="oe_inline" style="vertical-align:baseline"/> days + </div> </group> - - <group name="uom" string="Unit of Measure"> - <field name="uom_id" on_change="onchange_uom(uom_id,uom_po_id)" groups="product.group_uom"/> + <group name="procurement_uom" groups="product.group_uom" string="Purchase"> <field name="uom_po_id"/> </group> - - <group name="uos" groups="product.group_uom" string="Second Unit of Measure"> - <field name="uos_id"/> - <field name="uos_coeff"/> - <field name="mes_type"/> + </group> + <separator string="Suppliers"/> + <field name="seller_ids"/> + <separator string="Description for Suppliers"/> + <field name="description_purchase" placeholder="This note will be displayed on requests for quotation..."/> + </page> + <page string="Inventory"> + <group name="inventory"> + <group name="status" string="Status"> + <field name="state"/> + <field name="product_manager"/> </group> - - <group colspan="4" string="Product Variants" groups="product.group_product_variant"> - <field colspan="4" name="product_variant_ids" nolabel="1"> - <tree string="Product Variants" editable="bottom"> - <field name="active"/> - <field name="variants" required="1"/> - <field name="default_code"/> - <field name="price_margin"/> - <field name="price_extra"/> - </tree> - </field> + <group name ="weight" string="Weights"> + <field digits="(14, 3)" name="volume" attrs="{'readonly':[('type','=','service')]}"/> + <field digits="(14, 3)" name="weight" attrs="{'readonly':[('type','=','service')]}"/> + <field digits="(14, 3)" name="weight_net" attrs="{'readonly':[('type','=','service')]}"/> </group> </group> </page> - <page string="Procurement & Locations"> - <group> - <group name="delay" string="Delays"> - <label for="produce_delay"/> + <page string="Sales" attrs="{'invisible':[('sale_ok','=',False)]}"> + <group name="sale"> + <group name="sale_condition" string="Sale Conditions"> + <label for="warranty"/> <div> - <field name="produce_delay" class="oe_inline"/> days + <field name="warranty" class="oe_inline" style="vertical-align:baseline"/> months </div> - <field name="warranty"/> + </group> + <group groups="product.group_uos" string="Unit of Measure"> + <field name="uos_id"/> + <field name="uos_coeff"/> + <field name="mes_type"/> </group> </group> - - </page> - <page string="Suppliers"> - <field name="seller_ids"/> - </page> - <page string="Descriptions"> - <separator string="Internal Description"/> - <field name="description"/> - <separator string="Sale Description"/> - <field name="description_sale"/> - <separator string="Purchase Description"/> - <field name="description_purchase"/> + <separator string="Description for Quotations"/> + <field name="description_sale" placeholder="note to be displayed on quotations..."/> </page> </notebook> </sheet> @@ -848,17 +893,48 @@ </field> </record> - <record id="product_template_action_tree" model="ir.actions.act_window"> + <record model="ir.ui.view" id="product_template_kanban_view"> + <field name="name">Product Template Kanban</field> + <field name="model">product.template</field> + <field name="arch" type="xml"> + <kanban> + <field name="image_small"/> + <field name="list_price"/> + <templates> + <t t-name="kanban-box"> + <div class="oe_kanban_vignette oe_semantic_html_override"> + <a type="open"><img t-att-src="kanban_image('product.template', 'image_small', record.id.value)" class="oe_kanban_image"/></a> + <div class="oe_kanban_details"> + <h4> + <a type="open"> + <field name="name"/> + </a> + </h4> + <div name="tags"/> + <ul> + <li>Price: <field name="list_price"></field></li> + </ul> + </div> + </div> + </t> + </templates> + </kanban> + </field> + </record> + + <record id="product_template_action" model="ir.actions.act_window"> <field name="name">Product Templates</field> <field name="type">ir.actions.act_window</field> <field name="res_model">product.template</field> + <field name="view_mode">kanban,tree,form</field> <field name="view_type">form</field> - <field name="view_id" ref="product_template_tree_view"/> + <field name="view_id" ref="product_template_kanban_view"/> </record> - <menuitem id="product_template_menu" - parent="base.menu_product" sequence="25" - action="product_template_action_tree"/> + <menuitem action="product_template_action" + id="menu_product_template_action" + parent="base.menu_product" sequence="0" + groups="product.group_product_variant"/> </data> </openerp> diff --git a/addons/product/security/product_security.xml b/addons/product/security/product_security.xml index 11b6319329a..81a32967d59 100644 --- a/addons/product/security/product_security.xml +++ b/addons/product/security/product_security.xml @@ -5,7 +5,7 @@ DO NOT CHANGE IT IN TRUNK --> <record id="group_product_variant" model="res.groups"> - <field name="name">Product Variant (not supported)</field> + <field name="name">Manage Product Variants</field> <field name="category_id" ref="base.module_category_hidden"/> </record> |
