Commits

Raimon Esteve (Zikzakmedia) committed 64e9c04 Merge

Merge 2.9

  • Participants
  • Parent commits 03eac39, ebc9941

Comments (0)

Files changed (14)

File configuration.py

 #This file is part product_variant module for Tryton.
 #The COPYRIGHT file at the top level of this repository contains
 #the full copyright notices and license terms.
-
 from trytond.model import ModelView, ModelSQL, ModelSingleton, fields
 
-
 __all__ = ['Configuration']
 
 
 class Configuration(ModelSingleton, ModelSQL, ModelView):
     'Variant Configuration'
     __name__ = 'product.variant.configuration'
-
     code_separator = fields.Char('Code Separator')
-

File configuration.xml

 The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms. -->
 <tryton>
     <data>
-    
         <menuitem name="Variant Configuration" 
             parent="product.menu_main_product"
-            sequence="10" 
-            id="menu_product_configuration" 
-            />
-            
-        <record model="ir.ui.menu-res.group"
-            id="menu_product_configuration_group">
-            <field name="menu" ref="menu_product_configuration"/>
-            <field name="group" ref="product.group_product_admin"/>
-        </record>
+            id="menu_product_configuration"
+            sequence="10"/>
 
-        <record model="ir.ui.view" id="configuration_view_form">
+        <record model="ir.ui.view" id="product_variant_configuration_view_form">
             <field name="model">product.variant.configuration</field>
             <field name="type">form</field>
-            <field name="arch" type="xml">
-                <![CDATA[
-                <form string="Code Separator">
-                    <label name="code_separator"/>
-                    <field name="code_separator"/>
-                </form>
-                ]]>
-            </field>
+            <field name="name">configuration_form</field>
         </record>
-
         <record model="ir.action.act_window" id="act_product_variant_configuration_form">
-            <field name="name">Variant Configuration</field>
+            <field name="name">Product variants Configuration</field>
             <field name="res_model">product.variant.configuration</field>
         </record>
-
-        <record model="ir.action.act_window.view" id="act_product_configuration_view1">
-            <field name="sequence" eval="10"/>
-            <field name="view" ref="act_product_variant_configuration_form"/>
+        <record model="ir.action.act_window.view"
+            id="act_product_variant_configuration_view1">
+            <field name="sequence" eval="1"/>
+            <field name="view" ref="product_variant_configuration_view_form"/>
             <field name="act_window" ref="act_product_variant_configuration_form"/>
         </record>
-        
-        <menuitem parent="menu_product_configuration" 
-            id="menu_variant_configuration"
+        <menuitem parent="menu_product_configuration"
             action="act_product_variant_configuration_form"
-            sequence="10" icon="tryton-list"
-            />
-        <record model="ir.ui.menu-res.group"
-            id="menu_variant_configuration_group">
-            <field name="menu" ref="menu_variant_configuration"/>
-            <field name="group" ref="product.group_product_admin"/>
-        </record>
-
+            id="menu_product_variant_configuration" icon="tryton-list"/>
     </data>
 </tryton>
 #This file is part product_variant module for Tryton.
 #The COPYRIGHT file at the top level of this repository contains
 #the full copyright notices and license terms.
-
-import itertools
 from trytond.pool import Pool, PoolMeta
 from trytond.model import ModelView, ModelSQL, fields
-from trytond.pyson import Eval, Greater, Not, Bool
+from trytond.pyson import Eval, Not, Bool
 from trytond.transaction import Transaction
-
+import itertools
 
 __all__ = ['Product', 'Template', 'ProductAttribute', 'AttributeValue',
     'ProductTemplateAttribute', 'ProductAttributeValue']
     "Product Attribute"
     __name__ = "product.attribute"
     sequence = fields.Integer('Sequence')
-    name = fields.Char('Name', required=True, translate=True, select=1,
-                       order_field="%(table)s.sequence %(order)s")
+    name = fields.Char('Name', required=True, translate=True, select=1)
     values = fields.One2Many('product.attribute.value', 'attribute', 'Values')
 
     @classmethod
         cls._order.insert(0, ('sequence', 'ASC'))
 
     @staticmethod
