[MERGE] Merged with main addons.
authorThibault Delavallée <tde@openerp.com>
Thu, 28 Jun 2012 12:44:20 +0000 (14:44 +0200)
committerThibault Delavallée <tde@openerp.com>
Thu, 28 Jun 2012 12:44:20 +0000 (14:44 +0200)
bzr revid: tde@openerp.com-20120628124420-bxjjo2jhtzps0wsf

1  2 
addons/hr/hr.py
addons/hr/hr_view.xml
addons/product/product.py
addons/product/product_view.xml
addons/project/project_view.xml
addons/stock/product_view.xml

diff --combined addons/hr/hr.py
  ##############################################################################
  
  import addons
 -import io
  import logging
  from osv import fields, osv
 -from PIL import Image
 -import StringIO
 +import tools
  _logger = logging.getLogger(__name__)
  
  class hr_employee_category(osv.osv):
@@@ -106,7 -108,7 +106,7 @@@ class hr_job(osv.osv)
              },
              multi='no_of_employee'),
          'no_of_recruitment': fields.float('Expected in Recruitment', help='Number of new employees you expect to recruit.'),
-         'employee_ids': fields.one2many('hr.employee', 'job_id', 'Employees'),
+         'employee_ids': fields.one2many('hr.employee', 'job_id', 'Employees', groups='base.group_user'),
          'description': fields.text('Job Description'),
          'requirements': fields.text('Requirements'),
          'department_id': fields.many2one('hr.department', 'Department'),
@@@ -147,22 -149,33 +147,22 @@@ class hr_employee(osv.osv)
      _description = "Employee"
      _inherits = {'resource.resource': "resource_id"}
  
 -    def onchange_photo(self, cr, uid, ids, value, context=None):
 -        if not value:
 -            return {'value': {'photo_big': value, 'photo': value} }
 -        return {'value': {'photo_big': self._photo_resize(cr, uid, value, 540, 450, context=context), 'photo': self._photo_resize(cr, uid, value, context=context)} }
 -    
 -    def _set_photo(self, cr, uid, id, name, value, args, context=None):
 -        if not value:
 -            vals = {'photo_big': value}
 -        else:
 -            vals = {'photo_big': self._photo_resize(cr, uid, value, 540, 450, context=context)}
 -        return self.write(cr, uid, [id], vals, context=context)
 -    
 -    def _photo_resize(self, cr, uid, photo, heigth=180, width=150, context=None):
 -        image_stream = io.BytesIO(photo.decode('base64'))
 -        img = Image.open(image_stream)
 -        img.thumbnail((heigth, width), Image.ANTIALIAS)
 -        img_stream = StringIO.StringIO()
 -        img.save(img_stream, "JPEG")
 -        return img_stream.getvalue().encode('base64')
 -    
 -    def _get_photo(self, cr, uid, ids, name, args, context=None):
 +    def _get_image(self, cr, uid, ids, name, args, context=None):
          result = dict.fromkeys(ids, False)
 -        for hr_empl in self.browse(cr, uid, ids, context=context):
 -            if hr_empl.photo_big:
 -                result[hr_empl.id] = self._photo_resize(cr, uid, hr_empl.photo_big, context=context)
 +        for obj in self.browse(cr, uid, ids, context=context):
 +            resized_image_dict = tools.get_resized_images(obj.image)
 +            result[obj.id] = {
 +                'image_medium': resized_image_dict['image_medium'],
 +                'image_small': resized_image_dict['image_small'],
 +                }
          return result
      
 +    def _set_image(self, cr, uid, id, name, value, args, context=None):
 +        return self.write(cr, uid, [id], {'image': tools.resize_image_big(value)}, context=context)
 +    
 +    def onchange_image(self, cr, uid, ids, value, context=None):
 +        return {'value': tools.get_resized_images(value)}
 +    
      _columns = {
          'country_id': fields.many2one('res.country', 'Nationality'),
          'birthday': fields.date("Date of Birth"),
          'resource_id': fields.many2one('resource.resource', 'Resource', ondelete='cascade', required=True),
          'coach_id': fields.many2one('hr.employee', 'Coach'),
          'job_id': fields.many2one('hr.job', 'Job'),
 -        'photo_big': fields.binary('Big-sized employee photo', help="This field holds the photo of the employee. The photo field is used as an interface to access this field. The image is base64 encoded, and PIL-supported. Full-sized photo are however resized to 540x450 px."),
 -        'photo': fields.function(_get_photo, fnct_inv=_set_photo, string='Employee photo', type="binary",
 +        'image': fields.binary("Photo",
 +            help="This field holds the image used as a photo for the "\
 +                 "employee. The image is base64 encoded, and PIL-supported. "\
 +                 "It is limited to a 12024x1024 px image."),
 +        'image_medium': fields.function(_get_image, fnct_inv=_set_image,
 +            string="Medium-sized photo", type="binary", multi="_get_image",
 +            store = {
 +                'hr.employee': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
 +            },
 +            help="Medium-sized photo of the employee. It is automatically "\
 +                 "resized as a 180x180px image, with aspect ratio kept. "\
 +                 "Use this field in form views or some kanban views."),
 +        'image_small': fields.function(_get_image, fnct_inv=_set_image,
 +            string="Smal-sized photo", type="binary", multi="_get_image",
              store = {
 -                'hr.employee': (lambda self, cr, uid, ids, c={}: ids, ['photo_big'], 10),
 -            }, help="Image used as photo for the employee. It is automatically resized as a 180x150 px image. A larger photo is stored inside the photo_big field."),
 +                'hr.employee': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
 +            },
 +            help="Small-sized photo of the employee. It is automatically "\
 +                 "resized as a 50x50px image, with aspect ratio keps. "\
 +                 "Use this field anywhere a small image is required."),
 +        'active': fields.boolean('Active'),
          'passport_id':fields.char('Passport No', size=64),
          'color': fields.integer('Color Index'),
          'city': fields.related('address_id', 'city', type='char', string='City'),
          return {'value': {'work_email' : work_email}}
  
      def _get_photo(self, cr, uid, context=None):
 -        photo_path = addons.get_module_resource('hr','images','photo.png')
 -        return self._photo_resize(cr, uid, open(photo_path, 'rb').read().encode('base64'), context=context)
 +        image_path = addons.get_module_resource('hr', 'images', 'photo.png')
 +        return tools.resize_image_big(open(image_path, 'rb').read().encode('base64'))
  
      _defaults = {
          'active': 1,
 -        'photo': _get_photo,
 +        'image': _get_photo,
          'marital': 'single',
          'color': 0,
      }
diff --combined addons/hr/hr_view.xml
          <menuitem id="menu_hr_configuration" name="Configuration" parent="hr.menu_hr_root" groups="base.group_hr_manager" sequence="50"/>
          <menuitem id="menu_hr_management" name="Human Resources" parent="hr.menu_hr_configuration" sequence="25"/>
  
-         <!--
-         ==========
-         Employee
-         ==========
-         -->
+         <!--Employee form view -->
          <record id="view_employee_form" model="ir.ui.view">
              <field name="name">hr.employee.form</field>
              <field name="model">hr.employee</field>
@@@ -25,7 -21,7 +21,7 @@@
                      <div class="oe_right oe_button_box">
                          <!-- Put here related buttons -->
                      </div>
 -                    <field class="oe_right" name="photo" widget='image' on_change="onchange_photo(photo)"/>
 +                    <field class="oe_right" name="image_small" widget='image' on_change="onchange_image(image_small)"/>
                      <div class="oe_title">
                          <label for="name" class="oe_edit_only"/>
                          <h1><field name="name"/></h1>
@@@ -42,7 -38,7 +38,7 @@@
                                  <group string="General">
                                      <field name="user_id" on_change="onchange_user(user_id)"/>
                                      <field name="active"/>
-                                     <field name="parent_id" />
+                                     <field name="parent_id"/>
                                  </group>
                                  <group groups="base.group_hr_user" string="Social IDs">
                                      <field name="identification_id"/>
                                  </group>
                                  <group string="Contact Information">
                                      <field name="address_home_id"/>
-                                     <field name="address_id" on_change="onchange_address_id(address_id)" />
+                                     <field name="address_id" on_change="onchange_address_id(address_id)"/>
                                      <field name="work_phone"/>
                                      <field name="mobile_phone"/>
-                                     <field name="work_email" widget="email" />
+                                     <field name="work_email" widget="email"/>
                                      <field name="work_location"/>
                                  </group>
                                  <group string="Job Information">
                                      <field name="job_id" domain="[('state','!=','old')]" context="{'form_view_ref': 'hr.view_hr_job_employee_form'}"/>
-                                     <field name="coach_id" />
+                                     <field name="coach_id"/>
                                  </group>
                              </group>
                          </page>
@@@ -94,7 -90,7 +90,7 @@@
                      <field name="department_id"/>
                      <field name="job_id"/>
                      <field name="parent_id"/>
-                     <field name="coach_id" invisible="1" />
+                     <field name="coach_id" invisible="1"/>
                  </tree>
              </field>
          </record>
                      <t t-name="kanban-box">
                          <div class="oe_employee_vignette">
                              <div class="oe_employee_image">
 -                                <a type="edit"><img t-att-src="kanban_image('hr.employee', 'photo', record.id.value)" class="oe_employee_picture"/></a>
 +                                <a type="edit"><img t-att-src="kanban_image('hr.employee', 'image_medium', record.id.value)" class="oe_employee_picture"/></a>
                              </div>
                              <div class="oe_employee_details">
                                  <h4><a type="edit"><field name="name"/> (<field name="login"/>)</a></h4>
                      <field name="company_id" groups="base.group_multi_company"/>
                      <field name="department_id"/>
                      <field name="job_id"/>
-                     <field name="coach_id" invisible="1" />
+                     <field name="coach_id" invisible="1"/>
                  </tree>
              </field>
          </record>
              <field name="arch" type="xml">
                  <form string="Employee Category" version="7.0">
                      <group>
-                         <field name="name" />
-                         <field name="parent_id" />
+                         <field name="name"/>
+                         <field name="parent_id"/>
                      </group>
                  </form>
              </field>
              <field name="arch" type="xml">
                  <form string="Job" version="7.0">
                      <header>
-                         <button name="job_recruitement" string="In Recruitement" states="open" type="object"/>
-                         <button name="job_open" string="Recruitment Done" states="recruit" type="object"/>
+                         <span groups="base.group_user">
+                             <button name="job_recruitement" string="In Recruitement" states="open" type="object"/>
+                             <button name="job_open" string="Recruitment Done" states="recruit" type="object"/>
+                         </span>
                          <field name="state" widget="statusbar" statusbar_visible="recruit,open"/>
                      </header>
                      <sheet>
                          <group>
                              <group>
-                                 <field name="name" />
-                                 <field name="department_id" />
+                                 <field name="name"/>
+                                 <field name="department_id"/>
                                  <field name="company_id" widget="selection" groups="base.group_multi_company"/>
                              </group>
                              <group>
                                  <label for="requirements"/>
                                  <field name="requirements"/>
                              </page>
-                             <page string="Employees">
+                             <page string="Employees" groups="base.group_user">
                                  <field name="employee_ids" widget="many2many" mode="tree,form"/>
                              </page>
                          </notebook>
              <field name="type">tree</field>
              <field name="arch" type="xml">
                  <tree string="Job">
-                     <field name="name" />
-                     <field name="department_id" />
+                     <field name="name"/>
+                     <field name="department_id"/>
                      <field name="company_id" groups="base.group_multi_company"/>
                      <field name="expected_employees"/>
                      <field name="no_of_employee"/>
              <field name="arch" type="xml">
                  <form string="Job" version="7.0">
                      <group col="4">
-                         <field name="name" />
-                         <field name="department_id" />
+                         <field name="name"/>
+                         <field name="department_id"/>
                      </group>
                      <label for="description"/>
                      <field name="description"/>
@@@ -25,7 -25,6 +25,7 @@@ import decimal_precision as d
  import math
  from _common import rounding
  import re
 +import tools
  from tools.translate import _
  
  def is_pair(x):
@@@ -299,7 -298,7 +299,7 @@@ class product_template(osv.osv)
          'rental': fields.boolean('Can be Rent'),
          'categ_id': fields.many2one('product.category','Category', required=True, change_default=True, domain="[('type','=','normal')]" ,help="Select category for the current product"),
          'list_price': fields.float('Sale Price', digits_compute=dp.get_precision('Sale Price'), help="Base price for computing the customer price. Sometimes called the catalog price."),
-         'standard_price': fields.float('Cost Price', required=True, digits_compute=dp.get_precision('Purchase Price'), help="Product's cost for accounting stock valuation. It is the base price for the supplier price."),
+         'standard_price': fields.float('Cost Price', required=True, digits_compute=dp.get_precision('Purchase Price'), help="Product's cost for accounting stock valuation. It is the base price for the supplier price.", groups="base.group_user"),
          'volume': fields.float('Volume', help="The volume in m3."),
          'weight': fields.float('Gross Weight', digits_compute=dp.get_precision('Stock Weight'), help="The gross weight in Kg."),
          'weight_net': fields.float('Net Weight', digits_compute=dp.get_precision('Stock Weight'), help="The net weight in Kg."),
@@@ -493,22 -492,6 +493,22 @@@ class product_product(osv.osv)
                      (data['name'] or '') + (data['variants'] and (' - '+data['variants']) or '')
          return res
  
 +    def _get_image(self, cr, uid, ids, name, args, context=None):
 +        result = dict.fromkeys(ids, False)
 +        for obj in self.browse(cr, uid, ids, context=context):
 +            resized_image_dict = tools.get_resized_images(obj.image)
 +            result[obj.id] = {
 +                'image_medium': resized_image_dict['image_medium'],
 +                'image_small': resized_image_dict['image_small'],
 +                }
 +        return result
 +    
 +    def _set_image(self, cr, uid, id, name, value, args, context=None):
 +        return self.write(cr, uid, [id], {'image': tools.resize_image_big(value)}, context=context)
 +    
 +    def onchange_image(self, cr, uid, ids, value, context=None):
 +        return {'value': tools.get_resized_images(value)}
 +
      _defaults = {
          'active': lambda *a: 1,
          'price_extra': lambda *a: 0.0,
          'pricelist_id': fields.dummy(string='Pricelist', relation='product.pricelist', type='many2one'),
          'name_template': fields.related('product_tmpl_id', 'name', string="Name", type='char', size=128, store=True, select=True),
          'color': fields.integer('Color Index'),
 -        'product_image': fields.binary('Image'),
 +        'image': fields.binary("Image",
 +            help="This field holds the image used for the product. "\
 +                 "The image is base64 encoded, and PIL-supported. "\
 +                 "It is limited to a 12024x1024 px image."),
 +        'image_medium': fields.function(_get_image, fnct_inv=_set_image,
 +            string="Medium-sized image", type="binary", multi="_get_image",
 +            store = {
 +                'product.product': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
 +            },
 +            help="Medium-sized image of the product. It is automatically "\
 +                 "resized as a 180x180px image, with aspect ratio kept. "\
 +                 "Use this field in form views or some kanban views."),
 +        'image_small': fields.function(_get_image, fnct_inv=_set_image,
 +            string="Smal-sized image", type="binary", multi="_get_image",
 +            store = {
 +                'product.product': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
 +            },
 +            help="Small-sized image of the product. It is automatically "\
 +                 "resized as a 50x50px image, with aspect ratio keps. "\
 +                 "Use this field anywhere a small image is required."),
      }
  
      def create(self, cr, uid, vals, context=None):
                     <filter string="Services" icon="terp-accessories-archiver" domain="[('type','=','service')]"/>
                     <filter string="Products" icon="terp-accessories-archiver" domain="['|',('type','=','product'),('type','=','consu')]" help="Both stockable and consumable products"/>
                     <filter string="To Sell" name="filter_to_sell" icon="terp-accessories-archiver-minus" domain="[('sale_ok','=',1)]"/>
