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 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. def get_report_doc(report_name):
  12. bean = webnotes.bean("Report", report_name)
  13. if not bean.has_read_perm():
  14. raise webnotes.PermissionError("You don't have access to: {report}".format(report=report_name))
  15. if not webnotes.has_permission(bean.doc.ref_doctype, "report"):
  16. raise webnotes.PermissionError("You don't have access to get a report on: {doctype}".format(
  17. doctype=bean.doc.ref_doctype))
  18. return bean.doc
  19. @webnotes.whitelist()
  20. def get_script(report_name):
  21. report = get_report_doc(report_name)
  22. module = webnotes.conn.get_value("DocType", report.ref_doctype, "module")
  23. module_path = get_module_path(module)
  24. report_folder = os.path.join(module_path, "report", scrub(report.name))
  25. script_path = os.path.join(report_folder, scrub(report.name) + ".js")
  26. script = None
  27. if os.path.exists(script_path):
  28. with open(script_path, "r") as script:
  29. script = script.read()
  30. if not script and report.javascript:
  31. script = report.javascript
  32. if not script:
  33. script = "wn.query_reports['%s']={}" % report_name
  34. # load translations
  35. if webnotes.lang != "en":
  36. webnotes.response["__messages"] = webnotes.get_lang_dict("report", report_name)
  37. return script
  38. @webnotes.whitelist()
  39. def run(report_name, filters=()):
  40. report = get_report_doc(report_name)
  41. if filters and isinstance(filters, basestring):
  42. filters = json.loads(filters)
  43. if not webnotes.has_permission(report.ref_doctype, "report"):
  44. webnotes.msgprint(_("Must have report permission to access this report."),
  45. raise_exception=True)
  46. if report.report_type=="Query Report":
  47. if not report.query:
  48. webnotes.msgprint(_("Must specify a Query to run"), raise_exception=True)
  49. if not report.query.lower().startswith("select"):
  50. webnotes.msgprint(_("Query must be a SELECT"), raise_exception=True)
  51. result = [list(t) for t in webnotes.conn.sql(report.query, filters)]
  52. columns = [c[0] for c in webnotes.conn.get_description()]
  53. else:
  54. module = webnotes.conn.get_value("DocType", report.ref_doctype, "module")
  55. if report.is_standard=="Yes":
  56. method_name = webnotes.local.module_app[scrub(module)] + "." + scrub(module) \
  57. + ".report." + scrub(report.name) + "." + scrub(report.name) + ".execute"
  58. columns, result = webnotes.get_attr(method_name)(filters or {})
  59. result = get_filtered_data(report.ref_doctype, columns, result)
  60. if cint(report.add_total_row) and result:
  61. result = add_total_row(result, columns)
  62. return {
  63. "result": result,
  64. "columns": columns
  65. }
  66. def add_total_row(result, columns):
  67. total_row = [""]*len(columns)
  68. has_percent = []
  69. for row in result:
  70. for i, col in enumerate(columns):
  71. col = col.split(":")
  72. if len(col) > 1:
  73. if col[1] in ["Currency", "Int", "Float", "Percent"] and flt(row[i]):
  74. total_row[i] = flt(total_row[i]) + flt(row[i])
  75. if col[1] == "Percent" and i not in has_percent:
  76. has_percent.append(i)
  77. for i in has_percent:
  78. total_row[i] = total_row[i] / len(result)
  79. first_col = columns[0].split(":")
  80. if len(first_col) > 1 and first_col[1] not in ["Currency", "Int", "Float", "Percent"]:
  81. total_row[0] = "Total"
  82. result.append(total_row)
  83. return result
  84. def get_filtered_data(ref_doctype, columns, data):
  85. result = []
  86. linked_doctypes = get_linked_doctypes(columns)
  87. match_filters = get_user_match_filters(linked_doctypes, ref_doctype)
  88. if match_filters:
  89. matched_columns = get_matched_columns(linked_doctypes, match_filters)
  90. for row in data:
  91. match = True
  92. if not ("owner" in match_filters and matched_columns.get("profile", None)==match_filters["owner"]):
  93. for col, idx in matched_columns.items():
  94. if row[idx] not in match_filters[col]:
  95. match = False
  96. break
  97. if match:
  98. result.append(row)
  99. else:
  100. for row in data:
  101. result.append(row)
  102. return result
  103. def get_linked_doctypes(columns):
  104. linked_doctypes = {}
  105. for idx, col in enumerate(columns):
  106. col = col.split(":")
  107. if len(col) > 1 and col[1].startswith("Link"):
  108. link_dt = col[1].split("/")[1]
  109. linked_doctypes[link_dt] = idx
  110. return linked_doctypes
  111. def get_user_match_filters(doctypes, ref_doctype):
  112. match_filters = {}
  113. doctypes_meta = {}
  114. tables = []
  115. for dt in doctypes:
  116. tables.append("`tab" + dt + "`")
  117. doctypes_meta[dt] = webnotes.model.doctype.get(dt)
  118. webnotes.local.reportview_tables = tables
  119. webnotes.local.reportview_doctypes = doctypes_meta
  120. for dt in doctypes:
  121. match_filters.update(webnotes.widgets.reportview.build_match_conditions(dt,
  122. None, False))
  123. return match_filters
  124. def get_matched_columns(linked_doctypes, match_filters):
  125. if "owner" in match_filters:
  126. match_filters["profile"] = match_filters["owner"]
  127. col_idx_map = {}
  128. for dt, idx in linked_doctypes.items():
  129. link_field = dt.lower().replace(" ", "_")
  130. if link_field in match_filters:
  131. col_idx_map[link_field] = idx
  132. return col_idx_map