← Back to team overview

openerp-community-reviewer team mailing list archive

lp:~camptocamp/openerp-product-attributes/6.1-backport-lot-custom-attributes-lep into lp:openerp-product-attributes/6.1

 

Leonardo Pistone @ camptocamp has proposed merging lp:~camptocamp/openerp-product-attributes/6.1-backport-lot-custom-attributes-lep into lp:openerp-product-attributes/6.1.

Commit message:
[mrg] new modules: base_custom_attributes and production_lot_custom_attributes, backported from 7.0 and cleaned up

Requested reviews:
  Product Core Editors (product-core-editors)

For more details, see:
https://code.launchpad.net/~camptocamp/openerp-product-attributes/6.1-backport-lot-custom-attributes-lep/+merge/196538

This is to backport the modules base_custom_attributes and production_lot_custom_attributes to v6.1.

I added some docstrings and comments that should make creating a new similar module easier.

Warning: in v7.0 the module product_custom_attributes (where all that started) has been split to use base_custom_attributes. In 6.1 is hasn't, so at the moment in 6.1 product_custom_attributes and production_lot_custom_attributes are incompatible.

Thanks to Akretion for the original modules this is based on.
-- 
https://code.launchpad.net/~camptocamp/openerp-product-attributes/6.1-backport-lot-custom-attributes-lep/+merge/196538
Your team Product Core Editors is requested to review the proposed merge of lp:~camptocamp/openerp-product-attributes/6.1-backport-lot-custom-attributes-lep into lp:openerp-product-attributes/6.1.
=== added directory 'base_custom_attributes'
=== added file 'base_custom_attributes/__init__.py'
--- base_custom_attributes/__init__.py	1970-01-01 00:00:00 +0000
+++ base_custom_attributes/__init__.py	2013-11-25 13:51:36 +0000
@@ -0,0 +1,29 @@
+# -*- 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/>.     #
+#                                                                             #
+###############################################################################
+
+
+
+import ir_model
+import custom_attributes
+
+
+
+

=== added file 'base_custom_attributes/__openerp__.py'
--- base_custom_attributes/__openerp__.py	1970-01-01 00:00:00 +0000
+++ base_custom_attributes/__openerp__.py	2013-11-25 13:51:36 +0000
@@ -0,0 +1,48 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+#                                                                             #
+#   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      #
+#   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': 'base_custom_attributes',
+    'version': '0.1',
+    'category': 'Generic Modules/Others',
+    'license': 'AGPL-3',
+    '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': ['base'],
+    'init_xml': [],
+    'update_xml': [
+           'security/ir.model.access.csv',
+           'security/attribute_security.xml',
+           'custom_attributes_view.xml',
+    ],
+    'demo_xml': [],
+    'installable': True,
+    'active': False,
+    'external_dependencies' : {
+        'python' : ['unidecode'],
+    }
+
+}
+

