[MERGE] MyNotChatterTask: image resize.

This revision adds standard image field names and sizes (image: 1024x1024; image_medium: 180x180; image_small: 50x50, the last two being function fields). This addons-side branch holds the update for mail.group, product, point of sale and hr. Default image for new hr employee has also been updated. Hr module now has its icon for the module kanban view.

bzr revid: tde@openerp.com-20120807131152-qw0lw9s8s6lq5m2b
This commit is contained in:
Thibault Delavallée
2012-08-07 15:11:52 +02:00
29 changed files with 1180 additions and 1177 deletions
+1 -1
View File
@@ -7,7 +7,7 @@
<field name="password">anonymous</field>
<!-- Avoid auto-including this demo user in any default group -->
<field name="groups_id" eval="[(5,)]"/>
<field name="avatar">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</field>
<field name="image">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</field>
</record>
<!--
+1 -1
View File
@@ -347,7 +347,7 @@
<t t-if="record.date_deadline.raw_value and record.date_deadline.raw_value lt (new Date())" t-set="red">oe_kaban_status_red</t>
<span t-attf-class="oe_kanban_status #{red}"> </span>
-->
<img t-att-src="kanban_image('res.users', 'avatar', record.user_id.raw_value[0])" t-att-title="record.user_id.value" width="24" height="24" class="oe_kanban_avatar"/>
<img t-att-src="kanban_image('res.users', 'image_small', record.user_id.raw_value[0])" t-att-title="record.user_id.value" width="24" height="24" class="oe_kanban_avatar"/>
</div>
<div class="oe_kanban_footer_left">
<t t-if="record.needaction_pending.raw_value"><span class="oe_kanban_mail_new">New</span></t>
+6 -1
View File
@@ -38,7 +38,12 @@ You can manage:
""",
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
'images': ['images/hr_department.jpeg', 'images/hr_employee.jpeg','images/hr_job_position.jpeg'],
'images': [
'images/hr_department.jpeg',
'images/hr_employee.jpeg',
'images/hr_job_position.jpeg',
'static/src/img/default_image.png',
],
'depends': ['base_setup','mail', 'resource', 'board'],
'init_xml': [],
'update_xml': [
+30 -35
View File
@@ -20,11 +20,9 @@
##############################################################################
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):
@@ -149,33 +147,15 @@ 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):
result[obj.id] = tools.image_get_resized_images(obj.image)
return result
def _set_image(self, cr, uid, id, name, value, args, context=None):
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
_columns = {
'country_id': fields.many2one('res.country', 'Nationality'),
'birthday': fields.date("Date of Birth"),
@@ -200,11 +180,26 @@ class hr_employee(osv.osv):
'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 1024x1024 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, ['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="Medium-sized photo of the employee. It is automatically "\
"resized as a 180x180 px image, with aspect ratio preserved. "\
"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, ['image'], 10),
},
help="Small-sized photo of the employee. It is automatically "\
"resized as a 50x50 px image, with aspect ratio preserved. "\
"Use this field anywhere a small image is required."),
'passport_id':fields.char('Passport No', size=64),
'color': fields.integer('Color Index'),
'city': fields.related('address_id', 'city', type='char', string='City'),
@@ -260,13 +255,13 @@ class hr_employee(osv.osv):
work_email = self.pool.get('res.users').browse(cr, uid, user_id, context=context).user_email
return {'value': {'work_email' : work_email}}
def _default_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)
def _get_default_image(self, cr, uid, context=None):
image_path = addons.get_module_resource('hr', 'static/src/img', 'default_image.png')
return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
_defaults = {
'active': 1,
'photo': _default_get_photo,
'image': _get_default_image,
'marital': 'single',
'color': 0,
}
+21 -21
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -21,7 +21,7 @@
<field name="arch" type="xml">
<form string="Employee" version="7.0">
<sheet>
<field name="photo" widget='image' class="oe_right" on_change="onchange_photo(photo)"/>
<field name="image_small" widget='image' class="oe_right oe_image_small"/>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1>
@@ -136,7 +136,7 @@
<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>

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

@@ -320,7 +320,8 @@
<a type="object" name="set_priority" args="['1']">
<img t-attf-src="/web/static/src/img/icons/star-#{priority == 1 ? 'on' : 'off'}.png" width="16" height="16" title="Excellent"/>
</a>
<img t-att-src="kanban_image('res.users', 'avatar', record.user_id.raw_value[0])" t-att-title="record.user_id.value" width="24" height="24" class="oe_kanban_avatar"/>
<img t-att-src="kanban_image('res.users', 'image_small', record.user_id.raw_value[0])" t-att-title="record.user_id.value" width="24" height="24" class="oe_kanban_avatar"/>
</div>
</div>
<div class="oe_clear"></div>
+28 -38
View File
@@ -20,14 +20,11 @@
##############################################################################
import datetime as DT
import io
import openerp
import openerp.tools as tools
from operator import itemgetter
from osv import osv
from osv import fields
from PIL import Image
import StringIO
import tools
from tools.translate import _
from lxml import etree
@@ -51,32 +48,15 @@ class mail_group(osv.osv):
_inherit = ['mail.thread']
_inherits = {'mail.alias': 'alias_id'}
def onchange_photo(self, cr, uid, ids, value, context=None):
if not value:
return {'value': {'avatar_big': value, 'avatar': value} }
return {'value': {'photo_big': value, 'photo': self._photo_resize(cr, uid, value) } }
def _set_photo(self, cr, uid, id, name, value, args, context=None):
if value:
return self.write(cr, uid, [id], {'photo_big': value}, context=context)
else:
return self.write(cr, uid, [id], {'photo_big': value}, context=context)
def _photo_resize(self, cr, uid, photo, width=128, height=128, context=None):
image_stream = io.BytesIO(photo.decode('base64'))
img = Image.open(image_stream)
img.thumbnail((width, height), 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 group in self.browse(cr, uid, ids, context=context):
if group.photo_big:
result[group.id] = self._photo_resize(cr, uid, group.photo_big, context=context)
for obj in self.browse(cr, uid, ids, context=context):
result[obj.id] = tools.image_get_resized_images(obj.image)
return result
def _set_image(self, cr, uid, id, name, value, args, context=None):
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
def get_member_ids(self, cr, uid, ids, field_names, args, context=None):
if context is None:
context = {}
@@ -104,9 +84,9 @@ class mail_group(osv.osv):
result[id] = self.message_search(cr, uid, [id], limit=None, domain=[('date', '>=', lower_date)], count=True, context=context)
return result
def _get_default_photo(self, cr, uid, context=None):
avatar_path = openerp.modules.get_module_resource('mail', 'static/src/img', 'groupdefault.png')
return self._photo_resize(cr, uid, open(avatar_path, 'rb').read().encode('base64'), context=context)
def _get_default_image(self, cr, uid, context=None):
image_path = openerp.modules.get_module_resource('mail', 'static/src/img', 'groupdefault.png')
return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
_columns = {
'name': fields.char('Name', size=64, required=True),
@@ -121,16 +101,26 @@ class mail_group(osv.osv):
help="Members of those groups will automatically added as followers. "\
"Note that they will be able to manage their subscription manually "\
"if necessary."),
'photo_big': fields.binary('Full-size photo',
help='Field holding the full-sized PIL-supported and base64 encoded "\
version of the group image. The photo field is used as an "\
interface for this field.'),
'photo': fields.function(_get_photo, fnct_inv=_set_photo,
string='Photo', type="binary",
'image': fields.binary("Photo",
help="This field holds the image used as photo for the "\
"user. 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 = {
'mail.group': (lambda self, cr, uid, ids, c={}: ids, ['photo_big'], 10),
'mail.group': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
},
help='Field holding the automatically resized (128x128) PIL-supported and base64 encoded version of the group image.'),
help="Medium-sized photo of the group. It is automatically "\
"resized as a 180x180px image, with aspect ratio preserved. "\
"Use this field in form views or some kanban views."),
'image_small': fields.function(_get_image, fnct_inv=_set_image,
string="Small-sized photo", type="binary", multi="_get_image",
store = {
'mail.group': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
},
help="Small-sized photo of the group. It is automatically "\
"resized as a 50x50px image, with aspect ratio preserved. "\
"Use this field anywhere a small image is required."),
'member_ids': fields.function(get_member_ids, fnct_search=search_member_ids,
type='many2many', relation='res.users', string='Group members', multi='get_member_ids'),
'member_count': fields.function(get_member_ids, type='integer',
@@ -147,7 +137,7 @@ class mail_group(osv.osv):
_defaults = {
'public': True,
'responsible_id': (lambda s, cr, uid, ctx: uid),
'photo': _get_default_photo,
'image': _get_default_image,
}
def _subscribe_user_with_group_m2m_command(self, cr, uid, ids, group_ids_command, context=None):
+2 -3
View File
@@ -19,7 +19,7 @@
<t t-name="kanban-box">
<div t-attf-class="{record.is_subscriber.raw_value} oe_group_vignette">
<div class="oe_group_image">
<a type="edit"><img t-att-src="kanban_image('mail.group', 'photo', record.id.value)" class="oe_group_photo" tooltip="kanban-description"/></a>
<a type="edit"><img t-att-src="kanban_image('mail.group', 'image_medium', record.id.value)" class="oe_group_photo" tooltip="kanban-description"/></a>
</div>
<div class="oe_group_details">
<h4><a type="edit"><field name="name"/></a></h4>
@@ -33,7 +33,6 @@
</div>
</div>
<script>
$('.oe_group_photo').load(function() { if($(this).width() > $(this).height()) { $(this).addClass('oe_group_photo_wide') } });
$('.oe_group_join').mouseover(function () { $(this).html('Follow'); }).mouseleave(function () { $(this).html('Not following'); });
$('.oe_group_leave').mouseover(function () { $(this).html('Unfollow'); }).mouseleave(function () { $(this).html('Following'); });
</script>
@@ -54,7 +53,7 @@
<sheet class="openerp_mail_group_sheet">
<group colspan="4" col="8">
<group colspan="1" col="2">
<field name="photo" widget='image' nolabel="1" on_change="onchange_photo(photo)"/>
<field name="image_small" widget='image' class="oe_image_small" nolabel="1"/>
</group>
<group colspan="7" col="6">
<div class="oe_edit_only">
+1 -1
View File
@@ -893,7 +893,7 @@ class mail_thread(osv.Model):
subscr_ids = subscr_obj.search(cr, uid, ['&', ('res_model', '=', self._name), ('res_id', 'in', ids)], context=context)
return [sub['user_id'][0] for sub in subscr_obj.read(cr, uid, subscr_ids, ['user_id'], context=context)]
def message_read_subscribers(self, cr, uid, ids, fields=['id', 'name', 'avatar'], context=None):
def message_read_subscribers(self, cr, uid, ids, fields=['id', 'name', 'image_small'], context=None):
""" Returns the current document followers as a read result. Used
mainly for Chatter having only one method to call to have
details about users.
+1 -1
View File
@@ -9,7 +9,7 @@
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<xpath expr="//sheet" position="after">
<div class="oe_chatter oe_mail_group_footer">
<div class="oe_chatter">
<field name="message_ids" widget="mail_thread"
options='{"thread_level": 1}'/>
</div>
+1 -1
View File
@@ -27,7 +27,7 @@
<field name="notification_email_pref"/>
</field>
<xpath expr="/form/sheet" position="after">
<div class="oe_chatter oe_mail_group_footer">
<div class="oe_chatter">
<field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
</div>
</xpath>
+1 -13
View File
@@ -20,12 +20,6 @@
max-width: 80%;
}
/* Resize group logo */
.openerp .oe_form_sheetbg.openerp_mail_group_sheet .oe_form_field_image > img {
max-width: 100px;
max-height: 100px;
}
/* Resize group description */
.openerp .oe_form_sheetbg.openerp_mail_group_sheet .oe_form_field_text > textarea {
height: 40px;
@@ -63,14 +57,8 @@
.oe_group_photo {
width: 100px;
height: auto;
clip: rect(0px, 100px, 100px, 0px);
}
.oe_group_photo_wide {
height: 100px;
width: auto;
clip: rect(0px, 115px, 100px, 15px);
clip: rect(0px, 100px, 100px, 0px);
}
.oe_group_details {
+4 -4
View File
@@ -341,7 +341,7 @@ openerp.mail = function(session) {
this._super.apply(this, arguments);
// customize display: add avatar, clean previous content
var user_avatar = mail.ChatterUtils.get_image(this.session.prefix,
this.session.session_id, 'res.users', 'avatar', this.session.uid);
this.session.session_id, 'res.users', 'image_small', this.session.uid);
this.$element.find('img.oe_mail_icon').attr('src', user_avatar);
this.$element.find('div.oe_mail_msg_content').empty();
// create a context for the default_get of the compose form
@@ -742,7 +742,7 @@ openerp.mail = function(session) {
if (record.type == 'email') {
record.mini_url = ('/mail/static/src/img/email_icon.png');
} else {
record.mini_url = mail.ChatterUtils.get_image(this.session.prefix, this.session.session_id, 'res.users', 'avatar', record.user_id[0]);
record.mini_url = mail.ChatterUtils.get_image(this.session.prefix, this.session.session_id, 'res.users', 'image_small', record.user_id[0]);
}
// body text manipulation
if (record.subtype == 'plain') {
@@ -768,7 +768,7 @@ openerp.mail = function(session) {
},
display_current_user: function () {
var avatar = mail.ChatterUtils.get_image(this.session.prefix, this.session.session_id, 'res.users', 'avatar', this.params.uid);
var avatar = mail.ChatterUtils.get_image(this.session.prefix, this.session.session_id, 'res.users', 'image_small', this.params.uid);
return this.$element.find('img.oe_mail_icon').attr('src', avatar);
},
@@ -913,7 +913,7 @@ openerp.mail = function(session) {
this.$element.find('div.oe_mail_recthread_followers h4').html('Followers (' + records.length + ')');
_(records).each(function (record) {
if (record.id == self.session.uid) { self.is_subscriber = true; }
record.avatar_url = mail.ChatterUtils.get_image(self.session.prefix, self.session.session_id, 'res.users', 'avatar', record.id);
record.avatar_url = mail.ChatterUtils.get_image(self.session.prefix, self.session.session_id, 'res.users', 'image_small', record.id);
$(session.web.qweb.render('mail.record_thread.subscriber', {'record': record})).appendTo(user_list);
});
if (self.is_subscriber) {
+29 -39
View File
@@ -18,8 +18,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import pdb
import io
import openerp
import addons
@@ -27,10 +27,10 @@ import time
from datetime import datetime
from dateutil.relativedelta import relativedelta
import logging
from PIL import Image
import netsvc
from osv import fields, osv
import tools
from tools.translate import _
from decimal import Decimal
import decimal_precision as dp
@@ -1174,20 +1174,14 @@ class pos_category(osv.osv):
res = self.name_get(cr, uid, ids, context=context)
return dict(res)
def _get_small_image(self, cr, uid, ids, prop, unknow_none, context=None):
result = {}
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):
if not obj.category_image:
result[obj.id] = False
continue
image_stream = io.BytesIO(obj.category_image.decode('base64'))
img = Image.open(image_stream)
img.thumbnail((120, 100), Image.ANTIALIAS)
img_stream = StringIO.StringIO()
img.save(img_stream, "JPEG")
result[obj.id] = img_stream.getvalue().encode('base64')
result[obj.id] = tools.image_get_resized_images(obj.image)
return result
def _set_image(self, cr, uid, id, name, value, args, context=None):
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
_columns = {
'name': fields.char('Name', size=64, required=True, translate=True),
@@ -1195,20 +1189,34 @@ class pos_category(osv.osv):
'parent_id': fields.many2one('pos.category','Parent Category', select=True),
'child_id': fields.one2many('pos.category', 'parent_id', string='Children Categories'),
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of product categories."),
'category_image': fields.binary('Image'),
'category_image_small': fields.function(_get_small_image, string='Small Image', type="binary",
'image': fields.binary("Image",
help="This field holds the image used for the category. "\
"The image is base64 encoded, and PIL-supported. "\
"It is limited to a 1024x1024 px image."),
'image_medium': fields.function(_get_image, fnct_inv=_set_image,
string="Medium-sized image", type="binary", multi="_get_image",
store = {
'pos.category': (lambda self, cr, uid, ids, c={}: ids, ['category_image'], 10),
}),
'pos.category': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
},
help="Medium-sized image of the category. It is automatically "\
"resized as a 180x180 px image, with aspect ratio preserved. "\
"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 = {
'pos.category': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
},
help="Small-sized image of the category. It is automatically "\
"resized as a 50x50 px image, with aspect ratio preserved. "\
"Use this field anywhere a small image is required."),
}
def _get_default_image(self, cr, uid, context=None):
image_path = openerp.modules.get_module_resource('point_of_sale', 'images', 'default_category_photo.png')
return open(image_path, 'rb').read().encode('base64')
return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
_defaults = {
'category_image': _get_default_image,
'image': _get_default_image,
}
pos_category()
@@ -1217,30 +1225,12 @@ import io, StringIO
class product_product(osv.osv):
_inherit = 'product.product'
def _get_small_image(self, cr, uid, ids, prop, unknow_none, context=None):
result = {}
for obj in self.browse(cr, uid, ids, context=context):
if not obj.product_image:
result[obj.id] = False
continue
image_stream = io.BytesIO(obj.product_image.decode('base64'))
img = Image.open(image_stream)
img.thumbnail((120, 100), Image.ANTIALIAS)
img_stream = StringIO.StringIO()
img.save(img_stream, "JPEG")
result[obj.id] = img_stream.getvalue().encode('base64')
return result
_columns = {
'income_pdt': fields.boolean('Point of Sale Cash In', help="This is a product you can use to put cash into a statement for the point of sale backend."),
'expense_pdt': fields.boolean('Point of Sale Cash Out', help="This is a product you can use to take cash from a statement for the point of sale backend, exemple: money lost, transfer to bank, etc."),
'pos_categ_id': fields.many2one('pos.category','Point of Sale Category',
help="If you want to sell this product through the point of sale, select the category it belongs to."),
'product_image_small': fields.function(_get_small_image, string='Small Image', type="binary",
store = {
'product.product': (lambda self, cr, uid, ids, c={}: ids, ['product_image'], 10),
}),
'to_weight' : fields.boolean('To Weight', help="This category contains products that should be weighted, mainly used for the self-checkout interface"),
}
_defaults = {
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -660,7 +660,7 @@
<field name="arch" type="xml">
<form string="Product PoS Categories" version="7.0">
<sheet>
<field name="category_image" widget='image' class="oe_avatar oe_right"/>
<field name="image_medium" widget='image' class="oe_avatar oe_right"/>
<div class="oe_left">
<group>
<field name="name"/>
@@ -462,6 +462,10 @@
cursor: pointer;
}
.point-of-sale .category-button .category-img img {
height: 100px;
}
.point-of-sale .category-button .category-name {
position: absolute;
-webkit-box-sizing: border-box;
@@ -506,6 +510,10 @@
text-align: center;
}
.point-of-sale .product .product-img img {
height: 100px;
}
.point-of-sale .product .price-tag {
position: absolute;
top: 2px;
@@ -139,7 +139,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
self.set('currency',currencies[0]);
});
var cat_def = fetch('pos.category', ['id','name', 'parent_id', 'child_id', 'category_image_small'])
var cat_def = fetch('pos.category', ['id','name', 'parent_id', 'child_id', 'image_medium'])
.pipe(function(result){
return self.set({'categories': result});
});
@@ -219,7 +219,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
return fetch(
'product.product',
//context {pricelist: shop.pricelist_id[0]}
['name', 'list_price','price','pos_categ_id', 'taxes_id','product_image_small', 'ean13', 'to_weight', 'uom_id', 'uos_id', 'uos_coeff', 'mes_type'],
['name', 'list_price','price','pos_categ_id', 'taxes_id','image_medium', 'ean13', 'to_weight', 'uom_id', 'uos_id', 'uos_coeff', 'mes_type'],
[['pos_categ_id','!=', false]],
{pricelist: shops[0].pricelist_id[0]} // context for price
);
@@ -444,7 +444,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
},
get_product_image: function(){
var product = this.get_product();
return product ? product.get('product_image_small') : undefined;
return product ? product.get('image_medium') : undefined;
},
get_product_weight: function(){
return this.weight || 0;
+2 -3
View File
@@ -83,7 +83,7 @@
<t t-name="CategoryButton">
<li class='category-button'>
<div class="category-img">
<img t-att-src="'data:image/gif;base64,'+ category.category_image_small" />
<img t-att-src="'data:image/gif;base64,'+ category.image_medium" />
</div>
<div class="category-name">
<t t-esc="category.name"/>
@@ -342,8 +342,7 @@
<li class='product'>
<a href="#">
<div class="product-img">
<img t-att-src="'data:image/gif;base64,'+ widget.model.get('product_image_small')" />
<img t-att-src="'data:image/gif;base64,'+ widget.model.get('image_medium')" />
<t t-if="!widget.model.get('to_weight')">
<span class="price-tag">
<t t-esc="widget.format_currency(widget.model.get('list_price'))"/>
File diff suppressed because one or more lines are too long
@@ -49,7 +49,7 @@
<t t-if="record.date_deadline.raw_value and record.date_deadline.raw_value lt (new Date())">
<span t-attf-class="oe_kanban_status oe_kaban_status_red"> </span>
</t>
<img t-att-src="kanban_image('res.users', 'avatar', record.user_id.raw_value[0])" t-att-title="record.user_id.value" width="24" height="24" class="oe_kanban_avatar"/>
<img t-att-src="kanban_image('res.users', 'image_small', record.user_id.raw_value[0])" t-att-title="record.user_id.value" width="24" height="24" class="oe_kanban_avatar"/>
</div>
</div>
</div>
+30 -1
View File
@@ -25,6 +25,7 @@ import decimal_precision as dp
import math
from _common import rounding
import re
import tools
from tools.translate import _
def is_pair(x):
@@ -490,6 +491,15 @@ class product_product(osv.osv):
return result
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):
result[obj.id] = tools.image_get_resized_images(obj.image)
return result
def _set_image(self, cr, uid, id, name, value, args, context=None):
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
_defaults = {
'active': lambda *a: 1,
'price_extra': lambda *a: 0.0,
@@ -523,7 +533,26 @@ class product_product(osv.osv):
'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 1024x1024 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 180x180 px image, with aspect ratio preserved. "\
"Use this field in form views or some kanban views."),
'image_small': fields.function(_get_image, fnct_inv=_set_image,
string="Small-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 50x50 px image, with aspect ratio preserved. "\
"Use this field anywhere a small image is required."),
'seller_info_id': fields.function(_calc_seller, type='many2one', relation="product.supplierinfo", multi="seller_info"),
'seller_delay': fields.function(_calc_seller, type='integer', string='Supplier Lead Time', multi="seller_info", help="This is the average delay in days between the purchase order confirmation and the reception of goods for this product and for the default supplier. It is used by the scheduler to order requests based on reordering delays."),
'seller_qty': fields.function(_calc_seller, type='float', string='Supplier Quantity', multi="seller_info", help="This is minimum quantity to purchase from Main Supplier."),
+3 -4
View File
@@ -64,8 +64,7 @@
<field name="arch" type="xml">
<form string="Product" version="7.0">
<sheet>
<field name="product_image" widget="image" class="oe_avatar oe_right"/>
<field name="image_medium" widget="image" class="oe_avatar oe_right"/>
<div class="oe_title">
<div class="oe_edit_only">
<label for="name" string="Product Name"/>
@@ -194,7 +193,7 @@
<kanban>
<field name="color"/>
<field name="type"/>
<field name="product_image"/>
<field name="image_medium"/>
<field name="list_price"/>
<templates>
<t t-name="kanban-box">
@@ -205,7 +204,7 @@
<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'">
+2 -2
View File
@@ -263,7 +263,7 @@
</div>
<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>
@@ -555,7 +555,7 @@
<a t-if="record.kanban_state.raw_value === 'blocked'" type="object" string="Blocked" name="set_kanban_state_normal" class="oe_kanban_status oe_kanban_status_red"> </a>
<a t-if="record.priority.raw_value == 1" type="object" string="Priority" name="set_normal_priority" class="oe_e oe_star_on">7</a>
<a t-if="record.priority.raw_value != 1" type="object" string="Priority" name="set_high_priority" class="oe_e oe_star_off">7</a>
<img t-att-src="kanban_image('res.users', 'avatar', record.user_id.raw_value[0])" t-att-title="record.user_id.value" width="24" height="24" class="oe_kanban_avatar"/>
<img t-att-src="kanban_image('res.users', 'image_small', record.user_id.raw_value[0])" t-att-title="record.user_id.value" width="24" height="24" class="oe_kanban_avatar"/>
</div>
<div class="oe_kanban_footer_left">
<span groups="project.group_time_work_estimation_tasks" title="Remaining hours">
+1 -1
View File
@@ -310,7 +310,7 @@
<t t-if="record.date_deadline.raw_value and record.date_deadline.raw_value lt (new Date())">
<span t-attf-class="oe_kanban_status oe_kaban_status_red"> </span>
</t>
<img t-att-src="kanban_image('res.users', 'avatar', record.user_id.raw_value[0])" t-att-title="record.user_id.value" width="24" height="24" class="oe_kanban_avatar"/>
<img t-att-src="kanban_image('res.users', 'image_small', record.user_id.raw_value[0])" t-att-title="record.user_id.value" width="24" height="24" class="oe_kanban_avatar"/>
</div>
</div>
</div>
+2 -2
View File
@@ -174,7 +174,7 @@
<kanban>
<field name="color"/>
<field name="type"/>
<field name="product_image"/>
<field name="image_medium"/>
<field name="list_price"/>
<field name="reception_count"/>
<field name="delivery_count"/>
@@ -182,7 +182,7 @@
<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>