Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 
 

342 righe
9.6 KiB

  1. # Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
  2. #
  3. # MIT License (MIT)
  4. #
  5. # Permission is hereby granted, free of charge, to any person obtaining a
  6. # copy of this software and associated documentation files (the "Software"),
  7. # to deal in the Software without restriction, including without limitation
  8. # the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. # and/or sell copies of the Software, and to permit persons to whom the
  10. # Software is furnished to do so, subject to the following conditions:
  11. #
  12. # The above copyright notice and this permission notice shall be included in
  13. # all copies or substantial portions of the Software.
  14. #
  15. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  16. # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  17. # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18. # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  19. # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
  20. # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. #
  22. from __future__ import unicode_literals
  23. import webnotes
  24. session = webnotes.session
  25. sql = webnotes.conn.sql
  26. out = webnotes.response
  27. from webnotes.utils import cint
  28. import webnotes.defaults
  29. def get_sql_tables(q):
  30. if q.find('WHERE') != -1:
  31. tl = q.split('FROM')[1].split('WHERE')[0].split(',')
  32. elif q.find('GROUP BY') != -1:
  33. tl = q.split('FROM')[1].split('GROUP BY')[0].split(',')
  34. else:
  35. tl = q.split('FROM')[1].split('ORDER BY')[0].split(',')
  36. return [t.strip().strip('`')[3:] for t in tl]
  37. def get_parent_dt(dt):
  38. pdt = ''
  39. if sql('select name from `tabDocType` where istable=1 and name="%s"' % dt):
  40. import webnotes.model.meta
  41. return webnotes.model.meta.get_parent_dt(dt)
  42. return pdt
  43. def get_sql_meta(tl):
  44. std_columns = {
  45. 'owner':('Owner', '', '', '100'),
  46. 'creation':('Created on', 'Date', '', '100'),
  47. 'modified':('Last modified on', 'Date', '', '100'),
  48. 'modified_by':('Modified By', '', '', '100')
  49. }
  50. meta = {}
  51. for dt in tl:
  52. meta[dt] = std_columns.copy()
  53. # for table doctype, the ID is the parent id
  54. pdt = get_parent_dt(dt)
  55. if pdt:
  56. meta[dt]['parent'] = ('ID', 'Link', pdt, '200')
  57. # get the field properties from DocField
  58. res = sql("select fieldname, label, fieldtype, options, width from tabDocField where parent='%s'" % dt)
  59. for r in res:
  60. if r[0]:
  61. meta[dt][r[0]] = (r[1], r[2], r[3], r[4]);
  62. # name
  63. meta[dt]['name'] = ('ID', 'Link', dt, '200')
  64. return meta
  65. def add_match_conditions(q, tl):
  66. sl = []
  67. ur = webnotes.user.get_roles()
  68. for dt in tl:
  69. s = getmatchcondition(dt, ur)
  70. if s:
  71. sl.append(s)
  72. # insert the conditions
  73. if sl:
  74. condition_st = q.find('WHERE')!=-1 and ' AND ' or ' WHERE '
  75. condition_end = q.find('ORDER BY')!=-1 and 'ORDER BY' or 'LIMIT'
  76. condition_end = q.find('GROUP BY')!=-1 and 'GROUP BY' or condition_end
  77. if q.find('ORDER BY')!=-1 or q.find('LIMIT')!=-1 or q.find('GROUP BY')!=-1: # if query continues beyond conditions
  78. q = q.split(condition_end)
  79. q = q[0] + condition_st + '(' + ' OR '.join(sl) + ') ' + condition_end + q[1]
  80. else:
  81. q = q + condition_st + '(' + ' OR '.join(sl) + ')'
  82. return q
  83. def getmatchcondition(dt, ur):
  84. res = sql("SELECT `role`, `match` FROM tabDocPerm WHERE parent = '%s' AND (`read`=1) AND permlevel = 0" % dt)
  85. cond = []
  86. for r in res:
  87. if r[0] in ur: # role applicable to user
  88. if r[1]:
  89. if ":" in r[1]:
  90. keys = r[1].split(":")
  91. else:
  92. keys = [r[1], r[1]]
  93. for d in webnotes.defaults.get_user_default_as_list(keys[0]) or ["** No Match **"]:
  94. cond.append('`tab%s`.`%s`="%s"' % (dt, r[1], d))
  95. else:
  96. return ''
  97. return ' OR '.join(cond)
  98. def exec_report(code, res, colnames=[], colwidths=[], coltypes=[], coloptions=[], filter_values={}, query='', from_export=0):
  99. col_idx, i, out, style, header_html, footer_html, page_template = {}, 0, None, [], '', '', ''
  100. for c in colnames:
  101. col_idx[c] = i
  102. i+=1
  103. # load globals (api)
  104. from webnotes import *
  105. from webnotes.utils import *
  106. from webnotes.model.doc import *
  107. set = webnotes.conn.set
  108. sql = webnotes.conn.sql
  109. get_value = webnotes.conn.get_value
  110. convert_to_lists = webnotes.conn.convert_to_lists
  111. NEWLINE = '\n'
  112. exec str(code)
  113. if out!=None:
  114. res = out
  115. return res, style, header_html, footer_html, page_template
  116. def guess_type(m):
  117. """
  118. Returns fieldtype depending on the MySQLdb Description
  119. """
  120. import MySQLdb
  121. if m in MySQLdb.NUMBER:
  122. return 'Currency'
  123. elif m in MySQLdb.DATE:
  124. return 'Date'
  125. else:
  126. return 'Data'
  127. def build_description_simple():
  128. colnames, coltypes, coloptions, colwidths = [], [], [], []
  129. for m in webnotes.conn.get_description():
  130. colnames.append(m[0])
  131. coltypes.append(guess_type[m[0]])
  132. coloptions.append('')
  133. colwidths.append('100')
  134. return colnames, coltypes, coloptions, colwidths
  135. def build_description_standard(meta, tl):
  136. desc = webnotes.conn.get_description()
  137. colnames, coltypes, coloptions, colwidths = [], [], [], []
  138. # merged metadata - used if we are unable to
  139. # get both the table name and field name from
  140. # the description - in case of joins
  141. merged_meta = {}
  142. for d in meta:
  143. merged_meta.update(meta[d])
  144. for f in desc:
  145. fn, dt = f[0], ''
  146. if '.' in fn:
  147. dt, fn = fn.split('.')
  148. if (not dt) and merged_meta.get(fn):
  149. # no "AS" given, find type from merged description
  150. desc = merged_meta[fn]
  151. colnames.append(desc[0] or fn)
  152. coltypes.append(desc[1] or '')
  153. coloptions.append(desc[2] or '')
  154. colwidths.append(desc[3] or '100')
  155. elif meta.get(dt,{}).has_key(fn):
  156. # type specified for a multi-table join
  157. # usually from Report Builder
  158. desc = meta[dt][fn]
  159. colnames.append(desc[0] or fn)
  160. coltypes.append(desc[1] or '')
  161. coloptions.append(desc[2] or '')
  162. colwidths.append(desc[3] or '100')
  163. else:
  164. # nothing found
  165. # guess
  166. colnames.append(fn)
  167. coltypes.append(guess_type(f[1]))
  168. coloptions.append('')
  169. colwidths.append('100')
  170. return colnames, coltypes, coloptions, colwidths
  171. @webnotes.whitelist()
  172. def runquery(q='', ret=0, from_export=0):
  173. import webnotes.utils
  174. formatted = cint(webnotes.form_dict.get('formatted'))
  175. # CASE A: Simple Query
  176. # --------------------
  177. if webnotes.form_dict.get('simple_query') or webnotes.form_dict.get('is_simple'):
  178. if not q: q = webnotes.form_dict.get('simple_query') or webnotes.form_dict.get('query')
  179. if q.split()[0].lower() != 'select':
  180. raise Exception, 'Query must be a SELECT'
  181. as_dict = cint(webnotes.form_dict.get('as_dict'))
  182. res = sql(q, as_dict = as_dict, as_list = not as_dict, formatted=formatted)
  183. # build colnames etc from metadata
  184. colnames, coltypes, coloptions, colwidths = [], [], [], []
  185. # CASE B: Standard Query
  186. # -----------------------
  187. else:
  188. if not q: q = webnotes.form_dict.get('query')
  189. tl = get_sql_tables(q)
  190. meta = get_sql_meta(tl)
  191. q = add_match_conditions(q, tl)
  192. webnotes
  193. # replace special variables
  194. q = q.replace('__user', session['user'])
  195. q = q.replace('__today', webnotes.utils.nowdate())
  196. res = sql(q, as_list=1, formatted=formatted)
  197. colnames, coltypes, coloptions, colwidths = build_description_standard(meta, tl)
  198. # run server script
  199. # -----------------
  200. style, header_html, footer_html, page_template = '', '', '', ''
  201. if webnotes.form_dict.get('sc_id'):
  202. sc_id = webnotes.form_dict.get('sc_id')
  203. from webnotes.model.code import get_code
  204. sc_details = webnotes.conn.sql("select module, standard, server_script from `tabSearch Criteria` where name=%s", sc_id)[0]
  205. if sc_details[1]!='No':
  206. code = get_code(sc_details[0], 'Search Criteria', sc_id, 'py')
  207. else:
  208. code = sc_details[2]
  209. if code:
  210. filter_values = eval(webnotes.form_dict.get('filter_values','')) or {}
  211. res, style, header_html, footer_html, page_template = exec_report(code, res, colnames, colwidths, coltypes, coloptions, filter_values, q, from_export)
  212. out['colnames'] = colnames
  213. out['coltypes'] = coltypes
  214. out['coloptions'] = coloptions
  215. out['colwidths'] = colwidths
  216. out['header_html'] = header_html
  217. out['footer_html'] = footer_html
  218. out['page_template'] = page_template
  219. if style:
  220. out['style'] = style
  221. # just the data - return
  222. if ret==1:
  223. return res
  224. out['values'] = res
  225. # return num of entries
  226. qm = webnotes.form_dict.get('query_max') or ''
  227. if qm and qm.strip():
  228. if qm.split()[0].lower() != 'select':
  229. raise Exception, 'Query (Max) must be a SELECT'
  230. if not webnotes.form_dict.get('simple_query'):
  231. qm = add_match_conditions(qm, tl)
  232. out['n_values'] = webnotes.utils.cint(sql(qm)[0][0])
  233. @webnotes.whitelist()
  234. def runquery_csv():
  235. global out
  236. # run query
  237. res = runquery(from_export = 1)
  238. q = webnotes.form_dict.get('query')
  239. rep_name = webnotes.form_dict.get('report_name')
  240. if not webnotes.form_dict.get('simple_query'):
  241. # Report Name
  242. if not rep_name:
  243. rep_name = get_sql_tables(q)[0]
  244. if not rep_name: rep_name = 'DataExport'
  245. # Headings
  246. heads = []
  247. rows = [[rep_name], out['colnames']] + out['values']
  248. from cStringIO import StringIO
  249. import csv
  250. f = StringIO()
  251. writer = csv.writer(f)
  252. for r in rows:
  253. # encode only unicode type strings and not int, floats etc.
  254. writer.writerow(map(lambda v: isinstance(v, unicode) and v.encode('utf-8') or v, r))
  255. f.seek(0)
  256. out['result'] = unicode(f.read(), 'utf-8')
  257. out['type'] = 'csv'
  258. out['doctype'] = rep_name
  259. def add_limit_to_query(query, args):
  260. """
  261. Add limit condition to query
  262. can be used by methods called in listing to add limit condition
  263. """
  264. if args.get('limit_page_length'):
  265. query += """
  266. limit %(limit_start)s, %(limit_page_length)s"""
  267. import webnotes.utils
  268. args['limit_start'] = webnotes.utils.cint(args.get('limit_start'))
  269. args['limit_page_length'] = webnotes.utils.cint(args.get('limit_page_length'))
  270. return query, args