← Back to team overview

savoirfairelinux-openerp team mailing list archive

[Merge] lp:~savoirfairelinux-openerp/openerp-product-configurator/sale_package_configurator into lp:~akretion-team/openerp-product-configurator/trunk

 

Mathieu Benoit has proposed merging lp:~savoirfairelinux-openerp/openerp-product-configurator/sale_package_configurator into lp:~akretion-team/openerp-product-configurator/trunk.

Requested reviews:
  Akretion Team (akretion-team)

For more details, see:
https://code.launchpad.net/~savoirfairelinux-openerp/openerp-product-configurator/sale_package_configurator/+merge/220707

When clicking on the "add an item" button in Sales Orders, the user is presented with the list of packages.
The system automatically adds all mandatory products.
The user then sees a screen that will offer him all options for the selected package; if he selects them, they are added to the order.
-- 
https://code.launchpad.net/~savoirfairelinux-openerp/openerp-product-configurator/sale_package_configurator/+merge/220707
Your team Savoir-faire Linux' OpenERP is subscribed to branch lp:~savoirfairelinux-openerp/openerp-product-configurator/sale_package_configurator.
=== added directory 'sale_package_configurator'
=== added file 'sale_package_configurator/__init__.py'
--- sale_package_configurator/__init__.py	1970-01-01 00:00:00 +0000
+++ sale_package_configurator/__init__.py	2014-05-22 19:13:44 +0000
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    Copyright (C) 2014 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+#    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 wizard
+import sale
\ No newline at end of file

=== added file 'sale_package_configurator/__openerp__.py'
--- sale_package_configurator/__openerp__.py	1970-01-01 00:00:00 +0000
+++ sale_package_configurator/__openerp__.py	2014-05-22 19:13:44 +0000
@@ -0,0 +1,88 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    This module copyright (C) 2014 Savoir-faire Linux
+#    (<http://www.savoirfairelinux.com>).
+#
+#    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": "Sales package configurator",
+    "version": "1.0",
+    "author": "Savoir-faire Linux",
+    'maintainer': 'Savoir-faire Linux',
+    'website': 'http://www.savoirfairelinux.com',
+    'license': 'AGPL-3',
+    "category": "Sale",
+    'summary': 'Package selector for sales orders.',
+    "description": """
+A package product selector for sales orders.
+
+How it works
+============
+When clicking on the "add an item" button in Sales Orders, the user is \
+presented with the list of packages.
+The system automatically adds all mandatory products.
+The user then sees a screen that will offer him all options for the selected \
+package; if he selects them, they are added to the \
+order.
+
+IMPORTANT
+=========
+TODO:
+* Work only with product service. Need fix to work with stockable \
+product.
+* Need more test when add dependencies on package with category.
+
+Configuration
+=============
+* Add the repository: lp:openerp-isp/7.0
+* In Sales \ Configuration \ Products \ Product categories , add "Packages"
+* In Settings \ Companies \ Companies
+** Open the main company
+** In the ISP Contract Management tab, select the category "Packages" in the \
+field " Default Product Category"
+* In Sales in \ Products \ Products , add your package product.
+** Need to be in category "Packages" and add your dependencies to a product \
+or a category.
+
+To manage dependency
+--------------------
+* In Settings \ Technical \ Database Structure \ Models :
+** Find and open the model product.dependency
+** Click Create a Menu
+*** Menu name = Product dependencies
+*** Parent Menu = Sales / Configuration / Products ( you must find this Menu, \
+not create it)
+
+Test
+====
+* In the sales menu, create a purchase order,
+* Click on the "Add an item" button
+* Select a product ... and follow the steps.
+    """,
+    "depends": [
+        "base",
+        "sale",
+        "contract_isp_package_configurator"
+    ],
+    "data": [
+        "sale_package_configurator_view.xml",
+        "wizard/package_configurator.xml"
+    ],
+    "installable": True,
+}

=== added directory 'sale_package_configurator/demo'
=== added file 'sale_package_configurator/demo/product.category.csv'
--- sale_package_configurator/demo/product.category.csv	1970-01-01 00:00:00 +0000
+++ sale_package_configurator/demo/product.category.csv	2014-05-22 19:13:44 +0000
@@ -0,0 +1,5 @@
+External ID,name,parent_id/id
+product_category_package,Packages,
+demo_category_2,Produits,demo_category_1
+demo_category_3,Fruit,demo_category_2
+demo_category_4,Vegetable,demo_category_2

