diff --git a/frappe/app.py b/frappe/app.py index 2dc6c2fec0..09013cd7f4 100644 --- a/frappe/app.py +++ b/frappe/app.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import sys, os import json import logging +import MySQLdb from werkzeug.wrappers import Request, Response from werkzeug.local import LocalManager @@ -70,6 +71,14 @@ def application(request): except Exception, e: http_status_code = getattr(e, "http_status_code", 500) + if (http_status_code==500 + and isinstance(e, MySQLdb.OperationalError) + and e.args[0] in (1205, 1213)): + # 1205 = lock wait timeout + # 1213 = deadlock + # code 409 represents conflict + http_status_code = 409 + if frappe.local.is_ajax: response = frappe.utils.response.report_error(http_status_code) else: diff --git a/frappe/desk/form/meta.py b/frappe/desk/form/meta.py index c9808451d6..9bfca60494 100644 --- a/frappe/desk/form/meta.py +++ b/frappe/desk/form/meta.py @@ -68,6 +68,7 @@ class FormMeta(Meta): self.set("__listview_template", get_html_format(listview_template)) self.add_code_via_hook("doctype_js", "__js") + self.add_code_via_hook("doctype_list_js", "__list_js") self.add_custom_script() def _add_code(self, path, fieldname): diff --git a/frappe/model/rename_doc.py b/frappe/model/rename_doc.py index 0792d59270..44e9d19308 100644 --- a/frappe/model/rename_doc.py +++ b/frappe/model/rename_doc.py @@ -84,7 +84,9 @@ def rename_parent_and_child(doctype, old, new, meta): update_child_docs(old, new, meta) def validate_rename(doctype, new, meta, merge, force, ignore_permissions): - exists = frappe.db.get_value(doctype, new) + # using for update so that it gets locked and someone else cannot edit it while this rename is going on! + exists = frappe.db.sql("select name from `tab{doctype}` where name=%s for update".format(doctype=doctype), new) + exists = exists[0][0] if exists else None if merge and not exists: frappe.msgprint(_("{0} {1} does not exist, select a new target to merge").format(doctype, new), raise_exception=1) diff --git a/frappe/public/js/frappe/misc/number_format.js b/frappe/public/js/frappe/misc/number_format.js index 5e344fa9c7..35d093c46b 100644 --- a/frappe/public/js/frappe/misc/number_format.js +++ b/frappe/public/js/frappe/misc/number_format.js @@ -178,7 +178,7 @@ function _round(num, precision) { var m = Math.pow(10, d); var n = +(d ? num * m : num).toFixed(8); // Avoid rounding errors var i = Math.floor(n), f = n - i; - var r = (f == 0.5) ? ((i % 2 == 0) ? i : i + 1) : Math.round(n); + var r = (!precision && f == 0.5) ? ((i % 2 == 0) ? i : i + 1) : Math.round(n); return d ? r / m : r; } diff --git a/frappe/public/js/frappe/request.js b/frappe/public/js/frappe/request.js index 1753763652..00b0e0a546 100644 --- a/frappe/public/js/frappe/request.js +++ b/frappe/public/js/frappe/request.js @@ -68,6 +68,9 @@ frappe.request.call = function(opts) { msgprint(__("Not permitted")); }, + 409: function(xhr) { + msgprint(__("Another transaction is blocking this one. Please try again in a few seconds.")); + }, 417: function(data, xhr) { if(typeof data === "string") data = JSON.parse(data); opts.error_callback && opts.error_callback(data, xhr.responseText); diff --git a/frappe/utils/data.py b/frappe/utils/data.py index 08707b33e0..dd0db4cd87 100644 --- a/frappe/utils/data.py +++ b/frappe/utils/data.py @@ -210,12 +210,14 @@ def flt(s, precision=None): """Convert to float (ignore commas)""" if isinstance(s, basestring): s = s.replace(',','') + try: num = float(s) if precision is not None: num = rounded(num, precision) except Exception: num = 0 + return num def cint(s): @@ -235,7 +237,7 @@ def cstr(s): return unicode(s) def rounded(num, precision=0): - """round method for round halfs to nearest even algorithm""" + """round method for round halfs to nearest even algorithm aka banker's rounding - compatible with python3""" precision = cint(precision) multiplier = 10 ** precision @@ -245,7 +247,7 @@ def rounded(num, precision=0): floor = math.floor(num) decimal_part = num - floor - if decimal_part == 0.5: + if not precision and decimal_part == 0.5: num = floor if (floor % 2 == 0) else floor + 1 else: num = round(num)