summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2017-07-07 14:18:07 +0200
committerChristophe Simonis <chs@odoo.com>2017-07-07 14:18:07 +0200
commit0f2b2c4e2b99df8d68456016a4bea86e26c1c80e (patch)
tree37ecc505ddb81ec1cd048dba9655e03e3176c546
parent5241d479b222bc11ebd1c0ff41c38872a3fea8fd (diff)
parent514a1a76d81de3943f752ceaa5e487a2d25b9bb7 (diff)
[MERGE] forward port branch saas-15 up to 514a1a76d81
-rw-r--r--addons/account/models/partner.py9
-rw-r--r--addons/account/models/res_config.py4
-rw-r--r--addons/account/views/partner_view.xml11
-rw-r--r--addons/web_editor/static/src/js/base.js2
-rw-r--r--doc/cla/corporate/avoinsystems.md3
-rw-r--r--doc/cla/individual/pashute.md11
-rw-r--r--doc/reference/orm.rst10
-rw-r--r--odoo/tools/image.py5
-rw-r--r--odoo/tools/misc.py22
9 files changed, 71 insertions, 6 deletions
diff --git a/addons/account/models/partner.py b/addons/account/models/partner.py
index e826524eb57..a4bc99b8e7d 100644
--- a/addons/account/models/partner.py
+++ b/addons/account/models/partner.py
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
+from ast import literal_eval
from operator import itemgetter
import time
@@ -427,3 +428,11 @@ class ResPartner(models.Model):
return super(ResPartner, self)._commercial_fields() + \
['debit_limit', 'property_account_payable_id', 'property_account_receivable_id', 'property_account_position_id',
'property_payment_term_id', 'property_supplier_payment_term_id', 'last_time_entries_checked']
+
+ @api.multi
+ def action_view_partner_invoices(self):
+ self.ensure_one()
+ action = self.env.ref('account.action_invoice_refund_out_tree').read()[0]
+ action['domain'] = literal_eval(action['domain'])
+ action['domain'].append(('partner_id', 'child_of', self.id))
+ return action
diff --git a/addons/account/models/res_config.py b/addons/account/models/res_config.py
index eedcbe2b7a7..97362c5f41c 100644
--- a/addons/account/models/res_config.py
+++ b/addons/account/models/res_config.py
@@ -135,6 +135,6 @@ class AccountConfigSettings(models.TransientModel):
company = self.env['res.company'].browse(values.get('company_id'))
if company.currency_id.id == values.get('currency_id'):
values.pop('currency_id')
- if company.accounts_code_digits == vals.get('code_digits'):
- vals.pop('code_digits')
+ if company.accounts_code_digits == values.get('code_digits'):
+ values.pop('code_digits')
return super(AccountConfigSettings, self).create(values)
diff --git a/addons/account/views/partner_view.xml b/addons/account/views/partner_view.xml
index 84607ad971d..2f028d6f1c2 100644
--- a/addons/account/views/partner_view.xml
+++ b/addons/account/views/partner_view.xml
@@ -95,6 +95,17 @@
<field name="priority" eval="20"/>
<field name="groups_id" eval="[(4, ref('account.group_account_invoice'))]"/>
<field name="arch" type="xml">
+ <div name="button_box" position="inside">
+ <button type="object" class="oe_stat_button" icon="fa-pencil-square-o" name="action_view_partner_invoices"
+ attrs="{'invisible': [('customer', '=', False)]}">
+ <div class="o_form_field o_stat_info">
+ <span class="o_stat_value">
+ <field name="total_invoiced" widget='monetary' options="{'currency_field': 'currency_id'}"/>
+ </span>
+ <span class="o_stat_text">Invoiced</span>
+ </div>
+ </button>
+ </div>
<group name="container_row_2" position="inside">
<group string="Payments" name="banks">
<field name="currency_id" invisible="1"/>
diff --git a/addons/web_editor/static/src/js/base.js b/addons/web_editor/static/src/js/base.js
index e4e2fcd6cad..4368f6de274 100644
--- a/addons/web_editor/static/src/js/base.js
+++ b/addons/web_editor/static/src/js/base.js
@@ -36,7 +36,7 @@ data.ready = function () {
// TODO find a better way to find if we are in the backend or not
// We don't load translation if we are in the backend since it's already done by the webclient
if (!$(document).find('.o_web_client').length) {
- load_translations();
+ return load_translations();
}
});
} else if(all_ready.state() === "resolved") { // can add async template
diff --git a/doc/cla/corporate/avoinsystems.md b/doc/cla/corporate/avoinsystems.md
index 13209ca53a3..4009dc466e5 100644
--- a/doc/cla/corporate/avoinsystems.md
+++ b/doc/cla/corporate/avoinsystems.md
@@ -17,3 +17,6 @@ Svante Suominen svante.suominen@avoin.systems https://github.com/svantesuominen
Erno Iipponen erno.iipponen@avoin.systems https://github.com/iipponen
Tuomo Aura tuomo.aura@avoin.systems https://github.com/tuomoaura
Atte Isopuro atte.isopuro@avoin.systems https://github.com/aisopuro
+Mikko Närjänen mikko.narjanen@avoin.systems https://github.com/mtnarjan
+Toni Pesola toni.pesola@avoin.systems https://github.com/tonipes
+Santeri Valjakka santeri.valjakka@avoin.systems https://github.com/hegenator
diff --git a/doc/cla/individual/pashute.md b/doc/cla/individual/pashute.md
new file mode 100644
index 00000000000..e0dde9fed9a
--- /dev/null
+++ b/doc/cla/individual/pashute.md
@@ -0,0 +1,11 @@
+Israel, 2017-07-06
+
+I hereby agree to the terms of the Odoo Individual Contributor License
+Agreement v1.0.
+
+I declare that I am authorized and able to make this agreement and sign this
+declaration.
+
+Signed,
+
+Moshe Flam pashute@gmail.com https://github.com/pashute
diff --git a/doc/reference/orm.rst b/doc/reference/orm.rst
index 876d74f65cc..00b284f9cb2 100644
--- a/doc/reference/orm.rst
+++ b/doc/reference/orm.rst
@@ -45,14 +45,20 @@ Field access
------------
Recordsets provide an "Active Record" interface: model fields can be read and
-written directly from the record, but only on singletons (single-record
-recordsets). Setting a field's value triggers an update to the database::
+written directly from the record as attributes, but only on singletons
+(single-record recordsets).
+Field values can also be accessed like dict items, which is more elegant and
+safer than ``getattr()`` for dynamic field names.
+Setting a field's value triggers an update to the database::
>>> record.name
Example Name
>>> record.company_id.name
Company Name
>>> record.name = "Bob"
+ >>> field = "name"
+ >>> record[field]
+ Bob
Trying to read or write a field on multiple records will raise an error.
diff --git a/odoo/tools/image.py b/odoo/tools/image.py
index bacf6a9c999..0ff50967f0a 100644
--- a/odoo/tools/image.py
+++ b/odoo/tools/image.py
@@ -75,7 +75,7 @@ def image_resize_image(base64_source, size=(1024, 1024), encoding='base64', file
if image.size != size:
image = image_resize_and_sharpen(image, size)
- if image.mode not in ["1", "L", "P", "RGB", "RGBA"]:
+ if image.mode not in ["1", "L", "P", "RGB", "RGBA"] or (filetype == 'JPEG' and image.mode == 'RGBA'):
image = image.convert("RGB")
background_stream = StringIO.StringIO()
@@ -92,6 +92,7 @@ def image_resize_and_sharpen(image, size, preserve_aspect_ratio=False, factor=2.
:param preserve_aspect_ratio: boolean (default: False)
:param factor: Sharpen factor (default: 2.0)
"""
+ origin_mode = image.mode
if image.mode != 'RGBA':
image = image.convert('RGBA')
image.thumbnail(size, Image.ANTIALIAS)
@@ -102,6 +103,8 @@ def image_resize_and_sharpen(image, size, preserve_aspect_ratio=False, factor=2.
# create a transparent image for background and paste the image on it
image = Image.new('RGBA', size, (255, 255, 255, 0))
image.paste(resized_image, ((size[0] - resized_image.size[0]) / 2, (size[1] - resized_image.size[1]) / 2))
+ if image.mode != origin_mode:
+ image = image.convert(origin_mode)
return image
def image_save_for_web(image, fp=None, format=None):
diff --git a/odoo/tools/misc.py b/odoo/tools/misc.py
index 45ff5e28bbd..448ffdfed43 100644
--- a/odoo/tools/misc.py
+++ b/odoo/tools/misc.py
@@ -374,6 +374,28 @@ try:
except ImportError:
xlwt = None
+try:
+ import xlsxwriter
+
+ # add some sanitizations to respect the excel sheet name restrictions
+ # as the sheet name is often translatable, can not control the input
+ class PatchedXlsxWorkbook(xlsxwriter.Workbook):
+
+ # TODO when xlsxwriter bump to 0.9.8, add worksheet_class=None parameter instead of kw
+ def add_worksheet(self, name=None, **kw):
+ # invalid Excel character: []:*?/\
+ name = re.sub(r'[\[\]:*?/\\]', '', name)
+
+ # maximum size is 31 characters
+ name = name[:31]
+ return super(PatchedXlsxWorkbook, self).add_worksheet(name, **kw)
+
+ xlsxwriter.Workbook = PatchedXlsxWorkbook
+
+except ImportError:
+ xlsxwriter = None
+
+
def to_xml(s):
return s.replace('&','&amp;').replace('<','&lt;').replace('>','&gt;')