@@ -43,11 +43,11 @@ def export_csv(doctype, path): | |||
get_template(doctype=doctype, all_doctypes="Yes", with_data="Yes") | |||
csvfile.write(frappe.response.result.encode("utf-8")) | |||
def export_json(doctype, path): | |||
def export_json(doctype, path, filters=None): | |||
from frappe.utils.response import json_handler | |||
out = [] | |||
for doc in frappe.get_all(doctype, fields=["name"], limit_page_length=None): | |||
out.append(frappe.get_doc(doctype.doc.name).as_dict()) | |||
for doc in frappe.get_all(doctype, fields=["name"], filters=filters, limit_page_length=0, order_by="creation asc"): | |||
out.append(frappe.get_doc(doctype, doc.name).as_dict()) | |||
with open(path, "w") as outfile: | |||
outfile.write(json.dumps(out, default=json_handler, indent=1, sort_keys=True)) | |||
@@ -308,6 +308,8 @@ class Database: | |||
* ifnull(`fieldname`, default_value) = %(fieldname)s | |||
* `fieldname` [=, !=, >, >=, <, <=] %(fieldname)s | |||
""" | |||
conditions = [] | |||
values = {} | |||
def _build_condition(key): | |||
""" | |||
filter's key is passed by map function | |||
@@ -317,25 +319,38 @@ class Database: | |||
""" | |||
_operator = "=" | |||
value = filters.get(key) | |||
values[key] = value | |||
if isinstance(value, (list, tuple)): | |||
_operator = value[0] | |||
filters[key] = value[1] | |||
values[key] = value[1] | |||
if isinstance(value[1], (tuple, list)): | |||
inner_list = [] | |||
for i, v in enumerate(value[1]): | |||
inner_key = "{0}_{1}".format(key, i) | |||
values[inner_key] = v | |||
inner_list.append("%({0})s".format(inner_key)) | |||
if _operator not in ["=", "!=", ">", ">=", "<", "<=", "like"]: | |||
values[key] = "({0})".format(", ".join(inner_list)) | |||
if _operator not in ["=", "!=", ">", ">=", "<", "<=", "like", "in", "not in"]: | |||
_operator = "=" | |||
if "[" in key: | |||
split_key = key.split("[") | |||
return "ifnull(`" + split_key[0] + "`, " + split_key[1][:-1] + ") " \ | |||
condition = "ifnull(`" + split_key[0] + "`, " + split_key[1][:-1] + ") " \ | |||
+ _operator + " %(" + key + ")s" | |||
else: | |||
return "`" + key + "` " + _operator + " %(" + key + ")s" | |||
condition = "`" + key + "` " + _operator + " %(" + key + ")s" | |||
conditions.append(condition) | |||
if isinstance(filters, basestring): | |||
filters = { "name": filters } | |||
conditions = map(_build_condition, filters) | |||
return " and ".join(conditions), filters | |||
for f in filters: | |||
_build_condition(f) | |||
return " and ".join(conditions), values | |||
def get(self, doctype, filters=None, as_dict=True): | |||
"""Returns `get_value` with fieldname='*'""" | |||
@@ -487,12 +502,12 @@ class Database: | |||
if fields=="*": | |||
as_dict = True | |||
conditions, filters = self.build_conditions(filters) | |||
conditions, values = self.build_conditions(filters) | |||
order_by = ("order by " + order_by) if order_by else "" | |||
r = self.sql("select %s from `tab%s` where %s %s" % (fl, doctype, | |||
conditions, order_by), filters, as_dict=as_dict, debug=debug, update=update) | |||
r = self.sql("select {0} from `tab{1}` where {2} {3}".format(fl, doctype, | |||
conditions, order_by), values, as_dict=as_dict, debug=debug, update=update) | |||
return r | |||
@@ -211,7 +211,8 @@ class BaseDocument(object): | |||
return frappe._dict(doc) | |||
def as_json(self): | |||
return json.dumps(self.as_dict(), indent=1, sort_keys=True) | |||
from frappe.utils.response import json_handler | |||
return json.dumps(self.as_dict(), indent=1, sort_keys=True, default=json_handler) | |||
def get_table_field_doctype(self, fieldname): | |||
return self.meta.get_field(fieldname).options | |||
@@ -19,6 +19,8 @@ def set_new_name(doc): | |||
:param doc: Document to be named.""" | |||
doc.run_method("before_naming") | |||
autoname = frappe.get_meta(doc.doctype).autoname | |||
if getattr(doc, "amended_from", None): | |||
_set_amended_name(doc) | |||
@@ -1256,15 +1256,6 @@ frappe.ui.form.ControlTable = frappe.ui.form.Control.extend({ | |||
this._super(); | |||
// add title if prev field is not column / section heading or html | |||
var prev_fieldtype = ""; | |||
if(this.df.idx > 1) { | |||
var prev_fieldtype = cur_frm.meta.fields[this.df.idx - 2].fieldtype; | |||
} | |||
if(frappe.model.layout_fields.indexOf(prev_fieldtype)===-1) { | |||
$("<label>" + __(this.df.label) + "<label>").appendTo(this.wrapper); | |||
} | |||
this.grid = new frappe.ui.form.Grid({ | |||
frm: this.frm, | |||
df: this.df, | |||
@@ -101,6 +101,10 @@ $.extend(frappe.datetime, { | |||
return moment().format(); | |||
}, | |||
nowdate: function() { | |||
return frappe.datetime.get_today(); | |||
}, | |||
now_time: function() { | |||
return moment().format("HH:mm:ss"); | |||
}, | |||
@@ -8,18 +8,21 @@ import frappe | |||
import operator | |||
import re, urllib, datetime, math | |||
import babel.dates | |||
from dateutil import parser | |||
DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S.%f" | |||
# datetime functions | |||
def getdate(string_date): | |||
""" | |||
Coverts string date (yyyy-mm-dd) to datetime.date object | |||
""" | |||
if isinstance(string_date, datetime.date): | |||
return string_date | |||
elif isinstance(string_date, datetime.datetime): | |||
if isinstance(string_date, datetime.datetime): | |||
return string_date.date() | |||
elif isinstance(string_date, datetime.date): | |||
return string_date | |||
if " " in string_date: | |||
string_date = string_date.split(" ")[0] | |||
@@ -27,7 +30,15 @@ def getdate(string_date): | |||
def add_to_date(date, years=0, months=0, days=0): | |||
"""Adds `days` to the given date""" | |||
format = isinstance(date, basestring) | |||
# save time part | |||
with_time = False | |||
as_string = isinstance(date, basestring) | |||
if as_string: | |||
if " " in date: with_time = date.split()[1] | |||
elif isinstance(date, datetime.datetime): | |||
with_time = date.time().strftime(DATETIME_FORMAT.split()[1]) | |||
if date: | |||
date = getdate(date) | |||
else: | |||
@@ -36,8 +47,9 @@ def add_to_date(date, years=0, months=0, days=0): | |||
from dateutil.relativedelta import relativedelta | |||
date += relativedelta(years=years, months=months, days=days) | |||
if format: | |||
return date.strftime("%Y-%m-%d") | |||
if as_string: | |||
date = date.strftime("%Y-%m-%d") | |||
return (date + " " + with_time) if with_time else date | |||
else: | |||
return date | |||
@@ -89,7 +101,7 @@ def now(): | |||
return getdate(frappe.local.current_date).strftime("%Y-%m-%d") + " " + \ | |||
now_datetime().strftime('%H:%M:%S.%f') | |||
else: | |||
return now_datetime().strftime('%Y-%m-%d %H:%M:%S.%f') | |||
return now_datetime().strftime(DATETIME_FORMAT) | |||
def nowdate(): | |||
"""return current date as yyyy-mm-dd""" | |||
@@ -124,7 +136,7 @@ def get_last_day(dt): | |||
def get_datetime(datetime_str): | |||
try: | |||
return datetime.datetime.strptime(datetime_str, '%Y-%m-%d %H:%M:%S.%f') | |||
return datetime.datetime.strptime(datetime_str, DATETIME_FORMAT) | |||
except TypeError: | |||
if isinstance(datetime_str, datetime.datetime): | |||
@@ -138,11 +150,19 @@ def get_datetime(datetime_str): | |||
return datetime.datetime.strptime(datetime_str, '%Y-%m-%d %H:%M:%S') | |||
def get_time(time_str): | |||
if isinstance(time_str, datetime.datetime): | |||
return time_str.time() | |||
elif isinstance(time_str, datetime.time): | |||
return time_str | |||
return parser.parse(time_str).time() | |||
def get_datetime_str(datetime_obj): | |||
if isinstance(datetime_obj, basestring): | |||
datetime_obj = get_datetime(datetime_obj) | |||
return datetime_obj.strftime('%Y-%m-%d %H:%M:%S.%f') | |||
return datetime_obj.strftime(DATETIME_FORMAT) | |||
def formatdate(string_date=None, format_string=None): | |||
""" | |||
@@ -453,8 +473,8 @@ def pretty_date(iso_datetime): | |||
import math | |||
if isinstance(iso_datetime, basestring): | |||
iso_datetime = datetime.datetime.strptime(iso_datetime, '%Y-%m-%d %H:%M:%S.%f') | |||
now_dt = datetime.datetime.strptime(now(), '%Y-%m-%d %H:%M:%S.%f') | |||
iso_datetime = datetime.datetime.strptime(iso_datetime, DATETIME_FORMAT) | |||
now_dt = datetime.datetime.strptime(now(), DATETIME_FORMAT) | |||
dt_diff = now_dt - iso_datetime | |||
# available only in python 2.7+ | |||