=== added file 'base_custom_attributes/custom_attributes.py'
--- base_custom_attributes/custom_attributes.py	1970-01-01 00:00:00 +0000
+++ base_custom_attributes/custom_attributes.py	2013-11-25 13:51:36 +0000
@@ -0,0 +1,440 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+#                                                                             #
+#   base_attribute.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            #
+#   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/>.     #
+#                                                                             #
+###############################################################################
+
+import ast
+from openerp.osv import orm, fields
+from openerp.osv.osv import except_osv
+from openerp.tools.translate import _
+from lxml import etree
+from unidecode import unidecode # Debian package python-unidecode
+import re
+
+
+def safe_column_name(string):
+    """This function prevent portability problem in database column name
+    with other DBMS system
+    Use case : if you synchronise attributes with other applications """
+    string = unidecode(string.replace(' ', '_').lower())
+    return re.sub(r'[^0-9a-z_]','', string)
+
+
+class attribute_option(orm.Model):
+    _name = "attribute.option"
+    _description = "Attribute Option"
+    _order="sequence"
+
+    def _get_model_list(self, cr, uid, context=None):
+        model_pool = self.pool.get('ir.model')
+        ids = model_pool.search(cr, uid, [], context=context)
+        res = model_pool.read(cr, uid, ids, ['model', 'name'], context=context)
+        return [(r['model'], r['name']) for r in res]
+
+    _columns = {
+        'name': fields.char(
+            'Name',
+            size=128,
+            translate=True,
+            required=True),
+        'value_ref': fields.reference(
+            'Reference',
+            selection=_get_model_list,
+            size=128),
+        'attribute_id': fields.many2one(
+            'attribute.attribute',
+            'Product Attribute',
+            required=True),
+        'sequence': fields.integer('Sequence'),
+    }
+
+    def name_change(self, cr, uid, ids, name, relation_model_id, context=None):
+        if relation_model_id:
+            warning = {'title': _('Error!'),
+                       'message': _("Use the 'Load Options' button "
+                                    "instead to select appropriate "
+                                    "model references'")}
+            return {"value": {"name": False}, "warning": warning}
+        else:
+            return True
+
+
+class attribute_option_wizard(orm.TransientModel):
+    _name = "attribute.option.wizard"
+    _rec_name = 'attribute_id'
+
+    _columns = {
+        'attribute_id': fields.many2one(
+            'attribute.attribute',
+            'Product Attribute',
+            required=True),
+    }
+
+    _defaults = {
+        'attribute_id': lambda self, cr, uid, context:
+                            context.get('attribute_id',False)
+    }
+
+    def validate(self, cr, uid, ids, context=None):
+        return True
+
+    def create(self, cr, uid, vals, context=None):
+        attr_obj = self.pool.get("attribute.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")
+        opt_obj.unlink(cr, uid, op_ids)
+        for op_id in (vals.get("option_ids") and vals['option_ids'][0][2] or []):
+            model = attr.relation_model_id.model
+            name = self.pool.get(model).name_get(cr, uid, [op_id], context)[0][1]
+            opt_obj.create(cr, uid, {
+                'attribute_id': vals['attribute_id'],
+                'name': name,
+                'value_ref': "%s,%s" % (attr.relation_model_id.model, op_id)
+            })
+        res = super(attribute_option_wizard, self).create(cr, uid, vals, context)
+        return res
+
+    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 view_type == 'form' and context and context.get("attribute_id"):
+            attr_obj = self.pool.get("attribute.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': {
+                            'domain': [],
+                            'string': "Options",
+                            'type': 'many2many',
+                            'relation': relation,
+                            'required': True,
+                            }
+                        })
+            eview = etree.fromstring(res['arch'])
+            options = etree.Element('field', name='option_ids', colspan='6')
+            placeholder = eview.xpath("//separator[@string='options_placeholder']")[0]
+            placeholder.getparent().replace(placeholder, options)
+            res['arch'] = etree.tostring(eview, pretty_print=True)
+        return res
+
+
+class attribute_attribute(orm.Model):
+    _name = "attribute.attribute"
+    _description = "Attribute"
+    _inherits = {'ir.model.fields': 'field_id'}
+
+    def _build_attribute_field(self, cr, uid, page, attribute, context=None):
+        parent = etree.SubElement(page, 'group', colspan="2", col="4")
+        kwargs = {'name': "%s" % attribute.name}
+        if attribute.ttype in ['many2many', 'text']:
+            parent = etree.SubElement(parent, 'group', colspan="2", col="4")
+            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:
+                # attribute.domain is a string, it may be an empty list
+                try:
+                    domain = ast.literal_eval(attribute.domain)
+                except ValueError:
+                    domain = None
+                if 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
+        kwargs['context'] = "{'default_attribute_id': %s}" % attribute.attribute_id.id
+        kwargs['required'] = str(attribute.required or
+                                 attribute.required_on_views)
+        field = etree.SubElement(parent, 'field', **kwargs)
+        orm.setup_modifiers(field, self.fields_get(cr, uid, attribute.name,
+                                                   context))
+        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]}}
+
+    def button_add_options(self, cr, uid, ids, context=None):
+        return {
+            'context': "{'attribute_id': %s}" % (ids[0]),
+            'name': _('Options Wizard'),
+            'view_type': 'form',
+            'view_mode': 'form',
+            'res_model': 'attribute.option.wizard',
+            'type': 'ir.actions.act_window',
+            'target': 'new',
+        }
+
+    _columns = {
+        'field_id': fields.many2one(
+            'ir.model.fields',
+            'Ir Model Fields',
+            required=True,
+            ondelete="cascade"),
+        'attribute_type': fields.selection([
+            ('char', 'Char'),
+            ('text', 'Text'),
+            ('select', 'Select'),
+            ('multiselect', 'Multiselect'),
+            ('boolean', 'Boolean'),
+            ('integer', 'Integer'),
+            ('date', 'Date'),
+            ('datetime', 'Datetime'),
+            ('binary', 'Binary'),
+            ('float', 'Float')],
+            'Type', required=True),
+        '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"),
+        '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'),
+        'required_on_views': fields.boolean(
+            'Required (on views)',
+            help="If activated, the attribute will be mandatory on the views, "
+                 "but not in the database"),
+        }
+
+    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']
+        else:
+            relation = 'attribute.option'
+        if vals['attribute_type'] == 'select':
+            vals['ttype'] = 'many2one'
+            vals['relation'] = relation
+        elif vals['attribute_type'] == 'multiselect':
+            vals['ttype'] = 'many2many'
+            vals['relation'] = relation
+            vals['serialized'] = True
+        else:
+            vals['ttype'] = vals['attribute_type']
+
+        if vals.get('serialized'):
+            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': u'x_custom_json_attrs',
+                    'field_description': u'Serialized JSON Attributes',
+                    'ttype': 'serialized',
+                    'model_id': vals['model_id'],
+                }
+                vals['serialization_field_id'] = field_obj.create(
+                    cr, uid, f_vals, {'manual': True})
+        vals['state'] = 'manual'
+        return super(attribute_attribute, self).create(cr, uid, vals, context)
+
+    def onchange_field_description(self, cr, uid, ids, field_description,
+                                   name, create_date, context=None):
+        name = name or u'x_'
+        if field_description and not create_date:
+            name = unicode('x_' + safe_column_name(field_description))
+        return {'value': {'name': name}}
+
+    def onchange_name(self, cr, uid, ids, name, context=None):
+        res = {}
+        if not name.startswith('x_'):
+            name = u'x_%s' % name
+        else:
+            name = u'%s' % name
+        res = {'value': {'name': unidecode(name)}}
+
+        #FILTER ON MODEL
+        model_name = context.get('force_model')
+        if not model_name:
+            model_id = context.get('default_model_id')
+            if model_id:
+                model = self.pool['ir.model'].browse(cr, uid, model_id,
+                                                     context=context)
+                model_name = model.model
+        if model_name:
+            model_obj = self.pool[model_name]
+            allowed_model = [x for x in model_obj._inherits] + [model_name]
+            res['domain'] = {'model_id': [['model', 'in', allowed_model]]}
+
+        return res
+
+    def _get_default_model(self, cr, uid, context=None):
+        if context and context.get('force_model'):
+            model_id = self.pool['ir.model'].search(cr, uid, [
+                                        ('model', '=', context['force_model'])
+                                                             ], context=context)
+            if model_id:
+                return model_id[0]
+        return None
+
+    _defaults = {
+        'model_id': _get_default_model
+    }
+
+
+class attribute_group(orm.Model):
+    _name = "attribute.group"
+    _description = "Attribute Group"
+    _order ="sequence"
+
+    _columns = {
+        'name': fields.char(
+            'Name',
+            size=128,
+            required=True,
+            translate=True),
+        'sequence': fields.integer('Sequence'),
+        'attribute_set_id': fields.many2one(
+            'attribute.set',
+            'Attribute Set'),
+        'attribute_ids': fields.one2many(
+            'attribute.location',
+            'attribute_group_id',
+            'Attributes'),
+        'model_id': fields.many2one(
+            'ir.model',
+            'Model',
+            required=True),
+    }
+
+    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)
+
+    def _get_default_model(self, cr, uid, context=None):
+        if context and context.get('force_model'):
+            model_id = self.pool['ir.model'].search(
+                cr, uid, [['model', '=', context['force_model']]],
+                context=context)
+            if model_id:
+                return model_id[0]
+        return None
+
+    _defaults = {
+        'model_id': _get_default_model
+    }
+
+
+class attribute_set(orm.Model):
+    _name = "attribute.set"
+    _description = "Attribute Set"
+    _columns = {
+        'name': fields.char(
+            'Name',
+            size=128,
+            required=True,
+            translate=True),
+        'attribute_group_ids': fields.one2many(
+            'attribute.group',
+            'attribute_set_id',
+            'Attribute Groups'),
+        'model_id': fields.many2one(
+            'ir.model',
+            'Model',
+            required=True),
+        }
+
+    def _get_default_model(self, cr, uid, context=None):
+        if context and context.get('force_model'):
+            model_id = self.pool['ir.model'].search(
+                cr, uid, [['model', '=', context['force_model']]],
+                context=context)
+            if model_id:
+                return model_id[0]
+        return None
+
+    _defaults = {
+        'model_id': _get_default_model
+    }
+
+
+class attribute_location(orm.Model):
+    _name = "attribute.location"
+    _description = "Attribute Location"
+    _order="sequence"
+    _inherits = {'attribute.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(
+            'attribute.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 'base_custom_attributes/custom_attributes_view.xml'
--- base_custom_attributes/custom_attributes_view.xml	1970-01-01 00:00:00 +0000
+++ base_custom_attributes/custom_attributes_view.xml	2013-11-25 13:51:36 +0000
@@ -0,0 +1,312 @@
+<?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_admin" name="Attributes"
+            parent="base.next_id_9" sequence="1"/>
+
+    <!-- ATTRIBUTE SET VIEW -->
+
+        <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="type">form</field>
+            <field name="arch" type="xml">
+                <form string="Attribute Set">
+                    <field name="name"/>
+                    <field name="model_id" invisible="context.get('force_model')"/>
+                    <field name="attribute_group_ids" colspan="4"
+                           context="{'default_model_id': model_id, 'from_attribute_set':True}">
+                    </field>
+                </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="type">tree</field>
+            <field name="arch" type="xml">
+                <tree string="Attribute Set" >
+                    <field name="name" />
+                    <field name="model_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="type">search</field>
+            <field name="arch" type="xml">
+                <search string="Search Attribute Sets">
+                    <field name="name"/>
+                    <field name="model_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>
+
+         <menuitem
+             action="attribute_set_form_action" id="menu_attribute_set_action"
+             parent="menu_attribute_in_admin" sequence="10"/>
+ 
+
+
+    <!-- ATTRIBUTE GROUP VIEW -->
+
+        <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="type">form</field>
+            <field name="arch" type="xml">
+                <form string="Attribute Group">
+                    <field name="name" />
+                    <field name="sequence" />
+                    <field name="model_id" invisible="context.get('from_attribute_set') or context.get('force_model')"/>
+                    <field name="attribute_set_id" invisible="context.get('from_attribute_set')"/>
+                    <field name="attribute_ids" colspan="4" nolabel="1">
+                        <form string="Attribute Location">
+                            <field name="attribute_id" context="{'default_model_id': parent.model_id}"/>
+                            <field name="sequence" />
+                        </form>
+                        <tree string="Attribute Location" editable="top">
+                            <field name="attribute_id" context="{'default_model_id': parent.model_id}"/>
+                            <field name="sequence" />
+                        </tree>
+                    </field>
+                </form>
+            </field>
+        </record>
+
+        <record id="attribute_group_tree_view" model="ir.ui.view">
+            <field name="name">attribute.group.tree</field>
+            <field name="model">attribute.group</field>
+            <field name="type">tree</field>
+            <field name="arch" type="xml">
+                <tree string="Attribute Group">
+                    <field name="name" />
+                    <field name="sequence" />
+                    <field name="attribute_set_id" invisible="context.get('from_attribute_set')"/>
+                    <field name="model_id" invisible="context.get('from_attribute_set')"/>
+                </tree>
+            </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="type">search</field>
+            <field name="arch" type="xml">
+                <search string="Search Attribute Groups">
+                    <field name="name"/>
+                    <field name="attribute_set_id"/>
+                    <field name="model_id" />
+               </search>
+            </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="context">{"search_default_user_id":uid}</field>
+            <field name="help"></field>
+        </record>
+
+         <menuitem
+             action="attribute_group_form_action" id="menu_attribute_group_action"
+             parent="menu_attribute_in_admin" sequence="20"/>
+
+    <!-- ATTRIBUTE VIEW -->
+
+        <record id="attribute_attribute_form_view" model="ir.ui.view">
+            <field name="name">attribute.attribute.form</field>
+            <field name="model">attribute.attribute</field>
+            <field name="type">form</field>
+            <field name="arch" type="xml">
+                <form string="Attribute">
+                    <field name="field_description" on_change="onchange_field_description(field_description, name, create_date, context)"/>
+                    <field name="name" attrs="{'readonly':[('create_date', '!=', False)]}" on_change="onchange_name(name, context)"/>
+                    <field name="attribute_type" />
+                    <field name="model_id" />
+                    <field name="serialized" attrs="{'invisible':[('attribute_type', '=', 'multiselect')]}"/>
+                    <field name="size" attrs="{'invisible':[('attribute_type', '!=', 'char')]}"/>
+                    <field name="required_on_views"/>
+                    <field name="translate" attrs="{'invisible':[('attribute_type', 'not in', ('char', 'text'))]}"/>
+                    <newline />
+                    <group colspan="4" attrs="{'invisible':[('attribute_type', 'not in', ['select', 'multiselect'])]}">
+                        <group groups="base.group_advanced_attribute">
+                            <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)]}"/>
+                            <button name="button_add_options" attrs="{'invisible':[('relation_model_id', '=', False), ('domain', '!=', False)]}" type="object" string="Load Options"/>
+                        </group>
+                        <field name="option_ids" colspan="4" nolabel="1">
+                            <tree string="Attribute Options" editable="top">
+                                <field name="sequence" invisible="1"/>
+                                <field name="name" on_change="name_change(name, parent.relation_model_id, context)"/>
+                            </tree>
+                        </field>
+                    </group>
+                    <field name="create_date" invisible="1"/>
+                </form>
+            </field>
+        </record>
+        
+        <record id="attribute_attribute_tree_view" model="ir.ui.view">
+            <field name="name">attribute.attribute.tree</field>
+            <field name="model">attribute.attribute</field>
+            <field name="type">tree</field>
+            <field name="arch" type="xml">
+                <tree string="Attribute">
+                    <field name="name" />
+                    <field name="attribute_type" />
+                </tree>
+            </field>
+        </record>
+        
+        <record id="view_attribute_attribute_search" model="ir.ui.view">
+            <field name="name">attribute.attribute.list</field>
+            <field name="model">attribute.attribute</field>
+            <field name="type">search</field>
+            <field name="arch" type="xml">
+                <search string="Search Attributes">
+                    <field name="name"/>
+               </search>
+            </field>
+        </record>
+
+        <record id="attribute_attribute_form_action" model="ir.actions.act_window">
+            <field name="name">Attributes</field>
+            <field name="res_model">attribute.attribute</field>
+            <field name="view_type">form</field>
+            <field name="view_mode">tree,form</field>
+            <field name="search_view_id" ref="view_attribute_attribute_search"/>
+            <field name="context">{"search_default_user_id":uid}</field>
+            <field name="help"></field>
+        </record>
+        <menuitem
+            action="attribute_attribute_form_action" id="menu_attribute_attribute_action"
+            parent="menu_attribute_in_admin" sequence="30"/>
+
+    <!-- ATTRIBUTE OPTION VIEW -->
+        <record id="attribute_option_form_popup_view" model="ir.ui.view">
+            <field name="name">attribute.option.form.popup</field>
+            <field name="model">attribute.option</field>
+            <field name="priority" eval="6"/>
+            <field name="type">form</field>
+            <field name="arch" type="xml">
+                <form string="Attribute Option">
+                    <field name="name" colspan="2"/>
+                    <field name="value_ref" colspan="2" groups="base.group_advanced_attribute"/>
+                    <field name="sequence" colspan="2"/>
+                </form>
+            </field>
+        </record>
+
+        <record id="attribute_option_form_view" model="ir.ui.view">
+            <field name="name">attribute.option.form</field>
+            <field name="model">attribute.option</field>
+            <field name="type">form</field>
+            <field name="arch" type="xml">
+                <form string="Attribute Option">
+                    <field name="name" colspan="2"/>
+                    <field name="value_ref" colspan="2" groups="base.group_advanced_attribute"/>
+                    <field name="sequence" colspan="2"/>
+                    <field name="attribute_id" colspan="2"/>
+                </form>
+            </field>
+        </record>
+        
+        <record id="attribute_option_tree_view" model="ir.ui.view">
+            <field name="name">attribute.option.tree</field>
+            <field name="model">attribute.option</field>
+            <field eval="20" name="priority"/>
+            <field name="type">tree</field>
+            <field name="arch" type="xml">
+                <tree string="Attribute Option">
+                    <field name="name" />
+                    <field name="sequence" />
+                    <field name="value_ref" groups="base.group_advanced_attribute"/>
+                    <field name="attribute_id" />
+                </tree>
+            </field>
+        </record>
+
+        <record id="view_attribute_option_search" model="ir.ui.view">
+            <field name="name">attribute.option.list</field>
+            <field name="model">attribute.option</field>
+            <field name="type">search</field>
+            <field name="arch" type="xml">
+                <search string="Search Attribute Options">
+                    <field name="name" />
+                    <field name="attribute_id"/>
+               </search>
+            </field>
+        </record>
+
+        <record id="attribute_option_form_action" model="ir.actions.act_window">
+            <field name="name">Attribute Options</field>
+            <field name="res_model">attribute.option</field>
+            <field name="view_type">form</field>
+            <field name="view_mode">tree,form</field>
+            <field name="view_id" ref="attribute_option_tree_view"/>
+            <field name="search_view_id" ref="view_attribute_option_search"/>
+            <field name="context">{"search_default_user_id":uid}</field>
+            <field name="help"></field>
+        </record>
+
+        <record id="attribute_option_form_action_tree" model="ir.actions.act_window.view">
+            <field name="sequence" eval="1"/>
+            <field name="act_window_id" ref="attribute_option_form_action"/>
+            <field name="view_id" ref="attribute_option_tree_view"/>
+            <field name="view_mode">tree</field>
+        </record>
+
+        <record id="attribute_option_form_action_form" model="ir.actions.act_window.view">
+            <field name="sequence" eval="2"/>
+            <field name="act_window_id" ref="attribute_option_form_action"/>
+            <field name="view_id" ref="attribute_option_form_view"/>
+            <field name="view_mode">form</field>
+        </record>
+
+        <menuitem
+            action="attribute_option_form_action" id="menu_attribute_option_action"
+            parent="menu_attribute_in_admin" sequence="40"/>
+
+    <!-- ATTRIBUTE OPTION WIZARD -->
+        <record id="attribute_option_wizard_form_view" model="ir.ui.view">
+            <field name="name">attribute.option.wizard</field>
+            <field name="model">attribute.option.wizard</field>
+            <field name="type">form</field>
+            <field name="arch" type="xml">
+                <form string="Options Wizard" col="6">
+                    <field name="attribute_id" invisible="1" colspan="2"/>
+                    <separator string="options_placeholder"/>
+                    <button special="cancel" string="Cancel" icon="gtk-cancel"/>
+                    <button name="validate" string="Validate" type="object" icon="gtk-convert"/>
+                </form>
+            </field>
+        </record>
+
+    </data>
+</openerp>

