← Back to team overview

openerp-community-reviewer team mailing list archive

lp:~camptocamp/openerp-product-attributes/7.0-adding-stock_production_lot_custom_attributes-lep into lp:openerp-product-attributes

 

Leonardo Pistone @ camptocamp has proposed merging lp:~camptocamp/openerp-product-attributes/7.0-adding-stock_production_lot_custom_attributes-lep into lp:openerp-product-attributes.

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

For more details, see:
https://code.launchpad.net/~camptocamp/openerp-product-attributes/7.0-adding-stock_production_lot_custom_attributes-lep/+merge/195950

This is to add custom magento-style attributes on serial numbers (stock.production.lot), in the same fashion of product_custom_attributes.

TODO
* More comments, and/or a doc on how to make such a module
* Fix the YAML test
-- 
https://code.launchpad.net/~camptocamp/openerp-product-attributes/7.0-adding-stock_production_lot_custom_attributes-lep/+merge/195950
Your team Product Core Editors is requested to review the proposed merge of lp:~camptocamp/openerp-product-attributes/7.0-adding-stock_production_lot_custom_attributes-lep into lp:openerp-product-attributes.
=== 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 16:19:31 +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 16:19:31 +0000
@@ -0,0 +1,58 @@
+# -*- 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 fridge and a camera).
+In particular it's used by the Magento Magentoerpconnect module to match the
+EAV flexibility of Magento.
+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 16:19:31 +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 16:19:31 +0000
@@ -0,0 +1,133 @@
+# -*- 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 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):
+        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)
+        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 16:19:31 +0000
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  production_lot_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>
+
+        <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" version="7.0">
+                    <group name="name_set">
+                        <field name="name"/>
+                        <field name="attribute_set_id" />
+                    </group>
+                    <separator string="attributes_placeholder" colspan="4"/>
+                    <footer>
+                        <button name="save_and_close_lot_attributes" string="Save and Close" type="object" class="oe_highlight"/>
+                        or
+                        <button special="cancel" string="Cancel" class="oe_link"/>
+                    </footer>
+                </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 16:19:31 +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_7
+    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 16:19:31 +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 16:19:31 +0000
@@ -0,0 +1,67 @@
+# -*- 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
+
+        Returns a custom action built modifying the original one.
+        """
+
+        mod_obj = self.pool.get('ir.model.data')
+        act_obj = self.pool.get('ir.actions.act_window')
+
+        if context is None:
+            context = {}
+
+        # we expect one wizard instance at a time
+        for wiz in self.browse(cr, uid, ids, context=context):
+            action_id = mod_obj.get_object_reference(
+                cr, uid, 'stock', 'action_production_lot_form')[1]
+            action = act_obj.read(cr, uid, [action_id], context=context)[0]
+
+            ctx = (
+                "{'open_lot_by_attribute_set': True, "
+                "'attribute_group_ids': %s}"
+                % [
+                    group.id
+                    for group in wiz.attribute_set_id.attribute_group_ids
+                ]
+            )
+
+            action['context'] = ctx
+            action['domain'] = (
+                "[('attribute_set_id', '=', %s)]"
+                % wiz.attribute_set_id.id
+            )
+            action['name'] = wiz.attribute_set_id.name
+            return action

=== 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 16:19:31 +0000
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  lot_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>
+
+        <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" version="7.0">
+                    <group>
+                        <field name="attribute_set_id" />
+                    </group>
+                    <footer>
+                        <button name="open_lot_by_attribute" string="Open lot By attribute" type="object" class="oe_highlight"/>
+                        or
+                        <button special="cancel" string="Cancel" class="oe_link"/>
+                    </footer>
+                </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>


Follow ups