-    def default_sequence():
-        return 0
+    def order_sequence(tables):
+        table, _ = tables[None]
+        return [table.sequence == None, table.sequence]
 
 
 class AttributeValue(ModelSQL, ModelView):
             ondelete='CASCADE', required=True)
 
     @classmethod
-    def search(cls, domain, offset=0, limit=None, order=None, count=False):
+    def search(cls, args, offset=0, limit=None, order=None, count=False,
+            query=False):
         '''Order attributes value by sequence'''
-        res = super(ProductAttributeValue, cls).search(domain, offset=offset,
-                limit=limit, order=order, count=count)
+        res = super(ProductAttributeValue, cls).search(args, offset, limit,
+            order, count, query)
         obs = [(ob.value.attribute.sequence, ob.id) for ob in res]
         obs.sort()
         res = [cls(i[1]) for i in obs]
         <record model="ir.ui.view" id="template_view_form">
             <field name="model">product.template</field>
             <field name="inherit" ref="product.template_view_form"/>
-            <field name="arch" type="xml">
-                <![CDATA[
-                <data>
-                    <xpath expr="/form/field[@name=&quot;active&quot;]"
-                        position="after">
-                        <label name="basecode"/>
-                        <field name="basecode"/>
-                    </xpath>                    
-                    <xpath expr="/form/notebook/page[@id=&quot;general&quot;]"
-                        position="after">
-                        <page string="Variants" col="4" id="variants">
-                            <field name="attributes" colspan="2"/>
-                            <field name="products" colspan="2"/>
-                            <button name="generate_variants" 
-                                string="Generate Variants"
-                                icon="tryton-ok"
-                                colspan="4"/>
-                        </page>
-                    </xpath>
-                </data>
-                ]]>
-            </field>
+            <field name="name">template_form</field>
         </record>
-
         <record model="ir.ui.view" id="template_view_tree">
             <field name="model">product.template</field>
             <field name="inherit" ref="product.template_view_tree"/>
-            <field name="arch" type="xml">
-                <![CDATA[
-                <data>
-                    <xpath
-                        expr="/tree/field[@name=&quot;name&quot;]"
-                        position="after">
-                        <field name="variants"/>   
-                    </xpath>
-                </data>
-                ]]>
-            </field>
+            <field name="name">template_tree</field>
         </record>
 
         <record model="ir.action.act_window" id="act_relate_form">
             <field name="res_model">product.product</field>
             <field name="domain">[('template', '=', Eval('active_id'))]</field>
         </record>
-        
         <record model="ir.action.keyword" id="act_open_products">
             <field name="keyword">form_relate</field>
             <field name="model">product.template,-1</field>
         <record model="ir.ui.view" id="product_attribute_view_form">
             <field name="model">product.attribute</field>
             <field name="type">form</field>
-            <field name="arch" type="xml">
-                <![CDATA[
-                <form string="Product Attributes">
-                <label name="name"/>
-                <field name="name"/>
-                <label name="sequence"/>
-                <field name="sequence"/>
-                <newline/>
-                <field name="values" colspan="4"/>
-                </form>
-                ]]>
-            </field>
+            <field name="name">attribute_form</field>
         </record>
-
         <record model="ir.ui.view" id="product_attribute_view_tree">
             <field name="model">product.attribute</field>
             <field name="type">tree</field>
-            <field name="arch" type="xml">
-                <![CDATA[
-                <tree string="Product Attributes" sequence="sequence">
-                <field name="sequence" tree_invisible="1"/>
-                <field name="name"/>
-                <field name="values"/>
-                </tree>
-                ]]>
-            </field>
+            <field name="name">attribute_tree</field>
         </record>
 
         <record model="ir.action.act_window" id="act_product_attribute_form">
             <field name="view" ref="product_attribute_view_form"/>
             <field name="act_window" ref="act_product_attribute_form"/>
         </record>