=== added directory 'base_custom_attributes/i18n'
=== added file 'base_custom_attributes/i18n/base_custom_attributes.pot'
--- base_custom_attributes/i18n/base_custom_attributes.pot	1970-01-01 00:00:00 +0000
+++ base_custom_attributes/i18n/base_custom_attributes.pot	2013-11-25 13:51:36 +0000
@@ -0,0 +1,291 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+#	* base_custom_attributes
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-10-16 10:39+0000\n"
+"PO-Revision-Date: 2013-10-16 10:39+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: base_custom_attributes
+#: code:addons/base_custom_attributes/custom_attributes.py:44
+#, python-format
+msgid "Use the 'Load Options' button instead to select appropriate model references."
+msgstr ""
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Binary"
+msgstr ""
+
+#. module: base_custom_attributes
+#: view:attribute.attribute:0
+msgid "Search Attributes"
+msgstr ""
+
+#. module: base_custom_attributes
+#: view:attribute.group:0
+#: field:attribute.location,attribute_group_id:0
+#: model:ir.model,name:base_custom_attributes.model_attribute_group
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_location_attribute_group_id
+msgid "Attribute Group"
+msgstr ""
+
+#. module: base_custom_attributes
+#: view:attribute.group:0
+#: model:ir.model,name:base_custom_attributes.model_attribute_location
+msgid "Attribute Location"
+msgstr ""
+
+#. module: base_custom_attributes
+#: code:addons/base_custom_attributes/custom_attributes.py:154
+#: view:attribute.option.wizard:0
+#, python-format
+msgid "Options Wizard"
+msgstr ""
+
+#. module: base_custom_attributes
+#: view:attribute.group:0
+msgid "Search Attribute Groups"
+msgstr ""
+
+#. module: base_custom_attributes
+#: field:attribute.attribute,attribute_type:0
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_attribute_type
+msgid "Type"
+msgstr ""
+
+#. module: base_custom_attributes
+#: field:attribute.set,attribute_group_ids:0
+#: model:ir.actions.act_window,name:base_custom_attributes.attribute_group_form_action
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_set_attribute_group_ids
+#: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_group_action
+msgid "Attribute Groups"
+msgstr ""
+
+#. module: base_custom_attributes
+#: field:attribute.attribute,create_date:0
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_create_date
+msgid "Created date"
+msgstr ""
+
+#. module: base_custom_attributes
+#: view:attribute.set:0
+msgid "Search Attribute Sets"
+msgstr ""
+
+#. module: base_custom_attributes
+#: view:attribute.option:0
+#: model:ir.model,name:base_custom_attributes.model_attribute_option
+msgid "Attribute Option"
+msgstr ""
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Date"
+msgstr ""
+
+#. module: base_custom_attributes
+#: help:attribute.attribute,required_on_views:0
+msgid "If activated, the attribute will be mandatory on the views, but not in the database"
+msgstr ""
+
+#. module: base_custom_attributes
+#: field:attribute.attribute,field_id:0
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_field_id
+msgid "Ir Model Fields"
+msgstr ""
+
+#. module: base_custom_attributes
+#: view:attribute.option.wizard:0
+msgid "options_placeholder"
+msgstr ""
+
+#. module: base_custom_attributes
+#: field:attribute.group,name:0
+#: field:attribute.option,name:0
+#: field:attribute.set,name:0
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_name
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_name
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_set_name
+msgid "Name"
+msgstr ""
+
+#. module: base_custom_attributes
+#: help:attribute.attribute,serialized:0
+msgid "If serialized, the field will be stocked in the serialized field: attribute_custom_tmpl or attribute_custom_variant depending on the field based_on"
+msgstr ""
+
+#. module: base_custom_attributes
+#: field:attribute.attribute,required_on_views:0
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_required_on_views
+msgid "Required (on views)"
+msgstr ""
+
+#. module: base_custom_attributes
+#: model:ir.model,name:base_custom_attributes.model_ir_model_fields
+msgid "Fields"
+msgstr ""
+
+#. module: base_custom_attributes
+#: view:attribute.attribute:0
+#: field:attribute.attribute,option_ids:0
+#: model:ir.actions.act_window,name:base_custom_attributes.attribute_option_form_action
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_option_ids
+#: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_option_action
+msgid "Attribute Options"
+msgstr ""
+
+#. module: base_custom_attributes
+#: field:attribute.attribute,serialized:0
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_serialized
+msgid "Field serialized"
+msgstr ""
+
+#. module: base_custom_attributes
+#: code:addons/base_custom_attributes/custom_attributes.py:44
+#, python-format
+msgid "Error!"
+msgstr ""
+
+#. module: base_custom_attributes
+#: view:attribute.option.wizard:0
+msgid "Validate"
+msgstr ""
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Multiselect"
+msgstr ""
+
+#. module: base_custom_attributes
+#: view:attribute.option:0
+msgid "Search Attribute Options"
+msgstr ""
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Integer"
+msgstr ""
+
+#. module: base_custom_attributes
+#: field:attribute.group,attribute_ids:0
+#: model:ir.actions.act_window,name:base_custom_attributes.attribute_attribute_form_action
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_attribute_ids
+#: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_attribute_action
+#: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_in_admin
+msgid "Attributes"
+msgstr ""
+
+#. module: base_custom_attributes
+#: field:attribute.attribute,relation_model_id:0
+#: field:attribute.group,model_id:0
+#: field:attribute.set,model_id:0
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_relation_model_id
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_model_id
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_set_model_id
+msgid "Model"
+msgstr ""
+
+#. module: base_custom_attributes
+#: model:ir.actions.act_window,name:base_custom_attributes.attribute_set_form_action
+#: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_set_action
+msgid "Attribute Sets"
+msgstr ""
+
+#. module: base_custom_attributes
+#: view:attribute.attribute:0
+msgid "Load Options"
+msgstr ""
+
+#. module: base_custom_attributes
+#: field:attribute.option,value_ref:0
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_value_ref
+msgid "Reference"
+msgstr ""
+
+#. module: base_custom_attributes
+#: field:attribute.group,sequence:0
+#: field:attribute.location,sequence:0
+#: field:attribute.option,sequence:0
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_sequence
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_location_sequence
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_sequence
+msgid "Sequence"
+msgstr ""
+
+#. module: base_custom_attributes
+#: view:attribute.attribute:0
+#: field:attribute.location,attribute_id:0
+#: field:attribute.option,attribute_id:0
+#: field:attribute.option.wizard,attribute_id:0
+#: model:ir.model,name:base_custom_attributes.model_attribute_attribute
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_location_attribute_id
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_attribute_id
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_wizard_attribute_id
+msgid "Attribute"
+msgstr ""
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Float"
+msgstr ""
+
+#. module: base_custom_attributes
+#: field:attribute.group,attribute_set_id:0
+#: field:attribute.location,attribute_set_id:0
+#: view:attribute.set:0
+#: model:ir.model,name:base_custom_attributes.model_attribute_set
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_attribute_set_id
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_location_attribute_set_id
+msgid "Attribute Set"
+msgstr ""
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Datetime"
+msgstr ""
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Char"
+msgstr ""
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Boolean"
+msgstr ""
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Text"
+msgstr ""
+
+#. module: base_custom_attributes
+#: view:attribute.option.wizard:0
+msgid "Cancel"
+msgstr ""
+
+#. module: base_custom_attributes
+#: model:ir.model,name:base_custom_attributes.model_attribute_option_wizard
+msgid "attribute.option.wizard"
+msgstr ""
+
+#. module: base_custom_attributes
+#: sql_constraint:ir.model.fields:0
+msgid "The name of the field has to be uniq for a given model !"
+msgstr ""
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Select"
+msgstr ""
+

=== added file 'base_custom_attributes/i18n/fr.po'
--- base_custom_attributes/i18n/fr.po	1970-01-01 00:00:00 +0000
+++ base_custom_attributes/i18n/fr.po	2013-11-25 13:51:36 +0000
@@ -0,0 +1,291 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+#	* base_custom_attributes
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-10-16 09:03+0000\n"
+"PO-Revision-Date: 2013-10-16 09:03+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: base_custom_attributes
+#: code:addons/base_custom_attributes/custom_attributes.py:44
+#, python-format
+msgid "Use the 'Load Options' button instead to select appropriate model references."
+msgstr "Utiliser le bouton 'Charger les options' pour sélectionner le modèle de référence approprié."
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Binary"
+msgstr "Binary"
+
+#. module: base_custom_attributes
+#: view:attribute.attribute:0
+msgid "Search Attributes"
+msgstr "Rechercher des attributs"
+
+#. module: base_custom_attributes
+#: view:attribute.group:0
+#: field:attribute.location,attribute_group_id:0
+#: model:ir.model,name:base_custom_attributes.model_attribute_group
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_location_attribute_group_id
+msgid "Attribute Group"
+msgstr "Groupe d'attributs"
+
+#. module: base_custom_attributes
+#: view:attribute.group:0
+#: model:ir.model,name:base_custom_attributes.model_attribute_location
+msgid "Attribute Location"
+msgstr "Attribute Location"
+
+#. module: base_custom_attributes
+#: code:addons/base_custom_attributes/custom_attributes.py:154
+#: view:attribute.option.wizard:0
+#, python-format
+msgid "Options Wizard"
+msgstr "Options Wizard"
+
+#. module: base_custom_attributes
+#: view:attribute.group:0
+msgid "Search Attribute Groups"
+msgstr "Rechercher des groupes d'attributs"
+
+#. module: base_custom_attributes
+#: field:attribute.attribute,attribute_type:0
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_attribute_type
+msgid "Type"
+msgstr "Type"
+
+#. module: base_custom_attributes
+#: field:attribute.set,attribute_group_ids:0
+#: model:ir.actions.act_window,name:base_custom_attributes.attribute_group_form_action
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_set_attribute_group_ids
+#: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_group_action
+msgid "Attribute Groups"
+msgstr "Groupes d'attributs"
+
+#. module: base_custom_attributes
+#: field:attribute.attribute,create_date:0
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_create_date
+msgid "Created date"
+msgstr "Date de création"
+
+#. module: base_custom_attributes
+#: view:attribute.set:0
+msgid "Search Attribute Sets"
+msgstr "Rechercher des jeux d'attributs"
+
+#. module: base_custom_attributes
+#: view:attribute.option:0
+#: model:ir.model,name:base_custom_attributes.model_attribute_option
+msgid "Attribute Option"
+msgstr "Option d'attribut"
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Date"
+msgstr "Date"
+
+#. module: base_custom_attributes
+#: help:attribute.attribute,required_on_views:0
+msgid "If activated, the attribute will be mandatory on the views, but not in the database"
+msgstr "Si activé, l'attribut sera obligatoire dans les vues, mais pas dans la base de données."
+
+#. module: base_custom_attributes
+#: field:attribute.attribute,field_id:0
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_field_id
+msgid "Ir Model Fields"
+msgstr "Ir Model Fields"
+
+#. module: base_custom_attributes
+#: view:attribute.option.wizard:0
+msgid "options_placeholder"
+msgstr "options_placeholder"
+
+#. module: base_custom_attributes
+#: field:attribute.group,name:0
+#: field:attribute.option,name:0
+#: field:attribute.set,name:0
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_name
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_name
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_set_name
+msgid "Name"
+msgstr "Nom"
+
+#. module: base_custom_attributes
+#: help:attribute.attribute,serialized:0
+msgid "If serialized, the field will be stocked in the serialized field: attribute_custom_tmpl or attribute_custom_variant depending on the field based_on"
+msgstr "Si serialisé, le champ sera stocké dans un champ serialisé : attribute_custom_tmpl ou attribut_custom_variant selon la valeur du champ based_on"
+
+#. module: base_custom_attributes
+#: field:attribute.attribute,required_on_views:0
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_required_on_views
+msgid "Required (on views)"
+msgstr "Obligatoire (dans les vues)"
+
+#. module: base_custom_attributes
+#: model:ir.model,name:base_custom_attributes.model_ir_model_fields
+msgid "Fields"
+msgstr "Champs"
+
+#. module: base_custom_attributes
+#: view:attribute.attribute:0
+#: field:attribute.attribute,option_ids:0
+#: model:ir.actions.act_window,name:base_custom_attributes.attribute_option_form_action
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_option_ids
+#: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_option_action
+msgid "Attribute Options"
+msgstr "Options d'attribut"
+
+#. module: base_custom_attributes
+#: field:attribute.attribute,serialized:0
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_serialized
+msgid "Field serialized"
+msgstr "Champ serialisé"
+
+#. module: base_custom_attributes
+#: code:addons/base_custom_attributes/custom_attributes.py:44
+#, python-format
+msgid "Error!"
+msgstr "Erreur !"
+
+#. module: base_custom_attributes
+#: view:attribute.option.wizard:0
+msgid "Validate"
+msgstr "Valider"
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Multiselect"
+msgstr "Multiselect"
+
+#. module: base_custom_attributes
+#: view:attribute.option:0
+msgid "Search Attribute Options"
+msgstr "Rechercher des options d'attribut"
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Integer"
+msgstr "Integer"
+
+#. module: base_custom_attributes
+#: field:attribute.group,attribute_ids:0
+#: model:ir.actions.act_window,name:base_custom_attributes.attribute_attribute_form_action
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_attribute_ids
+#: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_attribute_action
+#: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_in_admin
+msgid "Attributes"
+msgstr "Attributs"
+
+#. module: base_custom_attributes
+#: field:attribute.attribute,relation_model_id:0
+#: field:attribute.group,model_id:0
+#: field:attribute.set,model_id:0
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_attribute_relation_model_id
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_model_id
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_set_model_id
+msgid "Model"
+msgstr "Modèle"
+
+#. module: base_custom_attributes
+#: model:ir.actions.act_window,name:base_custom_attributes.attribute_set_form_action
+#: model:ir.ui.menu,name:base_custom_attributes.menu_attribute_set_action
+msgid "Attribute Sets"
+msgstr "Jeux d'attributs"
+
+#. module: base_custom_attributes
+#: view:attribute.attribute:0
+msgid "Load Options"
+msgstr "Charger les options"
+
+#. module: base_custom_attributes
+#: field:attribute.option,value_ref:0
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_value_ref
+msgid "Reference"
+msgstr "Référence"
+
+#. module: base_custom_attributes
+#: field:attribute.group,sequence:0
+#: field:attribute.location,sequence:0
+#: field:attribute.option,sequence:0
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_sequence
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_location_sequence
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_sequence
+msgid "Sequence"
+msgstr "Séquence"
+
+#. module: base_custom_attributes
+#: view:attribute.attribute:0
+#: field:attribute.location,attribute_id:0
+#: field:attribute.option,attribute_id:0
+#: field:attribute.option.wizard,attribute_id:0
+#: model:ir.model,name:base_custom_attributes.model_attribute_attribute
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_location_attribute_id
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_attribute_id
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_option_wizard_attribute_id
+msgid "Attribute"
+msgstr "Attribut"
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Float"
+msgstr "Float"
+
+#. module: base_custom_attributes
+#: field:attribute.group,attribute_set_id:0
+#: field:attribute.location,attribute_set_id:0
+#: view:attribute.set:0
+#: model:ir.model,name:base_custom_attributes.model_attribute_set
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_group_attribute_set_id
+#: model:ir.model.fields,field_description:base_custom_attributes.field_attribute_location_attribute_set_id
+msgid "Attribute Set"
+msgstr "Jeux d'attributs"
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Datetime"
+msgstr "Datetime"
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Char"
+msgstr "Char"
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Boolean"
+msgstr "Boolean"
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Text"
+msgstr "Text"
+
+#. module: base_custom_attributes
+#: view:attribute.option.wizard:0
+msgid "Cancel"
+msgstr "Annuler"
+
+#. module: base_custom_attributes
+#: model:ir.model,name:base_custom_attributes.model_attribute_option_wizard
+msgid "attribute.option.wizard"
+msgstr "attribute.option.wizard"
+
+#. module: base_custom_attributes
+#: sql_constraint:ir.model.fields:0
+msgid "The name of the field has to be uniq for a given model !"
+msgstr "Le nom du champ doit être unique pour un modèle donné !"
+
+#. module: base_custom_attributes
+#: selection:attribute.attribute,attribute_type:0
+msgid "Select"
+msgstr "Select"
+

=== added file 'base_custom_attributes/ir_model.py'
--- base_custom_attributes/ir_model.py	1970-01-01 00:00:00 +0000
+++ base_custom_attributes/ir_model.py	2013-11-25 13:51:36 +0000
@@ -0,0 +1,39 @@
+# -*- 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
+
+
+class ir_model_fields(Model):
+
+    _inherit = "ir.model.fields"
+    _columns = {
+        'field_description': fields.char(
+            'Field Label',
+            required=True,
+            size=256,
+            translate=True),
+    }
+    _sql_constraints = [
+        ('name_model_uniq', 'unique (name, model_id)',
+            'The name of the field has to be uniq for a given model !'),
+    ]

=== added directory 'base_custom_attributes/security'
=== added file 'base_custom_attributes/security/attribute_security.xml'
--- base_custom_attributes/security/attribute_security.xml	1970-01-01 00:00:00 +0000
+++ base_custom_attributes/security/attribute_security.xml	2013-11-25 13:51:36 +0000
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+<data noupdate="0">
+
+    <record id="base.group_advanced_attribute" model="res.groups">
+        <field name="name">Advanced Attribute Option</field>
+        <field name="category_id" ref="base.module_category_hidden"/>
+    </record>
+
+</data>
+</openerp>

=== added file 'base_custom_attributes/security/ir.model.access.csv'
--- base_custom_attributes/security/ir.model.access.csv	1970-01-01 00:00:00 +0000
+++ base_custom_attributes/security/ir.model.access.csv	2013-11-25 13:51:36 +0000
@@ -0,0 +1,13 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+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_attribute_attribute_salemanager,base_custom_attributes_product_attribute,base_custom_attributes.model_attribute_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_location_salemanager,base_custom_attributes_attribute_location,base_custom_attributes.model_attribute_location,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,base.group_no_one,1,1,1,1
+access_base_custom_attributes_attribute_attribute_manager,base_custom_attributes_attribute_attribute,base_custom_attributes.model_attribute_attribute,base.group_no_one,1,1,1,1
+access_base_custom_attributes_attribute_option_manager,base_custom_attributes_attribute_option,base_custom_attributes.model_attribute_option,base.group_no_one,1,1,1,1
+access_base_custom_attributes_attribute_location_manager,base_custom_attributes_attribute_location,base_custom_attributes.model_attribute_location,base.group_no_one,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_attribute_attribute_user,base_custom_attributes_attribute_attribute,base_custom_attributes.model_attribute_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
+access_base_custom_attributes_attribute_location_user,base_custom_attributes_attribute_location,base_custom_attributes.model_attribute_location,base.group_user,1,1,1,0

