You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

пре 11 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. import webnotes
  5. import os, json
  6. import types
  7. from webnotes import _
  8. from webnotes.modules import scrub, get_module_path
  9. from webnotes.utils import flt, cint
  10. import webnotes.widgets.reportview
  11. import webnotes.plugins
  12. @webnotes.whitelist()
  13. def get_script(report_name):
  14. report = webnotes.doc("Report", report_name)
  15. module = webnotes.conn.get_value("DocType", report.ref_doctype, "module")
  16. module_path = get_module_path(module)
  17. report_folder = os.path.join(module_path, "report", scrub(report.name))
  18. script_path = os.path.join(report_folder, scrub(report.name) + ".js")
  19. script = None
  20. if os.path.exists(script_path):
  21. with open(script_path, "r") as script:
  22. script = script.read()
  23. if not script and report.is_standard == "No":
  24. script = webnotes.plugins.read_file(module, "Report", report.name, extn="js", cache=True)
  25. if not script and report.javascript:
  26. script = report.javascript
  27. if not script:
  28. script = "wn.query_reports['%s']={}" % report_name
  29. # load translations
  30. if webnotes.lang != "en":
  31. from webnotes.translate import get_lang_data
  32. if os.path.exists(report_folder):
  33. messages = get_lang_data(report_folder, webnotes.lang, 'js')
  34. webnotes.response["__messages"] = messages
  35. else:
  36. # TODO check if language files get exported here
  37. plugins_report_folder = webnotes.plugins.get_path(module, "Report", report.name)
  38. if os.path.exists(plugins_report_folder):
  39. messages = get_lang_data(plugins_report_folder, webnotes.lang, 'js')
  40. webnotes.response["__messages"] = messages
  41. return script
  42. @webnotes.whitelist()
  43. def run(report_name, filters=None):
  44. from webnotes.plugins import get_code_and_execute
  45. report = webnotes.doc("Report", report_name)
  46. if filters and isinstance(filters, basestring):
  47. filters = json.loads(filters)
  48. if not webnotes.has_permission(report.ref_doctype, "report"):
  49. webnotes.msgprint(_("Must have report permission to access this report."),
  50. raise_exception=True)
  51. if report.report_type=="Query Report":
  52. if not report.query:
  53. webnotes.msgprint(_("Must specify a Query to run"), raise_exception=True)
  54. if not report.query.lower().startswith("select"):
  55. webnotes.msgprint(_("Query must be a SELECT"), raise_exception=True)
  56. result = [list(t) for t in webnotes.conn.sql(report.query, filters)]
  57. columns = [c[0] for c in webnotes.conn.get_description()]
  58. else:
  59. module = webnotes.conn.get_value("DocType", report.ref_doctype, "module")
  60. if report.is_standard=="Yes":
  61. method_name = scrub(module) + ".report." + scrub(report.name) + "." + scrub(report.name) + ".execute"
  62. columns, result = webnotes.get_method(method_name)(filters or {})
  63. else:
  64. namespace = get_code_and_execute(module, "Report", report.name)
  65. columns, result = namespace["execute"](filters or {})
  66. result = get_filtered_data(report.ref_doctype, columns, result)
  67. if cint(report.add_total_row) and result:
  68. result = add_total_row(result, columns)
  69. return {
  70. "result": result,
  71. "columns": columns
  72. }
  73. def add_total_row(result, columns):
  74. total_row = [""]*len(columns)
  75. has_percent = []
  76. for row in result:
  77. for i, col in enumerate(columns):
  78. col = col.split(":")
  79. if len(col) > 1:
  80. if col[1] in ["Currency", "Int", "Float", "Percent"] and flt(row[i]):
  81. total_row[i] = flt(total_row[i]) + flt(row[i])
  82. if col[1] == "Percent" and i not in has_percent:
  83. has_percent.append(i)
  84. for i in has_percent:
  85. total_row[i] = total_row[i] / len(result)
  86. first_col = columns[0].split(":")
  87. if len(first_col) > 1 and first_col[1] not in ["Currency", "Int", "Float", "Percent"]:
  88. total_row[0] = "Total"
  89. result.append(total_row)
  90. return result
  91. def get_filtered_data(ref_doctype, columns, data):
  92. result = []
  93. linked_doctypes = get_linked_doctypes(columns)
  94. match_filters = get_user_match_filters(linked_doctypes, ref_doctype)
  95. if match_filters:
  96. matched_columns = get_matched_columns(linked_doctypes, match_filters)
  97. for row in data:
  98. match = True
  99. for col, idx in matched_columns.items():
  100. if row[idx] not in match_filters[col]:
  101. match = False
  102. if match:
  103. result.append(row)
  104. else:
  105. for row in data:
  106. result.append(row)
  107. return result
  108. def get_linked_doctypes(columns):
  109. linked_doctypes = {}
  110. for idx, col in enumerate(columns):
  111. col = col.split(":")
  112. if len(col) > 1 and col[1].startswith("Link"):
  113. link_dt = col[1].split("/")[1]
  114. linked_doctypes[link_dt] = idx
  115. return linked_doctypes
  116. def get_user_match_filters(doctypes, ref_doctype):
  117. match_filters = {}
  118. doctypes_meta = {}
  119. tables = []
  120. for dt in doctypes:
  121. tables.append("`tab" + dt + "`")
  122. doctypes_meta[dt] = webnotes.model.doctype.get(dt)
  123. webnotes.local.reportview_tables = tables
  124. webnotes.local.reportview_doctypes = doctypes_meta
  125. for dt in doctypes:
  126. match_filters.update(webnotes.widgets.reportview.build_match_conditions(dt,
  127. None, False))
  128. return match_filters
  129. def get_matched_columns(linked_doctypes, match_filters):
  130. if "owner" in match_filters:
  131. match_filters["profile"] = match_filters["owner"]
  132. col_idx_map = {}
  133. for dt, idx in linked_doctypes.items():
  134. link_field = dt.lower().replace(" ", "_")
  135. if link_field in match_filters:
  136. col_idx_map[link_field] = idx
  137. return col_idx_map