-        
+
         <menuitem name="Product Attributes" id="menu_product_attribute"
             parent="menu_product_configuration" sequence="10"
             action="act_product_attribute_form"/>        
         <record model="ir.ui.view" id="product_attribute_value_view_form">
             <field name="model">product.attribute.value</field>
             <field name="type">form</field>
-            <field name="arch" type="xml">
-                <![CDATA[
-                <form string="Product Attribute Values">
-                <label name="name"/>
-                <field name="name"/>
-                <label name="code"/>
-                <field name="code"/>
-                <label name="sequence"/>
-                <field name="sequence"/>
-                </form>
-                ]]>
-            </field>
+            <field name="name">attribute_value_form</field>
         </record>
-        
         <record model="ir.ui.view" id="product_attribute_value_view_tree">
             <field name="model">product.attribute.value</field>
             <field name="type">tree</field>
-            <field name="arch" type="xml">
-                <![CDATA[
-                <tree string="Product Attribute Values" sequence="sequence">
-                <field name="sequence" tree_invisible="1"/>
-                <field name="name"/>
-                <field name="code"/>
-                <field name="attribute"/>
-                </tree>
-                ]]>
-            </field>
+            <field name="name">attribute_value_tree</field>
         </record>
     </data>
 </tryton>

File tests/scenario_product_variant.rst

+========================
+Product Variant Scenario
+========================
+
+Imports::
+
+    >>> from decimal import Decimal
+    >>> from proteus import config, Model, Wizard
+
+Create database::
+
+    >>> config = config.set_trytond()
+    >>> config.pool.test = True
+
+Install product_variant::
+
+    >>> Module = Model.get('ir.module.module')
+    >>> product_variant_module, = Module.find([('name', '=', 'product_variant')])
+    >>> Module.install([product_variant_module.id], config.context)
+    >>> Wizard('ir.module.module.install_upgrade').execute('upgrade')
+
+Create attribute::
+
+    >>> Attribute = Model.get('product.attribute')
+    >>> AttributeValue = Model.get('product.attribute.value')
+
+    >>> attribute = Attribute()
+    >>> attribute.name = 'Color'
+    >>> attribute.save()
+
+    >>> attribute_value = AttributeValue()
+    >>> attribute_value.name = 'Red'
+    >>> attribute_value.code = 'R'
+    >>> attribute_value.attribute = attribute
+    >>> attribute_value.save()
+
+    >>> attribute_value = AttributeValue()
+    >>> attribute_value.name = 'Black'
+    >>> attribute_value.code = 'B'
+    >>> attribute_value.attribute = attribute
+    >>> attribute_value.save()
+
+    >>> attribute = Attribute()
+    >>> attribute.name = 'Size'
+    >>> attribute.save()
+
+    >>> attribute_value = AttributeValue()
+    >>> attribute_value.name = 'Large'
+    >>> attribute_value.code = 'L'
+    >>> attribute_value.attribute = attribute
+    >>> attribute_value.save()
+
+    >>> attribute_value = AttributeValue()
+    >>> attribute_value.name = 'Medium'
+    >>> attribute_value.code = 'M'
+    >>> attribute_value.attribute = attribute
+    >>> attribute_value.save()
+
+Create category::
+
+    >>> ProductCategory = Model.get('product.category')
+    >>> category = ProductCategory(name='Category')
+    >>> category.save()
+
+Create product::
+
+    >>> ProductUom = Model.get('product.uom')
+    >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+    >>> ProductTemplate = Model.get('product.template')
+    >>> template = ProductTemplate()
+    >>> template.name = 'Tryton T-Shirt'
+    >>> template.category = category
+    >>> template.default_uom = unit
+    >>> template.type = 'goods'
+    >>> template.list_price = Decimal('10')
+    >>> template.cost_price = Decimal('5')
+    >>> template.cost_price_method = 'fixed'
+    >>> template.basecode = '001-'
+    >>> attributes = Attribute.find()
+    >>> for attribute in attributes:
+    ...     template.attributes.append(attribute)
+    >>> template.save()
+    >>> ProductTemplate.generate_variants([template.id], config.context)
+    >>> Product = Model.get('product.product')
+    >>> product, = Product.find([('code', '=', '001-RL')])
+    >>> product.code
+    u'001-RL'