=== added file 'sale_package_configurator/demo/product.product.csv'
--- sale_package_configurator/demo/product.product.csv	1970-01-01 00:00:00 +0000
+++ sale_package_configurator/demo/product.product.csv	2014-05-22 19:13:44 +0000
@@ -0,0 +1,4 @@
+id,rental,sale_ok,categ_id/id,name,procure_method,type,supply_method
+demo_product_product_1,False,True,demo_category_3,Apple,Make to Stock,Stockable Product,Buy
+demo_product_product_2,False,True,demo_category_3,Pear,Make to Stock,Stockable Product,Buy
+demo_product_product_3,False,True,demo_category_1,Small package fruit 1,Make to Stock,Service,Buy

=== added directory 'sale_package_configurator/i18n'
=== added file 'sale_package_configurator/i18n/sale_package_configurator.pot'
--- sale_package_configurator/i18n/sale_package_configurator.pot	1970-01-01 00:00:00 +0000
+++ sale_package_configurator/i18n/sale_package_configurator.pot	2014-05-22 19:13:44 +0000
@@ -0,0 +1,50 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+#	* sale_package_configurator
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2014-04-07 21:45+0000\n"
+"PO-Revision-Date: 2014-04-07 21:45+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: sale_package_configurator
+#: model:ir.actions.act_window,name:sale_package_configurator.sale_package_configurator_action
+#: view:sale.order:0
+msgid "Package Configurator"
+msgstr ""
+
+#. module: sale_package_configurator
+#: model:ir.model,name:sale_package_configurator.model_contract_service_configurator_dependency_line
+msgid "contract.service.configurator.dependency.line"
+msgstr ""
+
+#. module: sale_package_configurator
+#: model:ir.model,name:sale_package_configurator.model_contract_service_configurator
+msgid "contract.service.configurator"
+msgstr ""
+
+#. module: sale_package_configurator
+#: code:addons/sale_package_configurator/wizard/package_configurator.py:99
+#: code:addons/sale_package_configurator/wizard/package_configurator.py:186
+#, python-format
+msgid "Cancel"
+msgstr ""
+
+#. module: sale_package_configurator
+#: model:ir.model,name:sale_package_configurator.model_contract_service_configurator_line
+msgid "contract.service.configurator.line"
+msgstr ""
+
+#. module: sale_package_configurator
+#: field:contract.service.configurator,order_id:0
+msgid "Order ID"
+msgstr ""
+

=== added file 'sale_package_configurator/sale.py'
--- sale_package_configurator/sale.py	1970-01-01 00:00:00 +0000
+++ sale_package_configurator/sale.py	2014-05-22 19:13:44 +0000
@@ -0,0 +1,44 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    This module copyright (C) 2014 Savoir-faire Linux
+#    (<http://www.savoirfairelinux.com>).
+#
+#    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 logging
+from openerp.osv import orm
+
+_logger = logging.getLogger(__name__)
+
+
+class sale_order(orm.Model):
+    _inherit = "sale.order"
+
+    def sale_package_configurator_action(self, cr, uid, ids, context=None):
+        # manage only one sale order
+        ids = ids[0]
+        so = self.browse(cr, uid, ids, context=context)
+
+        return {'type': 'ir.actions.act_window',
+                'name': 'Package Configurator',
+                'res_model': 'contract.service.configurator',
+                'view_type': 'form',
+                'view_mode': 'form',
+                'target': 'new',
+                'context': {'default_pricelist_id': so.pricelist_id.id,
+                            'default_partner_id': so.partner_id.id,
+                            'default_order_id': so.id}}

