diff options
| author | Christophe Simonis <chs@odoo.com> | 2018-07-30 14:08:56 +0200 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2018-07-30 14:08:56 +0200 |
| commit | a6e401a2eebd98adf3b0661a45cbe747384d3ae7 (patch) | |
| tree | 3a7ee35c3a937c87580586e412a6598d61b770c0 | |
| parent | 1fd430d08fc71bf4205e763c92fd4d77a2c28f72 (diff) | |
| parent | 44ea58234ec0d902ddf0caf7aefb367acc013627 (diff) | |
[MERGE] forward port branch 11.0 up to 44ea58234ec
| -rw-r--r-- | .tx/config | 5 | ||||
| -rw-r--r-- | addons/account/models/account_invoice.py | 2 | ||||
| -rw-r--r-- | addons/event/data/email_template_data.xml | 1 | ||||
| -rw-r--r-- | addons/event/models/event.py | 11 | ||||
| -rw-r--r-- | addons/hr_timesheet/report/report_timesheet_templates.xml | 6 | ||||
| -rw-r--r-- | addons/mail/models/mail_template.py | 2 | ||||
| -rw-r--r-- | addons/point_of_sale/models/pos_config.py | 5 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/kanban/kanban_column_progressbar.js | 8 | ||||
| -rw-r--r-- | addons/web/static/src/less/kanban_column_progressbar.less | 5 | ||||
| -rw-r--r-- | addons/website_sale_delivery/controllers/main.py | 2 | ||||
| -rw-r--r-- | odoo/addons/base/models/ir_qweb_fields.py | 12 | ||||
| -rw-r--r-- | odoo/addons/test_converter/tests/test_html.py | 4 | ||||
| -rw-r--r-- | odoo/service/server.py | 2 | ||||
| -rw-r--r-- | odoo/tools/safe_eval.py | 4 |
14 files changed, 49 insertions, 20 deletions
diff --git a/.tx/config b/.tx/config index ba9318f5a58..c9ebc9f6226 100644 --- a/.tx/config +++ b/.tx/config @@ -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 diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index d3aad9da4a9..8e8584d1151 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -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 diff --git a/addons/event/data/email_template_data.xml b/addons/event/data/email_template_data.xml index b7788cba9a3..38329a8c6f4 100644 --- a/addons/event/data/email_template_data.xml +++ b/addons/event/data/email_template_data.xml @@ -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> diff --git a/addons/event/models/event.py b/addons/event/models/event.py index 99f6b35eb52..afeb345b4ee 100644 --- a/addons/event/models/event.py +++ b/addons/event/models/event.py @@ -484,6 +484,17 @@ class EventRegistration(models.Model): 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' message loaded by default diff --git a/addons/hr_timesheet/report/report_timesheet_templates.xml b/addons/hr_timesheet/report/report_timesheet_templates.xml index fea714a5d7a..dbc0ad4a583 100644 --- a/addons/hr_timesheet/report/report_timesheet_templates.xml +++ b/addons/hr_timesheet/report/report_timesheet_templates.xml @@ -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 < 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> diff --git a/addons/mail/models/mail_template.py b/addons/mail/models/mail_template.py index f5d4b4e3ac6..cb9c4a433a8 100644 --- a/addons/mail/models/mail_template.py +++ b/addons/mail/models/mail_template.py @@ -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': diff --git a/addons/point_of_sale/models/pos_config.py b/addons/point_of_sale/models/pos_config.py index 67e4f5a527b..a43246e03bd 100644 --- a/addons/point_of_sale/models/pos_config.py +++ b/addons/point_of_sale/models/pos_config.py @@ -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 diff --git a/addons/web/static/src/js/views/kanban/kanban_column_progressbar.js b/addons/web/static/src/js/views/kanban/kanban_column_progressbar.js index fad822efdb9..b597ccf1c60 100644 --- a/addons/web/static/src/js/views/kanban/kanban_column_progressbar.js +++ b/addons/web/static/src/js/views/kanban/kanban_column_progressbar.js @@ -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', ''); } diff --git a/addons/web/static/src/less/kanban_column_progressbar.less b/addons/web/static/src/less/kanban_column_progressbar.less index f4cffd6c097..233ae5c0d01 100644 --- a/addons/web/static/src/less/kanban_column_progressbar.less +++ b/addons/web/static/src/less/kanban_column_progressbar.less @@ -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 { diff --git a/addons/website_sale_delivery/controllers/main.py b/addons/website_sale_delivery/controllers/main.py index 5a06774fcad..52522fa8117 100644 --- a/addons/website_sale_delivery/controllers/main.py +++ b/addons/website_sale_delivery/controllers/main.py @@ -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}') diff --git a/odoo/addons/base/models/ir_qweb_fields.py b/odoo/addons/base/models/ir_qweb_fields.py index 19e15ff4621..5a9000598de 100644 --- a/odoo/addons/base/models/ir_qweb_fields.py +++ b/odoo/addons/base/models/ir_qweb_fields.py @@ -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): diff --git a/odoo/addons/test_converter/tests/test_html.py b/odoo/addons/test_converter/tests/test_html.py index e915785e333..d04604a5c4f 100644 --- a/odoo/addons/test_converter/tests/test_html.py +++ b/odoo/addons/test_converter/tests/test_html.py @@ -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 diff --git a/odoo/service/server.py b/odoo/service/server.py index 8899760ce91..4820b1e3257 100644 --- a/odoo/service/server.py +++ b/odoo/service/server.py @@ -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') diff --git a/odoo/tools/safe_eval.py b/odoo/tools/safe_eval.py index 7a5ec03707a..ccb2e3e25b4 100644 --- a/odoo/tools/safe_eval.py +++ b/odoo/tools/safe_eval.py @@ -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)) |
