Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 
 

352 linhas
9.1 KiB

  1. # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. """build query for doclistview and return results"""
  5. import frappe, json
  6. import frappe.permissions
  7. from frappe.model.db_query import DatabaseQuery
  8. from frappe import _
  9. @frappe.whitelist()
  10. def get():
  11. args = get_form_params()
  12. data = compress(execute(**args), args = args)
  13. return data
  14. def execute(doctype, *args, **kwargs):
  15. return DatabaseQuery(doctype).execute(*args, **kwargs)
  16. def get_form_params():
  17. """Stringify GET request parameters."""
  18. data = frappe._dict(frappe.local.form_dict)
  19. del data["cmd"]
  20. if isinstance(data.get("filters"), basestring):
  21. data["filters"] = json.loads(data["filters"])
  22. if isinstance(data.get("fields"), basestring):
  23. data["fields"] = json.loads(data["fields"])
  24. if isinstance(data.get("docstatus"), basestring):
  25. data["docstatus"] = json.loads(data["docstatus"])
  26. if isinstance(data.get("save_user_settings"), basestring):
  27. data["save_user_settings"] = json.loads(data["save_user_settings"])
  28. else:
  29. data["save_user_settings"] = True
  30. fields = data["fields"]
  31. for field in fields:
  32. key = field.split(" as ")[0]
  33. if "." in key:
  34. parenttype, fieldname = key.split(".")[0][4:-1], key.split(".")[1].strip("`")
  35. else:
  36. parenttype = data.doctype
  37. fieldname = fieldname.strip("`")
  38. df = frappe.get_meta(parenttype).get_field(fieldname)
  39. report_hide = df.report_hide if df else None
  40. # remove the field from the query if the report hide flag is set
  41. if report_hide:
  42. fields.remove(field)
  43. # queries must always be server side
  44. data.query = None
  45. return data
  46. def compress(data, args = {}):
  47. """separate keys and values"""
  48. from frappe.desk.query_report import add_total_row
  49. if not data: return data
  50. values = []
  51. keys = data[0].keys()
  52. for row in data:
  53. new_row = []
  54. for key in keys:
  55. new_row.append(row[key])
  56. values.append(new_row)
  57. if args.get("add_total_row"):
  58. meta = frappe.get_meta(args.doctype)
  59. values = add_total_row(values, keys, meta)
  60. return {
  61. "keys": keys,
  62. "values": values
  63. }
  64. @frappe.whitelist()
  65. def save_report():
  66. """save report"""
  67. data = frappe.local.form_dict
  68. if frappe.db.exists('Report', data['name']):
  69. d = frappe.get_doc('Report', data['name'])
  70. else:
  71. d = frappe.new_doc('Report')
  72. d.report_name = data['name']
  73. d.ref_doctype = data['doctype']
  74. d.report_type = "Report Builder"
  75. d.json = data['json']
  76. frappe.get_doc(d).save()
  77. frappe.msgprint(_("{0} is saved").format(d.name))
  78. return d.name
  79. @frappe.whitelist()
  80. def export_query():
  81. """export from report builder"""
  82. form_params = get_form_params()
  83. form_params["limit_page_length"] = None
  84. form_params["as_list"] = True
  85. doctype = form_params.doctype
  86. add_totals_row = None
  87. file_format_type = form_params["file_format_type"]
  88. del form_params["doctype"]
  89. del form_params["file_format_type"]
  90. if 'add_totals_row' in form_params and form_params['add_totals_row']=='1':
  91. add_totals_row = 1
  92. del form_params["add_totals_row"]
  93. frappe.permissions.can_export(doctype, raise_exception=True)
  94. if 'selected_items' in form_params:
  95. si = json.loads(frappe.form_dict.get('selected_items'))
  96. form_params["filters"] = {"name": ("in", si)}
  97. del form_params["selected_items"]
  98. db_query = DatabaseQuery(doctype)
  99. ret = db_query.execute(**form_params)
  100. if add_totals_row:
  101. ret = append_totals_row(ret)
  102. data = [['Sr'] + get_labels(db_query.fields, doctype)]
  103. for i, row in enumerate(ret):
  104. data.append([i+1] + list(row))
  105. if file_format_type == "CSV":
  106. # convert to csv
  107. import csv
  108. from cStringIO import StringIO
  109. f = StringIO()
  110. writer = csv.writer(f)
  111. for r in data:
  112. # encode only unicode type strings and not int, floats etc.
  113. writer.writerow(map(lambda v: isinstance(v, unicode) and v.encode('utf-8') or v, r))
  114. f.seek(0)
  115. frappe.response['result'] = unicode(f.read(), 'utf-8')
  116. frappe.response['type'] = 'csv'
  117. frappe.response['doctype'] = doctype
  118. elif file_format_type == "Excel":
  119. from frappe.utils.xlsxutils import make_xlsx
  120. xlsx_file = make_xlsx(data, doctype)
  121. frappe.response['filename'] = doctype + '.xlsx'
  122. frappe.response['filecontent'] = xlsx_file.getvalue()
  123. frappe.response['type'] = 'binary'
  124. def append_totals_row(data):
  125. if not data:
  126. return data
  127. data = list(data)
  128. totals = []
  129. totals.extend([""]*len(data[0]))
  130. for row in data:
  131. for i in xrange(len(row)):
  132. if isinstance(row[i], (float, int)):
  133. totals[i] = (totals[i] or 0) + row[i]
  134. data.append(totals)
  135. return data
  136. def get_labels(fields, doctype):
  137. """get column labels based on column names"""
  138. labels = []
  139. for key in fields:
  140. key = key.split(" as ")[0]
  141. if "." in key:
  142. parenttype, fieldname = key.split(".")[0][4:-1], key.split(".")[1].strip("`")
  143. else:
  144. parenttype = doctype
  145. fieldname = fieldname.strip("`")
  146. df = frappe.get_meta(parenttype).get_field(fieldname)
  147. label = df.label if df else fieldname.title()
  148. if label in labels:
  149. label = doctype + ": " + label
  150. labels.append(label)
  151. return labels
  152. @frappe.whitelist()
  153. def delete_items():
  154. """delete selected items"""
  155. import json
  156. il = json.loads(frappe.form_dict.get('items'))
  157. doctype = frappe.form_dict.get('doctype')
  158. for i, d in enumerate(il):
  159. try:
  160. frappe.delete_doc(doctype, d)
  161. if len(il) >= 5:
  162. frappe.publish_realtime("progress",
  163. dict(progress=[i+1, len(il)], title=_('Deleting {0}').format(doctype)),
  164. user=frappe.session.user)
  165. except Exception:
  166. pass
  167. @frappe.whitelist()
  168. def get_sidebar_stats(stats, doctype, filters=[]):
  169. cat_tags = frappe.db.sql("""select tag.parent as category, tag.tag_name as tag
  170. from `tabTag Doc Category` as docCat
  171. INNER JOIN tabTag as tag on tag.parent = docCat.parent
  172. where docCat.tagdoc=%s
  173. ORDER BY tag.parent asc,tag.idx""",doctype,as_dict=1)
  174. return {"defined_cat":cat_tags, "stats":get_stats(stats, doctype, filters)}
  175. @frappe.whitelist()
  176. def get_stats(stats, doctype, filters=[]):
  177. """get tag info"""
  178. import json
  179. tags = json.loads(stats)
  180. if filters:
  181. filters = json.loads(filters)
  182. stats = {}
  183. columns = frappe.db.get_table_columns(doctype)
  184. for tag in tags:
  185. if not tag in columns: continue
  186. try:
  187. tagcount = frappe.get_list(doctype, fields=[tag, "count(*)"],
  188. #filters=["ifnull(`%s`,'')!=''" % tag], group_by=tag, as_list=True)
  189. filters = filters + ["ifnull(`%s`,'')!=''" % tag], group_by = tag, as_list = True)
  190. if tag=='_user_tags':
  191. stats[tag] = scrub_user_tags(tagcount)
  192. stats[tag].append([_("No Tags"), frappe.get_list(doctype,
  193. fields=[tag, "count(*)"],
  194. filters=filters +["({0} = ',' or {0} is null)".format(tag)], as_list=True)[0][1]])
  195. else:
  196. stats[tag] = tagcount
  197. except frappe.SQLError:
  198. # does not work for child tables
  199. pass
  200. return stats
  201. @frappe.whitelist()
  202. def get_filter_dashboard_data(stats, doctype, filters=[]):
  203. """get tags info"""
  204. import json
  205. tags = json.loads(stats)
  206. if filters:
  207. filters = json.loads(filters)
  208. stats = {}
  209. columns = frappe.db.get_table_columns(doctype)
  210. for tag in tags:
  211. if not tag["name"] in columns: continue
  212. tagcount = []
  213. if tag["type"] not in ['Date', 'Datetime']:
  214. tagcount = frappe.get_list(doctype,
  215. fields=[tag["name"], "count(*)"],
  216. filters = filters + ["ifnull(`%s`,'')!=''" % tag["name"]],
  217. group_by = tag["name"],
  218. as_list = True)
  219. if tag["type"] not in ['Check','Select','Date','Datetime','Int',
  220. 'Float','Currency','Percent'] and tag['name'] not in ['docstatus']:
  221. stats[tag["name"]] = list(tagcount)
  222. if stats[tag["name"]]:
  223. data =["No Data", frappe.get_list(doctype,
  224. fields=[tag["name"], "count(*)"],
  225. filters=filters + ["({0} = '' or {0} is null)".format(tag["name"])],
  226. as_list=True)[0][1]]
  227. if data and data[1]!=0:
  228. stats[tag["name"]].append(data)
  229. else:
  230. stats[tag["name"]] = tagcount
  231. return stats
  232. def scrub_user_tags(tagcount):
  233. """rebuild tag list for tags"""
  234. rdict = {}
  235. tagdict = dict(tagcount)
  236. for t in tagdict:
  237. if not t:
  238. continue
  239. alltags = t.split(',')
  240. for tag in alltags:
  241. if tag:
  242. if not tag in rdict:
  243. rdict[tag] = 0
  244. rdict[tag] += tagdict[t]
  245. rlist = []
  246. for tag in rdict:
  247. rlist.append([tag, rdict[tag]])
  248. return rlist
  249. # used in building query in queries.py
  250. def get_match_cond(doctype):
  251. cond = DatabaseQuery(doctype).build_match_conditions()
  252. return ((' and ' + cond) if cond else "").replace("%", "%%")
  253. def build_match_conditions(doctype, as_condition=True):
  254. match_conditions = DatabaseQuery(doctype).build_match_conditions(as_condition=as_condition)
  255. if as_condition:
  256. return match_conditions.replace("%", "%%")
  257. else:
  258. return match_conditions
  259. def get_filters_cond(doctype, filters, conditions):
  260. if filters:
  261. flt = filters
  262. if isinstance(filters, dict):
  263. filters = filters.items()
  264. flt = []
  265. for f in filters:
  266. if isinstance(f[1], basestring) and f[1][0] == '!':
  267. flt.append([doctype, f[0], '!=', f[1][1:]])
  268. else:
  269. value = frappe.db.escape(f[1]) if isinstance(f[1], basestring) else f[1]
  270. flt.append([doctype, f[0], '=', value])
  271. query = DatabaseQuery(doctype)
  272. query.filters = flt
  273. query.conditions = conditions
  274. query.build_filter_conditions(flt, conditions)
  275. cond = ' and ' + ' and '.join(query.conditions)
  276. else:
  277. cond = ''
  278. return cond