@@ -1,5 +1,6 @@ | |||
{ | |||
"allow_copy": 0, | |||
"allow_guest_to_view": 0, | |||
"allow_import": 0, | |||
"allow_rename": 0, | |||
"beta": 0, | |||
@@ -21,6 +22,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "", | |||
@@ -48,6 +50,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Country", | |||
@@ -77,6 +80,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 1, | |||
"in_standard_filter": 0, | |||
"label": "Language", | |||
@@ -105,6 +109,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"length": 0, | |||
@@ -132,6 +137,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Time Zone", | |||
@@ -159,6 +165,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Setup Complete", | |||
@@ -187,6 +194,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Date and Number Format", | |||
@@ -214,6 +222,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Date Format", | |||
@@ -242,6 +251,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"length": 0, | |||
@@ -269,6 +279,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Number Format", | |||
@@ -297,12 +308,13 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Float Precision", | |||
"length": 0, | |||
"no_copy": 0, | |||
"options": "\n2\n3\n4\n5\n6", | |||
"options": "\n2\n3\n4\n5\n6\n7\n8\n9", | |||
"permlevel": 0, | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
@@ -314,6 +326,37 @@ | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"description": "If not set, the currency precision will depend on number format", | |||
"fieldname": "currency_precision", | |||
"fieldtype": "Select", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Currency Precision", | |||
"length": 0, | |||
"no_copy": 0, | |||
"options": "\n1\n2\n3\n4\n5\n6\n7\n8\n9", | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"remember_last_selected_value": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
@@ -325,6 +368,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Backups", | |||
@@ -355,6 +399,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Number of Backups", | |||
@@ -383,6 +428,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Background Workers", | |||
@@ -412,6 +458,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Enable Scheduled Jobs", | |||
@@ -439,6 +486,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Scheduler Last Event", | |||
@@ -467,6 +515,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Security", | |||
@@ -496,6 +545,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Session Expiry", | |||
@@ -526,6 +576,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Session Expiry Mobile", | |||
@@ -554,6 +605,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"length": 0, | |||
@@ -582,6 +634,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Allow only one session per user", | |||
@@ -611,6 +664,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Ignore User Permissions If Missing", | |||
@@ -639,6 +693,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "EMail", | |||
@@ -668,6 +723,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Email Footer Address", | |||
@@ -696,6 +752,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"length": 0, | |||
@@ -723,6 +780,7 @@ | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Disable Standard Email Footer", | |||
@@ -741,18 +799,18 @@ | |||
"unique": 0 | |||
} | |||
], | |||
"has_web_view": 0, | |||
"hide_heading": 0, | |||
"hide_toolbar": 0, | |||
"icon": "fa fa-cog", | |||
"idx": 0, | |||
"image_view": 0, | |||
"in_create": 0, | |||
"in_dialog": 0, | |||
"is_submittable": 0, | |||
"issingle": 1, | |||
"istable": 0, | |||
"max_attachments": 0, | |||
"modified": "2016-12-29 14:40:33.023468", | |||
"modified": "2017-04-13 02:23:18.660325", | |||
"modified_by": "Administrator", | |||
"module": "Core", | |||
"name": "System Settings", | |||
@@ -769,7 +827,6 @@ | |||
"export": 0, | |||
"if_owner": 0, | |||
"import": 0, | |||
"is_custom": 0, | |||
"permlevel": 0, | |||
"print": 0, | |||
"read": 1, | |||
@@ -784,6 +841,7 @@ | |||
"quick_entry": 1, | |||
"read_only": 0, | |||
"read_only_onload": 0, | |||
"show_name_in_global_search": 0, | |||
"sort_order": "ASC", | |||
"track_changes": 1, | |||
"track_seen": 0 |
@@ -441,22 +441,10 @@ def get_field_precision(df, doc=None, currency=None): | |||
precision = cint(df.precision) | |||
elif df.fieldtype == "Currency": | |||
number_format = None | |||
if not currency and doc: | |||
currency = get_field_currency(df, doc) | |||
if not currency: | |||
# use default currency | |||
currency = frappe.db.get_default("currency") | |||
if currency: | |||
number_format = frappe.db.get_value("Currency", currency, "number_format", cache=True) | |||
if not number_format: | |||
precision = cint(frappe.db.get_default("currency_precision")) | |||
if not precision: | |||
number_format = frappe.db.get_default("number_format") or "#,###.##" | |||
decimal_str, comma_str, precision = get_number_format_info(number_format) | |||
decimal_str, comma_str, precision = get_number_format_info(number_format) | |||
else: | |||
precision = cint(frappe.db.get_default("float_precision")) or 3 | |||
@@ -600,7 +600,11 @@ frappe.ui.form.ControlCurrency = frappe.ui.form.ControlFloat.extend({ | |||
// always round based on field precision or currency's precision | |||
// this method is also called in this.parse() | |||
if (!this.df.precision) { | |||
this.df.precision = get_number_format_info(this.get_number_format()).precision; | |||
if(frappe.boot.sysdefaults.currency_precision) { | |||
this.df.precision = frappe.boot.sysdefaults.currency_precision; | |||
} else { | |||
this.df.precision = get_number_format_info(this.get_number_format()).precision; | |||
} | |||
} | |||
return this.df.precision; | |||
@@ -52,8 +52,9 @@ frappe.form.formatters = { | |||
}, | |||
Currency: function(value, docfield, options, doc) { | |||
var currency = frappe.meta.get_field_currency(docfield, doc); | |||
var precision = docfield.precision || cint(frappe.boot.sysdefaults.currency_precision) || 2; | |||
return frappe.form.formatters._right((value==null || value==="") | |||
? "" : format_currency(value, currency, docfield.precision || null), options); | |||
? "" : format_currency(value, currency, docfield.precision), options); | |||
}, | |||
Check: function(value) { | |||
if(value) { | |||
@@ -59,16 +59,16 @@ function strip_number_groups(v, number_format) { | |||
frappe.number_format_info = { | |||
"#,###.##": {decimal_str:".", group_sep:",", precision:2}, | |||
"#.###,##": {decimal_str:",", group_sep:".", precision:2}, | |||
"# ###.##": {decimal_str:".", group_sep:" ", precision:2}, | |||
"# ###,##": {decimal_str:",", group_sep:" ", precision:2}, | |||
"#'###.##": {decimal_str:".", group_sep:"'", precision:2}, | |||
"#, ###.##": {decimal_str:".", group_sep:", ", precision:2}, | |||
"#,##,###.##": {decimal_str:".", group_sep:",", precision:2}, | |||
"#,###.###": {decimal_str:".", group_sep:",", precision:3}, | |||
"#.###": {decimal_str:"", group_sep:".", precision:0}, | |||
"#,###": {decimal_str:"", group_sep:",", precision:0}, | |||
"#,###.##": {decimal_str:".", group_sep:","}, | |||
"#.###,##": {decimal_str:",", group_sep:"."}, | |||
"# ###.##": {decimal_str:".", group_sep:" "}, | |||
"# ###,##": {decimal_str:",", group_sep:" "}, | |||
"#'###.##": {decimal_str:".", group_sep:"'"}, | |||
"#, ###.##": {decimal_str:".", group_sep:", "}, | |||
"#,##,###.##": {decimal_str:".", group_sep:","}, | |||
"#,###.###": {decimal_str:".", group_sep:","}, | |||
"#.###": {decimal_str:"", group_sep:"."}, | |||
"#,###": {decimal_str:"", group_sep:","}, | |||
} | |||
window.format_number = function(v, format, decimals){ | |||
@@ -127,6 +127,7 @@ window.format_number = function(v, format, decimals){ | |||
function format_currency(v, currency, decimals) { | |||
var format = get_number_format(currency); | |||
var symbol = get_currency_symbol(currency); | |||
var decimals = frappe.boot.sysdefaults.currency_precision || null; | |||
if(symbol) | |||
return symbol + " " + format_number(v, format, decimals); | |||
@@ -151,29 +152,19 @@ function get_currency_symbol(currency) { | |||
var global_number_format = null; | |||
function get_number_format(currency) { | |||
if(!global_number_format) { | |||
if (frappe.boot && frappe.boot.sysdefaults) { | |||
global_number_format = frappe.boot.sysdefaults.number_format | |||
|| frappe.model.get_value(":Currency", frappe.boot.sysdefaults.currency, "number_format"); | |||
} | |||
global_number_format = global_number_format || "#,###.##"; | |||
} | |||
var number_format; | |||
if(currency && frappe.boot) { | |||
number_format = frappe.model.get_value(":Currency", currency, | |||
"number_format"); | |||
} | |||
return number_format || global_number_format; | |||
return (frappe.boot && frappe.boot.sysdefaults.number_format) || "#,###.##"; | |||
} | |||
function get_number_format_info(format) { | |||
var info = frappe.number_format_info[format]; | |||
if(!info) { | |||
info = {decimal_str:".", group_sep:",", precision:2}; | |||
info = {decimal_str:".", group_sep:","}; | |||
} | |||
// get the precision from the number format | |||
info.precision = format.split(info.decimal_str).slice(1)[0].length; | |||
return info; | |||
} | |||
@@ -8,7 +8,7 @@ frappe.utils.full_name = function(fn, ln) { | |||
function fmt_money(v, format){ | |||
// deprecated! | |||
// for backward compatibility | |||
return format_number(v, format); | |||
return format_currency(v, format); | |||
} | |||
@@ -4,63 +4,7 @@ from __future__ import unicode_literals | |||
import frappe | |||
from frappe import _ | |||
from frappe.utils import flt, cstr | |||
def fmt_money(amount, precision=None): | |||
""" | |||
Convert to string with commas for thousands, millions etc | |||
""" | |||
number_format = frappe.db.get_default("number_format") or "#,###.##" | |||
decimal_str, comma_str, precision = get_number_format_info(number_format) | |||
amount = '%.*f' % (precision, flt(amount)) | |||
if amount.find('.') == -1: | |||
decimals = '' | |||
else: | |||
decimals = amount.split('.')[1] | |||
parts = [] | |||
minus = '' | |||
if flt(amount) < 0: | |||
minus = '-' | |||
amount = cstr(abs(flt(amount))).split('.')[0] | |||
if len(amount) > 3: | |||
parts.append(amount[-3:]) | |||
amount = amount[:-3] | |||
val = number_format=="#,##,###.##" and 2 or 3 | |||
while len(amount) > val: | |||
parts.append(amount[-val:]) | |||
amount = amount[:-val] | |||
parts.append(amount) | |||
parts.reverse() | |||
amount = comma_str.join(parts) + (precision and (decimal_str + decimals) or "") | |||
amount = minus + amount | |||
return amount | |||
def get_number_format_info(format): | |||
if format=="#.###": | |||
return "", ".", 0 | |||
elif format=="#,###": | |||
return "", ",", 0 | |||
elif format=="#,###.##" or format=="#,##,###.##": | |||
return ".", ",", 2 | |||
elif format=="#.###,##": | |||
return ",", ".", 2 | |||
elif format=="# ###.##": | |||
return ".", " ", 2 | |||
else: | |||
return ".", ",", 2 | |||
from frappe.utils import flt, cstr, fmt_money | |||
import unittest | |||
class TestFmtMoney(unittest.TestCase): | |||
@@ -119,6 +63,19 @@ class TestFmtMoney(unittest.TestCase): | |||
self.assertEquals(fmt_money(-100.3), "-100") | |||
self.assertEquals(fmt_money(-1000.3), "-1,000") | |||
def test_currency_precision(self): | |||
frappe.db.set_default("currency_precision", "4") | |||
frappe.db.set_default("number_format", "#,###.##") | |||
self.assertEquals(fmt_money(100), "100.0000") | |||
self.assertEquals(fmt_money(1000), "1,000.0000") | |||
self.assertEquals(fmt_money(10000), "10,000.0000") | |||
self.assertEquals(fmt_money(100000), "100,000.0000") | |||
self.assertEquals(fmt_money(1000000), "1,000,000.0000") | |||
self.assertEquals(fmt_money(10000000), "10,000,000.0000") | |||
self.assertEquals(fmt_money(100000000), "100,000,000.0000") | |||
self.assertEquals(fmt_money(1000000000), "1,000,000,000.0000") | |||
frappe.db.set_default("currency_precision", "") | |||
if __name__=="__main__": | |||
frappe.connect() | |||
unittest.main() |
@@ -348,12 +348,9 @@ def fmt_money(amount, precision=None, currency=None): | |||
""" | |||
Convert to string with commas for thousands, millions etc | |||
""" | |||
number_format = None | |||
if currency: | |||
number_format = frappe.db.get_value("Currency", currency, "number_format", cache=True) | |||
if not number_format: | |||
number_format = frappe.db.get_default("number_format") or "#,###.##" | |||
number_format = frappe.db.get_default("number_format") or "#,###.##" | |||
if precision is None: | |||
precision = cint(frappe.db.get_default('currency_precision')) or None | |||
decimal_str, comma_str, number_format_precision = get_number_format_info(number_format) | |||