diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml index 61c397364b9e753e406a8c876fa2b2b5d471aa5c..fe701a85661243d37715fa6bdf2188e7f12a0c19 100644 --- a/addons/account/account_invoice_view.xml +++ b/addons/account/account_invoice_view.xml @@ -60,7 +60,7 @@ </group> <group> <field domain="[('company_id', '=', parent.company_id), ('journal_id', '=', parent.journal_id), ('type', '<>', 'view')]" name="account_id" on_change="onchange_account_id(product_id, parent.partner_id, parent.type, parent.fiscal_position,account_id)" groups="account.group_account_user"/> - <field name="invoice_line_tax_id" context="{'type':parent.type}" domain="[('parent_id','=',False),('company_id', '=', parent.company_id)]" widget="many2many_tags"/> + <field name="invoice_line_tax_id" context="{'type':parent.get('type')}" domain="[('parent_id','=',False),('company_id', '=', parent.company_id)]" widget="many2many_tags"/> <field domain="[('type','<>','view'), ('company_id', '=', parent.company_id)]" name="account_analytic_id" groups="analytic.group_analytic_accounting"/> <field name="company_id" groups="base.group_multi_company" readonly="1"/> </group> diff --git a/addons/account/report/account_aged_partner_balance.py b/addons/account/report/account_aged_partner_balance.py index 3fd83c19207090a3ef968b030a852b55999fbeb1..2e3c9b7c3748d2604c586cd4868e0b64133058b0 100644 --- a/addons/account/report/account_aged_partner_balance.py +++ b/addons/account/report/account_aged_partner_balance.py @@ -161,7 +161,7 @@ class aged_trial_report(report_sxw.rml_parse, common_report_header): dates_query += ' < %s)' args_list += (form[str(i)]['stop'],) args_list += (self.date_from,) - self.cr.execute('''SELECT l.partner_id, SUM(l.debit-l.credit) + self.cr.execute('''SELECT l.partner_id, SUM(l.debit-l.credit), l.reconcile_partial_id FROM account_move_line AS l, account_account, account_move am WHERE (l.account_id = account_account.id) AND (l.move_id=am.id) AND (am.state IN %s) @@ -173,12 +173,24 @@ class aged_trial_report(report_sxw.rml_parse, common_report_header): AND account_account.active AND ''' + dates_query + ''' AND (l.date <= %s) - GROUP BY l.partner_id''', args_list) - t = self.cr.fetchall() - d = {} - for i in t: - d[i[0]] = i[1] - history.append(d) + GROUP BY l.partner_id, l.reconcile_partial_id''', args_list) + partners_partial = self.cr.fetchall() + partners_amount = dict((i[0],0) for i in partners_partial) + for partner_info in partners_partial: + if partner_info[2]: + # in case of partial reconciliation, we want to keep the left amount in the oldest period + self.cr.execute('''SELECT MIN(COALESCE(date_maturity,date)) FROM account_move_line WHERE reconcile_partial_id = %s''', (partner_info[2],)) + date = self.cr.fetchall() + if date and args_list[-3] <= date[0][0] <= args_list[-2]: + # partial reconcilation + self.cr.execute('''SELECT SUM(l.debit-l.credit) + FROM account_move_line AS l + WHERE l.reconcile_partial_id = %s''', (partner_info[2],)) + unreconciled_amount = self.cr.fetchall() + partners_amount[partner_info[0]] += unreconciled_amount[0][0] + else: + partners_amount[partner_info[0]] += partner_info[1] + history.append(partners_amount) for partner in partners: values = {} diff --git a/addons/account_analytic_analysis/account_analytic_analysis.py b/addons/account_analytic_analysis/account_analytic_analysis.py index 36b829e07364beab9ea4ff26f9d12a951f187e00..31927036a38a1299c363e25a34cebf12b9692b07 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis.py +++ b/addons/account_analytic_analysis/account_analytic_analysis.py @@ -82,7 +82,7 @@ class account_analytic_invoice_line(osv.osv): if not name: name = self.pool.get('product.product').name_get(cr, uid, [res.id], context=local_context)[0][1] if res.description_sale: - result['name'] += '\n'+res.description_sale + name += '\n'+res.description_sale result.update({'name': name or False,'uom_id': uom_id or res.uom_id.id or False, 'price_unit': price}) @@ -756,6 +756,8 @@ class account_analytic_account(osv.osv): new_date = next_date+relativedelta(days=+interval) elif contract.recurring_rule_type == 'weekly': new_date = next_date+relativedelta(weeks=+interval) + elif contract.recurring_rule_type == 'yearly': + new_date = next_date+relativedelta(years=+interval) else: new_date = next_date+relativedelta(months=+interval) self.write(cr, uid, [contract.id], {'recurring_next_date': new_date.strftime('%Y-%m-%d')}, context=context) diff --git a/addons/account_analytic_analysis/account_analytic_analysis_view.xml b/addons/account_analytic_analysis/account_analytic_analysis_view.xml index a6fe828926aa64e1268bb486651d93e829218c2d..af4caae608f80b9f56d9a07d895e23854a10418d 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis_view.xml +++ b/addons/account_analytic_analysis/account_analytic_analysis_view.xml @@ -166,7 +166,7 @@ <div attrs="{'invisible': [('recurring_invoices','=',False)]}"> <field name="recurring_invoice_line_ids"> <tree string="Account Analytic Lines" editable="bottom"> - <field name="product_id" on_change="product_id_change(product_id, uom_id, quantity, name, parent.partner_id, price_unit, parent.pricelist_id, parent.company_id)"/> + <field name="product_id" on_change="product_id_change(product_id, uom_id, quantity, False, parent.partner_id, False, parent.pricelist_id, parent.company_id)"/> <field name="name"/> <field name="quantity"/> <field name="uom_id"/> diff --git a/addons/account_budget/account_budget.py b/addons/account_budget/account_budget.py index 753a5df79f4642308c0f71388090edd51ed4e993..78e85716bbdc3069a210092fc153ce80d617a403 100644 --- a/addons/account_budget/account_budget.py +++ b/addons/account_budget/account_budget.py @@ -22,6 +22,7 @@ import datetime from openerp.osv import fields, osv +from openerp.tools import ustr from openerp.tools.translate import _ import openerp.addons.decimal_precision as dp @@ -114,7 +115,7 @@ class crossovered_budget_lines(osv.osv): for line in self.browse(cr, uid, ids, context=context): acc_ids = [x.id for x in line.general_budget_id.account_ids] if not acc_ids: - raise osv.except_osv(_('Error!'),_("The Budget '%s' has no accounts!") % str(line.general_budget_id.name)) + raise osv.except_osv(_('Error!'),_("The Budget '%s' has no accounts!") % ustr(line.general_budget_id.name)) date_to = line.date_to date_from = line.date_from if context.has_key('wizard_date_from'): diff --git a/addons/delivery/delivery.py b/addons/delivery/delivery.py index 3827baaf1c5d791abd35c35f159b098ebaa5b22d..59542eefc90911926b239a2d099578b2677a2f39 100644 --- a/addons/delivery/delivery.py +++ b/addons/delivery/delivery.py @@ -191,14 +191,15 @@ class delivery_grid(osv.osv): total = 0 weight = 0 volume = 0 + product_uom_obj = self.pool.get('product.uom') for line in order.order_line: if not line.product_id or line.is_delivery: continue - weight += (line.product_id.weight or 0.0) * line.product_uom_qty - volume += (line.product_id.volume or 0.0) * line.product_uom_qty + q = product_uom_obj._compute_qty(cr, uid, line.product_uom.id, line.product_uos_qty, line.product_id.uom_id.id) + weight += (line.product_id.weight or 0.0) * q + volume += (line.product_id.volume or 0.0) * q total = order.amount_total or 0.0 - return self.get_price_from_picking(cr, uid, id, total,weight, volume, context=context) def get_price_from_picking(self, cr, uid, id, total, weight, volume, context=None): diff --git a/addons/hr/static/src/img/default_image.png b/addons/hr/static/src/img/default_image.png new file mode 100644 index 0000000000000000000000000000000000000000..87fdbc5af55a640792e97a49e80b0e7e47dfcd8e Binary files /dev/null and b/addons/hr/static/src/img/default_image.png differ diff --git a/addons/hr_recruitment/hr_recruitment.py b/addons/hr_recruitment/hr_recruitment.py index fa51f58d6961cfd22f772d843c03398efde5eabd..0d27418e40346a725cce5556d1a5c6465e20f77c 100644 --- a/addons/hr_recruitment/hr_recruitment.py +++ b/addons/hr_recruitment/hr_recruitment.py @@ -115,6 +115,15 @@ class hr_applicant(osv.Model): return int(department_ids[0][0]) return None + def _get_default_company_id(self, cr, uid, department_id=None, context=None): + company_id = False + if department_id: + department = self.pool['hr.department'].browse(cr, uid, department_id, context=context) + company_id = department.company_id.id if department and department.company_id else False + if not company_id: + company_id = self.pool['res.company']._company_default_get(cr, uid, 'hr.applicant', context=context) + return company_id + def _read_group_stage_ids(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None): access_rights_uid = access_rights_uid or uid stage_obj = self.pool.get('hr.recruitment.stage') @@ -232,7 +241,7 @@ class hr_applicant(osv.Model): 'user_id': lambda s, cr, uid, c: uid, 'stage_id': lambda s, cr, uid, c: s._get_default_stage_id(cr, uid, c), 'department_id': lambda s, cr, uid, c: s._get_default_department_id(cr, uid, c), - 'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'hr.applicant', context=c), + 'company_id': lambda s, cr, uid, c: s._get_default_company_id(cr, uid, s._get_default_department_id(cr, uid, c), c), 'color': 0, 'date_last_stage_update': fields.datetime.now, } diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 99a7751e15e9a5633406a421070d54a7f2186842..e5eca7246595c8776cf42bbea37d945353f51773 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -919,15 +919,45 @@ openerp.mail = function (session) { this.$('.oe_mail_expand').on('click', this.on_expand); this.$('.oe_mail_reduce').on('click', this.on_expand); this.$('.oe_mail_action_model').on('click', this.on_record_clicked); + this.$('.oe_mail_action_author').on('click', this.on_record_author_clicked); }, on_record_clicked: function (event) { + event.preventDefault(); + var self = this; var state = { 'model': this.model, 'id': this.res_id, 'title': this.record_name }; session.webclient.action_manager.do_push_state(state); + this.context.params = { + model: this.model, + res_id: this.res_id, + }; + this.thread.ds_thread.call("message_redirect_action", {context: this.context}).then(function(action){ + self.do_action(action); + }); + }, + + on_record_author_clicked: function (event) { + event.preventDefault(); + var partner_id = $(event.target).data('partner'); + var state = { + 'model': 'res.partner', + 'id': partner_id, + 'title': this.record_name + }; + session.webclient.action_manager.do_push_state(state); + var action = { + type:'ir.actions.act_window', + view_type: 'form', + view_mode: 'form', + res_model: 'res.partner', + views: [[false, 'form']], + res_id: partner_id, + } + this.do_action(action); }, /* Call the on_compose_message on the thread of this message. */ diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index 28cbbca1f2cd66af9a2ef654afb966b8a41aacbb..2a4ac8d1bf90e50155f60f86c1ea94dbf8fa5eb2 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -284,7 +284,7 @@ <t t-if="widget.attachment_ids.length > 0"> <div class="oe_msg_attachment_list"></div> </t> - <a t-if="widget.author_id and widget.options.show_link and widget.author_id[0]" t-attf-href="#model=res.partner&id=#{widget.author_id[0]}"><t t-esc="widget.author_id[2]"/></a> + <a t-if="widget.author_id and widget.options.show_link and widget.author_id[0]" t-attf-href="#model=res.partner&id=#{widget.author_id[0]}" t-att-data-partner="widget.author_id[0]" class="oe_mail_action_author"><t t-esc="widget.author_id[2]"/></a> <span t-if="widget.author_id and (!widget.options.show_link or !widget.author_id[0])"><t t-esc="widget.author_id[2]"/></span> <t t-if="widget.type == 'notification'"> updated document @@ -304,7 +304,7 @@ <t t-if="widget.type == 'notification' or ( (widget.type == 'email' or widget.type == 'comment') and (widget.subtype or widget.partner_ids.length > 0))" t-foreach="widget.partner_ids.slice(0, 3)" t-as="partner"> <span t-attf-class="oe_partner_follower"> - <a t-if="widget.options.show_link" t-attf-href="#model=res.partner&id=#{partner[0]}"><t t-esc="partner[1]"/></a> + <a t-if="widget.options.show_link" t-attf-href="#model=res.partner&id=#{partner[0]}" t-att-data-partner="partner[0]" class="oe_mail_action_author"><t t-esc="partner[1]"/></a> <t t-if="!widget.options.show_link" t-esc="partner[1]"/> </span> <t t-if="!partner_last">,</t> diff --git a/addons/pad/static/src/img/pad_link_companies.jpeg b/addons/pad/static/src/img/pad_link_companies.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..1bce3a5618652970429d1febfd7c613c1c330755 Binary files /dev/null and b/addons/pad/static/src/img/pad_link_companies.jpeg differ diff --git a/addons/purchase/edi/purchase_order_action_data.xml b/addons/purchase/edi/purchase_order_action_data.xml index 5bb56e8ab15cbd7ec44d6b7d2bd21c27af6322fd..51d075b0ce05d09d164443fa1b25e9c87302dbbf 100644 --- a/addons/purchase/edi/purchase_order_action_data.xml +++ b/addons/purchase/edi/purchase_order_action_data.xml @@ -37,7 +37,7 @@ <p style="border-left: 1px solid #8e0000; margin-left: 30px;"> <strong>REFERENCES</strong><br /> Order number: <strong>${object.name}</strong><br /> - Order total: <strong>${object.amount_total} ${object.pricelist_id.currency_id.name}</strong><br /> + Order total: <strong>${object.amount_total} ${object.currency_id.name}</strong><br /> Order date: ${object.date_order}<br /> % if object.origin: Order reference: ${object.origin}<br /> diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index e7b83b4894ea13a9d3af6bd51c0f49e6268ae455..fa074bb6bb285150d70182d1b1dbd65bee8cc85e 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -192,7 +192,7 @@ class purchase_order(osv.osv): 'picking_ids': fields.one2many('stock.picking.in', 'purchase_id', 'Picking List', readonly=True, help="This is the list of incoming shipments that have been generated for this purchase order."), 'shipped':fields.boolean('Received', readonly=True, select=True, help="It indicates that a picking has been done"), 'shipped_rate': fields.function(_shipped_rate, string='Received Ratio', type='float'), - 'invoiced': fields.function(_invoiced, string='Invoice Received', type='boolean', help="It indicates that an invoice has been paid"), + 'invoiced': fields.function(_invoiced, string='Invoice Received', type='boolean', help="It indicates that an invoice has been validated"), 'invoiced_rate': fields.function(_invoiced_rate, string='Invoiced', type='float'), 'invoice_method': fields.selection([('manual','Based on Purchase Order lines'),('order','Based on generated draft invoice'),('picking','Based on incoming shipments')], 'Invoicing Control', required=True, readonly=True, states={'draft':[('readonly',False)], 'sent':[('readonly',False)]}, diff --git a/addons/report_webkit/webkit_report.py b/addons/report_webkit/webkit_report.py index 60fb536ca961c3275bc9062fe5f06838d7a3c0ad..c442ea32549ae210a0b06ef5167a161e027e7862 100644 --- a/addons/report_webkit/webkit_report.py +++ b/addons/report_webkit/webkit_report.py @@ -156,8 +156,8 @@ class WebKitParser(report_sxw): """Call webkit in order to generate pdf""" if not webkit_header: webkit_header = report_xml.webkit_header - tmp_dir = tempfile.gettempdir() - out_filename = tempfile.mktemp(suffix=".pdf", prefix="webkit.tmp.") + fd, out_filename = tempfile.mkstemp(suffix=".pdf", + prefix="webkit.tmp.") file_to_del = [out_filename] if comm_path: command = [comm_path] @@ -168,25 +168,15 @@ class WebKitParser(report_sxw): # default to UTF-8 encoding. Use <meta charset="latin-1"> to override. command.extend(['--encoding', 'utf-8']) if header : - head_file = file( os.path.join( - tmp_dir, - str(time.time()) + '.head.html' - ), - 'w' - ) - head_file.write(self._sanitize_html(header.encode('utf-8'))) - head_file.close() + with tempfile.NamedTemporaryFile(suffix=".head.html", + delete=False) as head_file: + head_file.write(self._sanitize_html(header.encode('utf-8'))) file_to_del.append(head_file.name) command.extend(['--header-html', head_file.name]) if footer : - foot_file = file( os.path.join( - tmp_dir, - str(time.time()) + '.foot.html' - ), - 'w' - ) - foot_file.write(self._sanitize_html(footer.encode('utf-8'))) - foot_file.close() + with tempfile.NamedTemporaryFile(suffix=".foot.html", + delete=False) as foot_file: + foot_file.write(self._sanitize_html(footer.encode('utf-8'))) file_to_del.append(foot_file.name) command.extend(['--footer-html', foot_file.name]) @@ -204,10 +194,10 @@ class WebKitParser(report_sxw): command.extend(['--page-size', str(webkit_header.format).replace(',', '.')]) count = 0 for html in html_list : - html_file = file(os.path.join(tmp_dir, str(time.time()) + str(count) +'.body.html'), 'w') - count += 1 - html_file.write(self._sanitize_html(html.encode('utf-8'))) - html_file.close() + with tempfile.NamedTemporaryFile(suffix="%d.body.html" %count, + delete=False) as html_file: + count += 1 + html_file.write(self._sanitize_html(html.encode('utf-8'))) file_to_del.append(html_file.name) command.append(html_file.name) command.append(out_filename) @@ -227,9 +217,9 @@ class WebKitParser(report_sxw): if status : raise except_osv(_('Webkit error' ), _("The command 'wkhtmltopdf' failed with error code = %s. Message: %s") % (status, error_message)) - pdf_file = open(out_filename, 'rb') - pdf = pdf_file.read() - pdf_file.close() + with open(out_filename, 'rb') as pdf_file: + pdf = pdf_file.read() + os.close(fd) finally: if stderr_fd is not None: os.close(stderr_fd) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 7a869d72d55f7925ca7457ff79d4d302d7a11330..dee685602ff3da736f74957943a27b15e9e3a3ff 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -4337,7 +4337,11 @@ instance.web.form.One2ManyListView = instance.web.ListView.extend({ else return $.when(); }).done(function () { - if (!self.o2m.options.reload_on_button) { + var ds = self.o2m.dataset; + var cached_records = _.any([ds.to_create, ds.to_delete, ds.to_write], function(value) { + return value.length; + }); + if (!self.o2m.options.reload_on_button && !cached_records) { self.handle_button(name, id, callback); }else { self.handle_button(name, id, function(){ diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py index 62b6fa319e03021f592aa75d4c65723e6f60004e..d348d171076d3966a4dd9db203e66b45a9b0a46f 100644 --- a/addons/website/models/ir_http.py +++ b/addons/website/models/ir_http.py @@ -126,50 +126,50 @@ class ir_http(orm.AbstractModel): return response def _handle_exception(self, exception=None, code=500): - res = super(ir_http, self)._handle_exception(exception) - if isinstance(exception, werkzeug.exceptions.HTTPException) and hasattr(exception, 'response') and exception.response: - return exception.response + try: + return super(ir_http, self)._handle_exception(exception) + except Exception: attach = self._serve_attachment() if attach: return attach - if getattr(request, 'website_enabled', False) and request.website: - values = dict( - exception=exception, - traceback=traceback.format_exc(exception), - ) - if exception: - code = getattr(exception, 'code', code) - if isinstance(exception, ir_qweb.QWebException): - values.update(qweb_exception=exception) - if isinstance(exception.qweb.get('cause'), openerp.exceptions.AccessError): - code = 403 - if code == 500: - logger.error("500 Internal Server Error:\n\n%s", values['traceback']) - if 'qweb_exception' in values: - view = request.registry.get("ir.ui.view") - views = view._views_get(request.cr, request.uid, exception.qweb['template'], request.context) - to_reset = [v for v in views if v.model_data_id.noupdate is True] - values['views'] = to_reset - elif code == 403: - logger.warn("403 Forbidden:\n\n%s", values['traceback']) - - values.update( - status_message=werkzeug.http.HTTP_STATUS_CODES[code], - status_code=code, - ) - - if not request.uid: - self._auth_method_public() - - try: - html = request.website._render('website.%s' % code, values) - except Exception: - html = request.website._render('website.http_error', values) - return werkzeug.wrappers.Response(html, status=code, content_type='text/html;charset=utf-8') - - return res + if getattr(request, 'website_enabled', False) and request.website: + values = dict( + exception=exception, + traceback=traceback.format_exc(exception), + ) + if exception: + code = getattr(exception, 'code', code) + if isinstance(exception, ir_qweb.QWebException): + values.update(qweb_exception=exception) + if isinstance(exception.qweb.get('cause'), openerp.exceptions.AccessError): + code = 403 + if code == 500: + logger.error("500 Internal Server Error:\n\n%s", values['traceback']) + if 'qweb_exception' in values: + view = request.registry.get("ir.ui.view") + views = view._views_get(request.cr, request.uid, exception.qweb['template'], request.context) + to_reset = [v for v in views if v.model_data_id.noupdate is True] + values['views'] = to_reset + elif code == 403: + logger.warn("403 Forbidden:\n\n%s", values['traceback']) + + values.update( + status_message=werkzeug.http.HTTP_STATUS_CODES[code], + status_code=code, + ) + + if not request.uid: + self._auth_method_public() + + try: + html = request.website._render('website.%s' % code, values) + except Exception: + html = request.website._render('website.http_error', values) + return werkzeug.wrappers.Response(html, status=code, content_type='text/html;charset=utf-8') + + raise class ModelConverter(ir.ir_http.ModelConverter): def __init__(self, url_map, model=False, domain='[]'): diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index e49ed5f408997d5d6a73b5cfc4e745bb3e3527ba..89eae9f4a49c87cf5bfd5885985ce65f8e71b3df 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -78,8 +78,8 @@ class table_compute(object): index = 0 maxy = 0 for p in products: - x = p.website_size_x - y = p.website_size_y + x = min(max(p.website_size_x, 1), PPR) + y = min(max(p.website_size_y, 1), PPR) if index>PPG: x = y = 1 diff --git a/addons/website_sale/models/product.py b/addons/website_sale/models/product.py index bfb3c142ca198793d5f4ead727b9519dde38a39a..3f71340cb2d5f82f6f6c6d86fd2a6400e26f5148 100644 --- a/addons/website_sale/models/product.py +++ b/addons/website_sale/models/product.py @@ -33,6 +33,7 @@ class product_template(osv.Model): _inherit = ["product.template", "website.seo.metadata"] _order = 'website_published desc, website_sequence desc, name' _name = 'product.template' + _mail_post_access = 'read' def _website_url(self, cr, uid, ids, field_name, arg, context=None): res = dict.fromkeys(ids, '') diff --git a/openerp/http.py b/openerp/http.py index c5924b5d15d644b92784d940d973ac125589cd25..45a09f96ff570a35320d05a7f9eb1e9f3b60b6b9 100644 --- a/openerp/http.py +++ b/openerp/http.py @@ -268,6 +268,9 @@ class WebRequest(object): to abitrary responses. Anything returned (except None) will be used as response.""" self._failed = exception # prevent tx commit + if isinstance(exception, werkzeug.exceptions.HTTPException): + return exception + raise def _call_function(self, *args, **kwargs): request = self @@ -448,18 +451,20 @@ class JsonRequest(WebRequest): def _handle_exception(self, exception): """Called within an except block to allow converting exceptions to abitrary responses. Anything returned (except None) will - be used as response.""" - super(JsonRequest, self)._handle_exception(exception) - _logger.exception("Exception during JSON request handling.") - error = { - 'code': 200, - 'message': "OpenERP Server Error", - 'data': serialize_exception(exception) - } - if isinstance(exception, AuthenticationError): - error['code'] = 100 - error['message'] = "OpenERP Session Invalid" - return self._json_response(error=error) + be used as response.""" + try: + return super(JsonRequest, self)._handle_exception(exception) + except Exception: + _logger.exception("Exception during JSON request handling.") + error = { + 'code': 200, + 'message': "OpenERP Server Error", + 'data': serialize_exception(exception) + } + if isinstance(exception, AuthenticationError): + error['code'] = 100 + error['message'] = "OpenERP Session Invalid" + return self._json_response(error=error) def dispatch(self): """ Calls the method asked for by the JSON-RPC2 or JSONP request diff --git a/openerp/report/render/rml2pdf/trml2pdf.py b/openerp/report/render/rml2pdf/trml2pdf.py index 8d6edb8868815af39292519ff27e405b54503ab2..af046836192be2f56201c5276813349987f0b317 100644 --- a/openerp/report/render/rml2pdf/trml2pdf.py +++ b/openerp/report/render/rml2pdf/trml2pdf.py @@ -1007,6 +1007,8 @@ class _rml_template(object): if story_cnt > 0: fis.append(platypus.PageBreak()) fis += r.render(node_story) + # Reset Page Number with new story tag + fis.append(PageReset()) story_cnt += 1 try: if self.localcontext and self.localcontext.get('internal_header',False):