openerp-community-reviewer team mailing list archive
-
openerp-community-reviewer team
-
Mailing list archive
-
Message #01652
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>