diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml
index 61c397364b9..fe701a85661 100644
--- a/addons/account/account_invoice_view.xml
+++ b/addons/account/account_invoice_view.xml
@@ -60,7 +60,7 @@
REFERENCES
Order number: ${object.name}
- Order total: ${object.amount_total} ${object.pricelist_id.currency_id.name}
+ Order total: ${object.amount_total} ${object.currency_id.name}
Order date: ${object.date_order}
% if object.origin:
Order reference: ${object.origin}
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index e7b83b4894e..fa074bb6bb2 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 60fb536ca96..c442ea32549 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 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 7a869d72d55..dee685602ff 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 62b6fa319e0..d348d171076 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'])
+ 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,
- )
+ values.update(
+ status_message=werkzeug.http.HTTP_STATUS_CODES[code],
+ status_code=code,
+ )
- if not request.uid:
- self._auth_method_public()
+ 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')
+ 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
+ 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 e49ed5f4089..89eae9f4a49 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 bfb3c142ca1..3f71340cb2d 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 c5924b5d15d..45a09f96ff5 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 8d6edb88688..af046836192 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):