[MERGE] forward port branch 11.0 up to 2787de8c68
This commit is contained in:
@@ -57,7 +57,7 @@
|
||||
<span class="label label-default"><i class="fa fa-fw fa-remove"></i><span class="hidden-xs"> Cancelled</span></span>
|
||||
</t>
|
||||
</td>
|
||||
<td><span t-field="invoice.residual" t-options='{"widget": "monetary", "display_currency": invoice.currency_id}'/></td>
|
||||
<td><span t-esc="-invoice.residual if invoice.type == 'out_refund' else invoice.residual" t-options='{"widget": "monetary", "display_currency": invoice.currency_id}'/></td>
|
||||
</tr>
|
||||
</t>
|
||||
</table></div>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
</xpath>
|
||||
<xpath expr="//t[@t-foreach='invoices']/tr/td[last()]" position="before">
|
||||
<td>
|
||||
<a t-if="invoice.state == 'open'" t-att-href="'/my/invoices/%s#portal_pay' % invoice.id" alt="Pay Now" class="btn btn-xs btn-primary">
|
||||
<a t-if="invoice.state == 'open' and invoice.type == 'out_invoice'" t-att-href="'/my/invoices/%s#portal_pay' % invoice.id" alt="Pay Now" class="btn btn-xs btn-primary">
|
||||
<i class="fa fa-arrow-circle-right"/><span class='hidden-xs'> Pay Now</span>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
@@ -1237,7 +1237,12 @@ class Meeting(models.Model):
|
||||
def _rrule_parse(self, rule_str, data, date_start):
|
||||
day_list = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su']
|
||||
rrule_type = ['yearly', 'monthly', 'weekly', 'daily']
|
||||
rule = rrule.rrulestr(rule_str, dtstart=fields.Datetime.from_string(date_start))
|
||||
ddate = fields.Datetime.from_string(date_start)
|
||||
if 'Z' in rule_str and not ddate.tzinfo:
|
||||
ddate = ddate.replace(tzinfo=pytz.timezone('UTC'))
|
||||
rule = rrule.rrulestr(rule_str, dtstart=ddate)
|
||||
else:
|
||||
rule = rrule.rrulestr(rule_str, dtstart=ddate)
|
||||
|
||||
if rule._freq > 0 and rule._freq < 4:
|
||||
data['rrule_type'] = rrule_type[rule._freq]
|
||||
|
||||
@@ -194,7 +194,6 @@
|
||||
<group>
|
||||
<field name="privacy"/>
|
||||
<field name="show_as"/>
|
||||
<field name="rrule" invisible="1" readonly="0" />
|
||||
<field name="recurrent_id" invisible="1" />
|
||||
</group>
|
||||
</group>
|
||||
|
||||
@@ -159,7 +159,7 @@ class StockPicking(models.Model):
|
||||
def send_to_shipper(self):
|
||||
self.ensure_one()
|
||||
res = self.carrier_id.send_shipping(self)[0]
|
||||
if self.carrier_id.free_over and self.sale_id._compute_amount_total_without_delivery() >= self.carrier_id.amount:
|
||||
if self.carrier_id.free_over and self.sale_id and self.sale_id._compute_amount_total_without_delivery() >= self.carrier_id.amount:
|
||||
res['exact_price'] = 0.0
|
||||
self.carrier_price = res['exact_price']
|
||||
self.carrier_tracking_ref = res['tracking_number']
|
||||
|
||||
@@ -47,10 +47,14 @@ class GeoIPResolver(object):
|
||||
r = self._db.city(ip)
|
||||
except (ValueError, geoip2.errors.AddressNotFoundError):
|
||||
return {}
|
||||
# Compatibility with Legacy database.
|
||||
# Some ips cannot be located to a specific country. Legacy DB used to locate them in
|
||||
# continent instead of country. Do the same to not change behavior of existing code.
|
||||
country = r.country if r.country.geoname_id else r.continent
|
||||
return {
|
||||
'city': r.city.name,
|
||||
'country_code': r.country.iso_code,
|
||||
'country_name': r.country.name,
|
||||
'country_code': country.iso_code,
|
||||
'country_name': country.name,
|
||||
'region': r.subdivisions[0].iso_code if r.subdivisions else None,
|
||||
'time_zone': r.location.time_zone,
|
||||
}
|
||||
|
||||
@@ -1748,6 +1748,8 @@ class MailThread(models.AbstractModel):
|
||||
continue
|
||||
if isinstance(content, pycompat.text_type):
|
||||
content = content.encode('utf-8')
|
||||
elif content is None:
|
||||
continue
|
||||
data_attach = {
|
||||
'name': name,
|
||||
'datas': base64.b64encode(content),
|
||||
|
||||
@@ -14,6 +14,7 @@ from werkzeug import urls
|
||||
from odoo import api, fields, models, tools, _
|
||||
from odoo.addons.payment.models.payment_acquirer import ValidationError
|
||||
from odoo.addons.payment_adyen.controllers.main import AdyenController
|
||||
from odoo.tools.pycompat import to_native
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -192,7 +193,7 @@ class TxAdyen(models.Model):
|
||||
shasign_check = tx.acquirer_id._adyen_generate_merchant_sig_sha256('out', data)
|
||||
else:
|
||||
shasign_check = tx.acquirer_id._adyen_generate_merchant_sig('out', data)
|
||||
if shasign_check != data.get('merchantSig'):
|
||||
if to_native(shasign_check) != to_native(data.get('merchantSig')):
|
||||
error_msg = _('Adyen: invalid merchantSig, received %s, computed %s') % (data.get('merchantSig'), shasign_check)
|
||||
_logger.warning(error_msg)
|
||||
raise ValidationError(error_msg)
|
||||
|
||||
@@ -175,7 +175,7 @@ class PosOrder(models.Model):
|
||||
'comment': self.note or '',
|
||||
# considering partner's sale pricelist's currency
|
||||
'currency_id': self.pricelist_id.currency_id.id,
|
||||
'user_id': self.env.uid,
|
||||
'user_id': self.user_id.id,
|
||||
}
|
||||
|
||||
@api.model
|
||||
|
||||
@@ -1172,9 +1172,11 @@ var ClientListScreenWidget = ScreenWidget.extend({
|
||||
var order = this.pos.get_order();
|
||||
if( this.has_client_changed() ){
|
||||
var default_fiscal_position_id = _.findWhere(this.pos.fiscal_positions, {'id': this.pos.config.default_fiscal_position_id[0]});
|
||||
if ( this.new_client && this.new_client.property_account_position_id ) {
|
||||
var client_fiscal_position_id = _.findWhere(this.pos.fiscal_positions, {'id': this.new_client.property_account_position_id[0]});
|
||||
order.fiscal_position = client_fiscal_position_id || default_fiscal_position_id;
|
||||
if ( this.new_client ) {
|
||||
if (this.new_client.property_account_position_id ){
|
||||
var client_fiscal_position_id = _.findWhere(this.pos.fiscal_positions, {'id': this.new_client.property_account_position_id[0]});
|
||||
order.fiscal_position = client_fiscal_position_id || default_fiscal_position_id;
|
||||
}
|
||||
order.set_pricelist(_.findWhere(this.pos.pricelists, {'id': this.new_client.property_product_pricelist[0]}) || this.pos.default_pricelist);
|
||||
} else {
|
||||
order.fiscal_position = default_fiscal_position_id;
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<tr t-foreach='products' t-as='line'>
|
||||
<td><t t-esc="line['product_name']" /></td>
|
||||
<t t-set="internal_reference" t-value="line['code'] and '[%s] ' % line['code'] or ''" />
|
||||
<td><t t-esc="internal_reference" /><t t-esc="line['product_name']" /></td>
|
||||
<td>
|
||||
<t t-esc="line['quantity']" />
|
||||
<t t-if='line["uom"] != "Unit(s)"'>
|
||||
|
||||
@@ -1060,10 +1060,10 @@ class ProcurementRule(models.Model):
|
||||
'partner_id': partner.id,
|
||||
'picking_type_id': self.picking_type_id.id,
|
||||
'company_id': values['company_id'].id,
|
||||
'currency_id': partner.property_purchase_currency_id.id or self.env.user.company_id.currency_id.id,
|
||||
'currency_id': partner.with_context(force_company=values['company_id'].id).property_purchase_currency_id.id or self.env.user.company_id.currency_id.id,
|
||||
'dest_address_id': values.get('partner_dest_id', False) and values['partner_dest_id'].id,
|
||||
'origin': origin,
|
||||
'payment_term_id': partner.property_supplier_payment_term_id.id,
|
||||
'payment_term_id': partner.with_context(force_company=values['company_id'].id).property_supplier_payment_term_id.id,
|
||||
'date_order': purchase_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
'fiscal_position_id': fpos,
|
||||
'group_id': group
|
||||
|
||||
@@ -57,6 +57,7 @@ class PosSaleReport(models.Model):
|
||||
(cr.date_end IS NULL OR cr.date_end > COALESCE(so.date_order, now())))
|
||||
LEFT JOIN product_uom u on (u.id=sol.product_uom)
|
||||
LEFT JOIN product_uom u2 on (u2.id=pt.uom_id)
|
||||
WHERE so.state != 'cancel'
|
||||
""" % self.env['res.currency']._select_companies_rates()
|
||||
return so_str
|
||||
|
||||
|
||||
@@ -186,4 +186,5 @@ class SaleAdvancePaymentInv(models.TransientModel):
|
||||
'invoice_policy': 'order',
|
||||
'property_account_income_id': self.deposit_account_id.id,
|
||||
'taxes_id': [(6, 0, self.deposit_taxes_id.ids)],
|
||||
'company_id': False,
|
||||
}
|
||||
|
||||
@@ -19,6 +19,11 @@ class TestSaleTimesheet(TestSale):
|
||||
# after the 6 june of current year.
|
||||
self.env.ref('base.rateUSDbis').unlink()
|
||||
|
||||
# Make sure the company is in USD
|
||||
self.env.cr.execute(
|
||||
"UPDATE res_company SET currency_id = %s WHERE id = %s",
|
||||
[self.env.ref('base.USD').id, self.env.user.company_id.id])
|
||||
|
||||
# create project
|
||||
self.project = self.env['project.project'].create({
|
||||
'name': 'Project for my timesheets',
|
||||
|
||||
@@ -290,4 +290,145 @@ X-Attachment-Id: ii_151b51a290ed6a91
|
||||
R0lGODdhAgACALMAAAAAAP///wAAAP//AP8AAP+AAAD/AAAAAAAA//8A/wAAAP+AgAAAAAAAAAAA
|
||||
AAAAACwAAAAAAgACAAAEA3DJFQA7
|
||||
--001a11416b9e9b229a05272b7052--
|
||||
"""
|
||||
"""
|
||||
|
||||
MAIL_EML_ATTACHMENT = """Subject: Re: test attac
|
||||
From: Anon <anon@odoo.com>
|
||||
To: anon@gmail.com
|
||||
References: <f3b9f8f8-28fa-2543-cab2-7aa68f679ebb@odoo.com>
|
||||
Message-ID: <cb7eaf62-58dc-2017-148c-305d0c78892f@odoo.com>
|
||||
Date: Wed, 14 Mar 2018 14:26:58 +0100
|
||||
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101
|
||||
Thunderbird/52.6.0
|
||||
MIME-Version: 1.0
|
||||
In-Reply-To: <f3b9f8f8-28fa-2543-cab2-7aa68f679ebb@odoo.com>
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="------------A6B5FD5F68F4D73ECD739009"
|
||||
Content-Language: en-US
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
--------------A6B5FD5F68F4D73ECD739009
|
||||
Content-Type: text/plain; charset=utf-8; format=flowed
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
|
||||
|
||||
On 14/03/18 14:20, Anon wrote:
|
||||
> Some nice content
|
||||
>
|
||||
|
||||
|
||||
--------------A6B5FD5F68F4D73ECD739009
|
||||
Content-Type: message/rfc822;
|
||||
name="original_msg.eml"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: attachment;
|
||||
filename="original_msg.eml"
|
||||
|
||||
Delivered-To: anon2@gmail1.openerp.com
|
||||
Received: by 10.46.1.170 with SMTP id f42csp2379722lji;
|
||||
Mon, 5 Mar 2018 01:19:23 -0800 (PST)
|
||||
X-Google-Smtp-Source: AG47ELsYTlAcblMxfnaEENQuF+MFoac5Q07wieyw0cybq/qOX4+DmayqoQILkiWT+NiTOcnr/ACO
|
||||
X-Received: by 10.28.154.213 with SMTP id c204mr7237750wme.64.1520241563503;
|
||||
Mon, 05 Mar 2018 01:19:23 -0800 (PST)
|
||||
ARC-Seal: i=1; a=rsa-sha256; t=1520241563; cv=none;
|
||||
d=google.com; s=arc-20160816;
|
||||
b=BqgMSbqmbpYW1ZtfGTVjj/654MBmabw4XadNZEaI96hDaub6N6cP8Guu3PoxscI9os
|
||||
0OLYVP1s/B+Vv9rIzulCwHyHsgnX+aTxGYepTDN6x8SA9Qeb9aQoNSVvQLryTAoGpaFr
|
||||
vXhw8aPWyr28edE03TDFA/s7X65Bf6dV5zJdMiUPVqGkfYfcTHMf3nDER5vk8vQj7tve
|
||||
Cfyy0h9vLU9RSEtdFwmlEkLmgT9NQ3GDf0jQ97eMXPgR2q6duCPoMcz15KlWOno53xgH
|
||||
EiV7aIZ5ZMN/m+/2xt3br/ubJ5euFojWhDnHUZoaqd08TCSQPd4fFCCx75MjDeCnwYMn
|
||||
iKSg==
|
||||
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816;
|
||||
h=content-language:mime-version:user-agent:date:message-id:subject
|
||||
:from:to:dkim-signature:arc-authentication-results;
|
||||
bh=/UIFqhjCCbwBLsI4w7YY98QH6G/wxe+2W4bbMDCskjM=;
|
||||
b=Wv5jt+usnSgWI96GaZWUN8/VKl1drueDpU/4gkyX/iK4d6S4CuSDjwYAc3guz/TjeW
|
||||
GoKCqT30IGZoStpXQbuLry7ezXNK+Fp8MJKN2n/x5ClJWHxIsxIGlP2QC3TO8RI0P5o0
|
||||
GXG9izW93q1ubkdPJFt3unSjjwSYf5XVQAZQtRm9xKjqA+lbtFbsnbjJ4wgYBURnD8ma
|
||||
Qxb2xsxXDelaZvtdlzHRDn5SEkbqhcCclEYw6oRLpVQFZeYtPxcCleVybtj2owJxdaLp
|
||||
7wXuo/gpYe6E2cPuS2opei8AzjEhYTNzlYXTPvaoxCCTTjfGTaPv22TeRDehuIXngSEl
|
||||
Nmmw==
|
||||
ARC-Authentication-Results: i=1; mx.google.com;
|
||||
dkim=pass header.i=@odoo.com header.s=mail header.b=MCzhjB9b;
|
||||
spf=pass (google.com: domain of soup@odoo.com designates 149.202.180.44 as permitted sender) smtp.mailfrom=soup@odoo.com;
|
||||
dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=odoo.com
|
||||
Return-Path: <soup@odoo.com>
|
||||
Received: from mail2.odoo.com (mail2.odoo.com. [149.202.180.44])
|
||||
by mx.google.com with ESMTPS id y4si4279200wmy.148.2018.03.05.01.19.22
|
||||
(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
|
||||
Mon, 05 Mar 2018 01:19:23 -0800 (PST)
|
||||
Received-SPF: pass (google.com: domain of soup@odoo.com designates 149.202.180.44 as permitted sender) client-ip=149.202.180.44;
|
||||
Authentication-Results: mx.google.com;
|
||||
dkim=pass header.i=@odoo.com header.s=mail header.b=MCzhjB9b;
|
||||
spf=pass (google.com: domain of soup@odoo.com designates 149.202.180.44 as permitted sender) smtp.mailfrom=soup@odoo.com;
|
||||
dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=odoo.com
|
||||
Received: from [10.10.31.24] (unknown [91.183.114.50])
|
||||
(Authenticated sender: soup)
|
||||
by mail2.odoo.com (Postfix) with ESMTPSA id 7B571A4085
|
||||
for <what@odoo.com>; Mon, 5 Mar 2018 10:19:21 +0100 (CET)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=odoo.com; s=mail;
|
||||
t=1520241562; bh=L2r7Sp/vjogIdM1k8H9zDGDjnhKolsTTLLjndnFC4Jc=;
|
||||
h=To:From:Subject:Date:From;
|
||||
b=MCzhjB9bnsrJ3uKjq+GjujFxmtrq3fc7Vv7Vg2C72EPKnkxgqy6yPjWKtXbBlaiT3
|
||||
YjKI24aiSQlOeOPQiqFgiDzeqqemNDp+CRuhoYz1Vbz+ESRaHtkWRLb7ZjvohS2k7e
|
||||
RTq7tUxY2nUL2YrNHV7DFYtJVBwiTuyLP6eAiJdE=
|
||||
To: what@odoo.com
|
||||
From: Soup <soup@odoo.com>
|
||||
Subject: =?UTF-8?Q?Soupe_du_jour_:_Pois_cass=c3=a9s?=
|
||||
Message-ID: <a05d8334-7b7c-df68-c96a-4a88ed19f31b@odoo.com>
|
||||
Date: Mon, 5 Mar 2018 10:19:21 +0100
|
||||
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101
|
||||
Thunderbird/52.6.0
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/alternative;
|
||||
boundary="------------1F2D18B1129FC2F0B9EECF50"
|
||||
Content-Language: en-US
|
||||
X-Spam-Status: No, score=-1.2 required=5.0 tests=ALL_TRUSTED,BAYES_00,
|
||||
HTML_IMAGE_ONLY_08,HTML_MESSAGE,T_REMOTE_IMAGE autolearn=no
|
||||
autolearn_force=no version=3.4.0
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail2.odoo.com
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
--------------1F2D18B1129FC2F0B9EECF50
|
||||
Content-Type: text/plain; charset=utf-8; format=flowed
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Résultat de recherche d'images pour "dessin la princesse au petit pois"
|
||||
|
||||
--
|
||||
Soup
|
||||
|
||||
Odoo S.A.
|
||||
Chaussée de Namur, 40
|
||||
B-1367 Grand Rosière
|
||||
Web: http://www.odoo.com
|
||||
|
||||
|
||||
--------------1F2D18B1129FC2F0B9EECF50
|
||||
Content-Type: text/html; charset=utf-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#FFFFFF">
|
||||
<p><img
|
||||
src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjCNAadd3NDM8g9w0P_-gAVYrrqC0wmBNYKGsTZ2Pst5SsNxTRnA"
|
||||
alt="Résultat de recherche d'images pour "dessin la
|
||||
princesse au petit pois""></p>
|
||||
<pre class="moz-signature" cols="72">--
|
||||
Soup
|
||||
|
||||
Odoo S.A.
|
||||
Chaussée de Namur, 40
|
||||
B-1367 Grand Rosière
|
||||
Web: <a class="moz-txt-link-freetext" href="http://www.odoo.com">http://www.odoo.com</a> </pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
--------------1F2D18B1129FC2F0B9EECF50--
|
||||
|
||||
--------------A6B5FD5F68F4D73ECD739009--"""
|
||||
|
||||
@@ -7,7 +7,7 @@ from email.utils import formataddr
|
||||
|
||||
from odoo.addons.test_mail.data.test_mail_data import \
|
||||
MAIL_TEMPLATE, MAIL_TEMPLATE_PLAINTEXT, MAIL_MULTIPART_MIXED, MAIL_MULTIPART_MIXED_TWO, \
|
||||
MAIL_MULTIPART_IMAGE, MAIL_SINGLE_BINARY
|
||||
MAIL_MULTIPART_IMAGE, MAIL_SINGLE_BINARY, MAIL_EML_ATTACHMENT
|
||||
from odoo.addons.test_mail.tests.common import BaseFunctionalTest, MockEmails
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
@@ -78,6 +78,12 @@ class TestMailgateway(BaseFunctionalTest, MockEmails):
|
||||
'message_id': '<123456-openerp-%s-mail.test.simple@%s>' % (cls.test_record.id, socket.gethostname()),
|
||||
})
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_thread')
|
||||
def test_message_parse_eml(self):
|
||||
""" Test that the parsing of mail with embedded emails as eml(msg) which generates empty attachments, can be processed.
|
||||
"""
|
||||
self.env['mail.thread'].message_process('mail.channel', MAIL_EML_ATTACHMENT)
|
||||
|
||||
@mute_logger('odoo.addons.mail.models.mail_thread')
|
||||
def test_message_process_cid(self):
|
||||
record = self.format_and_process(MAIL_MULTIPART_IMAGE, to='groups@example.com')
|
||||
|
||||
@@ -1975,7 +1975,13 @@ eventHandler.modules.toolbar.button.updateRecentColor = function (elBtn, sEvent,
|
||||
};
|
||||
|
||||
$(document).on('click keyup', function () {
|
||||
var $popover = $((range.create()||{}).sc).closest('[contenteditable]');
|
||||
var current_range = {};
|
||||
try {
|
||||
current_range = range.create() || {};
|
||||
} catch (e) {
|
||||
// if range is on Restricted element ignore error
|
||||
}
|
||||
var $popover = $(current_range.sc).closest('[contenteditable]');
|
||||
var popover_history = ($popover.data()||{}).NoteHistory;
|
||||
if (!popover_history || popover_history === history) return;
|
||||
var editor = $popover.parent('.note-editor');
|
||||
|
||||
@@ -227,6 +227,26 @@ function imgToFont($editable) {
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility function to apply function over descendants elements
|
||||
*
|
||||
* This is needed until the following issue of jQuery is solved:
|
||||
* https://github.com./jquery/sizzle/issues/403
|
||||
*
|
||||
* @param {Element} node The root Element node
|
||||
* @param {Function} func The function applied over descendants
|
||||
*/
|
||||
function applyOverDescendants(node, func) {
|
||||
node = node.firstChild;
|
||||
while (node) {
|
||||
if (node.nodeType === 1) {
|
||||
func(node);
|
||||
applyOverDescendants(node, func);
|
||||
}
|
||||
node = node.nextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts css style to inline style (leave the classes on elements but forces
|
||||
* the style they give as inline style).
|
||||
@@ -237,9 +257,9 @@ function classToStyle($editable) {
|
||||
if (!rulesCache.length) {
|
||||
getMatchedCSSRules($editable[0]);
|
||||
}
|
||||
$editable.find('*').each(function () {
|
||||
var $target = $(this);
|
||||
var css = getMatchedCSSRules(this);
|
||||
applyOverDescendants($editable[0], function (node) {
|
||||
var $target = $(node);
|
||||
var css = getMatchedCSSRules(node);
|
||||
var style = $target.attr('style') || '';
|
||||
_.each(css, function (v,k) {
|
||||
if (!(new RegExp('(^|;)\s*' + k).test(style))) {
|
||||
@@ -252,12 +272,12 @@ function classToStyle($editable) {
|
||||
$target.attr('style', style);
|
||||
}
|
||||
// Apple Mail
|
||||
if (this.nodeName === 'TD' && !this.childNodes.length) {
|
||||
this.innerHTML = ' ';
|
||||
if (node.nodeName === 'TD' && !node.childNodes.length) {
|
||||
node.innerHTML = ' ';
|
||||
}
|
||||
|
||||
// Outlook
|
||||
if (this.nodeName === 'A' && $target.hasClass('btn') && !$target.children().length) {
|
||||
if (node.nodeName === 'A' && $target.hasClass('btn') && !$target.children().length) {
|
||||
var $hack = $('<table class="o_outlook_hack"><tr><td></td></tr></table>');
|
||||
$hack.find('td')
|
||||
.attr('height', $target.outerHeight())
|
||||
@@ -269,7 +289,7 @@ function classToStyle($editable) {
|
||||
$target.after($hack);
|
||||
$target.appendTo($hack.find('td'));
|
||||
// the space add a line when it's a table but it's invisible when it's a link
|
||||
var node = $hack[0].previousSibling;
|
||||
node = $hack[0].previousSibling;
|
||||
if (node && node.nodeType === Node.TEXT_NODE && !node.textContent.match(/\S/)) {
|
||||
$(node).remove();
|
||||
}
|
||||
@@ -297,9 +317,9 @@ function styleToClass($editable) {
|
||||
|
||||
var $c = $('<span/>').appendTo(document.body);
|
||||
|
||||
$editable.find('*').each(function () {
|
||||
var $target = $(this);
|
||||
var css = getMatchedCSSRules(this);
|
||||
applyOverDescendants($editable[0], function (node) {
|
||||
var $target = $(node);
|
||||
var css = getMatchedCSSRules(node);
|
||||
var style = '';
|
||||
_.each(css, function (v,k) {
|
||||
if (!(new RegExp('(^|;)\s*' + k).test(style))) {
|
||||
|
||||
@@ -7,4 +7,4 @@ from odoo import models, fields
|
||||
class ResPartner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
last_website_so_id = fields.Many2one('sale.order', string='Last Online Sales Order')
|
||||
last_website_so_id = fields.Many2one('sale.order', string='Last Online Sales Order', copy=False)
|
||||
|
||||
@@ -116,7 +116,7 @@ class TestSanitizer(unittest.TestCase):
|
||||
test_data = [
|
||||
(
|
||||
'<span style="position: fixed; top: 0px; left: 50px; width: 40%; height: 50%; background-color: red;">Coin coin </span>',
|
||||
['background-color: red', 'Coin coin'],
|
||||
['background-color:red', 'Coin coin'],
|
||||
['position', 'top', 'left']
|
||||
), (
|
||||
"""<div style='before: "Email Address; coincoin cheval: lapin";
|
||||
@@ -124,7 +124,7 @@ class TestSanitizer(unittest.TestCase):
|
||||
|
||||
this; means: anything ?#ùµ"
|
||||
; some-property: 2px; top: 3'>youplaboum</div>""",
|
||||
['font-size: 30px', 'youplaboum'],
|
||||
['font-size:30px', 'youplaboum'],
|
||||
['some-property', 'top', 'cheval']
|
||||
), (
|
||||
'<span style="width">Coincoin</span>',
|
||||
|
||||
@@ -510,7 +510,7 @@ REMOVE_CLASS = u"""
|
||||
</div>
|
||||
"""
|
||||
REMOVE_CLASS_IN = [
|
||||
u'<div style="font-size: 12pt; font-family: \'Times New Roman\'; color: #000000">',
|
||||
u'<div style="font-size:12pt; font-family:\'Times New Roman\'; color:#000000">',
|
||||
u'An error occured in a modal and I will send you back the html to try opening one on your end']
|
||||
REMOVE_CLASS_OUT = [
|
||||
u'<div class="modal-backdrop in">',
|
||||
|
||||
@@ -1825,6 +1825,8 @@ class Selection(Field):
|
||||
def convert_to_cache(self, value, record, validate=True):
|
||||
if not validate:
|
||||
return value or False
|
||||
if value and self.column_type[0] == 'int4':
|
||||
value = int(value)
|
||||
if value in self.get_values(record.env):
|
||||
return value
|
||||
elif not value:
|
||||
|
||||
+1
-1
@@ -155,7 +155,7 @@ class _Cleaner(clean.Cleaner):
|
||||
if style[0].lower() in self._style_whitelist:
|
||||
valid_styles[style[0].lower()] = style[1]
|
||||
if valid_styles:
|
||||
el.attrib['style'] = '; '.join('%s: %s' % (key, val) for (key, val) in valid_styles.items())
|
||||
el.attrib['style'] = '; '.join('%s:%s' % (key, val) for (key, val) in valid_styles.items())
|
||||
else:
|
||||
del el.attrib['style']
|
||||
|
||||
|
||||
Reference in New Issue
Block a user