From cf1b1b6e2c15c2ef443044ee58cfd04e1488039c Mon Sep 17 00:00:00 2001 From: chirag Date: Tue, 10 Apr 2018 16:02:05 +0530 Subject: [PATCH 1/5] [FIX] l10n_multilang: overwrite existing translations When a record is created in a different language than English, empty translations are created using the _set_ids method for translatable fields. l10n_multilang makes the account translatable, an empty translation is created when the CoA data is processed. After the CoA installation, l10n_multilang transfer the translations of the account templates to the related accounts. No need to create translation terms again, use _set_ids to update the existing translations. This will prevent a cause of translation duplication, forbidden in the future by 160d657704037 opw-1832071 Closes #24158 --- addons/l10n_multilang/models/l10n_multilang.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/addons/l10n_multilang/models/l10n_multilang.py b/addons/l10n_multilang/models/l10n_multilang.py index fe2f48a79e2..f43ebab1f29 100644 --- a/addons/l10n_multilang/models/l10n_multilang.py +++ b/addons/l10n_multilang/models/l10n_multilang.py @@ -32,14 +32,14 @@ class AccountChartTemplate(models.Model): for element in in_ids.with_context(lang=None): if value[element.id]: #copy Translation from Source to Destination object - xlat_obj.create({ - 'name': out_ids._name + ',' + in_field, - 'type': 'model', - 'res_id': out_ids[counter].id, - 'lang': lang, - 'src': element[in_field], - 'value': value[element.id], - }) + xlat_obj._set_ids( + out_ids._name + ',' + in_field, + 'model', + lang, + out_ids[counter].ids, + value[element.id], + element[in_field] + ) else: _logger.info('Language: %s. Translation from template: there is no translation available for %s!' % (lang, element[in_field])) counter += 1 From 468e2e454e1ad5b7a3fe02e50cd7920d63319581 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Thu, 3 May 2018 16:37:36 +0200 Subject: [PATCH 2/5] [FIX] sale: creating invoice name from SO ref Steps to reproduce the bug: - Create a SO with 2 lines and confirm it - Set a Customer reference on the SO with "This is, a ref" - Deliver it - Create an invoice from it with all the invoicable lines Bug: The name of the invoice was: "This is, a ref, This is, a ref" Expected behavior: The name of the invoice is: "This is, a ref" opw:1840738 --- addons/sale/sale.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/addons/sale/sale.py b/addons/sale/sale.py index 020219a7e8c..62b1598db66 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -311,6 +311,8 @@ class SaleOrder(models.Model): inv_obj = self.env['account.invoice'] precision = self.env['decimal.precision'].precision_get('Product Unit of Measure') invoices = {} + invoices_origin = {} + invoices_name = {} for order in self: group_key = order.id if grouped else (order.partner_invoice_id.id, order.currency_id.id) @@ -321,17 +323,21 @@ class SaleOrder(models.Model): inv_data = order._prepare_invoice() invoice = inv_obj.create(inv_data) invoices[group_key] = invoice + invoices_origin[group_key] = [invoice.origin] + invoices_name[group_key] = [invoice.name] elif group_key in invoices: vals = {} - if order.name not in invoices[group_key].origin.split(', '): - vals['origin'] = invoices[group_key].origin + ', ' + order.name - if order.client_order_ref and order.client_order_ref not in invoices[group_key].name.split(', '): - vals['name'] = invoices[group_key].name + ', ' + order.client_order_ref - invoices[group_key].write(vals) + if order.name not in invoices_origin[group_key]: + invoices_origin[group_key].append(order.name) + if order.client_order_ref and order.client_order_ref not in invoices_name[group_key]: + invoices_name[group_key].append(order.client_order_ref) if line.qty_to_invoice > 0: line.invoice_line_create(invoices[group_key].id, line.qty_to_invoice) elif line.qty_to_invoice < 0 and final: line.invoice_line_create(invoices[group_key].id, line.qty_to_invoice) + for group_key in invoices: + invoices[group_key].write({'name': ', '.join(invoices_name[group_key]), + 'origin': ', '.join(invoices_origin[group_key])}) if not invoices: raise UserError(_('There is no invoicable line.')) From b8006bfb1c30ee92e8374f135546764d1cae7db2 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Mon, 7 May 2018 13:52:26 +0200 Subject: [PATCH 3/5] [FIX] mail tools: html_sanitize must keep useful styles from mass mailing Issue: The clean removes too many tags so emails sent do not resemble the preview. opw-1841138 opw-1841105 --- odoo/tools/mail.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/odoo/tools/mail.py b/odoo/tools/mail.py index 328fa81465c..285808cd0cd 100644 --- a/odoo/tools/mail.py +++ b/odoo/tools/mail.py @@ -42,14 +42,23 @@ class _Cleaner(clean.Cleaner): _style_re = re.compile('''([\w-]+)\s*:\s*((?:[^;"']|"[^"]*"|'[^']*')+)''') _style_whitelist = [ - 'font-size', 'font-family', 'background-color', 'color', 'text-align', + 'font-size', 'font-family', 'font-weight', + 'background-color', 'color', 'float', 'vertical-align', + 'line-height', 'text-align', 'text-decoration', 'padding', 'padding-top', 'padding-left', 'padding-bottom', 'padding-right', - 'margin', 'margin-top', 'margin-left', 'margin-bottom', 'margin-right' + 'margin', 'margin-top', 'margin-left', 'margin-bottom', 'margin-right', # box model - 'border', 'border-color', 'border-radius', 'height', 'margin', 'padding', 'width', 'max-width', 'min-width', + 'border', 'border-color', 'border-style', 'border-radius', 'border-width', + 'height', 'margin', 'padding', 'width', 'max-width', 'min-width', # tables 'border-collapse', 'border-spacing', 'caption-side', 'empty-cells', 'table-layout'] + _style_whitelist.extend( + ['border-%s-%s' % (position, attribute) + for position in ['top', 'bottom', 'left', 'right'] + for attribute in ('style', 'color', 'width', 'left-radius', 'right-radius')] + ) + strip_classes = False sanitize_style = False From a8ab14a67263d094daa816557216087a4f680f80 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Thu, 3 May 2018 12:22:10 +0200 Subject: [PATCH 4/5] [FIX] stock: prevent to create the reception route over and over when deleted once When the reception route of a warehouse company is deleted by the user e.g. My company, Chicago Receipt in 1 step is deleted, and then changing the given warehouse `Incoming Shipments` multiple times e.g. from `one_step` to `two_steps` multiple time, the reception route is created again and again and again. This is because the reception route which is created for the warehouse is not being assigned to the warehouse as the `reception_route_id` once newly created. opw-1836544 --- addons/stock/models/stock_warehouse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/stock/models/stock_warehouse.py b/addons/stock/models/stock_warehouse.py index a1516d82ac0..61bba824328 100644 --- a/addons/stock/models/stock_warehouse.py +++ b/addons/stock/models/stock_warehouse.py @@ -285,7 +285,7 @@ class Warehouse(models.Model): reception_route.pull_ids.unlink() reception_route.push_ids.unlink() else: - reception_route = self.env['stock.location.route'].create(warehouse._get_reception_delivery_route_values(warehouse.reception_steps)) + warehouse.reception_route_id = reception_route = self.env['stock.location.route'].create(warehouse._get_reception_delivery_route_values(warehouse.reception_steps)) # push / procurement (pull) rules for reception routings = routes_data[warehouse.id][warehouse.reception_steps] push_rules_list, pull_rules_list = warehouse._get_push_pull_rules_values( From da6b4add237490d6415414a053d967d9a549a918 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Mon, 7 May 2018 16:47:38 +0200 Subject: [PATCH 5/5] [FIX] account: avoid cache invalidation at the opening of an invoice * Avoid to invalidate the cache if no actual deletion has been made when recomputing the taxes * Avoid to create analytic entries to delete them right away few lines further in the same method: - Analytic entries are created at line 903 - account_invoice.py:751 `move_line_dict['analytic_line_ids'] = [(0, 0, line._get_analytic_line())]` - account_invoice.py:840 `iml = inv.invoice_line_move_line_get()` - account_invoice.py:886 `line = inv.group_lines(iml, line)` - account_invoice.py:894 `'line_ids': line,` - account_invoice.py:903 `move = account_move.with_context(ctx_nolang).create(move_vals)` - Then, at line 907, they are deleted and others are created again: - account_invoice.py:907 `move.post()` - account_move.py:130 `move.line_ids.create_analytic_lines()` - account_move.py:1258 `self.mapped('analytic_line_ids').unlink()` - account_move.py:1262 `self.env['account.analytic.line'].create(vals_line)` Deleting these analytic entries indeed implies the invalidation of the cache. Besides, generally speaking, we should avoid to waste resources by creating/unlinking records without a good reason. --- addons/account/models/account_invoice.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index 5531a188202..709dd522400 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -431,7 +431,8 @@ class AccountInvoice(models.Model): for invoice in self: # Delete non-manual tax lines self._cr.execute("DELETE FROM account_invoice_tax WHERE invoice_id=%s AND manual is False", (invoice.id,)) - self.invalidate_cache() + if self._cr.rowcount: + self.invalidate_cache() # Generate one tax line per tax, however many invoice lines it's applied to tax_grouped = invoice.get_taxes_values() @@ -747,8 +748,6 @@ class AccountInvoice(models.Model): 'invoice_id': self.id, 'analytic_tag_ids': analytic_tag_ids } - if line['account_analytic_id']: - move_line_dict['analytic_line_ids'] = [(0, 0, line._get_analytic_line())] res.append(move_line_dict) return res