=== added file 'sale_package_configurator/sale_package_configurator_view.xml'
--- sale_package_configurator/sale_package_configurator_view.xml	1970-01-01 00:00:00 +0000
+++ sale_package_configurator/sale_package_configurator_view.xml	2014-05-22 19:13:44 +0000
@@ -0,0 +1,28 @@
+<openerp>
+  <data>
+
+    <record id="view_sale_package_configurator_form" model="ir.ui.view">
+      <field name="name">Sale Order Form</field>
+      <field name="model">sale.order</field>
+      <field name="inherit_id" ref="sale.view_order_form"/>
+      <field name="arch" type="xml">
+        <data>
+          <xpath expr="//header/field[@name='state']" position="before">
+            <button name="sale_package_configurator_action" type="object"
+                    string="Add an Item"/>
+          </xpath>
+          <xpath expr="//field[@name='order_line']/tree" position="attributes">
+            <attribute name="create">0</attribute>
+          </xpath>
+          <xpath
+              expr="//field[@name='order_line']/tree/field[@name='price_unit']"
+              position="attributes">
+            <attribute name="readonly">0</attribute>
+          </xpath>
+
+        </data>
+      </field>
+    </record>
+
+  </data>
+</openerp>

=== added directory 'sale_package_configurator/wizard'
=== added file 'sale_package_configurator/wizard/__init__.py'
--- sale_package_configurator/wizard/__init__.py	1970-01-01 00:00:00 +0000
+++ sale_package_configurator/wizard/__init__.py	2014-05-22 19:13:44 +0000
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    Copyright (C) 2014 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+#    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 package_configurator