File tests/test_product_variant.py

     sys.path.insert(0, os.path.dirname(DIR))
 
 import unittest
+import doctest
 import trytond.tests.test_tryton
 from trytond.tests.test_tryton import test_view, test_depends
+from trytond.backend.sqlite.database import Database as SQLiteDatabase
 
 
 class ProductVariantTestCase(unittest.TestCase):
         test_depends()
 
 
+def doctest_dropdb(test):
+    database = SQLiteDatabase().connect()
+    cursor = database.cursor(autocommit=True)
+    try:
+        database.drop(cursor, ':memory:')
+        cursor.commit()
+    finally:
+        cursor.close()
+
 def suite():
     suite = trytond.tests.test_tryton.suite()
     suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
         ProductVariantTestCase))
+    suite.addTests(doctest.DocFileSuite('scenario_product_variant.rst',
+            setUp=doctest_dropdb, tearDown=doctest_dropdb, encoding='utf-8',
+            optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
     return suite
 
 if __name__ == '__main__':
 [tryton]
-version=2.8.0
+version=2.9.0
 depends:
     ir
     res
     product
-xml:    configuration.xml
+xml:
+    configuration.xml
     product.xml

File view/attribute_form.xml

+<?xml version="1.0"?>
+<!-- This file is part product_variant module for Tryton.
+The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms. -->
+<form string="Product Attributes">
+    <label name="name"/>
+    <field name="name"/>
+    <label name="sequence"/>
+    <field name="sequence"/>
+    <newline/>
+    <field name="values" colspan="4"/>
+</form>

File view/attribute_tree.xml

+<?xml version="1.0"?>
+<!-- This file is part product_variant module for Tryton.
+The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms. -->
+<tree string="Product Attributes" sequence="sequence">
+    <field name="sequence" tree_invisible="1"/>
+    <field name="name"/>
+    <field name="values"/>
+</tree>

File view/attribute_value_form.xml

+<?xml version="1.0"?>
+<!-- This file is part product_variant module for Tryton.
+The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms. -->
+<form string="Product Attribute Values">
+    <label name="name"/>
+    <field name="name"/>
+    <label name="code"/>
+    <field name="code"/>
+    <label name="sequence"/>
+    <field name="sequence"/>
+</form>

File view/attribute_value_tree.xml

+<?xml version="1.0"?>
+<!-- This file is part product_variant module for Tryton.
+The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms. -->
+<tree string="Product Attribute Values" sequence="sequence">
+    <field name="sequence" tree_invisible="1"/>
+    <field name="name"/>
+    <field name="code"/>
+    <field name="attribute"/>
+</tree>

File view/configuration_form.xml

+<?xml version="1.0"?>
+<!-- This file is part product_variant module for Tryton.
+The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms. -->
+<form string="Product Variant Configuration">
+    <label name="code_separator"/>
+    <field name="code_separator"/>
+</form>

File view/template_form.xml

+<?xml version="1.0"?>
+<!-- This file is part product_variant module for Tryton.
+The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms. -->
+<data>
+    <xpath expr="/form/field[@name=&quot;active&quot;]"
+        position="after">
+        <label name="basecode"/>
+        <field name="basecode"/>
+    </xpath>
+    <xpath expr="/form/notebook/page[@id=&quot;general&quot;]"
+        position="after">
+        <page string="Variants" col="4" id="variants">
+            <field name="attributes" colspan="2"/>
+            <field name="products" colspan="2"/>
+            <button name="generate_variants" 
+                string="Generate Variants"
+                icon="tryton-ok"
+                colspan="4"/>
+        </page>
+    </xpath>
+</data>

File view/template_tree.xml

+<?xml version="1.0"?>
+<!-- This file is part product_variant module for Tryton.
+The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms. -->
+<data>
+    <xpath
+        expr="/tree/field[@name=&quot;name&quot;]"
+        position="after">
+        <field name="variants"/>   
+    </xpath>
+</data>