[MERGE] forward port of branch saas-9 up to 549daaa
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
@@ -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,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
|
|
||||||
|
|||||||
|
@@ -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
@@ -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
@@ -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
|
||||||
# --------------------------
|
# --------------------------
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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 = {
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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']
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user