=== added directory 'production_lot_custom_attributes'
=== added file 'production_lot_custom_attributes/__init__.py'
--- production_lot_custom_attributes/__init__.py	1970-01-01 00:00:00 +0000
+++ production_lot_custom_attributes/__init__.py	2013-11-25 13:51:36 +0000
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+###############################################################################
+#                                                                             #
+#   Author: Leonardo Pistone <leonardo.pistone@xxxxxxxxxxxxxx>                #
+#   Copyright 2013 Camptocamp SA                                              #
+#                                                                             #
+#   Inspired by the module product_custom_attributes                          #
+#   by Benoît GUILLOT <benoit.guillot@xxxxxxxxxxxx>, Akretion                 #
+#                                                                             #
+#   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 . import lot
+from . import wizard

=== added file 'production_lot_custom_attributes/__openerp__.py'
--- production_lot_custom_attributes/__openerp__.py	1970-01-01 00:00:00 +0000
+++ production_lot_custom_attributes/__openerp__.py	2013-11-25 13:51:36 +0000
@@ -0,0 +1,62 @@
+# -*- coding: utf-8 -*-
+###############################################################################
+#                                                                             #
+#   Author: Leonardo Pistone <leonardo.pistone@xxxxxxxxxxxxxx>                #
+#   Copyright 2013 Camptocamp SA                                              #
+#                                                                             #
+#   Inspired by the module product_custom_attributes                          #
+#   by Benoît GUILLOT <benoit.guillot@xxxxxxxxxxxx>, Akretion                 #
+#                                                                             #
+#   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': 'production_lot_custom_attributes',
+ 'version': '0.1',
+ 'category': 'Generic Modules/Others',
+ 'license': 'AGPL-3',
+ 'description': """
+Production lot custom attributes
+================================
+
+This module adds the possibility to easily create custom fields on stock
+production lots. Each lot can be linked to an attribute set.
+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.
+
+Warning: This module is not compatible with product_custom_attributes from 6.1.
+To make the two compatible, product_custom_attributes should be split to depend
+from base_custom_attributes, like it is already in 7.0.
+
+This module is inspired by the module product_custom_attributes by
+Benoît GUILLOT, Akretion
+
+""",
+ 'complexity': 'normal',
+ 'author': 'Camptocamp',
+ 'website': 'http://www.camptocamp.com/',
+ 'depends': ['stock', 'base_custom_attributes'],
+ 'init_xml': [],
+ 'update_xml': ['lot_view.xml',
+                'custom_attributes_view.xml',
+                'wizard/open_lot_by_attribute_set.xml'
+                ],
+ 'test': ['test/lot_attribute_test.yml',
+          ],
+ 'demo_xml': [],
+ 'installable': True,
+ 'active': False,
+ }

