openerp-community team mailing list archive
-
openerp-community team
-
Mailing list archive
-
Message #02393
[Merge] lp:~akretion-team/openerp-product-attributes/mixin-extraction into lp:openerp-product-attributes
Raphaël Valyi - http://www.akretion.com has proposed merging lp:~akretion-team/openerp-product-attributes/mixin-extraction into lp:openerp-product-attributes with lp:~akretion-team/openerp-product-attributes/polymorphic-relations as a prerequisite.
Requested reviews:
Product Core Editors (product-core-editors)
For more details, see:
https://code.launchpad.net/~akretion-team/openerp-product-attributes/mixin-extraction/+merge/151333
See commit messages:
no more code but but code is now split in two modules: product_custom_attributes and base_custom_attributes that can be reused in any OpenERP object (partner, project, production order etc...). That last module may be moved to another branch later if it makes more sense.
--
https://code.launchpad.net/~akretion-team/openerp-product-attributes/mixin-extraction/+merge/151333
Your team OpenERP Community is subscribed to branch lp:openerp-product-attributes.
=== renamed directory 'product_custom_attributes' => 'base_custom_attributes'
=== modified file 'base_custom_attributes/__init__.py'
--- product_custom_attributes/__init__.py 2012-08-03 14:33:51 +0000
+++ base_custom_attributes/__init__.py 2013-03-02 00:14:23 +0000
@@ -22,9 +22,7 @@
import ir_model
-import product_attribute
-import product
-import wizard
+import custom_attributes
=== modified file 'base_custom_attributes/__openerp__.py'
--- product_custom_attributes/__openerp__.py 2013-02-11 22:58:10 +0000
+++ base_custom_attributes/__openerp__.py 2013-03-02 00:14:23 +0000
@@ -1,7 +1,7 @@
# -*- encoding: utf-8 -*-
###############################################################################
# #
-# product_custom_attributes for OpenERP #
+# base_custom_attributes for OpenERP #
# Copyright (C) 2011 Akretion Benoît GUILLOT <benoit.guillot@xxxxxxxxxxxx> #
# #
# This program is free software: you can redistribute it and/or modify #
@@ -22,23 +22,19 @@
{
- 'name': 'product_custom_attributes',
+ 'name': 'base_custom_attributes',
'version': '0.1',
'category': 'Generic Modules/Others',
'license': 'AGPL-3',
- 'description': """This module adds the possibility to easily create custom fields on products.
-Each product can be linked to an attribute set (like camera, fridge...).
-Each attribute has custom fields (for example, you don't need the same field for a frigde and a camera).
+ 'description': """This module adds the possibility to easily create custom attributes in any OpenERP business object. See the product_custom_attributes module for instance.
""",
'author': 'Akretion',
'website': 'http://www.akretion.com/',
- 'depends': ['product'],
+ 'depends': ['base'],
'init_xml': [],
'update_xml': [
'security/ir.model.access.csv',
- 'product_attribute_view.xml',
- 'product_view.xml',
- 'wizard/open_product_by_attribute_set.xml',
+ 'custom_attributes_view.xml',
],
'demo_xml': [],
'installable': True,
=== renamed file 'product_custom_attributes/product_attribute.py' => 'base_custom_attributes/custom_attributes.py'
--- product_custom_attributes/product_attribute.py 2013-03-02 00:14:23 +0000
+++ base_custom_attributes/custom_attributes.py 2013-03-02 00:14:23 +0000
@@ -1,8 +1,9 @@
# -*- encoding: utf-8 -*-
###############################################################################
# #
-# product_custom_attributes for OpenERP #
+# base_custom_attributes for OpenERP #
# Copyright (C) 2011 Akretion Benoît GUILLOT <benoit.guillot@xxxxxxxxxxxx> #
+# Copyright (C) 2013 Akretion Raphaël VALYI <raphael.valyi@xxxxxxxxxxxx> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU Affero General Public License as #
@@ -35,7 +36,7 @@
_columns = {
'name': fields.char('Name', size=128, translate=True, required=True),
'value_ref': fields.reference('Reference', selection=[], size=128),
- 'attribute_id': fields.many2one('product.attribute', 'Product Attribute', required=True),
+ 'attribute_id': fields.many2one('custom.attribute', 'Product Attribute', required=True),
'sequence': fields.integer('Sequence'),
}
@@ -51,7 +52,7 @@
_rec_name = 'attribute_id'
_columns = {
- 'attribute_id': fields.many2one('product.attribute', 'Product Attribute', required=True),
+ 'attribute_id': fields.many2one('custom.attribute', 'Product Attribute', required=True),
}
_defaults = {
@@ -62,7 +63,7 @@
return True
def create(self, cr, uid, vals, context=None):
- attr_obj = self.pool.get("product.attribute")
+ attr_obj = self.pool.get("custom.attribute")
attr = attr_obj.browse(cr, uid, vals['attribute_id'])
op_ids = [op.id for op in attr.option_ids]
opt_obj = self.pool.get("attribute.option")
@@ -81,7 +82,7 @@
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
res = super(attribute_option_wizard, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
if context and context.get("attribute_id"):
- attr_obj = self.pool.get("product.attribute")
+ attr_obj = self.pool.get("custom.attribute")
model_id = attr_obj.read(cr, uid, [context.get("attribute_id")], ['relation_model_id'])[0]['relation_model_id'][0]
relation = self.pool.get("ir.model").read(cr, uid, [model_id], ["model"])[0]["model"]
res['fields'].update({'option_ids': {
@@ -100,11 +101,44 @@
return res
-class product_attribute(Model):
- _name = "product.attribute"
+class custom_attribute(Model):
+ _name = "custom.attribute"
_description = "Product Attribute"
_inherits = {'ir.model.fields': 'field_id'}
+ def _build_attribute_field(self, cr, uid, page, attribute, context=None):
+ parent = page
+ kwargs = {'name': "%s" % attribute.name}
+ if attribute.ttype == 'many2many':
+ parent = etree.SubElement(page, 'group', colspan="2", col="4")
+ #FIXME the following isn't displayed in v7:
+ sep = etree.SubElement(parent, 'separator',
+ string="%s" % attribute.field_description, colspan="4")
+ kwargs['nolabel'] = "1"
+ if attribute.ttype in ['many2one', 'many2many']:
+ if attribute.relation_model_id:
+ if attribute.domain:
+ kwargs['domain'] = attribute.domain
+ else:
+ ids = [op.value_ref.id for op in attribute.option_ids]
+ kwargs['domain'] = "[('id', 'in', %s)]" % ids
+ else:
+ kwargs['domain'] = "[('attribute_id', '=', %s)]" % attribute.attribute_id.id
+ field = etree.SubElement(parent, 'field', **kwargs)
+ return parent
+
+ def _build_attributes_notebook(self, cr, uid, attribute_group_ids, context=None):
+ notebook = etree.Element('notebook', name="attributes_notebook", colspan="4")
+ toupdate_fields = []
+ grp_obj = self.pool.get('attribute.group')
+ for group in grp_obj.browse(cr, uid, attribute_group_ids, context=context):
+ page = etree.SubElement(notebook, 'page', string=group.name.capitalize())
+ for attribute in group.attribute_ids:
+ if attribute.name not in toupdate_fields:
+ toupdate_fields.append(attribute.name)
+ self._build_attribute_field(cr, uid, page, attribute, context=context)
+ return notebook, toupdate_fields
+
def relation_model_id_change(self, cr, uid, ids, relation_model_id, option_ids, context=None):
"removed selected options as they would be inconsistent"
return {'value': {'option_ids': [(2, i[1]) for i in option_ids]}}
@@ -136,9 +170,6 @@
'serialized': fields.boolean('Field serialized',
help="If serialized, the field will be stocked in the serialized field: "
"attribute_custom_tmpl or attribute_custom_variant depending on the field based_on"),
- 'based_on': fields.selection([('product_template','Product Template'),
- ('product_product','Product Variant')],
- 'Based on', required=True),
'option_ids': fields.one2many('attribute.option', 'attribute_id', 'Attribute Options'),
'create_date': fields.datetime('Created date', readonly=True),
'relation_model_id': fields.many2one('ir.model', 'Model'),
@@ -147,17 +178,25 @@
def create(self, cr, uid, vals, context=None):
if vals.get('relation_model_id'):
- relation = self.pool.get('ir.model').read(cr, uid, [vals.get('relation_model_id')], ['model'])[0]['model']
+ relation = self.pool.get('ir.model').read(cr, uid,
+ [vals.get('relation_model_id')], ['model'])[0]['model']
else:
relation = 'attribute.option'
- if vals.get('based_on') == 'product_template':
- vals['model_id'] = self.pool.get('ir.model').search(cr, uid, [('model', '=', 'product.template')], context=context)[0]
- serial_name = 'attribute_custom_tmpl'
- else:
- vals['model_id'] = self.pool.get('ir.model').search(cr, uid, [('model', '=', 'product.product')], context=context)[0]
- serial_name = 'attribute_custom_variant'
if vals.get('serialized'):
- vals['serialization_field_id'] = self.pool.get('ir.model.fields').search(cr, uid, [('name', '=', serial_name)], context=context)[0]
+ field_obj = self.pool.get('ir.model.fields')
+ serialized_ids = field_obj.search(cr, uid,
+ [('ttype', '=', 'serialized'), ('model_id', '=', vals['model_id']),
+ ('name', '=', 'x_custom_json_attrs')], context=context)
+ if serialized_ids:
+ vals['serialization_field_id'] = serialized_ids[0]
+ else:
+ f_vals = {
+ 'name': 'x_custom_json_attrs',
+ 'field_description': 'Serialized JSON Attributes',
+ 'ttype': 'serialized',
+ 'model_id': vals['model_id'],
+ }
+ vals['serialization_field_id'] = field_obj.create(cr, uid, f_vals, {'manual': True})
if vals['attribute_type'] == 'select':
vals['ttype'] = 'many2one'
vals['relation'] = relation
@@ -169,7 +208,7 @@
else:
vals['ttype'] = vals['attribute_type']
vals['state'] = 'manual'
- return super(product_attribute, self).create(cr, uid, vals, context)
+ return super(custom_attribute, self).create(cr, uid, vals, context)
def onchange_field_description(self, cr, uid, ids, field_description, context=None):
name = 'x_'
@@ -182,51 +221,30 @@
name = 'x_%s' % name
return {'value' : {'name' : unidecode(name)}}
+
+class attribute_group(Model):
+ _name= "attribute.group"
+ _description = "Attribute Group"
+ _order="sequence"
+
+ _columns = {
+ 'name': fields.char('Name', size=128, required=True),
+ 'sequence': fields.integer('Sequence'),
+ 'attribute_ids': fields.one2many('attribute.location', 'attribute_group_id', 'Attributes'),
+ }
+
class attribute_location(Model):
_name = "attribute.location"
_description = "Attribute Location"
_order="sequence"
- _inherits = {'product.attribute': 'attribute_id'}
+ _inherits = {'custom.attribute': 'attribute_id'}
def _get_attribute_loc_from_group(self, cr, uid, ids, context=None):
return self.pool.get('attribute.location').search(cr, uid, [('attribute_group_id', 'in', ids)], context=context)
_columns = {
- 'attribute_id': fields.many2one('product.attribute', 'Product Attribute', required=True, ondelete="cascade"),
- 'attribute_set_id': fields.related('attribute_group_id', 'attribute_set_id', type='many2one', relation='attribute.set', string='Attribute Set', readonly=True,
-store={
- 'attribute.group': (_get_attribute_loc_from_group, ['attribute_set_id'], 10),
- }),
+ 'attribute_id': fields.many2one('custom.attribute', 'Product Attribute', required=True, ondelete="cascade"),
'attribute_group_id': fields.many2one('attribute.group', 'Attribute Group', required=True),
'sequence': fields.integer('Sequence'),
}
-
-
-
-class attribute_group(Model):
- _name= "attribute.group"
- _description = "Attribute Group"
- _order="sequence"
-
- _columns = {
- 'name': fields.char('Name', size=128, required=True),
- 'attribute_set_id': fields.many2one('attribute.set', 'Attribute Set'),
- 'attribute_ids': fields.one2many('attribute.location', 'attribute_group_id', 'Attributes'),
- 'sequence': fields.integer('Sequence'),
- }
-
- def create(self, cr, uid, vals, context=None):
- for attribute in vals['attribute_ids']:
- if vals.get('attribute_set_id') and attribute[2] and not attribute[2].get('attribute_set_id'):
- attribute[2]['attribute_set_id'] = vals['attribute_set_id']
- return super(attribute_group, self).create(cr, uid, vals, context)
-
-class attribute_set(Model):
- _name = "attribute.set"
- _description = "Attribute Set"
- _columns = {
- 'name': fields.char('Name', size=128, required=True),
- 'attribute_group_ids': fields.one2many('attribute.group', 'attribute_set_id', 'Attribute Groups'),
- }
-
=== renamed file 'product_custom_attributes/product_attribute_view.xml' => 'base_custom_attributes/custom_attributes_view.xml'
--- product_custom_attributes/product_attribute_view.xml 2013-03-02 00:14:23 +0000
+++ base_custom_attributes/custom_attributes_view.xml 2013-03-02 00:14:23 +0000
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- product_custom_attributes for OpenERP
+ base_custom_attributes for OpenERP
Copyright (C) 2011-2013 Akretion (http://www.akretion.com/)
@author: Benoît GUILLOT <benoit.guillot@xxxxxxxxxxxx>
The licence is in the file __openerp__.py
@@ -9,81 +9,15 @@
<openerp>
<data>
- <menuitem
- id="menu_attribute_in_config_product" name="Attributes"
- parent="product.prod_config_main" sequence="20"/>
-
- <record id="attribute_set_form_view" model="ir.ui.view">
- <field name="name">attribute.set.form</field>
- <field name="model">attribute.set</field>
- <field name="arch" type="xml">
- <form string="Attribute Set">
- <field name="name" colspan="4"/>
- <field name="attribute_group_ids" colspan="4" >
- <form string="Attribute Groups">
- <field name="name" />
- <field name="sequence" />
- <field name="attribute_ids" colspan="4">
- <form string="Attribute Location">
- <field name="attribute_id" />
- <field name="sequence" />
- </form>
- <tree string="Attribute Location">
- <field name="attribute_id" />
- </tree>
- </field>
- </form>
- <tree string="Attribute Groups">
- <field name="name" />
- </tree>
- </field>
- </form>
- </field>
- </record>
-
- <record id="attribute_group_form_view" model="ir.ui.view">
- <field name="name">attribute.group.form</field>
- <field name="model">attribute.group</field>
- <field name="arch" type="xml">
- <form string="Attribute Group">
- <field name="name" />
- <field name="sequence" />
- <field name="attribute_set_id" />
- <field name="attribute_ids" colspan="4" nolabel="1">
- <form string="Attribute Location">
- <field name="attribute_id" />
- <field name="sequence" />
- </form>
- <tree string="Attribute Location">
- <field name="attribute_id" />
- </tree>
- </field>
- </form>
- </field>
- </record>
-
- <record id="attribute_location_form_view" model="ir.ui.view">
- <field name="name">attribute.location.form</field>
- <field name="model">attribute.location</field>
- <field name="arch" type="xml">
- <form string="Attribute Location">
- <field name="attribute_id" />
- <field name="sequence" />
- <field name="attribute_group_id" />
- <field name="attribute_set_id" />
- </form>
- </field>
- </record>
-
- <record id="product_attribute_form_view" model="ir.ui.view">
- <field name="name">product.attribute.form</field>
- <field name="model">product.attribute</field>
+ <record id="custom_attribute_form_view" model="ir.ui.view">
+ <field name="name">custom.attribute.form</field>
+ <field name="model">custom.attribute</field>
<field name="arch" type="xml">
<form string="Product Attribute">
<field name="field_description" on_change="onchange_field_description(field_description, context)"/>
<field name="name" attrs="{'readonly':[('create_date', '!=', False)]}" on_change="onchange_name(name, context)"/>
<field name="attribute_type" />
- <field name="based_on" />
+ <field name="model_id" />
<field name="serialized" />
<field name="size" attrs="{'invisible':[('attribute_type', '!=', 'char')]}"/>
<field name="translate" attrs="{'invisible':[('attribute_type', 'not in', ('char', 'text'))]}"/>
@@ -91,8 +25,7 @@
<group colspan="4" attrs="{'invisible':[('attribute_type', 'not in', ['select', 'multiselect'])]}">
<field name="relation_model_id" on_change="relation_model_id_change(relation_model_id, option_ids, context)"/>
<field name="domain" attrs="{'invisible':[('relation_model_id', '=', False)]}"/>
- <group colspan="4" attrs="{'invisible':[('domain', '!=', False)]}">
- <button name="button_add_options" attrs="{'invisible':[('relation_model_id', '=', False)]}" type="object" string="Change Options"/>
+ <button name="button_add_options" attrs="{'invisible':[('relation_model_id', '=', False), ('domain', '!=', False)]}" type="object" string="Change Options"/>
<field name="option_ids" colspan="4" nolabel="1">
<tree string="Attribute Options" editable="top">
<field name="sequence" invisible="1"/>
@@ -100,7 +33,6 @@
</tree>
</field>
</group>
- </group>
<field name="create_date" invisible="1"/>
</form>
</field>
@@ -124,6 +56,7 @@
<field name="model">attribute.option</field>
<field name="arch" type="xml">
<form string="Attribute Option" col="6">
+ <field name="name" colspan="2"/>
<field name="value_ref" colspan="2"/>
<field name="sequence" colspan="2"/>
<field name="attribute_id" colspan="2"/>
@@ -131,13 +64,20 @@
</field>
</record>
- <record id="attribute_set_tree_view" model="ir.ui.view">
- <field name="name">attribute.set.tree</field>
- <field name="model">attribute.set</field>
+ <record id="attribute_group_form_view" model="ir.ui.view">
+ <field name="name">attribute.group.form</field>
+ <field name="model">attribute.group</field>
<field name="arch" type="xml">
- <tree string="Attribute Set" >
+ <form string="Attribute Group">
<field name="name" />
- </tree>
+ <field name="sequence" />
+ <field name="attribute_ids" colspan="4" nolabel="1">
+ <form string="Attribute Location">
+ <field name="attribute_id" />
+ <field name="sequence" />
+ </form>
+ </field>
+ </form>
</field>
</record>
@@ -148,27 +88,13 @@
<tree string="Attribute Group">
<field name="name" />
<field name="sequence" />
- <field name="attribute_set_id" />
- </tree>
- </field>
- </record>
-
- <record id="attribute_location_tree_view" model="ir.ui.view">
- <field name="name">attribute.location.tree</field>
- <field name="model">attribute.location</field>
- <field name="arch" type="xml">
- <tree string="Attribute Location">
- <field name="attribute_id" />
- <field name="sequence" />
- <field name="attribute_set_id" />
- <field name="attribute_group_id" />
- </tree>
- </field>
- </record>
-
- <record id="product_attribute_tree_view" model="ir.ui.view">
- <field name="name">product.attribute.tree</field>
- <field name="model">product.attribute</field>
+ </tree>
+ </field>
+ </record>
+
+ <record id="custom_attribute_tree_view" model="ir.ui.view">
+ <field name="name">custom.attribute.tree</field>
+ <field name="model">custom.attribute</field>
<field name="arch" type="xml">
<tree string="Product Attribute">
<field name="name" />
@@ -201,42 +127,9 @@
</field>
</record>
- <record id="view_attribute_set_search" model="ir.ui.view">
- <field name="name">attribute.set.list</field>
- <field name="model">attribute.set</field>
- <field name="arch" type="xml">
- <search string="Search Attribute Sets">
- <field name="name"/>
- </search>
- </field>
- </record>
-
- <record id="view_attribute_group_search" model="ir.ui.view">
- <field name="name">attribute.group.list</field>
- <field name="model">attribute.group</field>
- <field name="arch" type="xml">
- <search string="Search Attribute Groups">
- <field name="name"/>
- <field name="attribute_set_id"/>
- </search>
- </field>
- </record>
-
- <record id="view_attribute_location_search" model="ir.ui.view">
- <field name="name">attribute.location.list</field>
- <field name="model">attribute.location</field>
- <field name="arch" type="xml">
- <search string="Search Attribute Locations">
- <field name="name"/>
- <field name="attribute_set_id"/>
- <field name="attribute_group_id"/>
- </search>
- </field>
- </record>
-
- <record id="view_product_attribute_search" model="ir.ui.view">
- <field name="name">product.attribute.list</field>
- <field name="model">product.attribute</field>
+ <record id="view_custom_attribute_search" model="ir.ui.view">
+ <field name="name">custom.attribute.list</field>
+ <field name="model">custom.attribute</field>
<field name="arch" type="xml">
<search string="Search Product Attributes">
<field name="name"/>
@@ -255,48 +148,18 @@
</field>
</record>
- <record id="attribute_set_form_action" model="ir.actions.act_window">
- <field name="name">Attribute Sets</field>
- <field name="res_model">attribute.set</field>
- <field name="view_type">form</field>
- <field name="view_mode">tree,form</field>
- <field name="search_view_id" ref="view_attribute_set_search"/>
- <field name="context">{"search_default_user_id":uid}</field>
- <field name="help"></field>
- </record>
-
- <record id="attribute_group_form_action" model="ir.actions.act_window">
- <field name="name">Attribute Groups</field>
- <field name="res_model">attribute.group</field>
- <field name="view_type">form</field>
- <field name="view_mode">tree,form</field>
- <field name="search_view_id" ref="view_attribute_group_search"/>
- <field name="context">{"search_default_user_id":uid}</field>
- <field name="help"></field>
- </record>
-
- <record id="attribute_location_form_action" model="ir.actions.act_window">
- <field name="name">Attribute Locations</field>
- <field name="res_model">attribute.location</field>
- <field name="view_type">form</field>
- <field name="view_mode">tree,form</field>
- <field name="search_view_id" ref="view_attribute_location_search"/>
- <field name="context">{"search_default_user_id":uid}</field>
- <field name="help"></field>
- </record>
-
- <record id="product_attribute_form_action" model="ir.actions.act_window">
- <field name="name">Product Attributes</field>
- <field name="res_model">product.attribute</field>
- <field name="view_type">form</field>
- <field name="view_mode">tree,form</field>
- <field name="search_view_id" ref="view_product_attribute_search"/>
+ <record id="custom_attribute_form_action" model="ir.actions.act_window">
+ <field name="name">Custom Attributes</field>
+ <field name="res_model">custom.attribute</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ <field name="search_view_id" ref="view_custom_attribute_search"/>
<field name="context">{"search_default_user_id":uid}</field>
<field name="help"></field>
</record>
<record id="attribute_option_form_action" model="ir.actions.act_window">
- <field name="name">Attribute Options</field>
+ <field name="name">Custom Attribute Options</field>
<field name="res_model">attribute.option</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
@@ -306,21 +169,24 @@
<field name="help"></field>
</record>
- <menuitem
- action="attribute_set_form_action" id="menu_attribute_set_action"
- parent="product_custom_attributes.menu_attribute_in_config_product" sequence="1"/>
+ <record id="attribute_group_form_action" model="ir.actions.act_window">
+ <field name="name">Custom Attribute Groups</field>
+ <field name="res_model">attribute.group</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ <field name="context">{"search_default_user_id":uid}</field>
+ <field name="help"></field>
+ </record>
+
<menuitem
action="attribute_group_form_action" id="menu_attribute_group_action"
- parent="product_custom_attributes.menu_attribute_in_config_product" sequence="2"/>
- <menuitem
- action="attribute_location_form_action" id="menu_attribute_location_action"
- parent="product_custom_attributes.menu_attribute_in_config_product" sequence="3"/>
- <menuitem
- action="product_attribute_form_action" id="menu_product_attribute_action"
- parent="product_custom_attributes.menu_attribute_in_config_product" sequence="4"/>
+ parent="base.next_id_9" sequence="2"/>
+ <menuitem
+ action="custom_attribute_form_action" id="menu_custom_attribute_action"
+ parent="base.next_id_9" sequence="4"/>
<menuitem
action="attribute_option_form_action" id="menu_attribute_option_action"
- parent="product_custom_attributes.menu_attribute_in_config_product" sequence="5"/>
+ parent="base.next_id_9" sequence="5"/>
</data>
</openerp>
=== modified file 'base_custom_attributes/security/ir.model.access.csv'
--- product_custom_attributes/security/ir.model.access.csv 2013-02-11 22:58:10 +0000
+++ base_custom_attributes/security/ir.model.access.csv 2013-03-02 00:14:23 +0000
@@ -1,16 +1,10 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
-"access_product_custom_attributes_attribute_set_salemanager","product_custom_attributes_attribute_set","product_custom_attributes.model_attribute_set","base.group_sale_manager",1,1,1,1
-"access_product_custom_attributes_attribute_group_salemanager","product_custom_attributes_attribute_group","product_custom_attributes.model_attribute_group","base.group_sale_manager",1,1,1,1
-"access_product_custom_attributes_attribute_location_salemanager","product_custom_attributes_attribute_location","product_custom_attributes.model_attribute_location","base.group_sale_manager",1,1,1,1
-"access_product_custom_attributes_product_attribute_salemanager","product_custom_attributes_product_attribute","product_custom_attributes.model_product_attribute","base.group_sale_manager",1,1,1,1
-"access_product_custom_attributes_attribute_option_salemanager","product_custom_attributes_attribute_option","product_custom_attributes.model_attribute_option","base.group_sale_manager",1,1,1,1
-"access_product_custom_attributes_attribute_set_manager","product_custom_attributes_attribute_set","product_custom_attributes.model_attribute_set","product.group_product_variant",1,1,1,1
-"access_product_custom_attributes_attribute_group_manager","product_custom_attributes_attribute_group","product_custom_attributes.model_attribute_group","product.group_product_variant",1,1,1,1
-"access_product_custom_attributes_attribute_location_manager","product_custom_attributes_attribute_location","product_custom_attributes.model_attribute_location","product.group_product_variant",1,1,1,1
-"access_product_custom_attributes_product_attribute_manager","product_custom_attributes_product_attribute","product_custom_attributes.model_product_attribute","product.group_product_variant",1,1,1,1
-"access_product_custom_attributes_attribute_option_manager","product_custom_attributes_attribute_option","product_custom_attributes.model_attribute_option","product.group_product_variant",1,1,1,1
-"access_product_custom_attributes_attribute_set_user","product_custom_attributes_attribute_set","product_custom_attributes.model_attribute_set","base.group_user",1,0,0,0
-"access_product_custom_attributes_attribute_group_user","product_custom_attributes_attribute_group","product_custom_attributes.model_attribute_group","base.group_user",1,0,0,0
-"access_product_custom_attributes_attribute_location_user","product_custom_attributes_attribute_location","product_custom_attributes.model_attribute_location","base.group_user",1,0,0,0
-"access_product_custom_attributes_product_attribute_user","product_custom_attributes_product_attribute","product_custom_attributes.model_product_attribute","base.group_user",1,0,0,0
-"access_product_custom_attributes_attribute_option_user","product_custom_attributes_attribute_option","product_custom_attributes.model_attribute_option","base.group_user",1,0,0,0
+"access_base_custom_attributes_attribute_group_salemanager","base_custom_attributes_attribute_group","base_custom_attributes.model_attribute_group","base.group_sale_manager",1,1,1,1
+"access_base_custom_attributes_product_attribute_salemanager","base_custom_attributes_product_attribute","base_custom_attributes.model_custom_attribute","base.group_sale_manager",1,1,1,1
+"access_base_custom_attributes_attribute_option_salemanager","base_custom_attributes_attribute_option","base_custom_attributes.model_attribute_option","base.group_sale_manager",1,1,1,1
+"access_base_custom_attributes_attribute_group_manager","base_custom_attributes_attribute_group","base_custom_attributes.model_attribute_group","product.group_product_variant",1,1,1,1
+"access_base_custom_attributes_product_attribute_manager","base_custom_attributes_product_attribute","base_custom_attributes.model_custom_attribute","product.group_product_variant",1,1,1,1
+"access_base_custom_attributes_attribute_option_manager","base_custom_attributes_attribute_option","base_custom_attributes.model_attribute_option","product.group_product_variant",1,1,1,1
+"access_base_custom_attributes_attribute_group_user","base_custom_attributes_attribute_group","base_custom_attributes.model_attribute_group","base.group_user",1,0,0,0
+"access_base_custom_attributes_product_attribute_user","base_custom_attributes_product_attribute","base_custom_attributes.model_custom_attribute","base.group_user",1,0,0,0
+"access_base_custom_attributes_attribute_option_user","base_custom_attributes_attribute_option","base_custom_attributes.model_attribute_option","base.group_user",1,0,0,0
=== added directory 'product_categ_attributes'
=== added file 'product_categ_attributes/__init__.py'
--- product_categ_attributes/__init__.py 1970-01-01 00:00:00 +0000
+++ product_categ_attributes/__init__.py 2013-03-02 00:14:23 +0000
@@ -0,0 +1,1 @@
+import product
=== added file 'product_categ_attributes/__openerp__.py'
--- product_categ_attributes/__openerp__.py 1970-01-01 00:00:00 +0000
+++ product_categ_attributes/__openerp__.py 2013-03-02 00:14:23 +0000
@@ -0,0 +1,42 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# product_custom_attributes for OpenERP #
+# Copyright (C) 2013 Akretion Raphaël Valyi <raphael.valyi@xxxxxxxxxxxx> #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU Affero General Public License as #
+# published by the Free Software Foundation, either version 3 of the #
+# License, or (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU Affero General Public License for more details. #
+# #
+# You should have received a copy of the GNU Affero General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+###############################################################################
+
+
+
+{
+ 'name': 'product_categ_attributes',
+ 'version': '0.1',
+ 'category': 'Generic Modules/Others',
+ 'license': 'AGPL-3',
+ 'description': """Makes it possible to inherit product attributes from its categories
+ """,
+ 'author': 'Akretion',
+ 'website': 'http://www.akretion.com/',
+ 'depends': ['product_custom_attributes', 'product_m2mcategories'],
+ 'init_xml': [],
+ 'update_xml': [
+ "product_view.xml"
+ ],
+ 'demo_xml': [],
+ 'installable': True,
+ 'active': False,
+}
+
=== added file 'product_categ_attributes/product.py'
--- product_categ_attributes/product.py 1970-01-01 00:00:00 +0000
+++ product_categ_attributes/product.py 2013-03-02 00:14:23 +0000
@@ -0,0 +1,26 @@
+from openerp.osv.orm import Model
+from openerp.osv import fields
+from openerp.osv.osv import except_osv
+from openerp.tools.translate import _
+
+
+class product_category(Model):
+ _inherit = "product.category"
+ _columns = {
+ 'attribute_group_ids': fields.many2many('attribute.group', 'categ_attr_grp_rel', 'categ_id', 'grp_id', 'Attribute Groups'),
+ }
+
+
+class product_product(Model):
+ _inherit = "product.product"
+
+ def _attr_grp_ids(self, cr, uid, ids, field_names, arg=None, context=None):
+ print "AAAAAAAAAAAAAA"
+ res = {}
+ for product in self.browse(cr, uid, ids, context=context):
+ grp_ids = []
+ for categ in product.categ_ids:
+ grp_ids += [grp.id for grp in categ.attribute_group_ids]
+ res[product.id] = grp_ids
+ return res
+
=== added file 'product_categ_attributes/product_view.xml'
--- product_categ_attributes/product_view.xml 1970-01-01 00:00:00 +0000
+++ product_categ_attributes/product_view.xml 2013-03-02 00:14:23 +0000
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<openerp>
+ <data>
+
+ <record model="ir.ui.view" id="product_categ_form_view">
+ <field name="name">product_categ_form_view</field>
+ <field name="model">product.category</field>
+ <field name="inherit_id" ref="product.product_category_form_view" />
+ <field name="arch" type="xml">
+ <field name="type" position="after">
+ <field name="attribute_group_ids"/>
+ </field>
+ </field>
+ </record>
+
+ <record model="ir.ui.view" id="product_product_form_view_set_button">
+ <field name="name">attributes.product.normal.form</field>
+ <field name="model">product.product</field>
+ <field name="inherit_id" ref="product_custom_attributes.product_product_form_view_set_button" />
+ <field name="arch" type="xml">
+ <field name="attribute_set_id" position="replace">
+ </field>
+ <button name="open_attributes" position="replace">
+ <button name="open_attributes" string="Open Attributes" type="object" icon="gtk-ok"/>
+ </button>
+ </field>
+ </record>
+
+ <record id="attribute_group_form_view" model="ir.ui.view">
+ <field name="name">attribute.group.form</field>
+ <field name="model">attribute.group</field>
+ <field name="inherit_id" ref="base_custom_attributes.attribute_group_form_view" />
+ <field name="arch" type="xml">
+ <field name="attribute_set_id" position="replace">
+ </field>
+ </field>
+ </record>
+
+ </data>
+</openerp>
+
=== added directory 'product_custom_attributes'
=== added file 'product_custom_attributes/__init__.py'
--- product_custom_attributes/__init__.py 1970-01-01 00:00:00 +0000
+++ product_custom_attributes/__init__.py 2013-03-02 00:14:23 +0000
@@ -0,0 +1,3 @@
+import product
+import custom_attributes
+import wizard
=== added file 'product_custom_attributes/__openerp__.py'
--- product_custom_attributes/__openerp__.py 1970-01-01 00:00:00 +0000
+++ product_custom_attributes/__openerp__.py 2013-03-02 00:14:23 +0000
@@ -0,0 +1,47 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# product_custom_attributes for OpenERP #
+# Copyright (C) 2011 Akretion Benoît GUILLOT <benoit.guillot@xxxxxxxxxxxx> #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU Affero General Public License as #
+# published by the Free Software Foundation, either version 3 of the #
+# License, or (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU Affero General Public License for more details. #
+# #
+# You should have received a copy of the GNU Affero General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+###############################################################################
+
+
+
+{
+ 'name': 'product_custom_attributes',
+ 'version': '0.1',
+ 'category': 'Generic Modules/Others',
+ 'license': 'AGPL-3',
+ 'description': """This module adds the possibility to easily create custom fields on products.
+Each product can be linked to an attribute set (like camera, fridge...).
+Each attribute has custom fields (for example, you don't need the same field for a frigde and a camera).
+In particular it's used by the Magento Magentoerpconnect module to match the EAV flexibility of Magento.
+ """,
+ 'author': 'Akretion',
+ 'website': 'http://www.akretion.com/',
+ 'depends': ['product', 'base_custom_attributes'],
+ 'init_xml': [],
+ 'update_xml': [
+ 'product_view.xml',
+ 'custom_attributes_view.xml',
+ 'wizard/open_product_by_attribute_set.xml',
+ ],
+ 'demo_xml': [],
+ 'installable': True,
+ 'active': False,
+}
+
=== added file 'product_custom_attributes/custom_attributes.py'
--- product_custom_attributes/custom_attributes.py 1970-01-01 00:00:00 +0000
+++ product_custom_attributes/custom_attributes.py 2013-03-02 00:14:23 +0000
@@ -0,0 +1,67 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# product_custom_attributes for OpenERP #
+# Copyright (C) 2011 Akretion Benoît GUILLOT <benoit.guillot@xxxxxxxxxxxx> #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU Affero General Public License as #
+# published by the Free Software Foundation, either version 3 of the #
+# License, or (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU Affero General Public License for more details. #
+# #
+# You should have received a copy of the GNU Affero General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+###############################################################################
+
+from openerp.osv.orm import Model
+from openerp.osv import fields
+from tools.translate import _
+
+
+class attribute_group(Model):
+ _inherit= "attribute.group"
+
+ _columns = {
+ 'attribute_set_id': fields.many2one('attribute.set', 'Attribute Set'),
+ 'attribute_ids': fields.one2many('attribute.location', 'attribute_group_id', 'Attributes'),
+ }
+
+ def create(self, cr, uid, vals, context=None):
+ for attribute in vals['attribute_ids']:
+ if vals.get('attribute_set_id') and attribute[2] and not attribute[2].get('attribute_set_id'):
+ attribute[2]['attribute_set_id'] = vals['attribute_set_id']
+ return super(attribute_group, self).create(cr, uid, vals, context)
+
+class attribute_set(Model):
+ _name = "attribute.set"
+ _description = "Attribute Set"
+ _columns = {
+ 'name': fields.char('Name', size=128, required=True),
+ 'attribute_group_ids': fields.one2many('attribute.group', 'attribute_set_id', 'Attribute Groups'),
+ }
+
+class attribute_location(Model):
+ _name = "attribute.location"
+ _description = "Attribute Location"
+ _order="sequence"
+ _inherits = {'custom.attribute': 'attribute_id'}
+
+
+ def _get_attribute_loc_from_group(self, cr, uid, ids, context=None):
+ return self.pool.get('attribute.location').search(cr, uid, [('attribute_group_id', 'in', ids)], context=context)
+
+ _columns = {
+ 'attribute_id': fields.many2one('custom.attribute', 'Product Attribute', required=True, ondelete="cascade"),
+ 'attribute_set_id': fields.related('attribute_group_id', 'attribute_set_id', type='many2one', relation='attribute.set', string='Attribute Set', readonly=True,
+store={
+ 'attribute.group': (_get_attribute_loc_from_group, ['attribute_set_id'], 10),
+ }),
+ 'attribute_group_id': fields.many2one('attribute.group', 'Attribute Group', required=True),
+ 'sequence': fields.integer('Sequence'),
+ }
=== added file 'product_custom_attributes/custom_attributes_view.xml'
--- product_custom_attributes/custom_attributes_view.xml 1970-01-01 00:00:00 +0000
+++ product_custom_attributes/custom_attributes_view.xml 2013-03-02 00:14:23 +0000
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ base_custom_attributes for OpenERP
+ Copyright (C) 2011-2013 Akretion (http://www.akretion.com/)
+ @author: Benoît GUILLOT <benoit.guillot@xxxxxxxxxxxx>
+ The licence is in the file __openerp__.py
+-->
+
+<openerp>
+ <data>
+
+ <menuitem
+ id="menu_attribute_in_config_product" name="Attributes"
+ parent="product.prod_config_main" sequence="20"/>
+
+ <record id="attribute_set_form_view" model="ir.ui.view">
+ <field name="name">attribute.set.form</field>
+ <field name="model">attribute.set</field>
+ <field name="arch" type="xml">
+ <form string="Attribute Set">
+ <field name="name" colspan="4"/>
+ <field name="attribute_group_ids" colspan="4" >
+ <form string="Attribute Groups">
+ <field name="name" />
+ <field name="sequence" />
+ <field name="attribute_ids" colspan="4">
+ <form string="Attribute Location">
+ <field name="attribute_id" />
+ <field name="sequence" />
+ </form>
+ <tree string="Attribute Location">
+ <field name="attribute_id" />
+ </tree>
+ </field>
+ </form>
+ <tree string="Attribute Groups">
+ <field name="name" />
+ </tree>
+ </field>
+ </form>
+ </field>
+ </record>
+
+ <record id="attribute_location_form_view" model="ir.ui.view">
+ <field name="name">attribute.location.form</field>
+ <field name="model">attribute.location</field>
+ <field name="arch" type="xml">
+ <form string="Attribute Location">
+ <field name="attribute_id" />
+ <field name="sequence" />
+ <field name="attribute_group_id" />
+ <field name="attribute_set_id" />
+ </form>
+ </field>
+ </record>
+
+ <record id="attribute_set_tree_view" model="ir.ui.view">
+ <field name="name">attribute.set.tree</field>
+ <field name="model">attribute.set</field>
+ <field name="arch" type="xml">
+ <tree string="Attribute Set" >
+ <field name="name" />
+ </tree>
+ </field>
+ </record>
+
+ <record id="attribute_group_tree_view" model="ir.ui.view">
+ <field name="model">attribute.group</field>
+ <field name="inherit_id" ref="base_custom_attributes.attribute_group_tree_view" />
+ <field name="arch" type="xml">
+ <field name="sequence" position="after">
+ <field name="attribute_set_id" />
+ </field>
+ </field>
+ </record>
+
+ <record id="attribute_location_tree_view" model="ir.ui.view">
+ <field name="name">attribute.location.tree</field>
+ <field name="model">attribute.location</field>
+ <field name="arch" type="xml">
+ <tree string="Attribute Location">
+ <field name="attribute_id" />
+ <field name="sequence" />
+ <field name="attribute_set_id" />
+ <field name="attribute_group_id" />
+ </tree>
+ </field>
+ </record>
+
+ <record id="view_attribute_set_search" model="ir.ui.view">
+ <field name="name">attribute.set.list</field>
+ <field name="model">attribute.set</field>
+ <field name="arch" type="xml">
+ <search string="Search Attribute Sets">
+ <field name="name"/>
+ </search>
+ </field>
+ </record>
+
+ <record id="view_attribute_group_search" model="ir.ui.view">
+ <field name="name">attribute.group.list</field>
+ <field name="model">attribute.group</field>
+ <field name="arch" type="xml">
+ <search string="Search Attribute Groups">
+ <field name="name"/>
+ <field name="attribute_set_id"/>
+ </search>
+ </field>
+ </record>
+
+ <record id="view_attribute_location_search" model="ir.ui.view">
+ <field name="name">attribute.location.list</field>
+ <field name="model">attribute.location</field>
+ <field name="arch" type="xml">
+ <search string="Search Attribute Locations">
+ <field name="name"/>
+ <field name="attribute_set_id"/>
+ <field name="attribute_group_id"/>
+ </search>
+ </field>
+ </record>
+
+ <record id="attribute_set_form_action" model="ir.actions.act_window">
+ <field name="name">Attribute Sets</field>
+ <field name="res_model">attribute.set</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ <field name="search_view_id" ref="view_attribute_set_search"/>
+ <field name="context">{"search_default_user_id":uid}</field>
+ <field name="help"></field>
+ </record>
+
+ <record id="attribute_location_form_action" model="ir.actions.act_window">
+ <field name="name">Attribute Locations</field>
+ <field name="res_model">attribute.location</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ <field name="search_view_id" ref="view_attribute_location_search"/>
+ <field name="context">{"search_default_user_id":uid}</field>
+ <field name="help"></field>
+ </record>
+
+ <menuitem
+ action="attribute_set_form_action" id="menu_attribute_set_action"
+ parent="product_custom_attributes.menu_attribute_in_config_product" sequence="1"/>
+ <menuitem
+ action="base_custom_attributes.attribute_group_form_action" id="menu_attribute_group_action"
+ parent="product_custom_attributes.menu_attribute_in_config_product" sequence="2"/>
+ <menuitem
+ action="attribute_location_form_action" id="menu_attribute_location_action"
+ parent="product_custom_attributes.menu_attribute_in_config_product" sequence="3"/>
+ <menuitem
+ action="base_custom_attributes.custom_attribute_form_action" id="menu_custom_attribute_action"
+ parent="product_custom_attributes.menu_attribute_in_config_product" sequence="4"/>
+ <menuitem
+ action="base_custom_attributes.attribute_option_form_action" id="menu_attribute_option_action"
+ parent="product_custom_attributes.menu_attribute_in_config_product" sequence="5"/>
+
+ </data>
+</openerp>
=== renamed file 'product_custom_attributes/product.py' => 'product_custom_attributes/product.py'
--- product_custom_attributes/product.py 2013-03-02 00:14:23 +0000
+++ product_custom_attributes/product.py 2013-03-02 00:14:23 +0000
@@ -25,13 +25,6 @@
from lxml import etree
from tools.translate import _
-class product_template(Model):
-
- _inherit = "product.template"
-
- _columns = {
- 'attribute_custom_tmpl': fields.serialized('Custom Template Attributes'),
- }
class product_product(Model):
@@ -51,7 +44,6 @@
_columns = {
'attribute_set_id': fields.many2one('attribute.set', 'Attribute Set'),
- 'attribute_custom_variant': fields.serialized('Custom Variant Attributes'),
'attribute_group_ids': fields.function(_attr_grp_ids, type='one2many',
relation='attribute.group', string='Groups')
}
@@ -90,39 +82,6 @@
def save_and_close_product_attributes(self, cr, uid, ids, context=None):
return {'type': 'ir.actions.act_window_close'}
- def _build_attribute_field(self, cr, uid, page, attribute, context=None):
- parent = page
- kwargs = {'name': "%s" % attribute.name}
- if attribute.ttype == 'many2many':
- parent = etree.SubElement(page, 'group', colspan="2", col="4")
- #FIXME the following isn't displayed in v7:
- sep = etree.SubElement(parent, 'separator',
- string="%s" % attribute.field_description, colspan="4")
- kwargs['nolabel'] = "1"
- if attribute.ttype in ['many2one', 'many2many']:
- if attribute.relation_model_id:
- if attribute.domain:
- kwargs['domain'] = attribute.domain
- else:
- ids = [op.value_ref.id for op in attribute.option_ids]
- kwargs['domain'] = "[('id', 'in', %s)]" % ids
- else:
- kwargs['domain'] = "[('attribute_id', '=', %s)]" % attribute.attribute_id.id
- field = etree.SubElement(parent, 'field', **kwargs)
- return parent
-
- def _build_attributes_notebook(self, cr, uid, attribute_group_ids, context=None):
- notebook = etree.Element('notebook', name="attributes_notebook", colspan="4")
- toupdate_fields = []
- grp_obj = self.pool.get('attribute.group')
- for group in grp_obj.browse(cr, uid, attribute_group_ids, context=context):
- page = etree.SubElement(notebook, 'page', string=group.name.capitalize())
- for attribute in group.attribute_ids:
- if attribute.name not in toupdate_fields:
- toupdate_fields.append(attribute.name)
- self._build_attribute_field(cr, uid, page, attribute, context=context)
- return notebook, toupdate_fields
-
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
if context is None:
context = {}
@@ -134,7 +93,7 @@
if button:
button = button[0]
button.getparent().remove(button)
- attributes_notebook, toupdate_fields = self._build_attributes_notebook(cr, uid, context['attribute_group_ids'], context=context)
+ attributes_notebook, toupdate_fields = self.pool.get('custom.attribute')._build_attributes_notebook(cr, uid, context['attribute_group_ids'], context=context)
result['fields'].update(self.fields_get(cr, uid, toupdate_fields, context))
if context.get('open_attributes'):
placeholder = eview.xpath("//separator[@string='attributes_placeholder']")[0]
=== renamed file 'product_custom_attributes/product_view.xml' => 'product_custom_attributes/product_view.xml'
=== renamed directory 'product_custom_attributes/wizard' => 'product_custom_attributes/wizard'
Follow ups
-
[Merge] lp:~akretion-team/openerp-product-attributes/mixin-extraction into lp:openerp-product-attributes
From: noreply, 2013-06-21
-
Re: lp:~akretion-team/openerp-product-attributes/mixin-extraction into lp:openerp-product-attributes
From: Benoit Guillot - http://www.akretion.com, 2013-06-18
-
Re: lp:~akretion-team/openerp-product-attributes/mixin-extraction into lp:openerp-product-attributes
From: Guewen Baconnier @ Camptocamp, 2013-06-18
-
Re: lp:~akretion-team/openerp-product-attributes/mixin-extraction into lp:openerp-product-attributes
From: Sébastien BEAU - http : //www . akretion . com, 2013-06-17
-
Re: lp:~akretion-team/openerp-product-attributes/mixin-extraction into lp:openerp-product-attributes
From: Guewen Baconnier @ Camptocamp, 2013-06-17
-
Re: lp:~akretion-team/openerp-product-attributes/mixin-extraction into lp:openerp-product-attributes
From: Raphaël Valyi - http : //www . akretion . com, 2013-06-16
-
Re: lp:~akretion-team/openerp-product-attributes/mixin-extraction into lp:openerp-product-attributes
From: Raphaël Valyi - http : //www . akretion . com, 2013-06-16
-
Re: lp:~akretion-team/openerp-product-attributes/mixin-extraction into lp:openerp-product-attributes
From: Sébastien BEAU - http : //www . akretion . com, 2013-06-15
-
Re: lp:~akretion-team/openerp-product-attributes/mixin-extraction into lp:openerp-product-attributes
From: Guewen Baconnier @ Camptocamp, 2013-04-29
-
Re: lp:~akretion-team/openerp-product-attributes/mixin-extraction into lp:openerp-product-attributes
From: Guewen Baconnier @ Camptocamp, 2013-04-29
-
Re: lp:~akretion-team/openerp-product-attributes/mixin-extraction into lp:openerp-product-attributes
From: Guewen Baconnier @ Camptocamp, 2013-03-19
-
Re: lp:~akretion-team/openerp-product-attributes/mixin-extraction into lp:openerp-product-attributes
From: Alexandre Fayolle - camptocamp, 2013-03-18
-
Re: lp:~akretion-team/openerp-product-attributes/mixin-extraction into lp:openerp-product-attributes
From: Guewen Baconnier @ Camptocamp, 2013-03-04