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.
 
 
 
 
 
 

137 lines
3.8 KiB

  1. # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
  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. @webnotes.whitelist()
  12. def get_script(report_name):
  13. report = webnotes.doc("Report", report_name)
  14. script_path = os.path.join(get_module_path(webnotes.conn.get_value("DocType", report.ref_doctype, "module")),
  15. "report", scrub(report.name), scrub(report.name) + ".js")
  16. if os.path.exists(script_path):
  17. with open(script_path, "r") as script:
  18. return script.read()
  19. else:
  20. return "wn.query_reports['%s']={}" % report_name
  21. @webnotes.whitelist()
  22. def run(report_name, filters=None):
  23. report = webnotes.doc("Report", report_name)
  24. if not webnotes.has_permission(report.ref_doctype, "report"):
  25. webnotes.msgprint(_("Must have report permission to access this report."),
  26. raise_exception=True)
  27. if report.report_type=="Query Report":
  28. if not report.query:
  29. webnotes.msgprint(_("Must specify a Query to run"), raise_exception=True)
  30. if not report.query.lower().startswith("select"):
  31. webnotes.msgprint(_("Query must be a SELECT"), raise_exception=True)
  32. result = [list(t) for t in webnotes.conn.sql(report.query)]
  33. columns = [c[0] for c in webnotes.conn.get_description()]
  34. else:
  35. if filters:
  36. filters = json.loads(filters)
  37. method_name = scrub(webnotes.conn.get_value("DocType", report.ref_doctype, "module")) \
  38. + ".report." + scrub(report.name) + "." + scrub(report.name) + ".execute"
  39. columns, result = webnotes.get_method(method_name)(filters or {})
  40. result = get_filtered_data(report.ref_doctype, columns, result)
  41. if cint(report.add_total_row) and result:
  42. result = add_total_row(result, columns)
  43. return {
  44. "result": result,
  45. "columns": columns
  46. }
  47. def add_total_row(result, columns):
  48. total_row = [""]*len(columns)
  49. for row in result:
  50. for i, col in enumerate(columns):
  51. col = col.split(":")
  52. if len(col) > 1 and col[1] in ["Currency", "Int", "Float"] and flt(row[i]):
  53. total_row[i] = flt(total_row[i]) + flt(row[i])
  54. first_col = columns[0].split(":")
  55. if len(first_col) > 1 and first_col[1] not in ["Currency", "Int", "Float"]:
  56. total_row[0] = "Total"
  57. result.append(total_row)
  58. return result
  59. def get_filtered_data(ref_doctype, columns, data):
  60. result = []
  61. linked_doctypes = get_linked_doctypes(columns)
  62. match_filters = get_user_match_filters(linked_doctypes, ref_doctype)
  63. if match_filters:
  64. matched_columns = get_matched_columns(linked_doctypes, match_filters)
  65. for row in data:
  66. match = True
  67. for col, idx in matched_columns.items():
  68. if row[idx] not in match_filters[col]:
  69. match = False
  70. if match:
  71. result.append(row)
  72. else:
  73. for row in data:
  74. result.append(row)
  75. return result
  76. def get_linked_doctypes(columns):
  77. linked_doctypes = {}
  78. for idx, col in enumerate(columns):
  79. col = col.split(":")
  80. if len(col) > 1 and col[1].startswith("Link"):
  81. link_dt = col[1].split("/")[1]
  82. linked_doctypes[link_dt] = idx
  83. return linked_doctypes
  84. def get_user_match_filters(doctypes, ref_doctype):
  85. match_filters = {}
  86. doctypes_meta = {}
  87. tables = []
  88. doctypes[ref_doctype] = None
  89. for dt in doctypes:
  90. tables.append("`tab" + dt + "`")
  91. doctypes_meta[dt] = webnotes.model.doctype.get(dt)
  92. webnotes.widgets.reportview.tables = tables
  93. webnotes.widgets.reportview.doctypes = doctypes_meta
  94. for dt in doctypes:
  95. match_filters.update(webnotes.widgets.reportview.build_match_conditions(dt,
  96. None, False))
  97. return match_filters
  98. def get_matched_columns(linked_doctypes, match_filters):
  99. col_idx_map = {}
  100. for dt, idx in linked_doctypes.items():
  101. link_field = dt.lower().replace(" ", "_")
  102. if link_field in match_filters:
  103. col_idx_map[link_field] = idx
  104. return col_idx_map