-                    <filter name="filter_to_purchase" string="To Purchase" icon="terp-accessories-archiver+" domain="[('purchase_ok', '=', 1)]" />
+                    <filter name="filter_to_purchase" string="To Purchase" icon="terp-accessories-archiver+" domain="[('purchase_ok', '=', 1)]"/>
                     <separator orientation="vertical"/>
                     <field name="categ_id" widget="selection" operator="child_of"/>
                     <group expand="0" string="Context...">
                         <field name="pricelist_id" widget="selection" context="{'pricelist': self}" groups="product.group_sale_pricelist"/>
-                        <separator orientation="vertical" groups="base.group_multi_company" />
-                        <field name="company_id" widget="selection" groups="base.group_multi_company" />
+                        <separator orientation="vertical" groups="base.group_multi_company"/>
+                        <field name="company_id" widget="selection" groups="base.group_multi_company"/>
                     </group>
                     <newline/>
                     <group  expand='0' string='Group by...'>
                         <filter string='Category' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'categ_id'}"/>
                         <separator orientation="vertical"/>
-                        <filter string='Default Unit of Measure' icon="terp-mrp" domain="[]" context="{'group_by' : 'uom_id'}" />
+                        <filter string='Default Unit of Measure' icon="terp-mrp" domain="[]" context="{'group_by' : 'uom_id'}"/>
                         <separator orientation="vertical"/>
-                        <filter string='Type' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'type'}" />
+                        <filter string='Type' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'type'}"/>
                         <separator orientation="vertical" groups="base.group_multi_company"/>
-                        <filter string='Company' icon="terp-go-home" domain="[]" context="{'group_by' : 'company_id'}" groups="base.group_multi_company" />
+                        <filter string='Company' icon="terp-go-home" domain="[]" context="{'group_by' : 'company_id'}" groups="base.group_multi_company"/>
                     </group>
  
                  </search>
@@@ -60,6 -60,7 +60,7 @@@
                  </tree>
              </field>
          </record>
          <record id="product_normal_form_view" model="ir.ui.view">
              <field name="name">product.normal.form</field>
              <field name="model">product.product</field>
              <field name="arch" type="xml">
                  <form string="Product" layout="auto" version="7.0">
                      <sheet>
 -                        <field name="product_image" widget="image" class="oe_avatar oe_right"/>
 +                        <field name="image_small" widget="image" class="oe_avatar oe_right" on_change="onchange_image(image_small"/>
  
                          <div class="oe_title">
                              <div class="oe_edit_only">
-                                 <label for="name" string="Product Name" /> 
+                                 <label for="name" string="Product Name"/> 
                              </div>
                              <h1>
                                  <field name="name"/>
                              </h1>
-                             <label for="categ_id" class="oe_edit_only" />
-                             <h2><field name="categ_id" /></h2>
+                             <label for="categ_id" class="oe_edit_only"/>
+                             <h2><field name="categ_id"/></h2>
                          </div>
                          <notebook>
                              <page string="Information">
                                  <group>
                                      <group>
                                          <field name="default_code"/>
-                                         <field name="ean13" placeholder="5901234123457" />
-                                         <field groups="product.group_product_variant" name="variants" />
+                                         <field name="ean13" placeholder="5901234123457"/>
+                                         <field groups="product.group_product_variant" name="variants"/>
                                      </group>
-                                     <group>
+                                     <group groups="base.group_user">
                                          <field name="sale_ok"/>
                                          <field name="purchase_ok"/>
                                      </group>
                                      <group string="Procurement">
                                          <field name="type"/>
                                          <field name="procure_method"/>
-                                         <field name="supply_method"/>
+                                         <field name="supply_method" groups="base.group_user"/>
                                      </group>
                                      <group string="Prices">
                                          <field name="list_price"/>
  
                                  </group>
                              </page>
-                             <page string="Procurement &amp; Locations">
+                             <page string="Procurement &amp; Locations" groups="base.group_user">
                                  <group>
                                      <group name="delay" string="Delays">
                                          <field name="sale_delay" attrs="{'readonly':[('sale_ok','=',0)]}"/>
                                          <field name="warranty"/>
                                      </group>
                                      <group name="store" string="Storage Localisation">
