@@ -13,7 +13,7 @@ import os, sys, importlib, inspect, json | |||
from .exceptions import * | |||
from .utils.jinja import get_jenv, get_template, render_template | |||
__version__ = '8.0.65' | |||
__version__ = '8.0.66' | |||
__title__ = "Frappe Framework" | |||
local = Local() | |||
@@ -149,10 +149,12 @@ scheduler_events = { | |||
"frappe.utils.scheduler.restrict_scheduler_events_if_dormant", | |||
"frappe.email.doctype.auto_email_report.auto_email_report.send_daily", | |||
"frappe.core.doctype.feedback_request.feedback_request.delete_feedback_request", | |||
"frappe.core.doctype.authentication_log.authentication_log.clear_authentication_logs", | |||
"frappe.core.doctype.authentication_log.authentication_log.clear_authentication_logs" | |||
], | |||
"daily_long": [ | |||
"frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backups_daily" | |||
], | |||
"weekly": [ | |||
"weekly_long": [ | |||
"frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backups_weekly" | |||
], | |||
"monthly": [ | |||
@@ -5,10 +5,17 @@ | |||
from __future__ import unicode_literals | |||
import frappe | |||
import requests | |||
import socket | |||
from frappe.model.document import Document | |||
from frappe import _ | |||
try: | |||
from urllib.parse import urlparse | |||
except ImportError: | |||
from urlparse import urlparse | |||
class SocialLoginKeys(Document): | |||
def validate(self): | |||
self.validate_frappe_server_url() | |||
@@ -17,10 +24,16 @@ class SocialLoginKeys(Document): | |||
if self.frappe_server_url: | |||
if self.frappe_server_url.endswith('/'): | |||
self.frappe_server_url = self.frappe_server_url[:-1] | |||
import requests | |||
try: | |||
r = requests.get(self.frappe_server_url + "/api/method/frappe.handler.version", timeout=5) | |||
frappe_server_hostname = urlparse(self.frappe_server_url).netloc | |||
except: | |||
frappe.throw(_("Unable to make request to the Frappe Server URL")) | |||
if r.status_code != 200: | |||
frappe.throw(_("Check Frappe Server URL")) | |||
if socket.gethostname() != frappe_server_hostname or \ | |||
(frappe.local.conf.domains is not None) and \ | |||
(frappe_server_hostname not in frappe.local.conf.domains): | |||
try: | |||
requests.get(self.frappe_server_url + "/api/method/frappe.handler.version", timeout=5) | |||
except: | |||
frappe.throw(_("Unable to make request to the Frappe Server URL")) |
@@ -8,14 +8,14 @@ $.extend(frappe.model, { | |||
extract docs, docinfo (attachments, comments, assignments) | |||
from incoming request and set in `locals` and `frappe.model.docinfo` | |||
*/ | |||
var isPlain; | |||
if(!r.docs && !r.docinfo) r = {docs:r}; | |||
if($.isPlainObject(r.docs)) r.docs = [r.docs]; | |||
isPlain = $.isPlainObject(r.docs); | |||
if(isPlain) r.docs = [r.docs]; | |||
if(r.docs) { | |||
var last_parent_name = null; | |||
var dirty = []; | |||
for(var i=0, l=r.docs.length; i<l; i++) { | |||
var d = r.docs[i]; | |||
@@ -45,7 +45,7 @@ $.extend(frappe.model, { | |||
} | |||
} | |||
if(cur_frm && dirty.indexOf(cur_frm.doctype)!==-1) cur_frm.dirty(); | |||
if(cur_frm && isPlain) cur_frm.dirty(); | |||
} | |||
@@ -4,7 +4,7 @@ from __future__ import unicode_literals | |||
import unittest | |||
from frappe.utils import evaluate_filters | |||
from frappe.utils import evaluate_filters, money_in_words | |||
class TestFilters(unittest.TestCase): | |||
def test_simple_dict(self): | |||
@@ -34,3 +34,27 @@ class TestFilters(unittest.TestCase): | |||
{'status': 'Open', 'age': ('>', 10)})) | |||
self.assertFalse(evaluate_filters({'doctype': 'User', 'status': 'Open', 'age': 20}, | |||
{'status': 'Open', 'age': ('>', 30)})) | |||
class TestMoney(unittest.TestCase): | |||
def test_money_in_words(self): | |||
nums_bhd = [ | |||
(5000, "BHD Five Thousand only."), (5000.0, "BHD Five Thousand only."), | |||
(0.1, "One Hundred Fils only."), (0, "BHD Zero only."), ("Fail", "") | |||
] | |||
nums_ngn = [ | |||
(5000, "NGN Five Thousand only."), (5000.0, "NGN Five Thousand only."), | |||
(0.1, "Ten Kobo only."), (0, "NGN Zero only."), ("Fail", "") | |||
] | |||
for num in nums_bhd: | |||
self.assertEqual( | |||
money_in_words(num[0], "BHD"), num[1], "{0} is not the same as {1}". | |||
format(money_in_words(num[0], "BHD"), num[1]) | |||
) | |||
for num in nums_ngn: | |||
self.assertEqual( | |||
money_in_words(num[0], "NGN"), num[1], "{0} is not the same as {1}". | |||
format(money_in_words(num[0], "NGN"), num[1]) | |||
) |
@@ -420,7 +420,14 @@ def money_in_words(number, main_currency = None, fraction_currency=None): | |||
from frappe.utils import get_defaults | |||
_ = frappe._ | |||
if not number or flt(number) < 0: | |||
try: | |||
# note: `flt` returns 0 for invalid input and we don't want that | |||
number = float(number) | |||
except ValueError: | |||
return "" | |||
number = flt(number) | |||
if number < 0: | |||
return "" | |||
d = get_defaults() | |||
@@ -429,20 +436,30 @@ def money_in_words(number, main_currency = None, fraction_currency=None): | |||
if not fraction_currency: | |||
fraction_currency = frappe.db.get_value("Currency", main_currency, "fraction") or _("Cent") | |||
n = "%.2f" % flt(number) | |||
main, fraction = n.split('.') | |||
if len(fraction)==1: fraction += '0' | |||
number_format = frappe.db.get_value("Currency", main_currency, "number_format", cache=True) or \ | |||
frappe.db.get_default("number_format") or "#,###.##" | |||
fraction_length = len(number_format.rsplit('.', 1)[-1]) | |||
n = "%.{0}f".format(fraction_length) % number | |||
main, fraction = n.split('.') | |||
if len(fraction) < fraction_length: | |||
zeros = '0' * (fraction_length - len(fraction)) | |||
fraction += zeros | |||
in_million = True | |||
if number_format == "#,##,###.##": in_million = False | |||
out = main_currency + ' ' + in_words(main, in_million).title() | |||
if cint(fraction): | |||
out = out + ' ' + _('and') + ' ' + in_words(fraction, in_million).title() + ' ' + fraction_currency | |||
# 0.00 | |||
if main == '0' and fraction in ['00', '000']: | |||
out = "{0} {1}".format(main_currency, _('Zero')) | |||
# 0.XX | |||
elif main == '0': | |||
out = _(in_words(fraction, in_million).title()) + ' ' + fraction_currency | |||
else: | |||
out = main_currency + ' ' + _(in_words(main, in_million).title()) | |||
if cint(fraction): | |||
out = out + ' ' + _('and') + ' ' + _(in_words(fraction, in_million).title()) + ' ' + fraction_currency | |||
return out + ' ' + _('only.') | |||