=== added file 'production_lot_custom_attributes/custom_attributes_view.xml'
--- production_lot_custom_attributes/custom_attributes_view.xml	1970-01-01 00:00:00 +0000
+++ production_lot_custom_attributes/custom_attributes_view.xml	2013-11-25 13:51:36 +0000
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+    <data>
+
+        <menuitem
+            id="menu_lot_attribute_in_warehouse_config"
+            name="Serial Number Attributes"
+            parent="stock.menu_warehouse_config"
+            sequence="20"/>
+
+        <record id="lot_attribute_set_form_action" model="ir.actions.act_window">
+            <field name="name">Lot 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="base_custom_attributes.view_attribute_set_search"/>
+            <field name="context">{"force_model": 'stock.production.lot'}</field>
+            <field name="help"></field>
+        </record>
+
+        <record id="lot_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="base_custom_attributes.view_attribute_attribute_search"/>
+            <field name="context">{"force_model": 'stock.production.lot'}</field>
+            <field name="help"></field>
+        </record>
+
+        <record id="lot_attribute_attribute_form_action" model="ir.actions.act_window">
+            <field name="name">Lot Attributes</field>
+            <field name="res_model">attribute.attribute</field>
+            <field name="view_type">form</field>
+            <field name="view_mode">tree,form</field>
+            <field name="search_view_id" ref="base_custom_attributes.view_attribute_attribute_search"/>
+            <field name="context">{"force_model": 'stock.production.lot'}</field>
+            <field name="help"></field>
+        </record>
+
+        <menuitem
+            action="lot_attribute_set_form_action"
+            id="menu_lot_attribute_set_action"
+            parent="menu_lot_attribute_in_warehouse_config"
+            sequence="1"/>
+        <menuitem
+            action="lot_attribute_group_form_action"
+            id="menu_lot_attribute_group_action"
+            parent="menu_lot_attribute_in_warehouse_config"
+            sequence="2"/>
+        <menuitem
+            action="lot_attribute_attribute_form_action"
+            id="menu_lot_attribute_attribute_action"
+            parent="menu_lot_attribute_in_warehouse_config"
+            sequence="4"/>
+
+    </data>
+</openerp>