-                                         <field name="loc_rack" attrs="{'readonly':[('type','=','service')]}" />
+                                         <field name="loc_rack" attrs="{'readonly':[('type','=','service')]}"/>
                                          <field name="loc_row" attrs="{'readonly':[('type','=','service')]}"/>
                                          <field name="loc_case" attrs="{'readonly':[('type','=','service')]}"/>
                                      </group>
                                  </group>
  
                              </page>
-                             <page string="Suppliers">
+                             <page string="Suppliers" groups="base.group_user">
                                  <field name="seller_ids" context="{'uom_id': uom_id}"/>
                              </page>
-                             <page string="Descriptions">
-                                 <separator string="Internal Description"/>
+                             <page string="Descriptions" groups="base.group_user">
+                                 <separator string="Description"/>
                                  <field name="description"/>
                                  <separator string="Sale Description"/>
                                  <field name="description_sale" placeholder="This note will be displayed on quotations..."/>
                  <kanban>
                      <field name="color"/>
                      <field name="type"/>
 -                    <field name="product_image"/>
                      <field name="list_price"/>
                      <templates>
                          <t t-name="kanban-box">
                                          <field name="name"/>
                                      </div>
                                      <div class="oe_kanban_box_content oe_kanban_color_bglight oe_kanban_box_show_onclick_trigger">
 -                                        <img t-att-src="kanban_image('product.product', 'product_image', record.id.value)" width="48" style="float: left; padding: 0 4px 4px 0"/>
 +                                        <img t-att-src="kanban_image('product.product', 'image_medium', record.id.value)" width="48" style="float: left; padding: 0 4px 4px 0"/>
                                          Code: <field name="code"/>
                                          <div t-if="record.type.raw_value == 'service'">No Stock</div>
                                          <t t-if="record.type.raw_value != 'service'">
                                              <div>Stock: <field name="qty_available"/> on hand, <field name="virtual_available"/> available</div>
                                              <div t-if="record.list_price.raw_value != 0">Public Price: <field name="lst_price"/></div>
-                                             <div>Cost : <field name="standard_price"/></div>
+                                             <!-- TODO would deserve to be hidden at the field level -->
+                                             <div groups="base.group_user">Cost : <field name="standard_price"/></div>
                                          </t>
                                          <div class="oe_kanban_clear"/>
                                      </div>
              <field name="arch" type="xml">
                  <form string="Packaging" version="7.0">
                      <group>
-                         <field name="name" />
-                         <field name="type" />
+                         <field name="name"/>
+                         <field name="type"/>
                      </group>
                  </form>
              </field>
@@@ -93,7 -93,7 +93,7 @@@
                              <group>
                                  <group string="Administration">
                                      <field name="planned_hours" widget="float_time"/>
-                                     <field name="effective_hours" widget="float_time" />
+                                     <field name="effective_hours" widget="float_time"/>
                                      <field name="resource_calendar_id"/>
                                  </group>
                                  <group string="Miscellaneous" name="misc">
                     </group>
                     <newline />
                     <group expand="0" string="Group By...">
-                        <filter string="Manager" name="Manager"  icon="terp-personal" domain = "[]" context="{'group_by':'user_id'}"/>
-                        <filter string="Partner" name="Partner" icon="terp-partner" domain = "[]" context="{'group_by':'partner_id'}"/>
+                        <filter string="Manager" name="Manager" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>
+                        <filter string="Partner" name="Partner" icon="terp-partner" domain="[]" context="{'group_by':'partner_id'}"/>
                         <separator orientation="vertical"/>
-                        <filter string="Parent" name="Parent"  help="Parent" icon="terp-folder-blue" domain = "[]" context="{'group_by':'parent_id'}"/>
+                        <filter string="Parent" name="Parent" help="Parent" icon="terp-folder-blue" domain = "[]" context="{'group_by':'parent_id'}"/>
                     </group>
                 </search>
              </field>
  
                                      <div class="oe_kanban_project_avatars">
                                          <t t-foreach="record.members.raw_value" t-as="member">
 -                                            <img t-att-src="kanban_image('res.users', 'avatar', member)" t-att-data-member_id="member"/>
 +                                            <img t-att-src="kanban_image('res.users', 'image_small', member)" t-att-data-member_id="member"/>
                                          </t>
                                      </div>
                                  </div>
              <field name="arch" type="xml">
                  <form string="Project" version="7.0">
                      <header>
