[MERGE] forward port branch saas-15 up to 514a1a76d8
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from ast import literal_eval
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@@ -427,3 +428,11 @@ class ResPartner(models.Model):
|
|||||||
return super(ResPartner, self)._commercial_fields() + \
|
return super(ResPartner, self)._commercial_fields() + \
|
||||||
['debit_limit', 'property_account_payable_id', 'property_account_receivable_id', 'property_account_position_id',
|
['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']
|
'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
|
||||||
|
|||||||
@@ -135,6 +135,6 @@ class AccountConfigSettings(models.TransientModel):
|
|||||||
company = self.env['res.company'].browse(values.get('company_id'))
|
company = self.env['res.company'].browse(values.get('company_id'))
|
||||||
if company.currency_id.id == values.get('currency_id'):
|
if company.currency_id.id == values.get('currency_id'):
|
||||||
values.pop('currency_id')
|
values.pop('currency_id')
|
||||||
if company.accounts_code_digits == vals.get('code_digits'):
|
if company.accounts_code_digits == values.get('code_digits'):
|
||||||
vals.pop('code_digits')
|
values.pop('code_digits')
|
||||||
return super(AccountConfigSettings, self).create(values)
|
return super(AccountConfigSettings, self).create(values)
|
||||||
|
|||||||
@@ -95,6 +95,17 @@
|
|||||||
<field name="priority" eval="20"/>
|
<field name="priority" eval="20"/>
|
||||||
<field name="groups_id" eval="[(4, ref('account.group_account_invoice'))]"/>
|
<field name="groups_id" eval="[(4, ref('account.group_account_invoice'))]"/>
|
||||||
<field name="arch" type="xml">
|
<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 name="container_row_2" position="inside">
|
||||||
<group string="Payments" name="banks">
|
<group string="Payments" name="banks">
|
||||||
<field name="currency_id" invisible="1"/>
|
<field name="currency_id" invisible="1"/>
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ data.ready = function () {
|
|||||||
// TODO find a better way to find if we are in the backend or not
|
// 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
|
// 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) {
|
if (!$(document).find('.o_web_client').length) {
|
||||||
load_translations();
|
return load_translations();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if(all_ready.state() === "resolved") { // can add async template
|
} else if(all_ready.state() === "resolved") { // can add async template
|
||||||
|
|||||||
@@ -17,3 +17,6 @@ Svante Suominen svante.suominen@avoin.systems https://github.com/svantesuominen
|
|||||||
Erno Iipponen erno.iipponen@avoin.systems https://github.com/iipponen
|
Erno Iipponen erno.iipponen@avoin.systems https://github.com/iipponen
|
||||||
Tuomo Aura tuomo.aura@avoin.systems https://github.com/tuomoaura
|
Tuomo Aura tuomo.aura@avoin.systems https://github.com/tuomoaura
|
||||||
Atte Isopuro atte.isopuro@avoin.systems https://github.com/aisopuro
|
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
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -45,14 +45,20 @@ Field access
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
Recordsets provide an "Active Record" interface: model fields can be read and
|
Recordsets provide an "Active Record" interface: model fields can be read and
|
||||||
written directly from the record, but only on singletons (single-record
|
written directly from the record as attributes, but only on singletons
|
||||||
recordsets). Setting a field's value triggers an update to the database::
|
(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
|
>>> record.name
|
||||||
Example Name
|
Example Name
|
||||||
>>> record.company_id.name
|
>>> record.company_id.name
|
||||||
Company Name
|
Company Name
|
||||||
>>> record.name = "Bob"
|
>>> record.name = "Bob"
|
||||||
|
>>> field = "name"
|
||||||
|
>>> record[field]
|
||||||
|
Bob
|
||||||
|
|
||||||
Trying to read or write a field on multiple records will raise an error.
|
Trying to read or write a field on multiple records will raise an error.
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -75,7 +75,7 @@ def image_resize_image(base64_source, size=(1024, 1024), encoding='base64', file
|
|||||||
|
|
||||||
if image.size != size:
|
if image.size != size:
|
||||||
image = image_resize_and_sharpen(image, 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")
|
image = image.convert("RGB")
|
||||||
|
|
||||||
background_stream = StringIO.StringIO()
|
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 preserve_aspect_ratio: boolean (default: False)
|
||||||
:param factor: Sharpen factor (default: 2.0)
|
:param factor: Sharpen factor (default: 2.0)
|
||||||
"""
|
"""
|
||||||
|
origin_mode = image.mode
|
||||||
if image.mode != 'RGBA':
|
if image.mode != 'RGBA':
|
||||||
image = image.convert('RGBA')
|
image = image.convert('RGBA')
|
||||||
image.thumbnail(size, Image.ANTIALIAS)
|
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
|
# create a transparent image for background and paste the image on it
|
||||||
image = Image.new('RGBA', size, (255, 255, 255, 0))
|
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))
|
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
|
return image
|
||||||
|
|
||||||
def image_save_for_web(image, fp=None, format=None):
|
def image_save_for_web(image, fp=None, format=None):
|
||||||
|
|||||||
@@ -374,6 +374,28 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
xlwt = None
|
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):
|
def to_xml(s):
|
||||||
return s.replace('&','&').replace('<','<').replace('>','>')
|
return s.replace('&','&').replace('<','<').replace('>','>')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user