=== added file 'production_lot_custom_attributes/lot.py'
--- production_lot_custom_attributes/lot.py	1970-01-01 00:00:00 +0000
+++ production_lot_custom_attributes/lot.py	2013-11-25 13:51:36 +0000
@@ -0,0 +1,155 @@
+# -*- coding: utf-8 -*-
+###############################################################################
+#                                                                             #
+#   Author: Leonardo Pistone <leonardo.pistone@xxxxxxxxxxxxxx>                #
+#   Copyright 2013 Camptocamp SA                                              #
+#                                                                             #
+#   Inspired by the module product_custom_attributes                          #
+#   by Benoît GUILLOT <benoit.guillot@xxxxxxxxxxxx>, Akretion                 #
+#                                                                             #
+#   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 _
+from lxml import etree
+
+
+class stock_production_lot(Model):
+    _inherit = "stock.production.lot"
+
+    _columns = {
+        'attribute_set_id': fields.many2one('attribute.set', 'Attribute Set'),
+        'attribute_group_ids': fields.related(
+            'attribute_set_id',
+            'attribute_group_ids',
+            type='many2many',
+            relation='attribute.group'
+            )
+    }
+
+    def _fix_size_bug(self, cr, uid, result, context=None):
+        """When created a field text dynamicaly, its size is limited to 64 in
+        the view. The bug is fixed but not merged
+        https://code.launchpad.net/~openerp-dev/openerp-web/6.1-opw-579462-cpa
+        To remove when the fix will be merged
+
+        """
+        for field in result['fields']:
+            if result['fields'][field]['type'] == 'text':
+                if 'size' in result['fields'][field]:
+                    del result['fields'][field]['size']
+        return result
+
+    def open_attributes(self, cr, uid, ids, context=None):
+        """Open the attributes of an object
+
+        This method is called when the user presses the Open Attributes button
+        in the form view of the object. It opens a dinamically-built form view.
+
+        :param ids: this is normally a singleton. If a longer list is passed,
+                    we consider only the first item.
+
+        """
+
+        if context is None:
+            context = {}
+
+        model_data_pool = self.pool.get('ir.model.data')
+
+        for lot in self.browse(cr, uid, ids, context=context):
+            view_id = model_data_pool.get_object_reference(
+                cr, uid,
+                'production_lot_custom_attributes',
+                'lot_attributes_form_view')[1]
+            ctx = {
+                'open_attributes': True,
+                'attribute_group_ids': [
+                    group.id for group in lot.attribute_group_ids
+                ]
+            }
+
+            return {
+                'name': 'Lot Attributes',
+                'view_type': 'form',
+                'view_mode': 'form',
+                'view_id': [view_id],
+                'res_model': self._name,
+                'context': ctx,
+                'type': 'ir.actions.act_window',
+                'nodestroy': True,
+                'target': 'new',
+                'res_id': lot.id,
+            }
+
+    def save_and_close_lot_attributes(self, cr, uid, ids, context=None):
+        return {'type': 'ir.actions.act_window_close'}
+
+    def fields_view_get(self, cr, uid, view_id=None, view_type='form',
+                        context=None, toolbar=False, submenu=False):
+        """Dinamically adds attributes to the view
+
+        Modifies dinamically the view to show the attributes. If the users
+        presses the Open Attributes button, the attributes are shown in a
+        new form field. Otherwise, if the attribute set is known beforehand,
+        attributes are added to a new tab in the main form view.
+
+        """
+        if context is None:
+            context = {}
+        attr_pool = self.pool.get('attribute.attribute')
+        result = super(stock_production_lot, self).fields_view_get(
+            cr, uid, view_id, view_type, context, toolbar=toolbar,
+            submenu=submenu
+        )
+        if view_type == 'form' and context.get('attribute_group_ids'):
+            eview = etree.fromstring(result['arch'])
+            #hide button under the name
+            button = eview.xpath("//button[@name='open_attributes']")
+            if button:
+                button = button[0]
+                button.getparent().remove(button)
+            attributes_notebook, toupdate_fields = (
+                attr_pool._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'):
+                # i.e. the user pressed the open attributes button on the
+                # form view. We put the attributes in a separate form view
+                placeholder = eview.xpath(
+                    "//separator[@string='attributes_placeholder']"
+                )[0]
+                placeholder.getparent().replace(
+                    placeholder, attributes_notebook
+                )
+            elif context.get('open_lot_by_attribute_set'):
+                # in this case, we know the attribute set beforehand, and we
+                # add the attributes to the current view
+                main_page = etree.Element(
+                    'page', string=_('Custom Attributes')
+                )
+                main_page.append(attributes_notebook)
+                info_page = eview.xpath(
+                    "//page[@string='%s']" % (_('Stock Moves'),)
+                )[0]
+                info_page.addnext(main_page)
+            result['arch'] = etree.tostring(eview, pretty_print=True)
+            result = self._fix_size_bug(cr, uid, result, context=context)
+        return result

=== added file 'production_lot_custom_attributes/lot_view.xml'
--- production_lot_custom_attributes/lot_view.xml	1970-01-01 00:00:00 +0000
+++ production_lot_custom_attributes/lot_view.xml	2013-11-25 13:51:36 +0000
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<openerp>
+    <data>
+
+        <record model="ir.ui.view" id="lot_form_view_set_button">
+            <field name="name">attributes.lot.normal.form</field>
+            <field name="model">stock.production.lot</field>
+            <field name="inherit_id" ref="stock.view_production_lot_form"/>
+            <field name="arch" type="xml">
+                <notebook position="inside">
+                    <page string="Attributes">
+                        <group name="attribute_fields">
+                            <field name="attribute_set_id" />
+                            <button name="open_attributes" string="Open Attributes" type="object" icon="gtk-ok" attrs="{'invisible':[('attribute_set_id', '=', False)]}"/>
+                        </group>
+                    </page>
+                </notebook>
+            </field>
+        </record>
+
+        <record model="ir.ui.view" id="lot_attributes_form_view">
+            <field name="name">lot.attributes.normal.wizard</field>
+            <field name="model">stock.production.lot</field>
+            <field name="priority">20</field>
+            <field name="arch" type="xml">
+                <form string="Lot">
+                    <group name="name_set" colspan='4' col='8'>
+                        <field name="name"/>
+                        <field name="attribute_set_id" />
+                    </group>
+                    <separator string="attributes_placeholder" colspan="4"/>
+                    <group colspan='4' col='4'>
+                        <button icon="gtk-cancel" special="cancel" string="Cancel"/>
+                        <button icon="gtk-ok" name="save_and_close_lot_attributes" string="Save and Close" type="object"/>
+                    </group>
+                </form>
+            </field>
+        </record>
+
+    </data>
+</openerp>

=== added directory 'production_lot_custom_attributes/test'
=== added file 'production_lot_custom_attributes/test/lot_attribute_test.yml'
--- production_lot_custom_attributes/test/lot_attribute_test.yml	1970-01-01 00:00:00 +0000
+++ production_lot_custom_attributes/test/lot_attribute_test.yml	2013-11-25 13:51:36 +0000
@@ -0,0 +1,48 @@
+-
+  In order to test Production Lot Custom Fields
+-
+  First I create an Attribute Set
+-
+  !record {model: attribute.set, id: lot_attribute_set_A}:
+    name: Serial Number Attribute Set A
+    model_id: stock.model_stock_production_lot
+    attribute_group_ids: 
+      - name: Components
+        model_id: stock.model_stock_production_lot
+        sequence: 1
+        attribute_ids:
+          - name: x_ram_amount
+            model_id: stock.model_stock_production_lot
+            field_description: Amount of RAM
+            attribute_type: float
+          - name: x_has_display
+            model_id: stock.model_stock_production_lot
+            field_description: Has Display
+            attribute_type: boolean
+      - name: Characteristics
+        model_id: stock.model_stock_production_lot
+        sequence: 2
+        attribute_ids:
+          - name: x_color
+            model_id: stock.model_stock_production_lot
+            field_description: Color
+            attribute_type: char
+          - name: x_lenght
+            model_id: stock.model_stock_production_lot
+            field_description: Length
+            attribute_type: float
+-
+  Then I create a Serial Number and set some Attributes
+-
+  !record {model: stock.production.lot, id: lot_A}:
+    product_id: product.product_product_pc2
+    name: 0005
+    attribute_set_id: lot_attribute_set_A
+    x_color: green
+    x_length: 12.5
+-
+  Now I check that my attributes are there
+-
+  !assert {model: stock.production.lot, id: lot_A, string: Lot Attributes do now work}:
+    - x_color == 'green'
+    - x_length == 12.5

=== added directory 'production_lot_custom_attributes/wizard'
=== added file 'production_lot_custom_attributes/wizard/__init__.py'
--- production_lot_custom_attributes/wizard/__init__.py	1970-01-01 00:00:00 +0000
+++ production_lot_custom_attributes/wizard/__init__.py	2013-11-25 13:51:36 +0000
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+###############################################################################
+#                                                                             #
+#   Author: Leonardo Pistone <leonardo.pistone@xxxxxxxxxxxxxx>                #
+#   Copyright 2013 Camptocamp SA                                              #
+#                                                                             #
+#   Inspired by the module product_custom_attributes                          #
+#   by Benoît GUILLOT <benoit.guillot@xxxxxxxxxxxx>, Akretion                 #
+#                                                                             #
+#   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 . import open_lot_by_attribute_set

=== added file 'production_lot_custom_attributes/wizard/open_lot_by_attribute_set.py'
--- production_lot_custom_attributes/wizard/open_lot_by_attribute_set.py	1970-01-01 00:00:00 +0000
+++ production_lot_custom_attributes/wizard/open_lot_by_attribute_set.py	2013-11-25 13:51:36 +0000
@@ -0,0 +1,62 @@
+# -*- coding: utf-8 -*-
+###############################################################################
+#                                                                             #
+#   Author: Leonardo Pistone <leonardo.pistone@xxxxxxxxxxxxxx>                #
+#   Copyright 2013 Camptocamp SA                                              #
+#                                                                             #
+#   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 TransientModel
+from osv import fields
+
+
+class open_lot_by_attribute_set(TransientModel):
+    _name = 'open.lot.by.attribute.set'
+    _description = 'Wizard to open lots by attributes set'
+
+    _columns = {
+        'attribute_set_id': fields.many2one('attribute.set', 'Attribute Set'),
+    }
+
+    def open_lot_by_attribute(self, cr, uid, ids, context=None):
+        """Opens a Lot by attributes
+
+        :param cr: the current row, from the database cursor,
+        :param uid: the current user’s ID for security checks,
+        :param ids: List of account chart’s IDs
+        :return: dictionary of Lot list window for a given attributes set
+
+        """
+        mod_obj = self.pool.get('ir.model.data')
+        act_obj = self.pool.get('ir.actions.act_window')
+        context = context or {}
+        attribute_set = self.browse(
+            cr, uid, ids[0], context=context
+        ).attribute_set_id
+        result = mod_obj.get_object_reference(
+            cr, uid, 'stock', 'action_production_lot_form')
+        id = result[1] if result else False
+        result = act_obj.read(cr, uid, [id], context=context)[0]
+        grp_ids = self.pool.get('attribute.group').search(
+            cr, uid, [('attribute_set_id', '=', attribute_set.id)])
+        ctx = (
+            "{'open_lot_by_attribute_set': %s, 'attribute_group_ids': %s}"
+            % (True, grp_ids)
+        )
+        result['context'] = ctx
+        result['domain'] = "[('attribute_set_id', '=', %s)]" % attribute_set.id
+        result['name'] = attribute_set.name
+        return result

=== added file 'production_lot_custom_attributes/wizard/open_lot_by_attribute_set.xml'
--- production_lot_custom_attributes/wizard/open_lot_by_attribute_set.xml	1970-01-01 00:00:00 +0000
+++ production_lot_custom_attributes/wizard/open_lot_by_attribute_set.xml	2013-11-25 13:51:36 +0000
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<openerp>
+    <data>
+
+        <record id="open_lot_by_attribute_set_view" model="ir.ui.view">
+            <field name="name">open.lot.by.attribute.set.view</field>
+            <field name="model">open.lot.by.attribute.set</field>
+            <field name="arch" type="xml">
+                <form string="Open lot by attributes set">
+                    <field name="attribute_set_id" colspan="4"/>
+                    <button icon="gtk-cancel" special="cancel" string="Cancel"/>
+                    <button icon="gtk-ok" name="open_lot_by_attribute" string="Open Product By attribute" type="object"/>
+                </form>
+            </field>
+        </record>
+
+        <record id="open_lot_by_attribute_set" model="ir.actions.act_window">
+            <field name="name">Open lot By Attribute Set</field>
+            <field name="res_model">open.lot.by.attribute.set</field>
+            <field name="view_type">form</field>
+            <field name="target">new</field>
+            <field name="view_id" ref="open_lot_by_attribute_set_view"/>
+            <field name="help"></field>
+        </record>
+
+        <menuitem action="open_lot_by_attribute_set" id="open_lot_wizard" parent="stock.menu_traceability"/>
+
+    </data>
+</openerp>