-                         <!--
-                         <button name="do_open" string="Start Task" type="object"
-                                 states="draft,pending"/>
-                         <button name="do_draft" string="Draft" type="object"
-                                 states="cancel,done"/>
-                         -->
-                         <button name="%(action_project_task_reevaluate)d" string="Reactivate" type="action"
-                                 states="done,cancelled" context="{'button_reactivate':True}"/>
-                         <button name="action_close" string="Done" type="object"
-                                 states="draft,open,pending"/>
-                         <button name="do_pending" string="Pending" type="object"
-                                 states="open"/>
-                         <button name="%(action_project_task_delegate)d" string="Delegate" type="action"
-                                 states="pending,open,draft" groups="project.group_delegate_task"/>
-                         <button name="do_cancel" string="Cancel" type="object"
-                                 states="draft,open,pending" />
-                         <button name="stage_previous" string="Previous Stage" type="object"
-                                 states="open,pending" icon="gtk-go-back" attrs="{'invisible': [('stage_id','=', False)]}"/>
-                         <button name="stage_next" string="Next Stage" type="object"
-                                 states="open,pending" icon="gtk-go-forward" attrs="{'invisible': [('stage_id','=', False)]}"/>
+                         <span groups="base.group_user">
+                             <!--
+                             <button name="do_open" string="Start Task" type="object"
+                                     states="draft,pending"/>
+                             <button name="do_draft" string="Draft" type="object"
+                                     states="cancel,done"/>
+                             -->
+                             <button name="%(action_project_task_reevaluate)d" string="Reactivate" type="action"
+                                     states="done,cancelled" context="{'button_reactivate':True}"/>
+                             <button name="action_close" string="Done" type="object"
+                                     states="draft,open,pending"/>
+                             <button name="do_pending" string="Pending" type="object"
+                                     states="open"/>
+                             <button name="%(action_project_task_delegate)d" string="Delegate" type="action"
+                                     states="pending,open,draft" groups="project.group_delegate_task"/>
+                             <button name="do_cancel" string="Cancel" type="object"
+                                     states="draft,open,pending"/>
+                             <button name="stage_previous" string="Previous Stage" type="object"
+                                     states="open,pending" icon="gtk-go-back" attrs="{'invisible': [('stage_id','=', False)]}"/>
+                             <button name="stage_next" string="Next Stage" type="object"
+                                     states="open,pending" icon="gtk-go-forward" attrs="{'invisible': [('stage_id','=', False)]}"/>
+                         </span>
                          <field name="stage_id" widget="statusbar"/>
                      </header>
                      <sheet string="Task">
                      </group>
                      <notebook>
                          <page string="Description">
-                             <field name="description" attrs="{'readonly':[('state','=','done')]}" placeholder="Add a Description..." />
+                             <field name="description" attrs="{'readonly':[('state','=','done')]}" placeholder="Add a Description..."/>
                              <field name="work_ids" groups="project.group_tasks_work_on_tasks">
                                  <tree string="Task Work" editable="top">
                                      <field name="date"/>
                          </page>
                          <page string="Extra Info" attrs="{'readonly':[('state','=','done')]}">
                              <group col="4">
-                                 <field name="priority"/>
+                                 <field name="priority" groups="base.group_user"/>
                                  <field name="sequence"/>
-                                 <field name="partner_id" />
+                                 <field name="partner_id"/>
                                  <field name="state" groups="base.group_no_one"/>
                              </group>
                          </page>
              <field name="arch" type="xml">
                  <kanban default_group_by="stage_id" >
                      <field name="color"/>
-                     <field name="priority"/>
+                     <field name="priority" groups="base.group_user"/>
                      <field name="stage_id"/>
                      <field name="user_id"/>
                      <field name="user_email"/>
                                              <field name="name"/>
                                          </td>
                                          <td valign="top" width="22">
 -                                            <img t-att-src="kanban_image('res.users', 'avatar', record.user_id.raw_value[0])"  t-att-title="record.user_id.value"
 +                                            <img t-att-src="kanban_image('res.users', 'image_small', record.user_id.raw_value[0])"  t-att-title="record.user_id.value"
                                              width="22" height="22" class="oe_kanban_gravatar"/>
                                          </td>
                                      </tr>