=== added file 'sale_package_configurator/wizard/package_configurator.py'
--- sale_package_configurator/wizard/package_configurator.py	1970-01-01 00:00:00 +0000
+++ sale_package_configurator/wizard/package_configurator.py	2014-05-22 19:13:44 +0000
@@ -0,0 +1,256 @@
+# -*- coding: utf-8 -*-
+
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    Copyright (C) 2014 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+#    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 import orm, fields
+from openerp.tools.translate import _
+
+
+class contract_service_configurator_line(orm.TransientModel):
+    """Model contract.service.configurator.line"""
+
+    def _get_product_price(self, cr, uid, ids, field_name, arg, context=None):
+        return get_prices(self, cr, uid, ids, field_name, arg, context=context)
+
+    _name = 'contract.service.configurator.line'
+    _description = __doc__
+    _inherit = 'contract.service.configurator.line'
+    _columns = {
+        'price': fields.function(_get_product_price, type="float",
+                                 string="Price"),
+    }
+
+    def router(self, cr, uid, ids, data=None, context=None):
+        stock_move_id = None
+        if isinstance(ids, list):
+            ids = ids[0]
+        line = self.browse(cr, uid, ids, context=context)
+        if line.state == 'message':
+            if line.product_id.type == 'product' \
+                    and line.product_id.qty_available > 0.0:
+                state = 'serial'
+            else:
+                state = 'stock'
+        elif line.state in ('serial', 'stock'):
+            stock_move_obj = self.pool.get('stock.move')
+            location_id = self.pool.get('ir.model.data').get_object_reference(
+                cr, uid, 'stock', 'stock_location_stock')[1]
+            location_dest_id = line.configurator_id.order_id. \
+                partner_id.property_stock_customer.id
+            if line.product_id and line.product_id.uom_id \
+                    and line.product_id.uom_id:
+                product_uom = line.product_id.uom_id.id
+            else:
+                product_uom = None
+            move = {
+                'name': line.product_id and line.product_id.name or '',
+                'product_id': line.product_id and line.product_id.id,
+                'product_uom': product_uom,
+                'prodlot_id': line.serial and line.serial.id or None,
+                'location_id': location_id,
+                'location_dest_id': location_dest_id,
+                'partner_id': line.configurator_id.order_id.partner_id.id,
+                'type': 'out'
+            }
+            stock_move_id = stock_move_obj.create(
+                cr, uid, move, context=context)
+            stock_move_obj.action_confirm(
+                cr, uid, [stock_move_id], context=context)
+            stock_move_obj.action_done(
+                cr, uid, [stock_move_id], context=context)
+
+            state = 'done'
+
+        line.write({'state': state, 'stock_move_id': stock_move_id})
+
+        return line.configurator_id.router(data={})
+
+    def unlink(self, cr, uid, ids, context=None):
+        if isinstance(ids, int):
+            ids = [ids]
+
+        for line in self.browse(cr, uid, ids, context=context):
+            if line.product_id.type == 'product' and line.stock_move_id:
+                stock_move_obj = self.pool.get('stock.move')
+                name = ' '.join([_('Cancel'),
+                                 line.product_id and line.product_id.name
+                                 or ''])
+                if line.product_id and line.product_id.uom_id \
+                        and line.product_id.uom_id:
+                    product_uom = line.product_id.uom_id.id
+                else:
+                    product_uom = None
+                if line.configurator_id.contract_id:
+                    partner_id = line.configurator_id.contract_id.partner_id.id
+                else:
+                    partner_id = None
+                move = {
+                    'name': name,
+                    'product_id': line.product_id and line.product_id.id,
+                    'product_uom': product_uom,
+                    'prodlot_id': line.serial and line.serial.id or None,
+                    'location_id': line.stock_move_id.location_dest_id.id,
+                    'location_dest_id': line.stock_move_id.location_id.id,
+                    'partner_id': partner_id,
+                    'type': 'in'
+                }
+                stock_move_id = stock_move_obj.create(
+                    cr, uid, move, context=context)
+                stock_move_obj.action_confirm(
+                    cr, uid, [stock_move_id], context=context)
+                stock_move_obj.action_done(
+                    cr, uid, [stock_move_id], context=context)
+
+        return super(contract_service_configurator_line, self).unlink(
+            cr, uid, ids, context=context)
+
+
+class contract_service_configurator_dependency_line(orm.TransientModel):
+    def _get_product_price(self, cr, uid, ids, field_name, arg, context=None):
+        return get_prices(self, cr, uid, ids, field_name, arg, context=context)
+
+    _name = 'contract.service.configurator.dependency.line'
+    _inherit = 'contract.service.configurator.line'
+
+    _order = 'name'
+
+    _columns = {
+        'price': fields.function(_get_product_price,
+                                 type="float", string="Price"),
+    }
+
+
+class package_configurator(orm.TransientModel):
+    """Package Configurator wizard"""
+
+    _name = 'contract.service.configurator'
+    _description = __doc__
+    _inherit = 'contract.service.configurator'
+
+    _columns = {
+        'order_id': fields.many2one('sale.order', 'Order ID'),
+        'state': fields.selection((('draft', _('Start')),
+                                   ('product', _('Select product')),
+                                   ('dependency', _('Select options')),
+                                   ('done', _('Done'))), 'State'),
+        'pricelist_id': fields.many2one('product.pricelist', 'Pricelist',
+                                        required=True, readonly=True),
+        'partner_id': fields.many2one('res.partner', 'Customer', readonly=True,
+                                      required=True),
+    }
+    _defaults = {'current_product_id': False}
+
+    def do_done(self, cr, uid, ids, context=None):
+        sale_order_line_obj = self.pool.get('sale.order.line')
+        self.write(cr, uid, ids, {'state': 'done'}, context=context)
+        wizard = self.browse(cr, uid, ids[0], context=context)
+
+        for line in wizard.line_ids:
+            name = line.product_id and line.product_id.description_sale or ''
+            price = get_price_from_pricelist(self, cr, uid, wizard,
+                                             line.product_id, context=context)
+            l = {
+                'name': name,
+                'product_id': line.product_id.id,
+                'product_uom_qty': 1,
+                'price_unit': price
+            }
+            # add taxes from product
+            lst_tax = line.product_id.taxes_id
+            if lst_tax:
+                l['tax_id'] = [(6, 0, [tax.id for tax in lst_tax])]
+            sale_order_line_obj.create(cr, uid, l, context=context)
+
+        return {
+            'type': 'ir.actions.act_window',
+            'res_model': 'sale.order',
+            'view_type': 'form',
+            'view_mode': 'form',
+            'target': 'current',
+            'res_id': wizard.order_id.id,
+            'context': context
+        }
+
+    def do_cancel(self, cr, uid, ids, context=None):
+        if isinstance(ids, int):
+            ids = [ids]
+
+        for line in self.browse(cr, uid, ids[0], context=context).line_ids:
+            if line.product_id.type == 'product' and line.stock_move_id:
+                stock_move_obj = self.pool.get('stock.move')
+                name = ' '.join([_('Cancel'),
+                                 line.product_id and
+                                 line.product_id.name or ''])
+                if line.product_id and line.product_id.uom_id \
+                        and line.product_id.uom_id:
+                    product_uom = line.product_id.uom_id
+                else:
+                    product_uom = None
+                move = {
+                    'name': name,
+                    'product_id': line.product_id and line.product_id.id,
+                    'product_uom': product_uom,
+                    'prodlot_id': line.serial and line.serial.id or None,
+                    'location_id': line.stock_move_id.location_dest_id.id,
+                    'location_dest_id': line.stock_move_id.location_id.id,
+                    'partner_id': line.configurator_id.order_id.partner_id.id,
+                    'type': 'in'
+                }
+                stock_move_id = stock_move_obj.create(
+                    cr, uid, move, context=context)
+                stock_move_obj.action_confirm(
+                    cr, uid, [stock_move_id], context=context)
+                stock_move_obj.action_done(
+                    cr, uid, [stock_move_id], context=context)
+
+        return True
+
+
+def get_price_from_pricelist(self, cr, uid, configurator_id, product_id,
+                             context=None):
+    ppl_obj = self.pool.get('product.pricelist')
+    pricelist_id = configurator_id.pricelist_id.id
+    partner_id = configurator_id.partner_id.id
+    pricelist_lst = [pricelist_id]
+    price_lst = ppl_obj.price_get(cr, uid, pricelist_lst,
+                                  product_id.id, 1,
+                                  partner=partner_id, context=context)
+    price = price_lst[pricelist_id]
+    return price
+
+
+def get_prices(self, cr, uid, ids, field_name, arg, context=None):
+    context = context or {}
+    result = {}
+    configurator_line_ids = self.browse(cr, uid, ids, context=context)
+    # optimize, the pricelist is the same for all line
+    if not configurator_line_ids:
+        return result
+    configurator_id = configurator_line_ids[0].configurator_id
+    i = 0
+    # force pricelist of sale_order
+    for configurator_line in configurator_line_ids:
+        product_id = configurator_line.product_id
+        price = get_price_from_pricelist(self, cr, uid, configurator_id,
+                                         product_id, context=context)
+        result[ids[i]] = price
+        i += 1
+    return result

