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.
 
 
 
 
 
 

331 linhas
8.9 KiB

  1. import webnotes
  2. form = webnotes.form
  3. session = webnotes.session
  4. sql = webnotes.conn.sql
  5. out = webnotes.response
  6. from webnotes.utils import cint
  7. def get_search_criteria_list(dt):
  8. sc_list = sql("select criteria_name, doc_type from `tabSearch Criteria` where doc_type = '%s' or parent_doc_type = '%s'" % (dt, dt))
  9. return [list(s) for s in sc_list]
  10. def load_report_list():
  11. webnotes.response['rep_list'] = get_search_criteria_list(form.getvalue('dt'))
  12. # Get, scrub metadata
  13. # ====================================================================
  14. def get_sql_tables(q):
  15. if q.find('WHERE') != -1:
  16. tl = q.split('FROM')[1].split('WHERE')[0].split(',')
  17. elif q.find('GROUP BY') != -1:
  18. tl = q.split('FROM')[1].split('GROUP BY')[0].split(',')
  19. else:
  20. tl = q.split('FROM')[1].split('ORDER BY')[0].split(',')
  21. return [t.strip().strip('`')[3:] for t in tl]
  22. def get_parent_dt(dt):
  23. pdt = ''
  24. if sql('select name from `tabDocType` where istable=1 and name="%s"' % dt):
  25. res = sql('select parent from `tabDocField` where fieldtype="Table" and options="%s"' % dt)
  26. if res: pdt = res[0][0]
  27. return pdt
  28. def get_sql_meta(tl):
  29. std_columns = {
  30. 'owner':('Owner', '', '', '100'),
  31. 'creation':('Created on', 'Date', '', '100'),
  32. 'modified':('Last modified on', 'Date', '', '100'),
  33. 'modified_by':('Modified By', '', '', '100')
  34. }
  35. meta = {}
  36. for dt in tl:
  37. meta[dt] = std_columns.copy()
  38. # for table doctype, the ID is the parent id
  39. pdt = get_parent_dt(dt)
  40. if pdt:
  41. meta[dt]['parent'] = ('ID', 'Link', pdt, '200')
  42. # get the field properties from DocField
  43. res = sql("select fieldname, label, fieldtype, options, width from tabDocField where parent='%s'" % dt)
  44. for r in res:
  45. if r[0]:
  46. meta[dt][r[0]] = (r[1], r[2], r[3], r[4]);
  47. # name
  48. meta[dt]['name'] = ('ID', 'Link', dt, '200')
  49. return meta
  50. # Additional conditions to fulfill match permission rules
  51. # ====================================================================
  52. def getmatchcondition(dt, ud, ur):
  53. res = sql("SELECT `role`, `match` FROM tabDocPerm WHERE parent = '%s' AND (`read`=1) AND permlevel = 0" % dt)
  54. cond = []
  55. for r in res:
  56. if r[0] in ur: # role applicable to user
  57. if r[1]:
  58. defvalues = ud.get(r[1],['_NA'])
  59. for d in defvalues:
  60. cond.append('`tab%s`.`%s`="%s"' % (dt, r[1], d))
  61. else: # nomatch i.e. full read rights
  62. return ''
  63. return ' OR '.join(cond)
  64. def add_match_conditions(q, tl, ur, ud):
  65. sl = []
  66. for dt in tl:
  67. s = getmatchcondition(dt, ud, ur)
  68. if s:
  69. sl.append(s)
  70. # insert the conditions
  71. if sl:
  72. condition_st = q.find('WHERE')!=-1 and ' AND ' or ' WHERE '
  73. condition_end = q.find('ORDER BY')!=-1 and 'ORDER BY' or 'LIMIT'
  74. condition_end = q.find('GROUP BY')!=-1 and 'GROUP BY' or condition_end
  75. if q.find('ORDER BY')!=-1 or q.find('LIMIT')!=-1 or q.find('GROUP BY')!=-1: # if query continues beyond conditions
  76. q = q.split(condition_end)
  77. q = q[0] + condition_st + '(' + ' OR '.join(sl) + ') ' + condition_end + q[1]
  78. else:
  79. q = q + condition_st + '(' + ' OR '.join(sl) + ')'
  80. return q
  81. # execute server-side script from Search Criteria
  82. # ====================================================================
  83. def exec_report(code, res, colnames=[], colwidths=[], coltypes=[], coloptions=[], filter_values={}, query='', from_export=0):
  84. col_idx, i, out, style, header_html, footer_html, page_template = {}, 0, None, [], '', '', ''
  85. for c in colnames:
  86. col_idx[c] = i
  87. i+=1
  88. # load globals (api)
  89. from webnotes import *
  90. from webnotes.utils import *
  91. from webnotes.model.doc import *
  92. from webnotes.model.doclist import getlist
  93. from webnotes.model.db_schema import updatedb
  94. from webnotes.model.code import get_obj
  95. set = webnotes.conn.set
  96. sql = webnotes.conn.sql
  97. get_value = webnotes.conn.get_value
  98. convert_to_lists = webnotes.conn.convert_to_lists
  99. NEWLINE = '\n'
  100. exec str(code)
  101. if out!=None:
  102. res = out
  103. return res, style, header_html, footer_html, page_template
  104. # ====================================================================
  105. def guess_type(m):
  106. """
  107. Returns fieldtype depending on the MySQLdb Description
  108. """
  109. import MySQLdb
  110. if m in MySQLdb.NUMBER:
  111. return 'Currency'
  112. elif m in MySQLdb.DATE:
  113. return 'Date'
  114. else:
  115. return 'Data'
  116. def build_description_simple():
  117. colnames, coltypes, coloptions, colwidths = [], [], [], []
  118. for m in webnotes.conn.get_description():
  119. colnames.append(m[0])
  120. coltypes.append(guess_type[m[0]])
  121. coloptions.append('')
  122. colwidths.append('100')
  123. return colnames, coltypes, coloptions, colwidths
  124. # ====================================================================
  125. def build_description_standard(meta, tl):
  126. desc = webnotes.conn.get_description()
  127. colnames, coltypes, coloptions, colwidths = [], [], [], []
  128. # merged metadata - used if we are unable to
  129. # get both the table name and field name from
  130. # the description - in case of joins
  131. merged_meta = {}
  132. for d in meta:
  133. merged_meta.update(meta[d])
  134. for f in desc:
  135. fn, dt = f[0], ''
  136. if '.' in fn:
  137. dt, fn = fn.split('.')
  138. if (not dt) and merged_meta.get(fn):
  139. # no "AS" given, find type from merged description
  140. desc = merged_meta[fn]
  141. colnames.append(desc[0] or fn)
  142. coltypes.append(desc[1] or '')
  143. coloptions.append(desc[2] or '')
  144. colwidths.append(desc[3] or '100')
  145. elif meta.get(dt,{}).has_key(fn):
  146. # type specified for a multi-table join
  147. # usually from Report Builder
  148. desc = meta[dt][fn]
  149. colnames.append(desc[0] or fn)
  150. coltypes.append(desc[1] or '')
  151. coloptions.append(desc[2] or '')
  152. colwidths.append(desc[3] or '100')
  153. else:
  154. # nothing found
  155. # guess
  156. colnames.append(fn)
  157. coltypes.append(guess_type(f[1]))
  158. coloptions.append('')
  159. colwidths.append('100')
  160. return colnames, coltypes, coloptions, colwidths
  161. # Entry Point - Run the query
  162. # ====================================================================
  163. def runquery(q='', ret=0, from_export=0):
  164. import webnotes.utils
  165. formatted = cint(form.getvalue('formatted'))
  166. # CASE A: Simple Query
  167. # --------------------
  168. if form.getvalue('simple_query') or form.getvalue('is_simple'):
  169. if not q: q = form.getvalue('simple_query') or form.getvalue('query')
  170. if q.split()[0].lower() != 'select':
  171. raise Exception, 'Query must be a SELECT'
  172. as_dict = cint(form.getvalue('as_dict'))
  173. res = sql(q, as_dict = as_dict, as_list = not as_dict, formatted=formatted)
  174. # build colnames etc from metadata
  175. colnames, coltypes, coloptions, colwidths = [], [], [], []
  176. # CASE B: Standard Query
  177. # -----------------------
  178. else:
  179. if not q: q = form.getvalue('query')
  180. tl = get_sql_tables(q)
  181. meta = get_sql_meta(tl)
  182. q = add_match_conditions(q, tl, webnotes.user.roles, webnotes.user.get_defaults())
  183. # replace special variables
  184. q = q.replace('__user', session['user'])
  185. q = q.replace('__today', webnotes.utils.nowdate())
  186. res = sql(q, as_list=1, formatted=formatted)
  187. colnames, coltypes, coloptions, colwidths = build_description_standard(meta, tl)
  188. # run server script
  189. # -----------------
  190. style, header_html, footer_html, page_template = '', '', '', ''
  191. if form.has_key('sc_id') and form.getvalue('sc_id'):
  192. sc_id = form.getvalue('sc_id')
  193. from webnotes.model.code import get_code
  194. sc_details = webnotes.conn.sql("select module, standard, server_script from `tabSearch Criteria` where name=%s", sc_id)[0]
  195. if sc_details[1]!='No':
  196. code = get_code(sc_details[0], 'Search Criteria', sc_id, 'py')
  197. else:
  198. code = sc_details[2]
  199. if code:
  200. filter_values = form.has_key('filter_values') and eval(form.getvalue('filter_values','')) or {}
  201. res, style, header_html, footer_html, page_template = exec_report(code, res, colnames, colwidths, coltypes, coloptions, filter_values, q, from_export)
  202. out['colnames'] = colnames
  203. out['coltypes'] = coltypes
  204. out['coloptions'] = coloptions
  205. out['colwidths'] = colwidths
  206. out['header_html'] = header_html
  207. out['footer_html'] = footer_html
  208. out['page_template'] = page_template
  209. if style:
  210. out['style'] = style
  211. # just the data - return
  212. if ret==1:
  213. return res
  214. out['values'] = res
  215. # return num of entries
  216. qm = form.has_key('query_max') and form.getvalue('query_max') or ''
  217. if qm and qm.strip():
  218. if qm.split()[0].lower() != 'select':
  219. raise Exception, 'Query (Max) must be a SELECT'
  220. if not form.has_key('simple_query'):
  221. qm = add_match_conditions(qm, tl, webnotes.user.roles, webnotes.user.defaults)
  222. out['n_values'] = webnotes.utils.cint(sql(qm)[0][0])
  223. # Export to CSV
  224. # ====================================================================
  225. def runquery_csv():
  226. global out
  227. # run query
  228. res = runquery(from_export = 1)
  229. q = form.getvalue('query')
  230. rep_name = form.getvalue('report_name')
  231. if not form.has_key('simple_query'):
  232. # Report Name
  233. if not rep_name:
  234. rep_name = get_sql_tables(q)[0]
  235. if not rep_name: rep_name = 'DataExport'
  236. # Headings
  237. heads = []
  238. rows = [[rep_name], out['colnames']] + out['values']
  239. from cStringIO import StringIO
  240. import csv
  241. f = StringIO()
  242. writer = csv.writer(f)
  243. for r in rows:
  244. writer.writerow(r)
  245. f.seek(0)
  246. out['result'] = f.read()
  247. out['type'] = 'csv'
  248. out['doctype'] = rep_name