@@@ -61,8 -61,8 +61,8 @@@
              <field name="inherit_id" ref="product.product_normal_form_view"/>
              <field name="arch" type="xml">
                  <field name="standard_price" position="replace" version="7.0">
-                     <label string="Cost Price" for="standard_price" align="1.0"/>
-                     <div>
+                     <label string="Cost Price" for="standard_price" align="1.0" groups="base.group_user"/>
+                     <div groups="base.group_user">
                          <field name="standard_price" attrs="{'readonly':[('cost_method','=','average')]}" nolabel="1"/>
                          <button name="%(action_view_change_standard_price)d" string="Update"
                              type="action" icon="gtk-execute" attrs="{'invisible':[('cost_method','&lt;&gt;','average')]}"/>
                      <group string="Stock and Expected Variations">
                          <field name="qty_available"/>
                          <field name="incoming_qty"/>
-                         <label for="virtual_available" />
+                         <label for="virtual_available"/>
                          <div>
-                             <field name="virtual_available" class="oe_inline" />
+                             <field name="virtual_available" class="oe_inline"/>
  
                              <button name="%(action_view_change_product_quantity)d" string="Update" attrs="{'invisible': [('type', '=', 'service')]}"
-                                 type="action" icon="gtk-execute" groups="stock.group_stock_manager,stock.group_stock_user" class="oe_inline" />
+                                 type="action" icon="gtk-execute" groups="stock.group_stock_manager,stock.group_stock_user" class="oe_inline"/>
                          </div>
                          <field name="outgoing_qty"/>
                      </group>
                  <kanban>
                      <field name="color"/>
                      <field name="type"/>
 -                    <field name="product_image"/>
 +                    <field name="image"/>
                      <field name="list_price"/>
                      <field name="reception_count"/>
                      <field name="delivery_count"/>
                          <t t-name="kanban-box">
                              <div class="oe_product_vignette">
                                  <div class="oe_product_img">
 -                                <a type="edit"><img t-att-src="kanban_image('product.product', 'product_image', record.id.value)" class="oe_product_photo"/></a>
 +                                <a type="edit"><img t-att-src="kanban_image('product.product', 'image_medium', record.id.value)" class="oe_product_photo"/></a>
                                  </div>
                                  <div class="oe_product_desc">
                                      <h4><a type="edit"><field name="name"></field></a></h4>
                                          <li t-if="record.type.raw_value != 'service'">Stock on hand: <field name="qty_available"/> <field name="uom_id"/></li>
                                          <li t-if="record.type.raw_value != 'service'">Stock available: <field name="virtual_available"/> <field name="uom_id"/></li>
                                          <li>Price: <field name="lst_price"></field></li>
-                                         <li>Cost: <field name="standard_price"></field></li>
+                                         <!-- TODO the 'groups' attribute doesn't work in kanban views -->
+                                         <li groups="base.group_user">Cost: <field name="standard_price"></field></li>
                                      </ul>
-                                     <a name="%(action_receive_move)d" type="action">
-                                         <t t-if="record.reception_count.value">Receptions(<t t-esc="record.reception_count.value"/>)</t>
-                                     </a>
-                                     <a name="%(action_deliver_move)d" type="action">
-                                         <t t-if="record.delivery_count.value">Deliveries(<t t-esc="record.delivery_count.value"/>)</t>
-                                     </a>
+                                     <div groups="base.group_user">
+                                         <a name="%(action_receive_move)d" type="action">
+                                             <t t-if="record.reception_count.value">Receptions(<t t-esc="record.reception_count.value"/>)</t>
+                                         </a>
+                                         <a name="%(action_deliver_move)d" type="action">
+                                             <t t-if="record.delivery_count.value">Deliveries(<t t-esc="record.delivery_count.value"/>)</t>
+                                         </a>
+                                     </div>
                                  </div>
                              </div>
                              <script>