=== added file 'sale_package_configurator/wizard/package_configurator.xml'
--- sale_package_configurator/wizard/package_configurator.xml	1970-01-01 00:00:00 +0000
+++ sale_package_configurator/wizard/package_configurator.xml	2014-05-22 19:13:44 +0000
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+  <data>
+    <record id="view_sale_package_configurator_wizard" model="ir.ui.view">
+      <field name="name">Package Configurator</field>
+      <field name="model">contract.service.configurator</field>
+      <field name="inherit_id"
+             ref="contract_isp_package_configurator.view_contract_service_configurator"/>
+      <field name="arch" type="xml">
+        <xpath expr="//group[@attrs and not(@string)]/div/p"
+               position="replace">
+          <p>Click on add to view the available options</p>
+        </xpath>
+        <xpath expr="//group[@string='Category']" position="attributes">
+          <attribute name="invisible">True</attribute>
+        </xpath>
+        <xpath expr="//field[@name='current_product_id']"
+               position="attributes">
+          <attribute name="class"></attribute>
+          <attribute name="style">width:50%%</attribute>
+        </xpath>
+        <field name="contract_id" position="replace">
+          <field name="order_id" invisible="1"/>
+        </field>
+        <xpath
+            expr="//group[@string='Products']/group/field/tree/field[@name='serial']"
+            position="after">
+          <field name="price"/>
+        </xpath>
+        <xpath
+            expr="//group/field[@name='dependency_ids']/tree/field[@name='product_id']"
+            position="after">
+          <field name="price"/>
+        </xpath>
+      </field>
+    </record>
+
+    <record id="view_sale_package_configurator_dependency_line_tree"
+            model="ir.ui.view">
+      <field name="name">Dependencies</field>
+      <field name="model">contract.service.configurator.dependency.line</field>
+      <field name="arch" type="xml">
+        <tree string="Dependencies" version="7.0">
+          <field name="name"/>
+          <field name="price"/>
+        </tree>
+      </field>
+    </record>
+  </data>
+</openerp>