From 72ab3e81a52dc772e1b8670554870873229d999b Mon Sep 17 00:00:00 2001 From: Yannick Vaucher Date: Tue, 13 May 2014 18:23:48 +0200 Subject: [PATCH 01/19] Make report_webkit thread safe by removing parser_instance attribute, as a WebkitParser instance can be shared by multiple thread and thus we don't want a thread to erase parser_instance of anorther thread. --- addons/report_webkit/webkit_report.py | 41 ++++++++++++++------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/addons/report_webkit/webkit_report.py b/addons/report_webkit/webkit_report.py index c6a30f5e579..d5d921e84df 100644 --- a/addons/report_webkit/webkit_report.py +++ b/addons/report_webkit/webkit_report.py @@ -37,6 +37,7 @@ from openerp import report import tempfile import time import logging +from functools import partial from mako.template import Template from mako.lookup import TemplateLookup @@ -68,7 +69,6 @@ class WebKitParser(report_sxw): """ def __init__(self, name, table, rml=False, parser=False, header=True, store=False): - self.parser_instance = False self.localcontext = {} report_sxw.__init__(self, name, table, rml, parser, header, store) @@ -189,16 +189,16 @@ class WebKitParser(report_sxw): _logger.error('cannot remove file %s: %s', f_to_del, exc) return pdf - def translate_call(self, src): + def translate_call(self, parser_instance, src): """Translate String.""" - ir_translation = self.pool.get('ir.translation') + ir_translation = self.pool['ir.translation'] name = self.tmpl and 'addons/' + self.tmpl or None - res = ir_translation._get_source(self.parser_instance.cr, self.parser_instance.uid, - name, 'report', self.parser_instance.localcontext.get('lang', 'en_US'), src) + res = ir_translation._get_source(parser_instance.cr, parser_instance.uid, + name, 'report', parser_instance.localcontext.get('lang', 'en_US'), src) if res == src: # no translation defined, fallback on None (backward compatibility) - res = ir_translation._get_source(self.parser_instance.cr, self.parser_instance.uid, - None, 'report', self.parser_instance.localcontext.get('lang', 'en_US'), src) + res = ir_translation._get_source(parser_instance.cr, parser_instance.uid, + None, 'report', parser_instance.localcontext.get('lang', 'en_US'), src) if not res : return src return res @@ -213,14 +213,14 @@ class WebKitParser(report_sxw): if report_xml.report_type != 'webkit': return super(WebKitParser,self).create_single_pdf(cursor, uid, ids, data, report_xml, context=context) - self.parser_instance = self.parser(cursor, + parser_instance = self.parser(cursor, uid, self.name2, context=context) self.pool = pooler.get_pool(cursor.dbname) objs = self.getObjects(cursor, uid, ids, context) - self.parser_instance.set_context(objs, data, ids, report_xml.report_type) + parser_instance.set_context(objs, data, ids, report_xml.report_type) template = False @@ -250,17 +250,18 @@ class WebKitParser(report_sxw): if not css : css = '' + translate_call = partial(self.translate_call, parser_instance) #default_filters=['unicode', 'entity'] can be used to set global filter body_mako_tpl = mako_template(template) helper = WebKitHelper(cursor, uid, report_xml.id, context) if report_xml.precise_mode: for obj in objs: - self.parser_instance.localcontext['objects'] = [obj] + parser_instance.localcontext['objects'] = [obj] try : html = body_mako_tpl.render(helper=helper, css=css, - _=self.translate_call, - **self.parser_instance.localcontext) + _=translate_call, + **parser_instance.localcontext) htmls.append(html) except Exception: msg = exceptions.text_error_template().render() @@ -270,8 +271,8 @@ class WebKitParser(report_sxw): try : html = body_mako_tpl.render(helper=helper, css=css, - _=self.translate_call, - **self.parser_instance.localcontext) + _=translate_call, + **parser_instance.localcontext) htmls.append(html) except Exception: msg = exceptions.text_error_template().render() @@ -281,9 +282,9 @@ class WebKitParser(report_sxw): try : head = head_mako_tpl.render(helper=helper, css=css, - _=self.translate_call, + _=translate_call, _debug=False, - **self.parser_instance.localcontext) + **parser_instance.localcontext) except Exception: raise except_osv(_('Webkit render!'), exceptions.text_error_template().render()) @@ -293,8 +294,8 @@ class WebKitParser(report_sxw): try : foot = foot_mako_tpl.render(helper=helper, css=css, - _=self.translate_call, - **self.parser_instance.localcontext) + _=translate_call, + **parser_instance.localcontext) except: msg = exceptions.text_error_template().render() _logger.error(msg) @@ -304,8 +305,8 @@ class WebKitParser(report_sxw): deb = head_mako_tpl.render(helper=helper, css=css, _debug=tools.ustr("\n".join(htmls)), - _=self.translate_call, - **self.parser_instance.localcontext) + _=translate_call, + **parser_instance.localcontext) except Exception: msg = exceptions.text_error_template().render() _logger.error(msg) From e367a54640d579cce998ad33dfd22de8cffe58f9 Mon Sep 17 00:00:00 2001 From: Yannick Vaucher Date: Wed, 14 May 2014 11:50:27 +0200 Subject: [PATCH 02/19] fix indentation --- addons/report_webkit/webkit_report.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/report_webkit/webkit_report.py b/addons/report_webkit/webkit_report.py index d5d921e84df..10a98d30bf3 100644 --- a/addons/report_webkit/webkit_report.py +++ b/addons/report_webkit/webkit_report.py @@ -214,9 +214,9 @@ class WebKitParser(report_sxw): return super(WebKitParser,self).create_single_pdf(cursor, uid, ids, data, report_xml, context=context) parser_instance = self.parser(cursor, - uid, - self.name2, - context=context) + uid, + self.name2, + context=context) self.pool = pooler.get_pool(cursor.dbname) objs = self.getObjects(cursor, uid, ids, context) From 841e47a46ae65e858b2181fa74277095bf96ec85 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Wed, 4 Jun 2014 10:42:43 +0200 Subject: [PATCH 03/19] [FIX] stock: use correct vals in grouped invoice (opw 606535) When creating a grouped invoice, the invoice_vals value is used to create the invoice line. The value was not reset for grouped invoice and we reused the values of previous line. --- addons/stock/stock.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 4c45de266d7..fa4fd3d7ffa 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1132,13 +1132,13 @@ class stock_picking(osv.osv): if not inv_type: inv_type = self._get_invoice_type(picking) + invoice_vals = self._prepare_invoice(cr, uid, picking, partner, inv_type, journal_id, context=context) if group and partner.id in invoices_group: invoice_id = invoices_group[partner.id] invoice = invoice_obj.browse(cr, uid, invoice_id) invoice_vals_group = self._prepare_invoice_group(cr, uid, picking, partner, invoice, context=context) invoice_obj.write(cr, uid, [invoice_id], invoice_vals_group, context=context) else: - invoice_vals = self._prepare_invoice(cr, uid, picking, partner, inv_type, journal_id, context=context) invoice_id = invoice_obj.create(cr, uid, invoice_vals, context=context) invoices_group[partner.id] = invoice_id res[picking.id] = invoice_id From 7b31b082a1de0b888cb076447a65e9882b383a6f Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Wed, 4 Jun 2014 15:06:53 +0200 Subject: [PATCH 04/19] [FIX] kanban: avoid wrong placement of button on ie9 On ie9, the 'read more' button in kanban view was placed in the middle of the window instead of the bottom --- addons/web_kanban/static/src/css/kanban.css | 8 ++++---- addons/web_kanban/static/src/css/kanban.sass | 8 +++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/addons/web_kanban/static/src/css/kanban.css b/addons/web_kanban/static/src/css/kanban.css index 2c2a19724cf..63823c8d6ab 100644 --- a/addons/web_kanban/static/src/css/kanban.css +++ b/addons/web_kanban/static/src/css/kanban.css @@ -73,6 +73,9 @@ .openerp .oe_kanban_view.oe_kanban_ungrouped .oe_kanban_groups { width: 100%; } +.openerp .oe_kanban_view .oe_kanban_groups_records { + height: 100%; +} .openerp .oe_kanban_view.oe_kanban_grouped_by_m2o .oe_kanban_group_title { cursor: move; } @@ -140,10 +143,7 @@ padding: 0px; background: white; } -.openerp .oe_kanban_view .oe_kanban_column, .openerp .oe_kanban_view .oe_kanban_column_cards { - height: 100%; -} -.openerp .oe_kanban_view .oe_kanban_column, .openerp .oe_kanban_view .oe_kanban_column_cards { +.openerp .oe_kanban_view.oe_kanban_grouped .oe_kanban_column, .openerp .oe_kanban_view.oe_kanban_grouped .oe_kanban_column_cards { height: 100%; } .openerp .oe_kanban_view .oe_kanban_aggregates { diff --git a/addons/web_kanban/static/src/css/kanban.sass b/addons/web_kanban/static/src/css/kanban.sass index cac86ac327b..ae6f1d3fc11 100644 --- a/addons/web_kanban/static/src/css/kanban.sass +++ b/addons/web_kanban/static/src/css/kanban.sass @@ -101,6 +101,8 @@ height: inherit &.oe_kanban_ungrouped .oe_kanban_groups width: 100% + .oe_kanban_groups_records + height: 100% &.oe_kanban_grouped_by_m2o .oe_kanban_group_title cursor: move .oe_kanban_header @@ -160,9 +162,9 @@ .oe_kanban_column padding: 0px background: #ffffff - - .oe_kanban_column, .oe_kanban_column_cards - height: 100% + &.oe_kanban_grouped + .oe_kanban_column, .oe_kanban_column_cards + height: 100% .oe_kanban_aggregates padding: 0 margin: 0px From 25292ef0a5c1a7819d6de144e9f4ee59047380c9 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Wed, 4 Jun 2014 15:19:57 +0200 Subject: [PATCH 05/19] [FIX] point_of_sale: correct call to default value The default value should be called with a lambda otherwise the payment_date is set to the date the server was started (opw 606715) --- addons/point_of_sale/wizard/pos_payment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/point_of_sale/wizard/pos_payment.py b/addons/point_of_sale/wizard/pos_payment.py index 0a1684ca9ca..35e35e2df06 100644 --- a/addons/point_of_sale/wizard/pos_payment.py +++ b/addons/point_of_sale/wizard/pos_payment.py @@ -126,7 +126,7 @@ class pos_make_payment(osv.osv_memory): } _defaults = { 'journal_id' : _default_journal, - 'payment_date': time.strftime('%Y-%m-%d %H:%M:%S'), + 'payment_date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'), 'amount': _default_amount, } From 9bcda15b9768aa38c3d64f412442f19e2da650e9 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Wed, 4 Jun 2014 16:15:16 +0200 Subject: [PATCH 06/19] [FIX] website: prevent to split google analytics script --- addons/website/views/website_templates.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/website/views/website_templates.xml b/addons/website/views/website_templates.xml index 1640c9f51e2..ff4dbfd3f72 100644 --- a/addons/website/views/website_templates.xml +++ b/addons/website/views/website_templates.xml @@ -208,7 +208,8 @@ e=o.createElement(i);r=o.getElementsByTagName(i)[0]; e.src='//www.google-analytics.com/analytics.js'; r.parentNode.insertBefore(e,r)}(window,document,'script','ga')); - ga('create','');ga('send','pageview'); + ga('create',_.str.trim('')); + ga('send','pageview'); From 9c9cacd1d0d6379a700fc3e3bbf62f8f5401daa1 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Thu, 5 Jun 2014 10:42:02 +0200 Subject: [PATCH 07/19] [FIX] account_analytic_analysis: Recurring invoice lines price if pricelist does not match If the price according to price list is False, use default sale price in the recurring invoice lines --- addons/account_analytic_analysis/account_analytic_analysis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/account_analytic_analysis/account_analytic_analysis.py b/addons/account_analytic_analysis/account_analytic_analysis.py index 4034ee52b25..4409d99dd1a 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis.py +++ b/addons/account_analytic_analysis/account_analytic_analysis.py @@ -77,7 +77,7 @@ class account_analytic_invoice_line(osv.osv): price = price_unit elif pricelist_id: price = res.price - else: + if price is False: price = res.list_price if not name: name = self.pool.get('product.product').name_get(cr, uid, [res.id], context=local_context)[0][1] From 76d909bb460caa558b62ea0f8f46dc699b0fdfed Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Thu, 5 Jun 2014 10:45:14 +0200 Subject: [PATCH 08/19] [FIX] account_analytic_analysis: Only allow to select sale pricelist for contracts --- .../account_analytic_analysis_view.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/account_analytic_analysis/account_analytic_analysis_view.xml b/addons/account_analytic_analysis/account_analytic_analysis_view.xml index af4caae608f..ba17a3c6a24 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis_view.xml +++ b/addons/account_analytic_analysis/account_analytic_analysis_view.xml @@ -139,7 +139,8 @@ + attrs="{'required': [('invoice_on_timesheets', '=', True)]}" + domain="[('type', '=', 'sale')]"/> Date: Thu, 5 Jun 2014 12:52:11 +0200 Subject: [PATCH 09/19] uninstall: avoid errors during uninstall When uninstalling a module, remove the ir.model.constraint after removing the non-model records and before fields and model definition. Without this fix, some constraint would be removed too early allowing to have broken relations and data left from removed module. --- openerp/addons/base/ir/ir_model.py | 13 ++++++++++--- openerp/addons/base/module/module.py | 4 ---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/openerp/addons/base/ir/ir_model.py b/openerp/addons/base/ir/ir_model.py index 9614e2d31cf..e7775b8ecbc 100644 --- a/openerp/addons/base/ir/ir_model.py +++ b/openerp/addons/base/ir/ir_model.py @@ -1087,13 +1087,20 @@ class ir_model_data(osv.osv): # Remove non-model records first, then model fields, and finish with models unlink_if_refcount((model, res_id) for model, res_id in to_unlink - if model not in ('ir.model','ir.model.fields')) + if model not in ('ir.model','ir.model.fields','ir.model.constraint')) + unlink_if_refcount((model, res_id) for model, res_id in to_unlink + if model == 'ir.model.constraint') + + ir_module_module = self.pool['ir.module.module'] + ir_model_constraint = self.pool['ir.model.constraint'] + modules_to_remove_ids = ir_module_module.search(cr, uid, [('name', 'in', modules_to_remove)], context=context) + constraint_ids = ir_model_constraint.search(cr, uid, [('module', 'in', modules_to_remove_ids)], context=context) + ir_model_constraint._module_data_uninstall(cr, uid, constraint_ids, context) + unlink_if_refcount((model, res_id) for model, res_id in to_unlink if model == 'ir.model.fields') ir_model_relation = self.pool.get('ir.model.relation') - ir_module_module = self.pool.get('ir.module.module') - modules_to_remove_ids = ir_module_module.search(cr, uid, [('name', 'in', modules_to_remove)]) relation_ids = ir_model_relation.search(cr, uid, [('module', 'in', modules_to_remove_ids)]) ir_model_relation._module_data_uninstall(cr, uid, relation_ids, context) diff --git a/openerp/addons/base/module/module.py b/openerp/addons/base/module/module.py index 6b2ef46f68d..6d64abc455b 100644 --- a/openerp/addons/base/module/module.py +++ b/openerp/addons/base/module/module.py @@ -434,11 +434,7 @@ class module(osv.osv): including the deletion of all database structures created by the module: tables, columns, constraints, etc.""" ir_model_data = self.pool.get('ir.model.data') - ir_model_constraint = self.pool.get('ir.model.constraint') modules_to_remove = [m.name for m in self.browse(cr, uid, ids, context)] - modules_to_remove_ids = [m.id for m in self.browse(cr, uid, ids, context)] - constraint_ids = ir_model_constraint.search(cr, uid, [('module', 'in', modules_to_remove_ids)]) - ir_model_constraint._module_data_uninstall(cr, uid, constraint_ids, context) ir_model_data._module_data_uninstall(cr, uid, modules_to_remove, context) self.write(cr, uid, ids, {'state': 'uninstalled'}) return True From ab9ac783db123fbcd5ef12cf232711a64a9aa97b Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Thu, 5 Jun 2014 13:46:53 +0200 Subject: [PATCH 10/19] [FIX] web: many2many field handle "no_create" option --- addons/web/static/src/js/view_form.js | 3 ++- addons/web/static/src/xml/base.xml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index ce4246708b4..e9f195b892a 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -4360,7 +4360,8 @@ instance.web.form.Many2ManyListView = instance.web.ListView.extend(/** @lends in pop.select_element( this.model, { - title: _t("Add: ") + this.m2m_field.string + title: _t("Add: ") + this.m2m_field.string, + no_create: this.m2m_field.options.no_create, }, new instance.web.CompoundDomain(this.m2m_field.build_domain(), ["!", ["id", "in", this.m2m_field.dataset.ids]]), this.m2m_field.build_context() diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 10840087acc..3fc40128cf6 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -1402,8 +1402,9 @@ + - or Cancel + or Cancel From d66c96ffa9a92963c28dd814e011e1f5cc508990 Mon Sep 17 00:00:00 2001 From: Holger Brunn Date: Thu, 5 Jun 2014 15:44:18 +0200 Subject: [PATCH 11/19] [FIX] project_timesheet: don't trigger write if there is nothing to write Triggering an empty write could break constraint (can not update past timesheet) (opw 606963) --- addons/project_timesheet/project_timesheet.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/project_timesheet/project_timesheet.py b/addons/project_timesheet/project_timesheet.py index 3540c0c4d87..5945d52c5c2 100644 --- a/addons/project_timesheet/project_timesheet.py +++ b/addons/project_timesheet/project_timesheet.py @@ -200,7 +200,8 @@ class project_work(osv.osv): if amount_unit and 'amount' in amount_unit.get('value',{}): vals_line['amount'] = amount_unit['value']['amount'] - self.pool.get('hr.analytic.timesheet').write(cr, uid, [line_id.id], vals_line, context=context) + if vals_line: + self.pool.get('hr.analytic.timesheet').write(cr, uid, [line_id.id], vals_line, context=context) return super(project_work,self).write(cr, uid, ids, vals, context) From 7129ec957a7b83e85895271ecbd7302028e06819 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Thu, 5 Jun 2014 15:53:28 +0200 Subject: [PATCH 12/19] [FIX] document_page: allow other users than administrator to create menu to a static page User should be at least have Configuration settings group to be allowed to create actions. Basic document page users do not have this rights, therefore we temporary give superuser_id to create the action This is related to rev 133c5033a092845e462b894c0d7739191480c709 --- addons/document_page/wizard/document_page_create_menu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/document_page/wizard/document_page_create_menu.py b/addons/document_page/wizard/document_page_create_menu.py index 3d99518430d..3678820d14a 100644 --- a/addons/document_page/wizard/document_page_create_menu.py +++ b/addons/document_page/wizard/document_page_create_menu.py @@ -70,7 +70,7 @@ class document_page_create_menu(osv.osv_memory): value['domain'] = "[('parent_id','=',%d)]" % (page.id) value['res_id'] = page.id - action_id = obj_action.create(cr, uid, value) + action_id = obj_action.create(cr, SUPERUSER_ID, value) # only the super user is allowed to create menu due to security rules on ir.values menu_id = obj_menu.create(cr, SUPERUSER_ID, { 'name': data.menu_name, From 4b3cec8ecfa575037e3c57da1ab555eec84c3f5f Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Thu, 5 Jun 2014 17:50:15 +0200 Subject: [PATCH 13/19] [FIX] website_event_track: remove trailing comma in speakers name in event tracks --- addons/website_event_track/views/website_event.xml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/addons/website_event_track/views/website_event.xml b/addons/website_event_track/views/website_event.xml index 8f48110e416..5de72538ab9 100644 --- a/addons/website_event_track/views/website_event.xml +++ b/addons/website_event_track/views/website_event.xml @@ -148,9 +148,7 @@
  • - - , - +
  • From 81ae6cdeebae9d45063c1f32bd410f46087fa1e7 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Thu, 5 Jun 2014 18:38:19 +0200 Subject: [PATCH 14/19] [IMP] stock: when checking the state of the product, do not recompute the quantity on every move but only the one currently browsing (optiomisation) --- addons/stock/stock.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index fa4fd3d7ffa..981b6f749c0 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -2200,12 +2200,12 @@ class stock_move(osv.osv): done.append(move.id) pickings[move.picking_id.id] = 1 r = res.pop(0) - product_uos_qty = self.pool.get('stock.move').onchange_quantity(cr, uid, ids, move.product_id.id, r[0], move.product_id.uom_id.id, move.product_id.uos_id.id)['value']['product_uos_qty'] + product_uos_qty = self.pool.get('stock.move').onchange_quantity(cr, uid, [move.id], move.product_id.id, r[0], move.product_id.uom_id.id, move.product_id.uos_id.id)['value']['product_uos_qty'] cr.execute('update stock_move set location_id=%s, product_qty=%s, product_uos_qty=%s where id=%s', (r[1], r[0],product_uos_qty, move.id)) while res: r = res.pop(0) - product_uos_qty = self.pool.get('stock.move').onchange_quantity(cr, uid, ids, move.product_id.id, r[0], move.product_id.uom_id.id, move.product_id.uos_id.id)['value']['product_uos_qty'] + product_uos_qty = self.pool.get('stock.move').onchange_quantity(cr, uid, [move.id], move.product_id.id, r[0], move.product_id.uom_id.id, move.product_id.uos_id.id)['value']['product_uos_qty'] move_id = self.copy(cr, uid, move.id, {'product_uos_qty': product_uos_qty, 'product_qty': r[0], 'location_id': r[1]}) done.append(move_id) if done: From 4b884ed100f3d04fc7aec35f6f4943ae847a989d Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Thu, 5 Jun 2014 18:58:01 +0200 Subject: [PATCH 15/19] [FIX] website: on adding a slide to slider, new slide is last on save Before, the new slide was set as first slide Moreover, the indicators were not correct neither --- addons/website/static/src/js/website.snippets.editor.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/addons/website/static/src/js/website.snippets.editor.js b/addons/website/static/src/js/website.snippets.editor.js index dca134deadb..858ab989dca 100644 --- a/addons/website/static/src/js/website.snippets.editor.js +++ b/addons/website/static/src/js/website.snippets.editor.js @@ -1299,7 +1299,9 @@ }, clean_for_save: function () { this._super(); - this.$target.find(".item").removeClass("next prev left right"); + this.$target.find(".item").removeClass("next prev left right active"); + this.$indicators.find('li').removeClass('active'); + this.$indicators.find('li:first').addClass('active'); if(!this.$target.find(".item.active").length) { this.$target.find(".item:first").addClass("active"); } From 6788edcdd0d515da0e562bd37215c0a05723ba90 Mon Sep 17 00:00:00 2001 From: Laurent Mignon Date: Thu, 5 Jun 2014 18:59:03 +0200 Subject: [PATCH 16/19] [FIX] ir_cron: use the same search criteria as when listing job to excecyte when acquiring the ock on the job before its execution to prevent running already executed job Backport of fix made in trunk --- openerp/addons/base/ir/ir_cron.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/openerp/addons/base/ir/ir_cron.py b/openerp/addons/base/ir/ir_cron.py index 24a522f6309..77c9835d9be 100644 --- a/openerp/addons/base/ir/ir_cron.py +++ b/openerp/addons/base/ir/ir_cron.py @@ -216,12 +216,21 @@ class ir_cron(osv.osv): lock_cr = db.cursor() try: # Try to grab an exclusive lock on the job row from within the task transaction + # Restrict to the same conditions as for the search since the job may have already + # been run by an other thread when cron is running in multi thread lock_cr.execute("""SELECT * FROM ir_cron - WHERE id=%s + WHERE numbercall != 0 + AND active + AND nextcall <= (now() at time zone 'UTC') + AND id=%s FOR UPDATE NOWAIT""", (job['id'],), log_exceptions=False) + locked_job = lock_cr.fetchone() + if not locked_job: + _logger.debug("Job `%s` already executed by another process/thread. skipping it", job['name']) + continue # Got the lock on the job row, run its code _logger.debug('Starting job `%s`.', job['name']) job_cr = db.cursor() From 306d5c89a07ab05eb1637e3efc80e83a773c24d8 Mon Sep 17 00:00:00 2001 From: Oliver Laurent Date: Thu, 5 Jun 2014 19:00:14 +0200 Subject: [PATCH 17/19] [FIX] orm: do not resize unlimited char fields --- openerp/osv/orm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 2341b92e169..6e91ba46721 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -3125,7 +3125,7 @@ class BaseModel(object): ('numeric', 'float', get_pg_type(f)[1], '::'+get_pg_type(f)[1]), ('float8', 'float', get_pg_type(f)[1], '::'+get_pg_type(f)[1]), ] - if f_pg_type == 'varchar' and f._type == 'char' and ((f.size is None and f_pg_size) or f_pg_size < f.size): + if f_pg_type == 'varchar' and f._type == 'char' and f_pg_size and (f.size is None or f_pg_size < f.size): cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k)) cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, pg_varchar(f.size))) cr.execute('UPDATE "%s" SET "%s"=temp_change_size::%s' % (self._table, k, pg_varchar(f.size))) From 517162ce145e78795030cd956e3a0e6e2c8144c3 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Fri, 6 Jun 2014 10:53:42 +0200 Subject: [PATCH 18/19] [FIX] orm: do not recompute m2o stored function field at read. The get() method of m2o function fields is used for 2 different things: - call the function defining the m2o - get the name_get representation of the value Until this pathc, only the first case was handled, resulting to a useless recomputation of the field when reading it. --- openerp/osv/fields.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index 17e6147f588..529f0563f8d 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -1142,9 +1142,17 @@ class function(_column): return result def get(self, cr, obj, ids, name, uid=False, context=None, values=None): - result = self._fnct(obj, cr, uid, ids, name, self._arg, context) + multi = self._multi + # if we already have a value, don't recompute it. + # This happen if case of stored many2one fields + if values and not multi and name in values[0]: + result = {v['id']: v[name] for v in values} + elif values and multi and all(n in values[0] for n in name): + result = {v['id']: dict({n: v[n]} for n in name) for v in values} + else: + result = self._fnct(obj, cr, uid, ids, name, self._arg, context) for id in ids: - if self._multi and id in result: + if multi and id in result: for field, value in result[id].iteritems(): if value: result[id][field] = self.postprocess(cr, uid, obj, field, value, context) From 6eacf9167177b3809700b1ae96604fef03fb226b Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Tue, 10 Jun 2014 11:15:52 +0200 Subject: [PATCH 19/19] [FIX] logging PostgreSQLHandler: do not insert {create,write}_uid As logs can be stored in any database, we can't insert create_uid and write_uid as it refer to the current database not the logging one, where FK may not match --- openerp/netsvc.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/openerp/netsvc.py b/openerp/netsvc.py index 15f02645d52..7dc1d62ecce 100644 --- a/openerp/netsvc.py +++ b/openerp/netsvc.py @@ -75,7 +75,6 @@ class PostgreSQLHandler(logging.Handler): def emit(self, record): ct = threading.current_thread() ct_db = getattr(ct, 'dbname', None) - ct_uid = getattr(ct, 'uid', None) dbname = tools.config['log_db'] or ct_db if dbname: cr = None @@ -86,10 +85,10 @@ class PostgreSQLHandler(logging.Handler): if traceback: msg = "%s\n%s" % (msg, traceback) level = logging.getLevelName(record.levelno) - val = (ct_uid, ct_uid, 'server', ct_db, record.name, level, msg, record.pathname, record.lineno, record.funcName) + val = ('server', ct_db, record.name, level, msg, record.pathname, record.lineno, record.funcName) cr.execute(""" - INSERT INTO ir_logging(create_date, write_date, create_uid, write_uid, type, dbname, name, level, message, path, line, func) - VALUES (NOW() at time zone 'UTC', NOW() at time zone 'UTC', %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) + INSERT INTO ir_logging(create_date, type, dbname, name, level, message, path, line, func) + VALUES (NOW() at time zone 'UTC', %s, %s, %s, %s, %s, %s, %s, %s) """, val ) cr.commit() except Exception, e: