[MERGE] forward port branch 11.0 up to 44ea58234e

This commit is contained in:
Christophe Simonis
2018-07-30 14:08:56 +02:00
14 changed files with 49 additions and 20 deletions
+5
View File
@@ -32,6 +32,11 @@ file_filter = addons/account_budget/i18n/<lang>.po
source_file = addons/account_budget/i18n/account_budget.pot
source_lang = en
[odoo-master.account_cash_basis_base_account]
file_filter = addons/account_cash_basis_base_account/i18n/<lang>.po
source_file = addons/account_cash_basis_base_account/i18n/account_cash_basis_base_account.pot
source_lang = en
[odoo-master.account_cancel]
file_filter = addons/account_cancel/i18n/<lang>.po
source_file = addons/account_cancel/i18n/account_cancel.pot
+2
View File
@@ -1262,6 +1262,8 @@ class AccountInvoice(models.Model):
values[name] = line[name]
elif name == 'invoice_line_tax_ids':
values[name] = [(6, 0, line[name].ids)]
elif name == 'analytic_tag_ids':
values[name] = [(6, 0, line[name].ids)]
result.append((0, 0, values))
return result
@@ -326,7 +326,6 @@
<td style="padding:25px 0px;">
<strong>Add this event to your calendar</strong>
<a href="https://www.google.com/calendar/render?action=TEMPLATE&text=${object.event_id.name}&dates=${date_begin}/${date_end}&location=${location}" style="padding:3px 5px;border:1px solid #875A7B;color:#875A7B;text-decoration:none;border-radius:3px;" target="new"><img src="/web_editor/font_to_img/61525/rgb(135,90,123)/16" style="vertical-align:middle;" height="16"> Google</a>
<a href="https://bay02.calendar.live.com/calendar/calendar.aspx?rru=addevent&summary=${object.event_id.name}&dtstart=${date_begin}&dtend=${date_end}&location=${location}" style="padding:3px 5px;border:1px solid #875A7B;color:#875A7B;text-decoration:none;border-radius:3px;" target="new"><img src="/web_editor/font_to_img/61525/rgb(135,90,123)/16" style="vertical-align:middle;" height="16"> Outlook</a>
<a href="https://calendar.yahoo.com/?v=60&view=d&type=20&title=${object.event_id.name}&in_loc=${location}&st=${format_tz(object.event_id.date_begin, tz='UTC', format='%Y%m%dT%H%M%S')}&et=${format_tz(object.event_id.date_end, tz='UTC', format='%Y%m%dT%H%M%S')}" style="padding:3px 5px;border:1px solid #875A7B;color:#875A7B;text-decoration:none;border-radius:3px;" target="new"><img src="/web_editor/font_to_img/61525/rgb(135,90,123)/16" style="vertical-align:middle;" height="16"> Yahoo</a>
</td>
</tr>
+11
View File
@@ -483,6 +483,17 @@ class EventRegistration(models.Model):
]).write({'partner_id': new_partner.id})
return super(EventRegistration, self)._message_post_after_hook(message, values, notif_layout)
@api.multi
def message_get_default_recipients(self):
# Prioritize registration email over partner_id, which may be shared when a single
# partner booked multiple seats
return {
r.id: {'partner_ids': [],
'email_to': r.email,
'email_cc': False}
for r in self
}
@api.multi
def action_send_badge_email(self):
""" Open a window to compose an email, with the template - 'event_badge'
@@ -44,7 +44,7 @@
<t t-if="l.task_id"><span t-field="l.task_id.name"/></t>
</td>
<td class="text-right">
<span t-esc="'%s:%02.0f' % tuple(int(round(x)) for x in divmod(l.unit_amount*60,60))"/>
<span t-field="l.unit_amount" t-options="{'widget': 'float_time'}"/>
</td>
</tr>
</t>
@@ -53,7 +53,9 @@
<td />
<td t-if="show_task"/>
<td class="text-right"><strong>Total</strong></td>
<td class="text-right"><strong t-esc="'%s:%02.0f' % tuple(int(round(x)) for x in divmod(sum(docs.mapped('unit_amount'))*60,60))"/></td>
<t t-set="total_value" t-value="sum(docs.mapped('unit_amount'))" />
<t t-set="sign" t-value="'-' if total_value &lt; 0 else ''"/>
<td class="text-right"><strong t-esc="sign + '%s:%02.0f' % tuple(int(round(x)) for x in divmod(abs(total_value)*60,60))"/></td>
</tr>
</tbody>
</table>
+1 -1
View File
@@ -63,7 +63,7 @@ def format_amount(env, amount, currency):
lang = env['res.lang']._lang_get(env.context.get('lang') or 'en_US')
formatted_amount = lang.format(fmt, currency.round(amount), grouping=True, monetary=True)\
.replace(r' ', u'\N{NO-BREAK SPACE}').replace(r'-', u'\u2011')
.replace(r' ', u'\N{NO-BREAK SPACE}').replace(r'-', u'-\N{ZERO WIDTH NO-BREAK SPACE}')
pre = post = u''
if currency.position == 'before':
@@ -255,6 +255,11 @@ class PosConfig(models.Model):
if any(self.journal_ids.mapped(lambda journal: journal.currency_id and journal.currency_id != self.currency_id)):
raise ValidationError(_("All payment methods must be in the same currency as the Sales Journal or the company currency if that is not set."))
@api.constrains('company_id', 'available_pricelist_ids')
def _check_companies(self):
if any(self.available_pricelist_ids.mapped(lambda pl: pl.company_id.id not in (False, self.company_id.id))):
raise ValidationError(_("The selected pricelists must belong to no company or the company of the point of sale."))
@api.onchange('iface_print_via_proxy')
def _onchange_iface_print_via_proxy(self):
self.iface_print_auto = self.iface_print_via_proxy
@@ -141,6 +141,7 @@ var KanbanColumnProgressBar = Widget.extend({
}
// Display and animate the progress bars
var barNumber = 0;
_.each(self.colors, function (val, key) {
var $bar = self.$bars[val];
var count = self.subgroupCounts && self.subgroupCounts[key] || 0;
@@ -165,7 +166,14 @@ var KanbanColumnProgressBar = Widget.extend({
window.getComputedStyle($bar[0]).getPropertyValue('width'); // Force reflow so that animations work
if (count > 0) {
$bar.addClass('o_bar_has_records');
// Make sure every bar that has records has some space
// and that everything adds up to 100%
var minWidth = 6*barNumber;
var maxWidth = 100 - minWidth;
self.$('.progress-bar.o_bar_has_records').css('max-width', maxWidth + '%');
self.$('.progress-bar.o_bar_has_records').css('min-width', minWidth + '%');
$bar.css('width', (count * 100 / self.groupCount) + '%');
barNumber++;
} else {
$bar.css('width', '');
}
@@ -73,11 +73,6 @@
margin-bottom: 0;
box-shadow: none;
cursor: pointer;
// Be sure that a bar with data has a minimun width
&.o_bar_has_records {
min-width: 10px;
}
}
.o_kanban_counter_label {
@@ -76,4 +76,4 @@ class WebsiteSaleDelivery(WebsiteSale):
lang = request.env['res.lang']._lang_get(request.env.context.get('lang') or 'en_US')
return lang.format(fmt, currency.round(amount), grouping=True, monetary=True)\
.replace(r' ', u'\N{NO-BREAK SPACE}').replace(r'-', u'\u2011')
.replace(r' ', u'\N{NO-BREAK SPACE}').replace(r'-', u'-\N{ZERO WIDTH NO-BREAK SPACE}')
+7 -5
View File
@@ -7,6 +7,7 @@ from odoo import api, fields, models, _
from PIL import Image
import babel
from lxml import etree
import math
from odoo.tools import html_escape as escape, posix_to_ldml, safe_eval, float_utils, format_date, pycompat
@@ -125,7 +126,7 @@ class IntegerConverter(models.AbstractModel):
@api.model
def value_to_html(self, value, options):
return pycompat.to_text(self.user_lang().format('%d', value, grouping=True).replace(r'-', u'\u2011'))
return pycompat.to_text(self.user_lang().format('%d', value, grouping=True).replace(r'-', u'-\N{ZERO WIDTH NO-BREAK SPACE}'))
class FloatConverter(models.AbstractModel):
@@ -145,7 +146,7 @@ class FloatConverter(models.AbstractModel):
value = float_utils.float_round(value, precision_digits=precision)
fmt = '%.{precision}f'.format(precision=precision)
formatted = self.user_lang().format(fmt, value, grouping=True).replace(r'-', u'\u2011')
formatted = self.user_lang().format(fmt, value, grouping=True).replace(r'-', u'-\N{ZERO WIDTH NO-BREAK SPACE}')
# %f does not strip trailing zeroes. %g does but its precision causes
# it to switch to scientific notation starting at a million *and* to
@@ -325,7 +326,7 @@ class MonetaryConverter(models.AbstractModel):
lang = self.user_lang()
formatted_amount = lang.format(fmt, display_currency.round(value),
grouping=True, monetary=True).replace(r' ', u'\N{NO-BREAK SPACE}').replace(r'-', u'\u2011')
grouping=True, monetary=True).replace(r' ', u'\N{NO-BREAK SPACE}').replace(r'-', u'-\N{ZERO WIDTH NO-BREAK SPACE}')
pre = post = u''
if display_currency.position == 'before':
@@ -367,8 +368,9 @@ class FloatTimeConverter(models.AbstractModel):
@api.model
def value_to_html(self, value, options):
hours, minutes = divmod(value * 60, 60)
return '%02d:%02d' % (hours, minutes)
sign = math.copysign(1.0, value)
hours, minutes = divmod(abs(value) * 60, 60)
return '%02d:%02d' % (sign * hours, minutes)
class DurationConverter(models.AbstractModel):
@@ -73,7 +73,7 @@ class TestFloatExport(TestBasicExport):
converter = self.get_converter('float')
value = converter(-42.0)
self.assertEqual(value, u"\u201142.0")
self.assertEqual(value, u"-\N{ZERO WIDTH NO-BREAK SPACE}42.0")
value = converter(42.0100)
self.assertEqual(value, "42.01")
@@ -120,7 +120,7 @@ class TestCurrencyExport(TestExport):
converted = self.convert(obj, dest=currency)
self.assertEqual(
converted, u'<span class="oe_currency_value">\u20110.12</span>'
converted, u'<span class="oe_currency_value">-\N{ZERO WIDTH NO-BREAK SPACE}0.12</span>'
u'\N{NO-BREAK SPACE}{symbol}'.format(
obj=obj,
symbol=currency.symbol
+1 -1
View File
@@ -131,7 +131,7 @@ class FSWatcher(object):
if isinstance(event, (FileCreatedEvent, FileModifiedEvent, FileMovedEvent)):
if not event.is_directory:
path = getattr(event, 'dest_path', event.src_path)
if path.endswith('.py'):
if path.endswith('.py') and not os.path.basename(path).startswith('.~'):
try:
source = open(path, 'rb').read() + b'\n'
compile(source, path, 'exec')
+2 -2
View File
@@ -107,8 +107,8 @@ _SAFE_OPCODES = _EXPR_OPCODES.union(set(opmap[x] for x in [
'JUMP_FORWARD', 'JUMP_IF_TRUE', 'JUMP_IF_FALSE', 'JUMP_ABSOLUTE',
# New in Python 2.7 - http://bugs.python.org/issue4715 :
'JUMP_IF_FALSE_OR_POP', 'JUMP_IF_TRUE_OR_POP', 'POP_JUMP_IF_FALSE',
'POP_JUMP_IF_TRUE', 'SETUP_EXCEPT', 'END_FINALLY', 'RAISE_VARARGS',
'LOAD_NAME', 'STORE_NAME', 'DELETE_NAME', 'LOAD_ATTR',
'POP_JUMP_IF_TRUE', 'SETUP_EXCEPT', 'SETUP_FINALLY', 'END_FINALLY',
'RAISE_VARARGS', 'LOAD_NAME', 'STORE_NAME', 'DELETE_NAME', 'LOAD_ATTR',
'LOAD_FAST', 'STORE_FAST', 'DELETE_FAST', 'UNPACK_SEQUENCE',
'LOAD_GLOBAL', # Only allows access to restricted globals
] if x in opmap))