[MERGE] forward port of branch saas-9 up to 549daaa

This commit is contained in:
Christophe Simonis
2016-04-05 19:27:34 +02:00
25 changed files with 258 additions and 232 deletions
+2
View File
@@ -123,6 +123,8 @@ class AccountFiscalPosition(models.Model):
if not country_id: if not country_id:
return False return False
base_domain = [('auto_apply', '=', True), ('vat_required', '=', vat_required)] base_domain = [('auto_apply', '=', True), ('vat_required', '=', vat_required)]
if self.env.context.get('force_company'):
base_domain.append(('company_id', '=', self.env.context.get('force_company')))
null_state_dom = state_domain = [('state_ids', '=', False)] null_state_dom = state_domain = [('state_ids', '=', False)]
null_zip_dom = zip_domain = [('zip_from', '=', 0), ('zip_to', '=', 0)] null_zip_dom = zip_domain = [('zip_from', '=', 0), ('zip_to', '=', 0)]
null_country_dom = [('country_id', '=', False), ('country_group_id', '=', False)] null_country_dom = [('country_id', '=', False), ('country_group_id', '=', False)]
@@ -234,7 +234,7 @@
<div class="col-xs-6 o_kanban_primary_right"> <div class="col-xs-6 o_kanban_primary_right">
<div class="row"> <div class="row">
<div class="col-xs-6"> <div class="col-xs-6">
<span title="Balance in Odoo">Balance in Odoo</span> <span title="Balance in Odoo">Balance in GL</span>
</div> </div>
<div class="col-xs-6 text-right"> <div class="col-xs-6 text-right">
<span><t t-esc="dashboard.account_balance"/></span> <span><t t-esc="dashboard.account_balance"/></span>
+2 -1
View File
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import cgi
import json import json
from openerp.http import Controller, route from openerp.http import Controller, route
@@ -15,4 +16,4 @@ class ImportController(Controller):
}, req.context) }, req.context)
return 'window.top.%s(%s)' % ( return 'window.top.%s(%s)' % (
jsonp, json.dumps({'result': written})) cgi.escape(jsonp), json.dumps({'result': written}))
@@ -2,12 +2,30 @@
-- PostgreSQL database dump -- PostgreSQL database dump
-- --
-- Dumped from database version 9.5.2
-- Dumped by pg_dump version 9.5.2
SET statement_timeout = 0; SET statement_timeout = 0;
SET lock_timeout = 0;
SET client_encoding = 'UTF8'; SET client_encoding = 'UTF8';
SET standard_conforming_strings = off; SET standard_conforming_strings = on;
SET check_function_bodies = false; SET check_function_bodies = false;
SET client_min_messages = warning; SET client_min_messages = warning;
SET escape_string_warning = off; SET row_security = off;
--
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: -
--
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
--
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: -
--
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
SET search_path = public, pg_catalog; SET search_path = public, pg_catalog;
@@ -16,7 +34,7 @@ SET default_tablespace = '';
SET default_with_oids = false; SET default_with_oids = false;
-- --
-- Name: companies; Type: TABLE; Schema: public; Owner: fp; Tablespace: -- Name: companies; Type: TABLE; Schema: public; Owner: -
-- --
CREATE TABLE companies ( CREATE TABLE companies (
@@ -25,38 +43,27 @@ CREATE TABLE companies (
); );
ALTER TABLE public.companies OWNER TO fp;
-- --
-- Name: companies_id_seq; Type: SEQUENCE; Schema: public; Owner: fp -- Name: companies_id_seq; Type: SEQUENCE; Schema: public; Owner: -
-- --
CREATE SEQUENCE companies_id_seq CREATE SEQUENCE companies_id_seq
START WITH 1 START WITH 1
INCREMENT BY 1 INCREMENT BY 1
NO MAXVALUE
NO MINVALUE NO MINVALUE
NO MAXVALUE
CACHE 1; CACHE 1;
ALTER TABLE public.companies_id_seq OWNER TO fp;
-- --
-- Name: companies_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: fp -- Name: companies_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
-- --
ALTER SEQUENCE companies_id_seq OWNED BY companies.id; ALTER SEQUENCE companies_id_seq OWNED BY companies.id;
-- --
-- Name: companies_id_seq; Type: SEQUENCE SET; Schema: public; Owner: fp -- Name: persons; Type: TABLE; Schema: public; Owner: -
--
SELECT pg_catalog.setval('companies_id_seq', 3, true);
--
-- Name: persons; Type: TABLE; Schema: public; Owner: fp; Tablespace:
-- --
CREATE TABLE persons ( CREATE TABLE persons (
@@ -66,52 +73,41 @@ CREATE TABLE persons (
); );
ALTER TABLE public.persons OWNER TO fp;
-- --
-- Name: persons_id_seq; Type: SEQUENCE; Schema: public; Owner: fp -- Name: persons_id_seq; Type: SEQUENCE; Schema: public; Owner: -
-- --
CREATE SEQUENCE persons_id_seq CREATE SEQUENCE persons_id_seq
START WITH 1 START WITH 1
INCREMENT BY 1 INCREMENT BY 1
NO MAXVALUE
NO MINVALUE NO MINVALUE
NO MAXVALUE
CACHE 1; CACHE 1;
ALTER TABLE public.persons_id_seq OWNER TO fp;
-- --
-- Name: persons_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: fp -- Name: persons_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
-- --
ALTER SEQUENCE persons_id_seq OWNED BY persons.id; ALTER SEQUENCE persons_id_seq OWNED BY persons.id;
-- --
-- Name: persons_id_seq; Type: SEQUENCE SET; Schema: public; Owner: fp -- Name: id; Type: DEFAULT; Schema: public; Owner: -
--
SELECT pg_catalog.setval('persons_id_seq', 4, true);
--
-- Name: id; Type: DEFAULT; Schema: public; Owner: fp
-- --
ALTER TABLE ONLY companies ALTER COLUMN id SET DEFAULT nextval('companies_id_seq'::regclass); ALTER TABLE ONLY companies ALTER COLUMN id SET DEFAULT nextval('companies_id_seq'::regclass);
-- --
-- Name: id; Type: DEFAULT; Schema: public; Owner: fp -- Name: id; Type: DEFAULT; Schema: public; Owner: -
-- --
ALTER TABLE ONLY persons ALTER COLUMN id SET DEFAULT nextval('persons_id_seq'::regclass); ALTER TABLE ONLY persons ALTER COLUMN id SET DEFAULT nextval('persons_id_seq'::regclass);
-- --
-- Data for Name: companies; Type: TABLE DATA; Schema: public; Owner: fp -- Data for Name: companies; Type: TABLE DATA; Schema: public; Owner: -
-- --
COPY companies (id, company_name) FROM stdin; COPY companies (id, company_name) FROM stdin;
@@ -122,19 +118,33 @@ COPY companies (id, company_name) FROM stdin;
-- --
-- Data for Name: persons; Type: TABLE DATA; Schema: public; Owner: fp -- Name: companies_id_seq; Type: SEQUENCE SET; Schema: public; Owner: -
--
SELECT pg_catalog.setval('companies_id_seq', 3, true);
--
-- Data for Name: persons; Type: TABLE DATA; Schema: public; Owner: -
-- --
COPY persons (id, company_id, person_name) FROM stdin; COPY persons (id, company_id, person_name) FROM stdin;
1 1 Fabien 1 1 Fabien
2 1 Laurence 2 1 Laurence
3 2 Eric 3 2 Eric
4 3 Ramsy 4 3 Ramzy
\. \.
-- --
-- Name: companies_pkey; Type: CONSTRAINT; Schema: public; Owner: fp; Tablespace: -- Name: persons_id_seq; Type: SEQUENCE SET; Schema: public; Owner: -
--
SELECT pg_catalog.setval('persons_id_seq', 4, true);
--
-- Name: companies_pkey; Type: CONSTRAINT; Schema: public; Owner: -
-- --
ALTER TABLE ONLY companies ALTER TABLE ONLY companies
@@ -142,13 +152,23 @@ ALTER TABLE ONLY companies
-- --
-- Name: persons_company_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: fp -- Name: persons_company_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
-- --
ALTER TABLE ONLY persons ALTER TABLE ONLY persons
ADD CONSTRAINT persons_company_id_fkey FOREIGN KEY (company_id) REFERENCES companies(id); ADD CONSTRAINT persons_company_id_fkey FOREIGN KEY (company_id) REFERENCES companies(id);
--
-- Name: public; Type: ACL; Schema: -; Owner: -
--
REVOKE ALL ON SCHEMA public FROM PUBLIC;
REVOKE ALL ON SCHEMA public FROM postgres;
GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO PUBLIC;
-- --
-- PostgreSQL database dump complete -- PostgreSQL database dump complete
-- --
@@ -1,10 +1,6 @@
Order Date,Order Reference,Supplier,Destination,Pricelist,Order Lines / Product,Order Lines / Quantity "Order Date","Order Reference",Vendor,"Order Lines / Product","Order Lines / Description","Order Lines / Quantity","Order Lines / Product Unit of Measure","Order Lines / Unit Price","Order Lines / Scheduled Date"
2012-12-15,PO00008,ASUSTeK,Stock,Default Purchase Pricelist,ADPT,20 2016-12-15,PO00008,ASUSTeK,ADPT,ADPT,20.0,"Unit(s)",13.0,2016-12-15
,,,,,CARD,30 ,,,CARD,CARD,30,"Unit(s)",876.0,2016-12-15
,,,,,C-Case,40 ,,,C-Case,C-Case,40,"Unit(s)",20.0,2016-12-15
2012-12-15,PO00009,Axelor,Stock,Default Purchase Pricelist,CD,5 2016-12-15,PO00009,Camptocamp,CD,CD,5,"Unit(s)",18.4,2016-12-15
,,,,,CPUa8,15 ,,,CPUa8,CPUa8,15,"Unit(s)",1910.0,2016-12-15
2012-12-15,PO000010,China Export,Stock,Default Purchase Pricelist,HDD SH-1,10
,,,,,HDD SH-2,20
,,,,,LAP-CUS,35
,,,,,LAP-E5,40
1 Order Date Order Reference Supplier Vendor Destination Order Lines / Product Pricelist Order Lines / Description Order Lines / Quantity Order Lines / Product Unit of Measure Order Lines / Unit Price Order Lines / Scheduled Date
2 2012-12-15 2016-12-15 PO00008 ASUSTeK ASUSTeK Stock ADPT Default Purchase Pricelist ADPT 20 20.0 Unit(s) 13.0 2016-12-15
3 CARD CARD 30 Unit(s) 876.0 2016-12-15
4 C-Case C-Case 40 Unit(s) 20.0 2016-12-15
5 2012-12-15 2016-12-15 PO00009 Axelor Camptocamp Stock CD Default Purchase Pricelist CD 5 Unit(s) 18.4 2016-12-15
6 CPUa8 CPUa8 15 Unit(s) 1910.0 2016-12-15
2012-12-15 PO000010 China Export Stock HDD SH-1 Default Purchase Pricelist 10
HDD SH-2 20
LAP-CUS 35
LAP-E5 40
@@ -1,6 +1,3 @@
"Order Reference","Supplier","Destination","Pricelist","Order Lines / Product","Order Lines / Quantity" "Order Reference","Vendor"
"PO000020","ASUSTeK","Stock","Default Purchase Pricelist","ADPT",20 "PO000020","ASUSTeK"
,,,,"CARD",30 "PO000021","Camptocamp"
,,,,"C-Case",40
"PO000021","Axelor","Stock","Default Purchase Pricelist","CD",5
,,,,"CPUa8",15
1 Order Reference Supplier Vendor Destination Pricelist Order Lines / Product Order Lines / Quantity
2 PO000020 ASUSTeK ASUSTeK Stock Default Purchase Pricelist ADPT 20
3 PO000021 Camptocamp CARD 30
C-Case 40
PO000021 Axelor Stock Default Purchase Pricelist CD 5
CPUa8 15
+24
View File
@@ -1372,6 +1372,30 @@ class calendar_event(osv.Model):
('user_id', '=', uid), ('user_id', '=', uid),
] ]
@api.multi
def _get_message_unread(self):
id_map = {x: calendar_id2real_id(x) for x in self.ids}
real = self.browse(set(id_map.values()))
super(calendar_event, real)._get_message_unread()
for event in self:
if event.id == id_map[event.id]:
continue
rec = self.browse(id_map[event.id])
event.message_unread_counter = rec.message_unread_counter
event.message_unread = rec.message_unread
@api.multi
def _get_message_needaction(self):
id_map = {x: calendar_id2real_id(x) for x in self.ids}
real = self.browse(set(id_map.values()))
super(calendar_event, real)._get_message_needaction()
for event in self:
if event.id == id_map[event.id]:
continue
rec = self.browse(id_map[event.id])
event.message_needaction_counter = rec.message_needaction_counter
event.message_needaction = rec.message_needaction
@api.cr_uid_ids_context @api.cr_uid_ids_context
def message_post(self, cr, uid, thread_id, context=None, **kwargs): def message_post(self, cr, uid, thread_id, context=None, **kwargs):
if isinstance(thread_id, basestring): if isinstance(thread_id, basestring):
+10 -16
View File
@@ -142,30 +142,24 @@ class fleet_vehicle_model_brand(osv.Model):
image = openerp.fields.Binary("Logo", attachment=True, image = openerp.fields.Binary("Logo", attachment=True,
help="This field holds the image used as logo for the brand, limited to 1024x1024px.") help="This field holds the image used as logo for the brand, limited to 1024x1024px.")
image_medium = openerp.fields.Binary("Medium-sized image", image_medium = openerp.fields.Binary("Medium-sized image", attachment=True,
compute='_compute_images', inverse='_inverse_image_medium', store=True, attachment=True,
help="Medium-sized logo of the brand. It is automatically "\ help="Medium-sized logo of the brand. It is automatically "\
"resized as a 128x128px image, with aspect ratio preserved. "\ "resized as a 128x128px image, with aspect ratio preserved. "\
"Use this field in form views or some kanban views.") "Use this field in form views or some kanban views.")
image_small = openerp.fields.Binary("Small-sized image", image_small = openerp.fields.Binary("Small-sized image", attachment=True,
compute='_compute_images', inverse='_inverse_image_small', store=True, attachment=True,
help="Small-sized logo of the brand. It is automatically "\ help="Small-sized logo of the brand. It is automatically "\
"resized as a 64x64px image, with aspect ratio preserved. "\ "resized as a 64x64px image, with aspect ratio preserved. "\
"Use this field anywhere a small image is required.") "Use this field anywhere a small image is required.")
@openerp.api.depends('image') @openerp.api.model
def _compute_images(self): def create(self, vals):
for rec in self: tools.image_resize_images(vals)
rec.image_medium = tools.image_resize_image_medium(rec.image) return super(fleet_vehicle_model_brand, self).create(vals)
rec.image_small = tools.image_resize_image_small(rec.image)
def _inverse_image_medium(self): @openerp.api.multi
for rec in self: def write(self, vals):
rec.image = tools.image_resize_image_big(rec.image_medium) tools.image_resize_images(vals)
return super(fleet_vehicle_model_brand, self).write(vals)
def _inverse_image_small(self):
for rec in self:
rec.image = tools.image_resize_image_big(rec.image_small)
class fleet_vehicle(osv.Model): class fleet_vehicle(osv.Model):
+12 -18
View File
@@ -172,31 +172,15 @@ class hr_employee(osv.osv):
# image: all image fields are base64 encoded and PIL-supported # image: all image fields are base64 encoded and PIL-supported
image = openerp.fields.Binary("Photo", attachment=True, image = openerp.fields.Binary("Photo", attachment=True,
help="This field holds the image used as photo for the employee, limited to 1024x1024px.") help="This field holds the image used as photo for the employee, limited to 1024x1024px.")
image_medium = openerp.fields.Binary("Medium-sized photo", image_medium = openerp.fields.Binary("Medium-sized photo", attachment=True,
compute='_compute_images', inverse='_inverse_image_medium', store=True, attachment=True,
help="Medium-sized photo of the employee. It is automatically "\ help="Medium-sized photo of the employee. It is automatically "\
"resized as a 128x128px image, with aspect ratio preserved. "\ "resized as a 128x128px image, with aspect ratio preserved. "\
"Use this field in form views or some kanban views.") "Use this field in form views or some kanban views.")
image_small = openerp.fields.Binary("Small-sized photo", image_small = openerp.fields.Binary("Small-sized photo", attachment=True,
compute='_compute_images', inverse='_inverse_image_small', store=True, attachment=True,
help="Small-sized photo of the employee. It is automatically "\ help="Small-sized photo of the employee. It is automatically "\
"resized as a 64x64px image, with aspect ratio preserved. "\ "resized as a 64x64px image, with aspect ratio preserved. "\
"Use this field anywhere a small image is required.") "Use this field anywhere a small image is required.")
@api.depends('image')
def _compute_images(self):
for rec in self:
rec.image_medium = tools.image_resize_image_medium(rec.image)
rec.image_small = tools.image_resize_image_small(rec.image)
def _inverse_image_medium(self):
for rec in self:
rec.image = tools.image_resize_image_big(rec.image_medium)
def _inverse_image_small(self):
for rec in self:
rec.image = tools.image_resize_image_big(rec.image_small)
def _get_default_image(self, cr, uid, context=None): def _get_default_image(self, cr, uid, context=None):
image_path = get_module_resource('hr', 'static/src/img', 'default_image.png') image_path = get_module_resource('hr', 'static/src/img', 'default_image.png')
return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64')) return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
@@ -207,6 +191,16 @@ class hr_employee(osv.osv):
'color': 0, 'color': 0,
} }
@api.model
def create(self, vals):
tools.image_resize_images(vals)
return super(hr_employee, self).create(vals)
@api.multi
def write(self, vals):
tools.image_resize_images(vals)
return super(hr_employee, self).write(vals)
def unlink(self, cr, uid, ids, context=None): def unlink(self, cr, uid, ids, context=None):
resource_ids = [] resource_ids = []
for employee in self.browse(cr, uid, ids, context=context): for employee in self.browse(cr, uid, ids, context=context):
@@ -48,13 +48,11 @@ class ImLivechatChannel(models.Model):
# images fields # images fields
image = fields.Binary('Image', default=_default_image, attachment=True, image = fields.Binary('Image', default=_default_image, attachment=True,
help="This field holds the image used as photo for the group, limited to 1024x1024px.") help="This field holds the image used as photo for the group, limited to 1024x1024px.")
image_medium = fields.Binary('Medium', image_medium = fields.Binary('Medium', attachment=True,
compute='_compute_image', store=True, attachment=True,
help="Medium-sized photo of the group. It is automatically "\ help="Medium-sized photo of the group. It is automatically "\
"resized as a 128x128px image, with aspect ratio preserved. "\ "resized as a 128x128px image, with aspect ratio preserved. "\
"Use this field in form views or some kanban views.") "Use this field in form views or some kanban views.")
image_small = fields.Binary('Thumbnail', image_small = fields.Binary('Thumbnail', attachment=True,
compute='_compute_image', store=True, attachment=True,
help="Small-sized photo of the group. It is automatically "\ help="Small-sized photo of the group. It is automatically "\
"resized as a 64x64px image, with aspect ratio preserved. "\ "resized as a 64x64px image, with aspect ratio preserved. "\
"Use this field anywhere a small image is required.") "Use this field anywhere a small image is required.")
@@ -69,12 +67,6 @@ class ImLivechatChannel(models.Model):
def _are_you_inside(self): def _are_you_inside(self):
self.are_you_inside = bool(self.env.uid in [u.id for u in self.user_ids]) self.are_you_inside = bool(self.env.uid in [u.id for u in self.user_ids])
@api.one
@api.depends('image')
def _compute_image(self):
self.image_medium = tools.image_resize_image_medium(self.image)
self.image_small = tools.image_resize_image_small(self.image)
@api.multi @api.multi
def _compute_script_external(self): def _compute_script_external(self):
view = self.env['ir.model.data'].get_object('im_livechat', 'external_loader') view = self.env['ir.model.data'].get_object('im_livechat', 'external_loader')
@@ -111,6 +103,16 @@ class ImLivechatChannel(models.Model):
else: else:
record.rating_percentage_satisfaction = -1 record.rating_percentage_satisfaction = -1
@api.model
def create(self, vals):
tools.image_resize_images(vals)
return super(ImLivechatChannel, self).create(vals)
@api.multi
def write(self, vals):
tools.image_resize_images(vals)
return super(ImLivechatChannel, self).write(vals)
# -------------------------- # --------------------------
# Action Methods # Action Methods
# -------------------------- # --------------------------
+4 -16
View File
@@ -69,13 +69,11 @@ class Channel(models.Model):
# image: all image fields are base64 encoded and PIL-supported # image: all image fields are base64 encoded and PIL-supported
image = fields.Binary("Photo", default=_get_default_image, attachment=True, image = fields.Binary("Photo", default=_get_default_image, attachment=True,
help="This field holds the image used as photo for the group, limited to 1024x1024px.") help="This field holds the image used as photo for the group, limited to 1024x1024px.")
image_medium = fields.Binary('Medium-sized photo', image_medium = fields.Binary('Medium-sized photo', attachment=True,
compute='_get_image', inverse='_set_image_medium', store=True, attachment=True,
help="Medium-sized photo of the group. It is automatically " help="Medium-sized photo of the group. It is automatically "
"resized as a 128x128px image, with aspect ratio preserved. " "resized as a 128x128px image, with aspect ratio preserved. "
"Use this field in form views or some kanban views.") "Use this field in form views or some kanban views.")
image_small = fields.Binary('Small-sized photo', image_small = fields.Binary('Small-sized photo', attachment=True,
compute='_get_image', inverse='_set_image_small', store=True, attachment=True,
help="Small-sized photo of the group. It is automatically " help="Small-sized photo of the group. It is automatically "
"resized as a 64x64px image, with aspect ratio preserved. " "resized as a 64x64px image, with aspect ratio preserved. "
"Use this field anywhere a small image is required.") "Use this field anywhere a small image is required.")
@@ -100,20 +98,9 @@ class Channel(models.Model):
for record in self: for record in self:
record.is_member = record in membership_ids record.is_member = record in membership_ids
@api.one
@api.depends('image')
def _get_image(self):
self.image_medium = tools.image_resize_image_medium(self.image)
self.image_small = tools.image_resize_image_small(self.image)
def _set_image_medium(self):
self.image = tools.image_resize_image_big(self.image_medium)
def _set_image_small(self):
self.image = tools.image_resize_image_big(self.image_small)
@api.model @api.model
def create(self, vals): def create(self, vals):
tools.image_resize_images(vals)
# Create channel and alias # Create channel and alias
channel = super(Channel, self.with_context( channel = super(Channel, self.with_context(
alias_model_name=self._name, alias_parent_model_name=self._name, mail_create_nolog=True, mail_create_nosubscribe=True) alias_model_name=self._name, alias_parent_model_name=self._name, mail_create_nolog=True, mail_create_nosubscribe=True)
@@ -147,6 +134,7 @@ class Channel(models.Model):
@api.multi @api.multi
def write(self, vals): def write(self, vals):
tools.image_resize_images(vals)
result = super(Channel, self).write(vals) result = super(Channel, self).write(vals)
if vals.get('group_ids'): if vals.get('group_ids'):
self._subscribe_users() self._subscribe_users()
+13 -19
View File
@@ -3,7 +3,7 @@ import logging
import openerp import openerp
from openerp.osv import osv, fields from openerp.osv import osv, fields
from openerp.tools import float_round, float_repr, image_get_resized_images, image_resize_image_big from openerp.tools import float_round, float_repr, image_resize_images
from openerp.tools.translate import _ from openerp.tools.translate import _
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@@ -97,31 +97,15 @@ class PaymentAcquirer(osv.Model):
image = openerp.fields.Binary("Image", attachment=True, image = openerp.fields.Binary("Image", attachment=True,
help="This field holds the image used for this provider, limited to 1024x1024px") help="This field holds the image used for this provider, limited to 1024x1024px")
image_medium = openerp.fields.Binary("Medium-sized image", image_medium = openerp.fields.Binary("Medium-sized image", attachment=True,
compute='_compute_images', inverse='_inverse_image_medium', store=True, attachment=True,
help="Medium-sized image of this provider. It is automatically "\ help="Medium-sized image of this provider. It is automatically "\
"resized as a 128x128px image, with aspect ratio preserved. "\ "resized as a 128x128px image, with aspect ratio preserved. "\
"Use this field in form views or some kanban views.") "Use this field in form views or some kanban views.")
image_small = openerp.fields.Binary("Small-sized image", image_small = openerp.fields.Binary("Small-sized image", attachment=True,
compute='_compute_images', inverse='_inverse_image_small', store=True, attachment=True,
help="Small-sized image of this provider. It is automatically "\ help="Small-sized image of this provider. It is automatically "\
"resized as a 64x64px image, with aspect ratio preserved. "\ "resized as a 64x64px image, with aspect ratio preserved. "\
"Use this field anywhere a small image is required.") "Use this field anywhere a small image is required.")
@openerp.api.depends('image')
def _compute_images(self):
for rec in self:
rec.image_medium = openerp.tools.image_resize_image_medium(rec.image)
rec.image_small = openerp.tools.image_resize_image_small(rec.image)
def _inverse_image_medium(self):
for rec in self:
rec.image = openerp.tools.image_resize_image_big(rec.image_medium)
def _inverse_image_small(self):
for rec in self:
rec.image = openerp.tools.image_resize_image_big(rec.image_small)
_defaults = { _defaults = {
'company_id': lambda self, cr, uid, obj, ctx=None: self.pool['res.users'].browse(cr, uid, uid).company_id.id, 'company_id': lambda self, cr, uid, obj, ctx=None: self.pool['res.users'].browse(cr, uid, uid).company_id.id,
'environment': 'test', 'environment': 'test',
@@ -145,6 +129,16 @@ class PaymentAcquirer(osv.Model):
(_check_required_if_provider, 'Required fields not filled', ['required for this provider']), (_check_required_if_provider, 'Required fields not filled', ['required for this provider']),
] ]
@openerp.api.model
def create(self, vals):
image_resize_images(vals)
return super(PaymentAcquirer, self).create(vals)
@openerp.api.multi
def write(self, vals):
image_resize_images(vals)
return super(PaymentAcquirer, self).write(vals)
def get_form_action_url(self, cr, uid, id, context=None): def get_form_action_url(self, cr, uid, id, context=None):
""" Returns the form action URL, for form-based acquirer implementations. """ """ Returns the form action URL, for form-based acquirer implementations. """
acquirer = self.browse(cr, uid, id, context=context) acquirer = self.browse(cr, uid, id, context=context)
+10 -17
View File
@@ -2,7 +2,6 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details. # Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, tools, _ from odoo import api, fields, models, tools, _
class PosCategory(models.Model): class PosCategory(models.Model):
_name = "pos.category" _name = "pos.category"
_description = "Public Category" _description = "Public Category"
@@ -23,30 +22,24 @@ class PosCategory(models.Model):
# buttons have consistent styling. # buttons have consistent styling.
image = fields.Binary(attachment=True, image = fields.Binary(attachment=True,
help="This field holds the image used as image for the cateogry, limited to 1024x1024px.") help="This field holds the image used as image for the cateogry, limited to 1024x1024px.")
image_medium = fields.Binary(string="Medium-sized image", image_medium = fields.Binary(string="Medium-sized image", attachment=True,
compute='_compute_images', inverse='_inverse_image_medium', store=True, attachment=True,
help="Medium-sized image of the category. It is automatically " help="Medium-sized image of the category. It is automatically "
"resized as a 128x128px image, with aspect ratio preserved. " "resized as a 128x128px image, with aspect ratio preserved. "
"Use this field in form views or some kanban views.") "Use this field in form views or some kanban views.")
image_small = fields.Binary(string="Small-sized image", image_small = fields.Binary(string="Small-sized image", attachment=True,
compute='_compute_images', inverse='_inverse_image_small', store=True, attachment=True,
help="Small-sized image of the category. It is automatically " help="Small-sized image of the category. It is automatically "
"resized as a 64x64px image, with aspect ratio preserved. " "resized as a 64x64px image, with aspect ratio preserved. "
"Use this field anywhere a small image is required.") "Use this field anywhere a small image is required.")
@api.depends('image') @api.model
def _compute_images(self): def create(self, vals):
for rec in self: tools.image_resize_images(vals)
rec.image_medium = tools.image_resize_image_medium(rec.image) return super(PosCategory, self).create(vals)
rec.image_small = tools.image_resize_image_small(rec.image)
def _inverse_image_medium(self): @api.multi
for rec in self: def write(self, vals):
rec.image = tools.image_resize_image_big(rec.image_medium) tools.image_resize_images(vals)
return super(PosCategory, self).write(vals)
def _inverse_image_small(self):
for rec in self:
rec.image = tools.image_resize_image_big(rec.image_small)
@api.multi @api.multi
def name_get(self): def name_get(self):
+4 -18
View File
@@ -537,31 +537,15 @@ class product_template(osv.osv):
# image: all image fields are base64 encoded and PIL-supported # image: all image fields are base64 encoded and PIL-supported
image = openerp.fields.Binary("Image", attachment=True, image = openerp.fields.Binary("Image", attachment=True,
help="This field holds the image used as image for the product, limited to 1024x1024px.") help="This field holds the image used as image for the product, limited to 1024x1024px.")
image_medium = openerp.fields.Binary("Medium-sized image", image_medium = openerp.fields.Binary("Medium-sized image", attachment=True,
compute='_compute_images', inverse='_inverse_image_medium', store=True, attachment=True,
help="Medium-sized image of the product. It is automatically "\ help="Medium-sized image of the product. It is automatically "\
"resized as a 128x128px image, with aspect ratio preserved, "\ "resized as a 128x128px image, with aspect ratio preserved, "\
"only when the image exceeds one of those sizes. Use this field in form views or some kanban views.") "only when the image exceeds one of those sizes. Use this field in form views or some kanban views.")
image_small = openerp.fields.Binary("Small-sized image", image_small = openerp.fields.Binary("Small-sized image", attachment=True,
compute='_compute_images', inverse='_inverse_image_small', store=True, attachment=True,
help="Small-sized image of the product. It is automatically "\ help="Small-sized image of the product. It is automatically "\
"resized as a 64x64px image, with aspect ratio preserved. "\ "resized as a 64x64px image, with aspect ratio preserved. "\
"Use this field anywhere a small image is required.") "Use this field anywhere a small image is required.")
@api.depends('image')
def _compute_images(self):
for rec in self:
rec.image_medium = tools.image_resize_image_medium(rec.image, avoid_if_small=True)
rec.image_small = tools.image_resize_image_small(rec.image)
def _inverse_image_medium(self):
for rec in self:
rec.image = tools.image_resize_image_big(rec.image_medium)
def _inverse_image_small(self):
for rec in self:
rec.image = tools.image_resize_image_big(rec.image_small)
def _price_get(self, cr, uid, products, ptype='list_price', context=None): def _price_get(self, cr, uid, products, ptype='list_price', context=None):
if context is None: if context is None:
context = {} context = {}
@@ -687,6 +671,7 @@ class product_template(osv.osv):
def create(self, cr, uid, vals, context=None): def create(self, cr, uid, vals, context=None):
''' Store the initial standard price in order to be able to retrieve the cost of a product template for a given date''' ''' Store the initial standard price in order to be able to retrieve the cost of a product template for a given date'''
tools.image_resize_images(vals)
product_template_id = super(product_template, self).create(cr, uid, vals, context=context) product_template_id = super(product_template, self).create(cr, uid, vals, context=context)
if not context or "create_product_product" not in context: if not context or "create_product_product" not in context:
self.create_variant_ids(cr, uid, [product_template_id], context=context) self.create_variant_ids(cr, uid, [product_template_id], context=context)
@@ -710,6 +695,7 @@ class product_template(osv.osv):
return product_template_id return product_template_id
def write(self, cr, uid, ids, vals, context=None): def write(self, cr, uid, ids, vals, context=None):
tools.image_resize_images(vals)
res = super(product_template, self).write(cr, uid, ids, vals, context=context) res = super(product_template, self).write(cr, uid, ids, vals, context=context)
if 'attribute_line_ids' in vals or vals.get('active'): if 'attribute_line_ids' in vals or vals.get('active'):
self.create_variant_ids(cr, uid, ids, context=context) self.create_variant_ids(cr, uid, ids, context=context)
+7 -4
View File
@@ -348,14 +348,17 @@ class PurchaseOrder(models.Model):
# this product. We limit to 10 the number of suppliers for a product to avoid the mess that # this product. We limit to 10 the number of suppliers for a product to avoid the mess that
# could be caused for some generic products ("Miscellaneous"). # could be caused for some generic products ("Miscellaneous").
for line in self.order_line: for line in self.order_line:
if self.partner_id not in line.product_id.seller_ids.mapped('name') and len(line.product_id.seller_ids) <= 10: # Do not add a contact as a supplier
partner = self.partner_id if not self.partner_id.parent_id else self.partner_id.parent_id
if partner not in line.product_id.seller_ids.mapped('name') and len(line.product_id.seller_ids) <= 10:
currency = partner.property_purchase_currency_id or self.env.user.company_id.currency_id
supplierinfo = { supplierinfo = {
'name': self.partner_id.id, 'name': partner.id,
'sequence': max(line.product_id.seller_ids.mapped('sequence')) + 1 if line.product_id.seller_ids else 1, 'sequence': max(line.product_id.seller_ids.mapped('sequence')) + 1 if line.product_id.seller_ids else 1,
'product_uom': line.product_uom.id, 'product_uom': line.product_uom.id,
'min_qty': 0.0, 'min_qty': 0.0,
'price': line.price_unit, 'price': self.currency_id.compute(line.price_unit, currency),
'currency_id': self.partner_id.currency_id.id, 'currency_id': currency.id,
'delay': 0, 'delay': 0,
} }
vals = { vals = {
+8 -6
View File
@@ -15,13 +15,15 @@ class CrmTeam(models.Model):
def _get_default_team_id(self, user_id=None): def _get_default_team_id(self, user_id=None):
if not user_id: if not user_id:
user_id = self.env.uid user_id = self.env.uid
team_id = self.env['crm.team'].search([ team_id = self.env['crm.team'].search(
'|', ['|', ('user_id', '=', user_id), ('member_ids', 'in', [user_id])],
('user_id', '=', user_id), limit=1)
('member_ids', 'in', [user_id])], if not team_id and 'default_team_id' in self.env.context:
limit=1) or self.env.ref('sales_team.team_sales_department', raise_if_not_found=False)
if not team_id and self.env.context.get('default_team_id'):
team_id = self.env['crm.team'].browse(self.env.context.get('default_team_id')) team_id = self.env['crm.team'].browse(self.env.context.get('default_team_id'))
if not team_id and 'default_team_id' not in self.env.context:
default_team_id = self.env.ref('sales_team.team_sales_department', raise_if_not_found=False)
if default_team_id and (self.env.context.get('default_type') != 'lead' or default_team_id.use_leads):
team_id = default_team_id
return team_id return team_id
name = fields.Char('Sales Team', required=True, translate=True) name = fields.Char('Sales Team', required=True, translate=True)
+2 -4
View File
@@ -336,9 +336,8 @@ var PropertiesMixin = _.extend({}, EventDispatcherMixin, {
// remove this, or move it elsewhere. Also, learn OO programming. // remove this, or move it elsewhere. Also, learn OO programming.
if (key === 'value' && self.field && self.field.type === 'float' && tmp && val){ if (key === 'value' && self.field && self.field.type === 'float' && tmp && val){
var digits = self.field.digits; var digits = self.field.digits;
if (digits !== 0){ if (_.isArray(digits)) {
digits = digits ? digits[1] : 2; if (utils.float_is_zero(tmp - val, digits[1])) {
if (utils.float_is_zero(tmp - val, digits)) {
return; return;
} }
} }
@@ -366,4 +365,3 @@ return {
}; };
}); });
+1 -1
View File
@@ -1155,7 +1155,7 @@ ListView.List = Class.extend( /** @lends instance.web.ListView.List# */{
record.set(column.id, names[0]); record.set(column.id, names[0]);
}); });
} }
} else if (column.type === 'many2many' || column.type === 'one2many') { } else if (column.type === 'many2many') {
value = record.get(column.id); value = record.get(column.id);
// non-resolved (string) m2m values are arrays // non-resolved (string) m2m values are arrays
if (value instanceof Array && !_.isEmpty(value) if (value instanceof Array && !_.isEmpty(value)
@@ -86,6 +86,9 @@ var CalendarView = View.extend({
this.title = (this.options.action)? this.options.action.name : ''; this.title = (this.options.action)? this.options.action.name : '';
this.shown = $.Deferred(); this.shown = $.Deferred();
self.current_start = null;
self.current_end = null;
self.previous_ids = [];
}, },
set_default_options: function(options) { set_default_options: function(options) {
@@ -729,11 +732,25 @@ var CalendarView = View.extend({
); );
} }
} }
// read_slice is launched uncoditionally, when quickly
// changing the range in the calender view, all of
// these RPC calls will race each other. Because of
// this we keep track of the current range of the
// calendar view.
self.current_start = start;
self.current_end = end;
self.dataset.read_slice(_.keys(self.fields), { self.dataset.read_slice(_.keys(self.fields), {
offset: 0, offset: 0,
domain: event_domain, domain: event_domain,
context: context, context: context,
}).done(function(events) { }).done(function(events) {
// undo the read_slice if it the range has changed since it launched
if (self.current_start.getTime() != start.getTime() || self.current_end.getTime() != end.getTime()) {
self.dataset.ids = self.previous_ids;
return;
}
self.previous_ids = self.dataset.ids.slice();
if (self.dataset.index === null) { if (self.dataset.index === null) {
if (events.length) { if (events.length) {
self.dataset.index = 0; self.dataset.index = 0;
+10 -16
View File
@@ -60,30 +60,24 @@ class product_public_category(osv.osv):
# In this case, the default image is set by the js code. # In this case, the default image is set by the js code.
image = openerp.fields.Binary("Image", attachment=True, image = openerp.fields.Binary("Image", attachment=True,
help="This field holds the image used as image for the category, limited to 1024x1024px.") help="This field holds the image used as image for the category, limited to 1024x1024px.")
image_medium = openerp.fields.Binary("Medium-sized image", image_medium = openerp.fields.Binary("Medium-sized image", attachment=True,
compute='_compute_images', inverse='_inverse_image_medium', store=True, attachment=True,
help="Medium-sized image of the category. It is automatically "\ help="Medium-sized image of the category. It is automatically "\
"resized as a 128x128px image, with aspect ratio preserved. "\ "resized as a 128x128px image, with aspect ratio preserved. "\
"Use this field in form views or some kanban views.") "Use this field in form views or some kanban views.")
image_small = openerp.fields.Binary("Small-sized image", image_small = openerp.fields.Binary("Small-sized image", attachment=True,
compute='_compute_images', inverse='_inverse_image_small', store=True, attachment=True,
help="Small-sized image of the category. It is automatically "\ help="Small-sized image of the category. It is automatically "\
"resized as a 64x64px image, with aspect ratio preserved. "\ "resized as a 64x64px image, with aspect ratio preserved. "\
"Use this field anywhere a small image is required.") "Use this field anywhere a small image is required.")
@openerp.api.depends('image') @openerp.api.model
def _compute_images(self): def create(self, vals):
for rec in self: tools.image_resize_images(vals)
rec.image_medium = tools.image_resize_image_medium(rec.image) return super(product_public_category, self).create(vals)
rec.image_small = tools.image_resize_image_small(rec.image)
def _inverse_image_medium(self): @openerp.api.multi
for rec in self: def write(self, vals):
rec.image = tools.image_resize_image_big(rec.image_medium) tools.image_resize_images(vals)
return super(product_public_category, self).write(vals)
def _inverse_image_small(self):
for rec in self:
rec.image = tools.image_resize_image_big(rec.image_small)
class product_template(osv.Model): class product_template(osv.Model):
_inherit = ["product.template", "website.seo.metadata", 'website.published.mixin', 'rating.mixin'] _inherit = ["product.template", "website.seo.metadata", 'website.published.mixin', 'rating.mixin']
+20 -8
View File
@@ -12,7 +12,7 @@ from openerp import SUPERUSER_ID, tools
from openerp.exceptions import AccessError from openerp.exceptions import AccessError
from openerp.osv import fields,osv from openerp.osv import fields,osv
from openerp.tools.translate import _ from openerp.tools.translate import _
from openerp.tools.misc import ustr from openerp.tools.misc import ustr, html_escape
from openerp.tools.mimetypes import guess_mimetype from openerp.tools.mimetypes import guess_mimetype
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@@ -199,14 +199,26 @@ class ir_attachment(osv.osv):
:param values : dict of values to create or write an ir_attachment :param values : dict of values to create or write an ir_attachment
:return mime : string indicating the mimetype, or application/octet-stream by default :return mime : string indicating the mimetype, or application/octet-stream by default
""" """
mimetype = 'application/octet-stream' mimetype = None
if values.get('datas_fname'): if values.get('mimetype'):
mimetype = values['mimetype']
if not mimetype and values.get('datas_fname'):
mimetype = mimetypes.guess_type(values['datas_fname'])[0] mimetype = mimetypes.guess_type(values['datas_fname'])[0]
if values.get('url'): if not mimetype and values.get('url'):
mimetype = mimetypes.guess_type(values['url'])[0] mimetype = mimetypes.guess_type(values['url'])[0]
if values.get('datas') and (not mimetype or mimetype == 'application/octet-stream'): if values.get('datas') and (not mimetype or mimetype == 'application/octet-stream'):
mimetype = guess_mimetype(values['datas'].decode('base64')) mimetype = guess_mimetype(values['datas'].decode('base64'))
return mimetype return mimetype or 'application/octet-stream'
def _check_contents(self, cr, uid, values, context=None):
mimetype = values['mimetype'] = self._compute_mimetype(values)
needs_escape = 'htm' in mimetype or '/ht' in mimetype # hta, html, xhtml, etc.
if needs_escape and not self.pool['res.users']._is_admin(cr, uid, [uid]):
if 'datas' in values:
values['datas'] = html_escape(values['datas'].decode('base64')).encode('base64')
else:
values['mimetype'] = 'text/plain'
return values
def _index(self, cr, uid, bin_data, datas_fname, file_type): def _index(self, cr, uid, bin_data, datas_fname, file_type):
""" compute the index content of the given filename, or binary data. """ compute the index content of the given filename, or binary data.
@@ -382,6 +394,8 @@ class ir_attachment(osv.osv):
# remove computed field depending of datas # remove computed field depending of datas
for field in ['file_size', 'checksum']: for field in ['file_size', 'checksum']:
vals.pop(field, False) vals.pop(field, False)
if 'mimetype' in vals or 'datas' in vals:
vals = self._check_contents(cr, uid, vals, context=context)
return super(ir_attachment, self).write(cr, uid, ids, vals, context) return super(ir_attachment, self).write(cr, uid, ids, vals, context)
def copy(self, cr, uid, id, default=None, context=None): def copy(self, cr, uid, id, default=None, context=None):
@@ -409,9 +423,7 @@ class ir_attachment(osv.osv):
# remove computed field depending of datas # remove computed field depending of datas
for field in ['file_size', 'checksum']: for field in ['file_size', 'checksum']:
values.pop(field, False) values.pop(field, False)
# if mimetype not given, compute it ! values = self._check_contents(cr, uid, values, context=context)
if 'mimetype' not in values:
values['mimetype'] = self._compute_mimetype(values)
self.check(cr, uid, [], mode='write', context=context, values=values) self.check(cr, uid, [], mode='write', context=context, values=values)
return super(ir_attachment, self).create(cr, uid, values, context) return super(ir_attachment, self).create(cr, uid, values, context)
+6 -18
View File
@@ -198,13 +198,11 @@ class Partner(models.Model, FormatAddress):
# image: all image fields are base64 encoded and PIL-supported # image: all image fields are base64 encoded and PIL-supported
image = fields.Binary("Image", attachment=True, image = fields.Binary("Image", attachment=True,
help="This field holds the image used as avatar for this contact, limited to 1024x1024px",) help="This field holds the image used as avatar for this contact, limited to 1024x1024px",)
image_medium = fields.Binary("Medium-sized image", image_medium = fields.Binary("Medium-sized image", attachment=True,
compute='_compute_images', inverse='_inverse_image_medium', store=True, attachment=True,
help="Medium-sized image of this contact. It is automatically "\ help="Medium-sized image of this contact. It is automatically "\
"resized as a 128x128px image, with aspect ratio preserved. "\ "resized as a 128x128px image, with aspect ratio preserved. "\
"Use this field in form views or some kanban views.") "Use this field in form views or some kanban views.")
image_small = fields.Binary("Small-sized image", image_small = fields.Binary("Small-sized image", attachment=True,
compute='_compute_images', inverse='_inverse_image_small', store=True, attachment=True,
help="Small-sized image of this contact. It is automatically "\ help="Small-sized image of this contact. It is automatically "\
"resized as a 64x64px image, with aspect ratio preserved. "\ "resized as a 64x64px image, with aspect ratio preserved. "\
"Use this field anywhere a small image is required.") "Use this field anywhere a small image is required.")
@@ -238,20 +236,6 @@ class Partner(models.Model, FormatAddress):
else: else:
partner.commercial_partner_id = partner.parent_id.commercial_partner_id partner.commercial_partner_id = partner.parent_id.commercial_partner_id
@api.depends('image')
def _compute_images(self):
for rec in self:
rec.image_medium = tools.image_resize_image_medium(rec.image)
rec.image_small = tools.image_resize_image_small(rec.image)
def _inverse_image_medium(self):
for rec in self:
rec.image = tools.image_resize_image_big(rec.image_medium)
def _inverse_image_small(self):
for rec in self:
rec.image = tools.image_resize_image_big(rec.image_small)
@api.model @api.model
def _get_default_image(self, partner_type, is_company, parent_id): def _get_default_image(self, partner_type, is_company, parent_id):
if getattr(threading.currentThread(), 'testing', False) or self._context.get('install_mode'): if getattr(threading.currentThread(), 'testing', False) or self._context.get('install_mode'):
@@ -484,10 +468,13 @@ class Partner(models.Model, FormatAddress):
companies = set(user.company_id for user in partner.user_ids) companies = set(user.company_id for user in partner.user_ids)
if len(companies) > 1 or company not in companies: if len(companies) > 1 or company not in companies:
raise UserError(_("You can not change the company as the partner/user has multiple user linked with different companies.")) raise UserError(_("You can not change the company as the partner/user has multiple user linked with different companies."))
tools.image_resize_images(vals)
result = super(Partner, self).write(vals) result = super(Partner, self).write(vals)
for partner in self: for partner in self:
partner._fields_sync(vals) partner._fields_sync(vals)
if any(u.has_group('base.group_user') for u in partner.user_ids):
self.env['res.users'].check_access_rights('write')
return result return result
@api.model @api.model
@@ -501,6 +488,7 @@ class Partner(models.Model, FormatAddress):
partner = super(Partner, self).create(vals) partner = super(Partner, self).create(vals)
partner._fields_sync(vals) partner._fields_sync(vals)
partner._handle_first_contact_creation() partner._handle_first_contact_creation()
tools.image_resize_images(vals)
return partner return partner
@api.multi @api.multi
+3 -3
View File
@@ -174,7 +174,7 @@ class Users(models.Model):
__uid_cache = defaultdict(dict) # {dbname: {uid: password}} __uid_cache = defaultdict(dict) # {dbname: {uid: password}}
# User can write on a few of his own fields (but not his groups for example) # User can write on a few of his own fields (but not his groups for example)
SELF_WRITEABLE_FIELDS = ['password', 'signature', 'action_id', 'company_id', 'email', 'name', 'image', 'image_medium', 'image_small', 'lang', 'tz'] SELF_WRITEABLE_FIELDS = ['signature', 'action_id', 'company_id', 'email', 'name', 'image', 'image_medium', 'image_small', 'lang', 'tz']
# User can read a few of his own fields # User can read a few of his own fields
SELF_READABLE_FIELDS = ['signature', 'company_id', 'login', 'email', 'name', 'image', 'image_medium', 'image_small', 'lang', 'tz', 'tz_offset', 'groups_id', 'partner_id', '__last_update', 'action_id'] SELF_READABLE_FIELDS = ['signature', 'company_id', 'login', 'email', 'name', 'image', 'image_medium', 'image_small', 'lang', 'tz', 'tz_offset', 'groups_id', 'partner_id', '__last_update', 'action_id']
@@ -510,8 +510,8 @@ class Users(models.Model):
""" """
self.check(self._cr.dbname, self._uid, old_passwd) self.check(self._cr.dbname, self._uid, old_passwd)
if new_passwd: if new_passwd:
# do not use self.env.user here, since it has uid=SUPERUSER_ID # use self.env.user here, because it has uid=SUPERUSER_ID
return self.browse(self._uid).write({'password': new_passwd}) return self.env.user.write({'password': new_passwd})
raise UserError(_("Setting empty passwords is not allowed for security reasons!")) raise UserError(_("Setting empty passwords is not allowed for security reasons!"))
@api.multi @api.multi
+4 -1
View File
@@ -418,7 +418,10 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
t0 = time.time() t0 = time.time()
t0_sql = openerp.sql_db.sql_counter t0_sql = openerp.sql_db.sql_counter
if openerp.tools.config['test_enable']: if openerp.tools.config['test_enable']:
cr.execute("SELECT name FROM ir_module_module WHERE state='installed'") if update_module:
cr.execute("SELECT name FROM ir_module_module WHERE state='installed' and name = ANY(%s)", (processed_modules,))
else:
cr.execute("SELECT name FROM ir_module_module WHERE state='installed'")
for module_name in cr.fetchall(): for module_name in cr.fetchall():
report.record_result(openerp.modules.module.run_unit_tests(module_name[0], cr.dbname, position=runs_post_install)) report.record_result(openerp.modules.module.run_unit_tests(module_name[0], cr.dbname, position=runs_post_install))
_logger.log(25, "All post-tested in %.2fs, %s queries", time.time() - t0, openerp.sql_db.sql_counter - t0_sql) _logger.log(25, "All post-tested in %.2fs, %s queries", time.time() - t0, openerp.sql_db.sql_counter - t0_sql)
+18
View File
@@ -256,6 +256,24 @@ def image_get_resized_images(base64_source, return_big=False, return_medium=True
return_dict[small_name] = image_resize_image_small(base64_source, avoid_if_small=avoid_resize_small) return_dict[small_name] = image_resize_image_small(base64_source, avoid_if_small=avoid_resize_small)
return return_dict return return_dict
def image_resize_images(vals, big_name='image', medium_name='image_medium', small_name='image_small'):
""" Update ``vals`` with image fields resized as expected. """
if big_name in vals:
vals.update(image_get_resized_images(vals[big_name],
return_big=True, return_medium=True, return_small=True,
big_name=big_name, medium_name=medium_name, small_name=small_name,
avoid_resize_big=True, avoid_resize_medium=False, avoid_resize_small=False))
elif medium_name in vals:
vals.update(image_get_resized_images(vals[medium_name],
return_big=True, return_medium=True, return_small=True,
big_name=big_name, medium_name=medium_name, small_name=small_name,
avoid_resize_big=True, avoid_resize_medium=True, avoid_resize_small=False))
elif small_name in vals:
vals.update(image_get_resized_images(vals[small_name],
return_big=True, return_medium=True, return_small=True,
big_name=big_name, medium_name=medium_name, small_name=small_name,
avoid_resize_big=True, avoid_resize_medium=True, avoid_resize_small=True))
if __name__=="__main__": if __name__=="__main__":
import sys import sys