django-advanced-report-builder 1.2.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (360) hide show
  1. advanced_report_builder/.DS_Store +0 -0
  2. advanced_report_builder/.ruff_cache/.gitignore +2 -0
  3. advanced_report_builder/.ruff_cache/0.11.9/16555798982502606642 +0 -0
  4. advanced_report_builder/.ruff_cache/CACHEDIR.TAG +1 -0
  5. advanced_report_builder/__init__.py +0 -0
  6. advanced_report_builder/admin.py +264 -0
  7. advanced_report_builder/apps.py +7 -0
  8. advanced_report_builder/column_types.py +26 -0
  9. advanced_report_builder/columns.py +296 -0
  10. advanced_report_builder/customise.py +2 -0
  11. advanced_report_builder/data_merge/__init__.py +0 -0
  12. advanced_report_builder/data_merge/utils.py +112 -0
  13. advanced_report_builder/data_merge/widget.py +30 -0
  14. advanced_report_builder/duplicate.py +171 -0
  15. advanced_report_builder/exceptions.py +9 -0
  16. advanced_report_builder/field_types.py +466 -0
  17. advanced_report_builder/field_utils.py +401 -0
  18. advanced_report_builder/filter_query.py +862 -0
  19. advanced_report_builder/form_utils.py +12 -0
  20. advanced_report_builder/generate_series.py +14 -0
  21. advanced_report_builder/globals.py +276 -0
  22. advanced_report_builder/includes.py +72 -0
  23. advanced_report_builder/migrations/0001_initial.py +246 -0
  24. advanced_report_builder/migrations/0002_auto_20220209_1657.py +23 -0
  25. advanced_report_builder/migrations/0003_auto_20220215_1219.py +42 -0
  26. advanced_report_builder/migrations/0004_customreport.py +27 -0
  27. advanced_report_builder/migrations/0005_auto_20220303_0958.py +84 -0
  28. advanced_report_builder/migrations/0006_auto_20220310_1147.py +32 -0
  29. advanced_report_builder/migrations/0007_auto_20220322_1939.py +23 -0
  30. advanced_report_builder/migrations/0008_auto_20220404_1144.py +28 -0
  31. advanced_report_builder/migrations/0009_auto_20230428_1554.py +53 -0
  32. advanced_report_builder/migrations/0010_auto_20230428_2033.py +23 -0
  33. advanced_report_builder/migrations/0011_auto_20230620_1449.py +23 -0
  34. advanced_report_builder/migrations/0012_auto_20230718_1642.py +24 -0
  35. advanced_report_builder/migrations/0013_reportqueryorder.py +30 -0
  36. advanced_report_builder/migrations/0014_auto_20240706_2207.py +24 -0
  37. advanced_report_builder/migrations/0015_report_user_created_report_user_updated.py +26 -0
  38. advanced_report_builder/migrations/0016_calendarreport_dashboardreport_options_and_more.py +74 -0
  39. advanced_report_builder/migrations/0017_alter_barchartreport_options_and_more.py +57 -0
  40. advanced_report_builder/migrations/0018_reportquery_target_target_period_type.py +24 -0
  41. advanced_report_builder/migrations/0019_multicellstyle_and_more.py +107 -0
  42. advanced_report_builder/migrations/0020_alter_multicellstyle_font_size.py +18 -0
  43. advanced_report_builder/migrations/0021_multivalueheldquery_and_more.py +36 -0
  44. advanced_report_builder/migrations/0022_dashboardreport_show_options_report_template_style_and_more.py +44 -0
  45. advanced_report_builder/migrations/0023_rename_colour_target_default_colour_and_more.py +41 -0
  46. advanced_report_builder/migrations/0024_alter_target_period_type.py +18 -0
  47. advanced_report_builder/migrations/__init__.py +0 -0
  48. advanced_report_builder/models.py +954 -0
  49. advanced_report_builder/report_builder.py +28 -0
  50. advanced_report_builder/signals.py +3 -0
  51. advanced_report_builder/static/.DS_Store +0 -0
  52. advanced_report_builder/static/advanced_report_builder/.DS_Store +0 -0
  53. advanced_report_builder/static/advanced_report_builder/chart-js/js/chart.esm.js +10553 -0
  54. advanced_report_builder/static/advanced_report_builder/chart-js/js/chart.js +13190 -0
  55. advanced_report_builder/static/advanced_report_builder/chart-js/js/chart.min.js +13 -0
  56. advanced_report_builder/static/advanced_report_builder/chart-js/js/chartjs-adapter-moment.min.js +8 -0
  57. advanced_report_builder/static/advanced_report_builder/chart-js/js/chartjs-plugin-datalabels.min.js +7 -0
  58. advanced_report_builder/static/advanced_report_builder/chart-js/js/chunks/helpers.segment.js +2499 -0
  59. advanced_report_builder/static/advanced_report_builder/chart-js/js/helpers.esm.js +7 -0
  60. advanced_report_builder/static/advanced_report_builder/d3/js/d3.js +20196 -0
  61. advanced_report_builder/static/advanced_report_builder/d3/js/d3.min.js +2 -0
  62. advanced_report_builder/static/advanced_report_builder/d3-funnel/js/d3-funnel.js +6087 -0
  63. advanced_report_builder/static/advanced_report_builder/d3-funnel/js/d3-funnel.min.js +2 -0
  64. advanced_report_builder/static/advanced_report_builder/dashboard/js/dashboard.js +19 -0
  65. advanced_report_builder/static/advanced_report_builder/dot/js/.gitignore +31 -0
  66. advanced_report_builder/static/advanced_report_builder/dot/js/.travis.yml +9 -0
  67. advanced_report_builder/static/advanced_report_builder/dot/js/LICENSE-DOT.txt +24 -0
  68. advanced_report_builder/static/advanced_report_builder/dot/js/README.md +90 -0
  69. advanced_report_builder/static/advanced_report_builder/dot/js/bin/dot-packer +52 -0
  70. advanced_report_builder/static/advanced_report_builder/dot/js/bower.json +21 -0
  71. advanced_report_builder/static/advanced_report_builder/dot/js/doT.js +141 -0
  72. advanced_report_builder/static/advanced_report_builder/dot/js/doT.min.js +8 -0
  73. advanced_report_builder/static/advanced_report_builder/dot/js/doU.js +56 -0
  74. advanced_report_builder/static/advanced_report_builder/dot/js/index.js +143 -0
  75. advanced_report_builder/static/advanced_report_builder/dot/js/package.json +46 -0
  76. advanced_report_builder/static/advanced_report_builder/fullcalendar/.DS_Store +0 -0
  77. advanced_report_builder/static/advanced_report_builder/fullcalendar/LICENSE.txt +20 -0
  78. advanced_report_builder/static/advanced_report_builder/fullcalendar/README.md +10 -0
  79. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/LICENSE.txt +20 -0
  80. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/README.md +8 -0
  81. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/af.js +30 -0
  82. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/ar-dz.js +31 -0
  83. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/ar-kw.js +31 -0
  84. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/ar-ly.js +31 -0
  85. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/ar-ma.js +31 -0
  86. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/ar-sa.js +31 -0
  87. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/ar-tn.js +31 -0
  88. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/ar.js +31 -0
  89. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/bg.js +31 -0
  90. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/bs.js +32 -0
  91. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/ca.js +30 -0
  92. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/cs.js +32 -0
  93. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/da.js +30 -0
  94. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/de.js +33 -0
  95. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/el.js +30 -0
  96. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/en-au.js +17 -0
  97. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/en-gb.js +17 -0
  98. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/en-nz.js +17 -0
  99. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/es-us.js +30 -0
  100. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/es.js +30 -0
  101. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/et.js +32 -0
  102. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/eu.js +30 -0
  103. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/fa.js +33 -0
  104. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/fi.js +30 -0
  105. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/fr-ca.js +27 -0
  106. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/fr-ch.js +31 -0
  107. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/fr.js +31 -0
  108. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/gl.js +30 -0
  109. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/he.js +27 -0
  110. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/hi.js +32 -0
  111. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/hr.js +32 -0
  112. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/hu.js +30 -0
  113. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/id.js +30 -0
  114. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/is.js +30 -0
  115. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/it.js +32 -0
  116. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/ja.js +28 -0
  117. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/ka.js +32 -0
  118. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/kk.js +32 -0
  119. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/ko.js +26 -0
  120. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/lb.js +30 -0
  121. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/lt.js +30 -0
  122. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/lv.js +32 -0
  123. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/mk.js +28 -0
  124. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/ms.js +32 -0
  125. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/nb.js +30 -0
  126. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/nl.js +30 -0
  127. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/nn.js +30 -0
  128. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/pl.js +30 -0
  129. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/pt-br.js +28 -0
  130. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/pt.js +30 -0
  131. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/ro.js +32 -0
  132. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/ru.js +32 -0
  133. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/sk.js +32 -0
  134. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/sl.js +30 -0
  135. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/sq.js +32 -0
  136. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/sr-cyrl.js +32 -0
  137. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/sr.js +32 -0
  138. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/sv.js +30 -0
  139. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/th.js +25 -0
  140. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/tr.js +30 -0
  141. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/uk.js +32 -0
  142. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/vi.js +32 -0
  143. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/zh-cn.js +33 -0
  144. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales/zh-tw.js +26 -0
  145. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales-all.js +1348 -0
  146. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/locales-all.min.js +1 -0
  147. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/main.css +1052 -0
  148. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/main.d.ts +2730 -0
  149. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/main.esm.js +8558 -0
  150. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/main.js +8717 -0
  151. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/main.min.css +1 -0
  152. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/main.min.js +6 -0
  153. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/core/package.json +30 -0
  154. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/daygrid/LICENSE.txt +20 -0
  155. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/daygrid/README.md +8 -0
  156. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/daygrid/main.css +78 -0
  157. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/daygrid/main.d.ts +310 -0
  158. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/daygrid/main.esm.js +1627 -0
  159. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/daygrid/main.js +1641 -0
  160. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/daygrid/main.min.css +1 -0
  161. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/daygrid/main.min.js +6 -0
  162. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/daygrid/package.json +33 -0
  163. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/fullcalendar-yearview/LICENSE +21 -0
  164. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/fullcalendar-yearview/css/main.css +85 -0
  165. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/fullcalendar-yearview/js/main.js +2018 -0
  166. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/google-calendar/LICENSE.txt +20 -0
  167. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/google-calendar/README.md +8 -0
  168. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/google-calendar/main.d.ts +20 -0
  169. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/google-calendar/main.esm.js +162 -0
  170. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/google-calendar/main.js +170 -0
  171. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/google-calendar/main.min.js +6 -0
  172. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/google-calendar/package.json +33 -0
  173. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/interaction/LICENSE.txt +20 -0
  174. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/interaction/README.md +8 -0
  175. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/interaction/main.d.ts +323 -0
  176. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/interaction/main.esm.js +2132 -0
  177. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/interaction/main.js +2143 -0
  178. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/interaction/main.min.js +6 -0
  179. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/interaction/package.json +33 -0
  180. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/list/LICENSE.txt +20 -0
  181. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/list/README.md +8 -0
  182. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/list/main.css +118 -0
  183. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/list/main.d.ts +33 -0
  184. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/list/main.esm.js +335 -0
  185. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/list/main.js +343 -0
  186. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/list/main.min.css +1 -0
  187. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/list/main.min.js +6 -0
  188. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/list/package.json +33 -0
  189. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/luxon/LICENSE.txt +20 -0
  190. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/luxon/README.md +8 -0
  191. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/luxon/main.d.ts +14 -0
  192. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/luxon/main.esm.js +162 -0
  193. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/luxon/main.js +170 -0
  194. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/luxon/main.min.js +6 -0
  195. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/luxon/package.json +34 -0
  196. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/moment/LICENSE.txt +20 -0
  197. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/moment/README.md +8 -0
  198. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/moment/main.d.ts +14 -0
  199. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/moment/main.esm.js +102 -0
  200. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/moment/main.js +110 -0
  201. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/moment/main.min.js +6 -0
  202. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/moment/package.json +34 -0
  203. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/moment-timezone/LICENSE.txt +20 -0
  204. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/moment-timezone/README.md +8 -0
  205. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/moment-timezone/main.d.ts +11 -0
  206. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/moment-timezone/main.esm.js +58 -0
  207. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/moment-timezone/main.js +64 -0
  208. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/moment-timezone/main.min.js +6 -0
  209. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/moment-timezone/package.json +35 -0
  210. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/rrule/LICENSE.txt +20 -0
  211. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/rrule/README.md +8 -0
  212. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/rrule/main.d.ts +9 -0
  213. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/rrule/main.esm.js +121 -0
  214. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/rrule/main.js +128 -0
  215. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/rrule/main.min.js +6 -0
  216. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/rrule/package.json +34 -0
  217. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/timegrid/LICENSE.txt +20 -0
  218. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/timegrid/README.md +8 -0
  219. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/timegrid/main.css +309 -0
  220. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/timegrid/main.d.ts +220 -0
  221. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/timegrid/main.esm.js +1345 -0
  222. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/timegrid/main.js +1357 -0
  223. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/timegrid/main.min.css +1 -0
  224. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/timegrid/main.min.js +6 -0
  225. advanced_report_builder/static/advanced_report_builder/fullcalendar/packages/timegrid/package.json +36 -0
  226. advanced_report_builder/static/advanced_report_builder/fullcalendar/vendor/rrule.js +3782 -0
  227. advanced_report_builder/static/advanced_report_builder/jquery_extendext/js/jQuery.extendext.js +132 -0
  228. advanced_report_builder/static/advanced_report_builder/jquery_extendext/js/jQuery.extendext.min.js +9 -0
  229. advanced_report_builder/static/advanced_report_builder/moment/locales.js +9769 -0
  230. advanced_report_builder/static/advanced_report_builder/moment/locales.min.js +1 -0
  231. advanced_report_builder/static/advanced_report_builder/moment/moment-with-locales.js +14289 -0
  232. advanced_report_builder/static/advanced_report_builder/moment/moment-with-locales.min.js +1 -0
  233. advanced_report_builder/static/advanced_report_builder/moment/moment.min.js +1 -0
  234. advanced_report_builder/static/advanced_report_builder/query_builder/.DS_Store +0 -0
  235. advanced_report_builder/static/advanced_report_builder/query_builder/css/.DS_Store +0 -0
  236. advanced_report_builder/static/advanced_report_builder/query_builder/css/query-builder.dark.css +173 -0
  237. advanced_report_builder/static/advanced_report_builder/query_builder/css/query-builder.dark.min.css +6 -0
  238. advanced_report_builder/static/advanced_report_builder/query_builder/css/query-builder.default.css +173 -0
  239. advanced_report_builder/static/advanced_report_builder/query_builder/css/query-builder.default.min.css +6 -0
  240. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.ar.js +80 -0
  241. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.az.js +79 -0
  242. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.bg.js +79 -0
  243. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.cs.js +79 -0
  244. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.da.js +56 -0
  245. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.de.js +76 -0
  246. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.el.js +80 -0
  247. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.en.js +83 -0
  248. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.es.js +81 -0
  249. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.fa-IR.js +79 -0
  250. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.fr.js +83 -0
  251. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.he.js +81 -0
  252. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.it.js +79 -0
  253. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.nl.js +76 -0
  254. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.no.js +54 -0
  255. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.pl.js +80 -0
  256. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.pt-BR.js +80 -0
  257. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.pt-PT.js +75 -0
  258. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.ro.js +54 -0
  259. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.ru.js +77 -0
  260. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.sq.js +78 -0
  261. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.tr.js +82 -0
  262. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.ua.js +79 -0
  263. advanced_report_builder/static/advanced_report_builder/query_builder/i18n/query-builder.zh-CN.js +80 -0
  264. advanced_report_builder/static/advanced_report_builder/query_builder/js/.DS_Store +0 -0
  265. advanced_report_builder/static/advanced_report_builder/query_builder/js/plugins/.DS_Store +0 -0
  266. advanced_report_builder/static/advanced_report_builder/query_builder/js/plugins/currency/plugin.js +30 -0
  267. advanced_report_builder/static/advanced_report_builder/query_builder/js/query-builder.js +6200 -0
  268. advanced_report_builder/static/advanced_report_builder/query_builder/js/query-builder.min.js +7 -0
  269. advanced_report_builder/static/advanced_report_builder/query_builder/js/query-builder.standalone.js +6477 -0
  270. advanced_report_builder/static/advanced_report_builder/query_builder/js/query-builder.standalone.min.js +7 -0
  271. advanced_report_builder/static/advanced_report_builder/query_builder/scss/.DS_Store +0 -0
  272. advanced_report_builder/static/advanced_report_builder/query_builder/scss/dark.scss +19 -0
  273. advanced_report_builder/static/advanced_report_builder/query_builder/scss/default.scss +186 -0
  274. advanced_report_builder/static/advanced_report_builder/query_builder/scss/plugins/_bt-checkbox.scss +12 -0
  275. advanced_report_builder/static/advanced_report_builder/query_builder/scss/plugins/_bt-tooltip-errors.scss +9 -0
  276. advanced_report_builder/static/advanced_report_builder/query_builder/scss/plugins/_filter-description.scss +21 -0
  277. advanced_report_builder/static/advanced_report_builder/query_builder/scss/plugins/_invert.scss +5 -0
  278. advanced_report_builder/static/advanced_report_builder/query_builder/scss/plugins/_sortable.scss +28 -0
  279. advanced_report_builder/static/advanced_report_builder/query_builder/scss/plugins/bt-tooltip-errors.scss +9 -0
  280. advanced_report_builder/static/advanced_report_builder/query_builder/scss/plugins/filter-description.scss +21 -0
  281. advanced_report_builder/static/advanced_report_builder/query_builder/scss/plugins/invert.scss +5 -0
  282. advanced_report_builder/static/advanced_report_builder/query_builder/scss/plugins/sortable.scss +27 -0
  283. advanced_report_builder/template_types.py +34 -0
  284. advanced_report_builder/templates/advanced_report_builder/calendar/description_modal.html +12 -0
  285. advanced_report_builder/templates/advanced_report_builder/calendar/middle.html +33 -0
  286. advanced_report_builder/templates/advanced_report_builder/calendar/modal.html +10 -0
  287. advanced_report_builder/templates/advanced_report_builder/calendar/report.html +80 -0
  288. advanced_report_builder/templates/advanced_report_builder/charts/bar/middle.html +122 -0
  289. advanced_report_builder/templates/advanced_report_builder/charts/funnel/middle.html +46 -0
  290. advanced_report_builder/templates/advanced_report_builder/charts/funnel/report.html +34 -0
  291. advanced_report_builder/templates/advanced_report_builder/charts/line/middle.html +119 -0
  292. advanced_report_builder/templates/advanced_report_builder/charts/modal.html +12 -0
  293. advanced_report_builder/templates/advanced_report_builder/charts/modal_field.html +13 -0
  294. advanced_report_builder/templates/advanced_report_builder/charts/pie/middle.html +58 -0
  295. advanced_report_builder/templates/advanced_report_builder/charts/report.html +33 -0
  296. advanced_report_builder/templates/advanced_report_builder/data_merge/data_merge.html +144 -0
  297. advanced_report_builder/templates/advanced_report_builder/datatables/fields/modal.html +13 -0
  298. advanced_report_builder/templates/advanced_report_builder/datatables/fields/single_query_builder.html +87 -0
  299. advanced_report_builder/templates/advanced_report_builder/datatables/modal.html +13 -0
  300. advanced_report_builder/templates/advanced_report_builder/datatables/onclick_menu.html +14 -0
  301. advanced_report_builder/templates/advanced_report_builder/datatables/report.html +37 -0
  302. advanced_report_builder/templates/advanced_report_builder/datatables/select_pivot.html +199 -0
  303. advanced_report_builder/templates/advanced_report_builder/error.html +21 -0
  304. advanced_report_builder/templates/advanced_report_builder/extra_query_modal.html +13 -0
  305. advanced_report_builder/templates/advanced_report_builder/kanban/description_modal.html +12 -0
  306. advanced_report_builder/templates/advanced_report_builder/kanban/middle.html +63 -0
  307. advanced_report_builder/templates/advanced_report_builder/kanban/modal.html +10 -0
  308. advanced_report_builder/templates/advanced_report_builder/kanban/report.html +71 -0
  309. advanced_report_builder/templates/advanced_report_builder/multi_values/held_modal.html +14 -0
  310. advanced_report_builder/templates/advanced_report_builder/multi_values/middle.html +61 -0
  311. advanced_report_builder/templates/advanced_report_builder/multi_values/modal.html +15 -0
  312. advanced_report_builder/templates/advanced_report_builder/multi_values/report.html +19 -0
  313. advanced_report_builder/templates/advanced_report_builder/query_builder.html +88 -0
  314. advanced_report_builder/templates/advanced_report_builder/query_modal.html +12 -0
  315. advanced_report_builder/templates/advanced_report_builder/select_column.html +230 -0
  316. advanced_report_builder/templates/advanced_report_builder/single_values/gauge_middle.html +143 -0
  317. advanced_report_builder/templates/advanced_report_builder/single_values/middle.html +63 -0
  318. advanced_report_builder/templates/advanced_report_builder/single_values/modal.html +13 -0
  319. advanced_report_builder/templates/advanced_report_builder/single_values/report.html +56 -0
  320. advanced_report_builder/toggle.py +9 -0
  321. advanced_report_builder/urls.py +237 -0
  322. advanced_report_builder/utils.py +171 -0
  323. advanced_report_builder/variable_date.py +670 -0
  324. advanced_report_builder/view_types.py +27 -0
  325. advanced_report_builder/views/.DS_Store +0 -0
  326. advanced_report_builder/views/__init__.py +0 -0
  327. advanced_report_builder/views/bar_charts.py +746 -0
  328. advanced_report_builder/views/calendar.py +745 -0
  329. advanced_report_builder/views/charts_base.py +625 -0
  330. advanced_report_builder/views/custom.py +147 -0
  331. advanced_report_builder/views/dashboard.py +357 -0
  332. advanced_report_builder/views/datatables/__init__.py +0 -0
  333. advanced_report_builder/views/datatables/datatables.py +151 -0
  334. advanced_report_builder/views/datatables/modal.py +1151 -0
  335. advanced_report_builder/views/datatables/utils.py +701 -0
  336. advanced_report_builder/views/error_pod.py +50 -0
  337. advanced_report_builder/views/funnel_charts.py +289 -0
  338. advanced_report_builder/views/helpers.py +22 -0
  339. advanced_report_builder/views/kanban.py +868 -0
  340. advanced_report_builder/views/line_charts.py +415 -0
  341. advanced_report_builder/views/modals_base.py +213 -0
  342. advanced_report_builder/views/multi_value.py +1160 -0
  343. advanced_report_builder/views/pie_charts.py +290 -0
  344. advanced_report_builder/views/query_modal/__init__.py +0 -0
  345. advanced_report_builder/views/query_modal/mixin.py +161 -0
  346. advanced_report_builder/views/query_modal/modal.py +274 -0
  347. advanced_report_builder/views/report.py +241 -0
  348. advanced_report_builder/views/report_utils_mixin.py +312 -0
  349. advanced_report_builder/views/reports.py +154 -0
  350. advanced_report_builder/views/single_values.py +792 -0
  351. advanced_report_builder/views/targets/__init__.py +0 -0
  352. advanced_report_builder/views/targets/utils.py +251 -0
  353. advanced_report_builder/views/targets/views.py +139 -0
  354. advanced_report_builder/views/value_base.py +198 -0
  355. advanced_report_builder/widgets.py +5 -0
  356. django_advanced_report_builder-1.2.9.dist-info/METADATA +35 -0
  357. django_advanced_report_builder-1.2.9.dist-info/RECORD +360 -0
  358. django_advanced_report_builder-1.2.9.dist-info/WHEEL +5 -0
  359. django_advanced_report_builder-1.2.9.dist-info/licenses/LICENSE +21 -0
  360. django_advanced_report_builder-1.2.9.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1160 @@
1
+ import contextlib
2
+ import json
3
+ from copy import deepcopy
4
+
5
+ from django.conf import settings
6
+ from django.core.exceptions import FieldDoesNotExist, FieldError
7
+ from django.forms import CharField, ChoiceField, ModelChoiceField
8
+ from django.http import JsonResponse
9
+ from django.shortcuts import get_object_or_404
10
+ from django.urls import reverse
11
+ from django_datatables.columns import ColumnBase, MenuColumn
12
+ from django_datatables.datatables import DatatableTable
13
+ from django_datatables.helpers import DUMMY_ID
14
+ from django_datatables.widgets import DataTableWidget
15
+ from django_menus.menu import HtmlMenu, MenuItem
16
+ from django_modals.fields import FieldEx
17
+ from django_modals.form_helpers import HorizontalNoEnterHelper
18
+ from django_modals.forms import CrispyForm
19
+ from django_modals.helper import show_modal
20
+ from django_modals.modals import FormModal, Modal, ModelFormModal
21
+ from django_modals.processes import PERMISSION_OFF, PROCESS_EDIT_DELETE
22
+ from django_modals.widgets.select2 import Select2, Select2Multiple
23
+ from django_modals.widgets.widgets import Toggle
24
+ from expression_builder.exceptions import ExpressionVariableError
25
+ from expression_builder.expression_builder import ExpressionBuilder
26
+
27
+ from advanced_report_builder.columns import ReportBuilderNumberColumn
28
+ from advanced_report_builder.exceptions import ReportError
29
+ from advanced_report_builder.globals import ANNOTATION_CHOICE_AVERAGE_SUM_FROM_COUNT, ANNOTATION_CHOICE_SUM
30
+ from advanced_report_builder.models import (
31
+ MultiCellStyle,
32
+ MultiValueHeldQuery,
33
+ MultiValueReport,
34
+ MultiValueReportCell,
35
+ MultiValueReportColumn,
36
+ ReportType,
37
+ )
38
+ from advanced_report_builder.toggle import RBToggle
39
+ from advanced_report_builder.utils import crispy_modal_link_args, excel_column_name, get_report_builder_class
40
+ from advanced_report_builder.variable_date import VariableDate
41
+ from advanced_report_builder.views.charts_base import ChartJSTable
42
+ from advanced_report_builder.views.datatables.modal import TableFieldForm, TableFieldModal
43
+ from advanced_report_builder.views.datatables.utils import TableUtilsMixin
44
+ from advanced_report_builder.views.helpers import QueryBuilderModelForm
45
+ from advanced_report_builder.views.modals_base import QueryBuilderModalBase
46
+ from advanced_report_builder.views.query_modal.mixin import MultiQueryModalMixin
47
+ from advanced_report_builder.views.value_base import ValueBaseView
48
+ from advanced_report_builder.widgets import SmallNumberInputWidget
49
+
50
+
51
+ class MultiValueModal(ModelFormModal):
52
+ size = 'xl'
53
+ process = PROCESS_EDIT_DELETE
54
+ permission_delete = PERMISSION_OFF
55
+ model = MultiValueReport
56
+ widgets = {
57
+ 'report_tags': Select2Multiple,
58
+ 'rows': SmallNumberInputWidget,
59
+ 'columns': SmallNumberInputWidget,
60
+ }
61
+ ajax_commands = ['datatable', 'button']
62
+
63
+ form_fields = ['name', 'notes', 'report_tags', 'rows', 'columns']
64
+
65
+ def form_setup(self, form, *_args, **_kwargs):
66
+ org_id = self.object.id if hasattr(self, 'object') else None
67
+ if org_id is not None:
68
+ cell_styles_menu_items = [
69
+ MenuItem(
70
+ f'advanced_report_builder:multi_value_cell_style_modal,pk-{DUMMY_ID}',
71
+ menu_display='Edit',
72
+ css_classes='btn btn-sm btn-outline-dark',
73
+ font_awesome='fas fa-pencil',
74
+ ),
75
+ ]
76
+
77
+ form.fields['cell_styles'] = CharField(
78
+ required=False,
79
+ label='Cell Styles',
80
+ widget=DataTableWidget(
81
+ model=MultiCellStyle,
82
+ fields=[
83
+ '_.index',
84
+ '.id',
85
+ ColumnBase(column_name='cell_style_name', field='name', title='Name'),
86
+ MenuColumn(
87
+ column_name='menu',
88
+ field='id',
89
+ column_defs={'orderable': False, 'className': 'dt-right'},
90
+ menu=HtmlMenu(self.request, 'button_group').add_items(*cell_styles_menu_items),
91
+ ),
92
+ ],
93
+ attrs={'filter': {'multi_value_report__id': self.object.id}},
94
+ ),
95
+ )
96
+
97
+ query_menu_items = [
98
+ MenuItem(
99
+ f'advanced_report_builder:multi_value_query_modal,pk-{DUMMY_ID}',
100
+ menu_display='Edit',
101
+ css_classes='btn btn-sm btn-outline-dark',
102
+ font_awesome='fas fa-pencil',
103
+ ),
104
+ ]
105
+
106
+ form.fields['held_queries'] = CharField(
107
+ required=False,
108
+ label='Held Queries',
109
+ widget=DataTableWidget(
110
+ model=MultiValueHeldQuery,
111
+ fields=[
112
+ '_.index',
113
+ '.id',
114
+ ColumnBase(column_name='held_report_name', field='name', title='Name'),
115
+ ColumnBase(
116
+ column_name='held_report_report_name', field='report_type__name', title='Report Type'
117
+ ),
118
+ MenuColumn(
119
+ column_name='menu',
120
+ field='id',
121
+ column_defs={'orderable': False, 'className': 'dt-right'},
122
+ menu=HtmlMenu(self.request, 'button_group').add_items(*query_menu_items),
123
+ ),
124
+ ],
125
+ attrs={'filter': {'multi_value_report__id': self.object.id}},
126
+ ),
127
+ )
128
+
129
+ return [
130
+ *self.form_fields,
131
+ crispy_modal_link_args(
132
+ 'advanced_report_builder:multi_value_cell_style_modal',
133
+ 'Add Cell Style',
134
+ 'multi_value_report_id-',
135
+ self.object.id,
136
+ div=True,
137
+ div_classes='form-buttons',
138
+ button_classes='btn btn-primary',
139
+ font_awesome='fa fa-plus',
140
+ ),
141
+ 'cell_styles',
142
+ crispy_modal_link_args(
143
+ 'advanced_report_builder:multi_value_query_modal',
144
+ 'Add Held Query',
145
+ 'multi_value_report_id-',
146
+ self.object.id,
147
+ div=True,
148
+ div_classes='form-buttons',
149
+ button_classes='btn btn-primary',
150
+ font_awesome='fa fa-plus',
151
+ ),
152
+ 'held_queries',
153
+ crispy_modal_link_args(
154
+ 'advanced_report_builder:multi_value_cells_modal',
155
+ 'Edit Cells',
156
+ 'multi_value_report_id-',
157
+ self.object.id,
158
+ div=True,
159
+ div_classes='form-buttons',
160
+ button_classes='btn btn-primary',
161
+ font_awesome='fas fa-edit',
162
+ ),
163
+ ]
164
+
165
+ def form_valid(self, form):
166
+ org_id = self.object.pk if hasattr(self, 'object') else None
167
+ created = org_id is None
168
+ instance = form.save(commit=False)
169
+ instance._current_user = self.request.user
170
+ instance.save()
171
+
172
+ if created:
173
+ self.modal_redirect(
174
+ self.request.resolver_match.view_name,
175
+ slug=f'pk-{self.object.id}-new-True',
176
+ )
177
+ else:
178
+ url_name = getattr(settings, 'REPORT_BUILDER_DETAIL_URL_NAME', '')
179
+ if url_name and self.slug.get('new'):
180
+ url = reverse(url_name, kwargs={'slug': self.object.slug})
181
+ self.add_command('redirect', url=url)
182
+ if not self.response_commands:
183
+ self.add_command('reload')
184
+
185
+ return self.command_response()
186
+
187
+
188
+ class MultiValueCellStyleModal(ModelFormModal):
189
+ size = 'xl'
190
+ process = PROCESS_EDIT_DELETE
191
+ permission_delete = PERMISSION_OFF
192
+ model = MultiCellStyle
193
+
194
+ widgets = {
195
+ 'bold': RBToggle,
196
+ 'italic': RBToggle,
197
+ 'font_size': SmallNumberInputWidget,
198
+ 'align_type': Select2,
199
+ }
200
+
201
+ form_fields = ['name', 'align_type', 'bold', 'italic', 'font_size', 'font_colour', 'background_colour']
202
+
203
+
204
+ class MultiValueReportColumnModal(ModelFormModal):
205
+ process = PROCESS_EDIT_DELETE
206
+ permission_delete = PERMISSION_OFF
207
+ model = MultiValueReportColumn
208
+
209
+ widgets = {
210
+ 'width': SmallNumberInputWidget,
211
+ 'width_type': Select2,
212
+ }
213
+
214
+ form_fields = ['width', 'width_type']
215
+
216
+
217
+ class MultiValueHeldQueryForm(QueryBuilderModelForm):
218
+ cancel_class = 'btn-secondary modal-cancel'
219
+
220
+ class Meta:
221
+ model = MultiValueHeldQuery
222
+ fields = ['name', 'query', 'report_type']
223
+
224
+
225
+ class MultiValueHeldQueryModal(QueryBuilderModalBase):
226
+ process = PROCESS_EDIT_DELETE
227
+ permission_delete = PERMISSION_OFF
228
+ form_class = MultiValueHeldQueryForm
229
+ template_name = 'advanced_report_builder/multi_values/held_modal.html'
230
+
231
+ def form_setup(self, form, *_args, **_kwargs):
232
+ fields = [
233
+ 'name',
234
+ 'report_type',
235
+ FieldEx('query', template='advanced_report_builder/query_builder.html'),
236
+ ]
237
+ return fields
238
+
239
+ def form_valid(self, form):
240
+ form.save()
241
+ return self.command_response('reload')
242
+
243
+
244
+ class MultiValueReportCellForm(QueryBuilderModelForm):
245
+ cancel_class = 'btn-secondary modal-cancel'
246
+
247
+ class Meta:
248
+ model = MultiValueReportCell
249
+ fields = [
250
+ 'multi_value_type',
251
+ 'text',
252
+ 'multi_cell_style',
253
+ 'label',
254
+ 'row',
255
+ 'column',
256
+ 'col_span',
257
+ 'row_span',
258
+ 'report_type',
259
+ 'field',
260
+ 'numerator',
261
+ 'prefix',
262
+ 'decimal_places',
263
+ 'multi_value_held_query',
264
+ 'show_breakdown',
265
+ 'breakdown_fields',
266
+ 'average_scale',
267
+ 'average_start_period',
268
+ 'average_end_period',
269
+ 'query_data',
270
+ 'extra_query_data',
271
+ ]
272
+ widgets = {
273
+ 'report_tags': Select2Multiple,
274
+ 'show_breakdown': Toggle(attrs={'data-onstyle': 'success', 'data-on': 'YES', 'data-off': 'NO'}),
275
+ 'row': SmallNumberInputWidget,
276
+ 'column': SmallNumberInputWidget,
277
+ 'col_span': SmallNumberInputWidget,
278
+ 'row_span': SmallNumberInputWidget,
279
+ 'decimal_places': SmallNumberInputWidget,
280
+ }
281
+
282
+
283
+ class MultiValueReportCellModal(MultiQueryModalMixin, QueryBuilderModalBase):
284
+ template_name = 'advanced_report_builder/multi_values/modal.html'
285
+ size = 'xl'
286
+ process = PROCESS_EDIT_DELETE
287
+ permission_delete = PERMISSION_OFF
288
+ model = MultiValueReportCell
289
+ helper_class = HorizontalNoEnterHelper
290
+ form_class = MultiValueReportCellForm
291
+
292
+ @property
293
+ def modal_title(self):
294
+ if self.object.row and self.object.column:
295
+ title = excel_column_name(int(self.object.column), row=int(self.object.row))
296
+ else:
297
+ title = ' value'
298
+
299
+ return [f'Add {title}', f'Edit {title}']
300
+
301
+ def form_setup(self, form, *_args, **_kwargs):
302
+ form.fields['label'].help_text = 'Used when setting up the table and for the show breakdown title.'
303
+ form.fields['multi_cell_style'] = ModelChoiceField(
304
+ queryset=MultiCellStyle.objects.filter(multi_value_report_id=self.object.multi_value_report_id),
305
+ widget=Select2(),
306
+ required=False,
307
+ )
308
+
309
+ form.fields['extra_query_data'].label = 'Numerator'
310
+
311
+ form.add_trigger(
312
+ 'multi_value_type',
313
+ 'onchange',
314
+ [
315
+ {
316
+ 'selector': '#div_id_text',
317
+ 'values': {
318
+ MultiValueReportCell.MultiValueType.STATIC_TEXT: 'show',
319
+ MultiValueReportCell.MultiValueType.EQUATION: 'show',
320
+ },
321
+ 'default': 'hide',
322
+ },
323
+ {
324
+ 'selector': '#div_id_label_text',
325
+ 'values': {
326
+ MultiValueReportCell.MultiValueType.STATIC_TEXT: 'hide',
327
+ },
328
+ 'default': 'show',
329
+ },
330
+ {
331
+ 'selector': '#div_id_field',
332
+ 'values': {
333
+ MultiValueReportCell.MultiValueType.STATIC_TEXT: 'hide',
334
+ MultiValueReportCell.MultiValueType.EQUATION: 'hide',
335
+ MultiValueReportCell.MultiValueType.COUNT: 'hide',
336
+ MultiValueReportCell.MultiValueType.PERCENT_FROM_COUNT: 'hide',
337
+ },
338
+ 'default': 'show',
339
+ },
340
+ {
341
+ 'selector': '#div_id_prefix',
342
+ 'values': {
343
+ MultiValueReportCell.MultiValueType.STATIC_TEXT: 'hide',
344
+ MultiValueReportCell.MultiValueType.EQUATION: 'hide',
345
+ MultiValueReportCell.MultiValueType.COUNT: 'hide',
346
+ MultiValueReportCell.MultiValueType.PERCENT_FROM_COUNT: 'hide',
347
+ },
348
+ 'default': 'show',
349
+ },
350
+ {
351
+ 'selector': '#div_id_numerator',
352
+ 'values': {MultiValueReportCell.MultiValueType.PERCENT: 'show'},
353
+ 'default': 'hide',
354
+ },
355
+ {
356
+ 'selector': 'label[for=id_field]',
357
+ 'values': {
358
+ MultiValueReportCell.MultiValueType.PERCENT: (
359
+ 'html',
360
+ 'Denominator field',
361
+ )
362
+ },
363
+ 'default': ('html', 'Field'),
364
+ },
365
+ {
366
+ 'selector': '#div_id_average_scale',
367
+ 'values': {MultiValueReportCell.MultiValueType.AVERAGE_SUM_OVER_TIME: 'show'},
368
+ 'default': 'hide',
369
+ },
370
+ {
371
+ 'selector': '#div_id_average_start_period',
372
+ 'values': {MultiValueReportCell.MultiValueType.AVERAGE_SUM_OVER_TIME: 'show'},
373
+ 'default': 'hide',
374
+ },
375
+ {
376
+ 'selector': '#div_id_average_end_period',
377
+ 'values': {MultiValueReportCell.MultiValueType.AVERAGE_SUM_OVER_TIME: 'show'},
378
+ 'default': 'hide',
379
+ },
380
+ {
381
+ 'selector': '#div_id_report_type',
382
+ 'values': {
383
+ MultiValueReportCell.MultiValueType.STATIC_TEXT: 'hide',
384
+ MultiValueReportCell.MultiValueType.EQUATION: 'hide',
385
+ },
386
+ 'default': 'show',
387
+ },
388
+ {
389
+ 'selector': '#div_id_decimal_places',
390
+ 'values': {
391
+ MultiValueReportCell.MultiValueType.STATIC_TEXT: 'hide',
392
+ MultiValueReportCell.MultiValueType.EQUATION: 'hide',
393
+ },
394
+ 'default': 'show',
395
+ },
396
+ {
397
+ 'selector': '#div_id_show_breakdown',
398
+ 'values': {
399
+ MultiValueReportCell.MultiValueType.STATIC_TEXT: 'hide',
400
+ MultiValueReportCell.MultiValueType.EQUATION: 'hide',
401
+ },
402
+ 'default': 'show',
403
+ },
404
+ {
405
+ 'selector': '#div_id_query_data',
406
+ 'values': {
407
+ MultiValueReportCell.MultiValueType.STATIC_TEXT: 'hide',
408
+ MultiValueReportCell.MultiValueType.EQUATION: 'hide',
409
+ },
410
+ 'default': 'show',
411
+ },
412
+ {
413
+ 'selector': '#div_id_extra_query_data',
414
+ 'values': {
415
+ MultiValueReportCell.MultiValueType.PERCENT: 'show',
416
+ },
417
+ 'default': 'hide',
418
+ },
419
+ {
420
+ 'selector': '#div_id_multi_value_held_query',
421
+ 'values': {
422
+ MultiValueReportCell.MultiValueType.STATIC_TEXT: 'hide',
423
+ MultiValueReportCell.MultiValueType.EQUATION: 'hide',
424
+ },
425
+ 'default': 'show',
426
+ },
427
+ ],
428
+ )
429
+
430
+ form.add_trigger(
431
+ 'show_breakdown',
432
+ 'onchange',
433
+ [
434
+ {
435
+ 'selector': '#div_id_breakdown_fields',
436
+ 'values': {'checked': 'show'},
437
+ 'default': 'hide',
438
+ },
439
+ ],
440
+ )
441
+ if 'data' in _kwargs and len(_kwargs['data']) > 0:
442
+ field = _kwargs['data'].get('field')
443
+ numerator = _kwargs['data'].get('numerator')
444
+ report_type_id = _kwargs['data'].get('report_type')
445
+ if report_type_id != '':
446
+ report_type = get_object_or_404(ReportType, id=report_type_id)
447
+ else:
448
+ report_type = form.instance.report_type
449
+ else:
450
+ field = form.instance.field
451
+ report_type = form.instance.report_type
452
+ numerator = form.instance.numerator
453
+
454
+ self.setup_field(
455
+ field_type='number',
456
+ form=form,
457
+ field_name='field',
458
+ selected_field_id=field,
459
+ report_type=report_type,
460
+ )
461
+
462
+ self.setup_field(
463
+ field_type='number',
464
+ form=form,
465
+ field_name='numerator',
466
+ selected_field_id=numerator,
467
+ report_type=report_type,
468
+ )
469
+
470
+ url = reverse(
471
+ 'advanced_report_builder:multi_value_field_modal',
472
+ kwargs={'slug': 'selector-99999-data-FIELD_INFO-report_type_id-REPORT_TYPE_ID'},
473
+ )
474
+
475
+ range_type_choices = VariableDate.RANGE_TYPE_CHOICES
476
+ form.fields['average_start_period'] = ChoiceField(required=False, choices=range_type_choices)
477
+ form.fields['average_end_period'] = ChoiceField(required=False, choices=range_type_choices)
478
+
479
+ form.fields['multi_value_held_query'].widget = Select2(attrs={'ajax': True})
480
+
481
+ if self.object.multi_value_held_query is not None:
482
+ selected_data = [
483
+ {'id': self.object.multi_value_held_query_id, 'text': self.object.multi_value_held_query.name}
484
+ ]
485
+ form.fields['multi_value_held_query'].widget.select_data = selected_data
486
+
487
+ fields = [
488
+ 'multi_value_type',
489
+ 'text',
490
+ 'label',
491
+ 'multi_cell_style',
492
+ 'row',
493
+ 'column',
494
+ 'col_span',
495
+ 'row_span',
496
+ 'report_type',
497
+ 'field',
498
+ 'numerator',
499
+ 'prefix',
500
+ 'decimal_places',
501
+ 'multi_value_held_query',
502
+ 'show_breakdown',
503
+ 'average_scale',
504
+ 'average_start_period',
505
+ 'average_end_period',
506
+ FieldEx(
507
+ 'breakdown_fields',
508
+ template='advanced_report_builder/select_column.html',
509
+ extra_context={'select_column_url': url, 'command_prefix': ''},
510
+ ),
511
+ FieldEx('query_data', template='advanced_report_builder/query_builder.html'),
512
+ FieldEx('extra_query_data', template='advanced_report_builder/query_builder.html'),
513
+ ]
514
+ return fields
515
+
516
+ def select2_multi_value_held_query(self, **kwargs):
517
+ results = []
518
+ if kwargs.get('report_type') != '':
519
+ multi_value_held_queries = MultiValueHeldQuery.objects.filter(
520
+ report_type_id=kwargs['report_type'], multi_value_report=self.object.multi_value_report
521
+ )
522
+ search = kwargs.get('search', '')
523
+ if search != '':
524
+ multi_value_held_queries = multi_value_held_queries.filter(name__icontains=search)
525
+ for multi_value_held_query in multi_value_held_queries:
526
+ results.append({'id': multi_value_held_query.id, 'text': multi_value_held_query.name})
527
+
528
+ return JsonResponse({'results': results})
529
+
530
+ def select2_field(self, **kwargs):
531
+ return self.get_fields_for_select2(
532
+ field_type='number',
533
+ report_type=kwargs['report_type'],
534
+ search_string=kwargs.get('search'),
535
+ )
536
+
537
+ def select2_numerator(self, **kwargs):
538
+ return self.get_fields_for_select2(
539
+ field_type='number',
540
+ report_type=kwargs['report_type'],
541
+ search_string=kwargs.get('search'),
542
+ )
543
+
544
+ def ajax_get_fields(self, **kwargs):
545
+ report_type_id = kwargs['report_type']
546
+ report_builder_fields, base_model = self.get_report_builder_class(report_type_id=report_type_id)
547
+ fields = []
548
+ tables = []
549
+ self._get_fields(
550
+ base_model=base_model,
551
+ fields=fields,
552
+ tables=tables,
553
+ report_builder_class=report_builder_fields,
554
+ )
555
+ return self.command_response('report_fields', data=json.dumps({'fields': fields, 'tables': tables}))
556
+
557
+ def form_valid(self, form):
558
+ chart_report = form.save(commit=False)
559
+ chart_report._current_user = self.request.user
560
+ chart_report.save()
561
+ return self.command_response('reload')
562
+
563
+
564
+ class MultiValueReportCellsModal(Modal):
565
+ button_container_class = 'text-center'
566
+ modal_title = 'Edit Cells'
567
+ size = 'xl'
568
+
569
+ @staticmethod
570
+ def render_html(table_data, multi_value_report):
571
+ html = '<table class="table table-bordered kanban_summary"><tr><td></td>'
572
+ columns_data = {}
573
+ for multi_value_report_column in multi_value_report.multivaluereportcolumn_set.all():
574
+ columns_data[multi_value_report_column.column] = multi_value_report_column
575
+
576
+ for cols_index, cell in enumerate(table_data[0], start=1):
577
+ letter = excel_column_name(cols_index)
578
+ if cols_index in columns_data:
579
+ multi_value_report_column = columns_data[cols_index]
580
+ link = show_modal(
581
+ 'advanced_report_builder:multi_value_column_modal',
582
+ '',
583
+ f'pk-{multi_value_report_column.id}',
584
+ href=True,
585
+ )
586
+ style = multi_value_report_column.get_td_style()
587
+ html += (
588
+ f'<td style="{style}"><div class="d-flex align-items-center">{letter}'
589
+ f'<a href="{link}" class="ml-auto"><i class="fas fa-edit ml-auto"></i></a></div></td>'
590
+ )
591
+ else:
592
+ link = show_modal(
593
+ 'advanced_report_builder:multi_value_column_modal',
594
+ '',
595
+ f'multi_value_report_id-{multi_value_report.id}-column-{cols_index}',
596
+ href=True,
597
+ )
598
+ html += (
599
+ f'<td><div class="d-flex align-items-center">{letter}'
600
+ f'<a href="{link}" class="ml-auto"><i class="fas fa-plus ml-auto"></i></a></div></td>'
601
+ )
602
+ html += '</tr>'
603
+ for row_index, row in enumerate(table_data, start=1):
604
+ html += f'<tr><td>{row_index}</td>'
605
+ for cols_index, cell in enumerate(row, start=1):
606
+ if cell is None:
607
+ add_link = show_modal(
608
+ 'advanced_report_builder:multi_value_cell_modal',
609
+ '',
610
+ f'multi_value_report_id-{multi_value_report.id}-row-{row_index}-column-{cols_index}',
611
+ href=True,
612
+ )
613
+ copy_from_link = show_modal(
614
+ 'advanced_report_builder:multi_value_cell_copy_from_modal',
615
+ '',
616
+ f'pk-{multi_value_report.id}-row-{row_index}-column-{cols_index}',
617
+ href=True,
618
+ )
619
+
620
+ html += f'''
621
+ <td>
622
+ <div class="d-flex align-items-center">
623
+ <div class="ml-auto btn-group" role="group">
624
+ <a href="{add_link}" class="btn btn-outline-primary btn-sm">
625
+ <i class="fas fa-plus"></i>
626
+ </a>
627
+ <a href="{copy_from_link}" class="btn btn-outline-secondary btn-sm">
628
+ <i class="fas fa-file-import"></i>
629
+ </a>
630
+ </div>
631
+ </div>
632
+ </td>
633
+ '''
634
+ elif cell['value'] is not None:
635
+ attrs = []
636
+ multi_value_report_cell = cell['cell']
637
+ col_span = multi_value_report_cell.col_span
638
+ row_span = multi_value_report_cell.row_span
639
+ if col_span > 1:
640
+ attrs.append(f'colspan="{col_span}"')
641
+ if row_span > 1:
642
+ attrs.append(f'rowspan="{row_span}"')
643
+ value = cell['value']
644
+
645
+ link = show_modal(
646
+ 'advanced_report_builder:multi_value_cell_modal',
647
+ '',
648
+ 'pk-',
649
+ cell['cell'].id,
650
+ href=True,
651
+ )
652
+ if multi_value_report_cell.multi_cell_style is not None:
653
+ attrs.append('style="' + multi_value_report_cell.multi_cell_style.get_td_style() + '"')
654
+ attrs.append('class="' + multi_value_report_cell.multi_cell_style.get_td_class() + '"')
655
+ attrs_html = ''
656
+ if len(attrs) > 0:
657
+ attrs_html = ' ' + ' '.join(attrs)
658
+
659
+ html += f'''
660
+ <td{attrs_html}>
661
+ <div class="d-flex align-items-center">
662
+ {value}
663
+ <div class="ml-auto btn-group" role="group">
664
+ <a href="{link}" class="btn btn-outline-primary btn-sm">
665
+ <i class="fas fa-edit"></i>
666
+ </a>
667
+ </div>
668
+ </div>
669
+ </td>
670
+ '''
671
+ html += '</tr>'
672
+
673
+ html += '</table>'
674
+ return html
675
+
676
+ def get_table_data(self, multi_value_report):
677
+ table_data = [[None for _ in range(multi_value_report.columns)] for _ in range(multi_value_report.rows)]
678
+ multi_value_report_cells = MultiValueReportCell.objects.filter(
679
+ multi_value_report=multi_value_report,
680
+ row__lte=multi_value_report.rows,
681
+ column__lte=multi_value_report.columns,
682
+ ).order_by('row', 'column')
683
+ for multi_value_report_cell in multi_value_report_cells:
684
+ row = multi_value_report_cell.row - 1
685
+ column = multi_value_report_cell.column - 1
686
+ if table_data[row][column] is not None:
687
+ continue
688
+ multi_value_type = multi_value_report_cell.multi_value_type
689
+ if multi_value_type == MultiValueReportCell.MultiValueType.STATIC_TEXT:
690
+ value = multi_value_report_cell.text
691
+ elif multi_value_report_cell.label:
692
+ value = multi_value_report_cell.label
693
+ else:
694
+ value = '123'
695
+
696
+ table_data[row][column] = {'value': value, 'cell': multi_value_report_cell}
697
+
698
+ if multi_value_report_cell.row_span > 1 or multi_value_report_cell.col_span > 1:
699
+ for row_offset in range(multi_value_report_cell.row_span):
700
+ for col_offset in range(multi_value_report_cell.col_span):
701
+ # skip the main (top-left) cell
702
+ if row_offset == 0 and col_offset == 0:
703
+ continue
704
+ if (
705
+ len(table_data) > row + row_offset
706
+ and len(table_data[row + row_offset]) > column + col_offset
707
+ ):
708
+ table_data[row + row_offset][column + col_offset] = {'value': None}
709
+
710
+ return table_data
711
+
712
+ def modal_content(self):
713
+ multi_value_report = MultiValueReport.objects.get(pk=self.slug['multi_value_report_id'])
714
+ table_data = self.get_table_data(multi_value_report)
715
+
716
+ return self.render_html(table_data=table_data, multi_value_report=multi_value_report)
717
+
718
+
719
+ class MultiValueView(ValueBaseView):
720
+ number_field = ReportBuilderNumberColumn
721
+ template_name = 'advanced_report_builder/multi_values/report.html'
722
+ chart_js_table = ChartJSTable
723
+
724
+ def __init__(self, *args, **kwargs):
725
+ self.current_multi_value_report_cell = None
726
+ super().__init__(*args, **kwargs)
727
+
728
+ def setup_menu(self):
729
+ super().setup_menu()
730
+ if self.dashboard_report and self.enable_edit:
731
+ report_menu = self.pod_dashboard_edit_menu()
732
+ elif self.dashboard_report and not self.enable_edit:
733
+ report_menu = self.pod_dashboard_view_menu()
734
+ else:
735
+ report_menu = self.pod_report_menu()
736
+ self.add_menu('button_menu', 'button_group').add_items(
737
+ *report_menu,
738
+ *self.queries_option_menus(report=self.report, dashboard_report=self.dashboard_report),
739
+ )
740
+
741
+ def dispatch(self, request, *args, **kwargs):
742
+ self.report = kwargs.get('report')
743
+ self.chart_report = self.report.multivaluereport
744
+ self.dashboard_report = kwargs.get('dashboard_report')
745
+ self.enable_edit = kwargs.get('enable_edit')
746
+ return super().dispatch(request, *args, **kwargs)
747
+
748
+ def pod_dashboard_view_menu(self):
749
+ return []
750
+
751
+ def pod_report_menu(self):
752
+ return self.edit_report_menu(request=self.request, chart_report_id=self.chart_report.id)
753
+
754
+ def edit_report_menu(self, request, chart_report_id, slug_str=None):
755
+ return [
756
+ MenuItem(
757
+ f'advanced_report_builder:multi_value_modal,pk-{chart_report_id}',
758
+ menu_display='Edit',
759
+ font_awesome='fas fa-pencil-alt',
760
+ css_classes=['btn-primary'],
761
+ ),
762
+ *self.duplicate_menu(request=request, report_id=chart_report_id),
763
+ ]
764
+
765
+ def get_context_data(self, **kwargs):
766
+ context = super().get_context_data(**kwargs) if hasattr(super(), 'get_context_data') else {}
767
+
768
+ multi_value_report_cells = (
769
+ MultiValueReportCell.objects.filter(
770
+ multi_value_report=self.chart_report,
771
+ row__lte=self.chart_report.rows,
772
+ column__lte=self.chart_report.columns,
773
+ )
774
+ .select_related('multi_value_held_query')
775
+ .order_by('row', 'column')
776
+ )
777
+
778
+ table_data = [[None for _ in range(self.chart_report.columns)] for _ in range(self.chart_report.rows)]
779
+ exp = ExpressionBuilder()
780
+ multi_value_report_equations = []
781
+ for multi_value_report_cell in multi_value_report_cells:
782
+ cell_name = excel_column_name(multi_value_report_cell.column, row=multi_value_report_cell.row)
783
+ base_model = multi_value_report_cell.get_base_model()
784
+ value = ''
785
+ report_builder_class = None
786
+
787
+ row = multi_value_report_cell.row - 1
788
+ column = multi_value_report_cell.column - 1
789
+ if table_data[row][column] is not None:
790
+ continue
791
+
792
+ multi_value_type = multi_value_report_cell.multi_value_type
793
+ if base_model is not None:
794
+ report_builder_class = get_report_builder_class(
795
+ model=base_model, report_type=multi_value_report_cell.report_type
796
+ )
797
+
798
+ fields = []
799
+ append_str = ''
800
+ try:
801
+ if multi_value_type == MultiValueReportCell.MultiValueType.STATIC_TEXT:
802
+ value = multi_value_report_cell.text
803
+ elif multi_value_type == MultiValueReportCell.MultiValueType.COUNT:
804
+ self._get_count(fields=fields)
805
+ elif multi_value_type == MultiValueReportCell.MultiValueType.SUM:
806
+ if multi_value_report_cell.field is None:
807
+ value = 'Error no field selected'
808
+ else:
809
+ self._process_aggregations(
810
+ field=multi_value_report_cell.field,
811
+ report_builder_class=report_builder_class,
812
+ base_model=base_model,
813
+ decimal_places=multi_value_report_cell.decimal_places,
814
+ fields=fields,
815
+ aggregations_type=ANNOTATION_CHOICE_SUM,
816
+ )
817
+ elif multi_value_type == MultiValueReportCell.MultiValueType.AVERAGE_SUM_FROM_COUNT:
818
+ self._process_aggregations(
819
+ field=multi_value_report_cell.field,
820
+ report_builder_class=report_builder_class,
821
+ base_model=base_model,
822
+ decimal_places=multi_value_report_cell.decimal_places,
823
+ fields=fields,
824
+ aggregations_type=ANNOTATION_CHOICE_AVERAGE_SUM_FROM_COUNT,
825
+ )
826
+
827
+ elif multi_value_type in [
828
+ MultiValueReportCell.MultiValueType.AVERAGE_SUM_OVER_TIME,
829
+ MultiValueReportCell.MultiValueType.AVERAGE_SUM_OVER_TIME_EXCLUDING_WEEKENDS,
830
+ ]:
831
+ exclude_weekdays = None
832
+ if multi_value_type == MultiValueReportCell.MultiValueType.AVERAGE_SUM_OVER_TIME_EXCLUDING_WEEKENDS:
833
+ exclude_weekdays = [1, 7]
834
+
835
+ divider = self.get_period_divider(
836
+ annotation_value_choice=multi_value_report_cell.average_scale,
837
+ start_date_type=multi_value_report_cell.average_start_period,
838
+ end_date_type=multi_value_report_cell.average_end_period,
839
+ exclude_weekdays=exclude_weekdays,
840
+ )
841
+ self._process_aggregations(
842
+ field=multi_value_report_cell.field,
843
+ report_builder_class=report_builder_class,
844
+ base_model=base_model,
845
+ decimal_places=multi_value_report_cell.decimal_places,
846
+ fields=fields,
847
+ aggregations_type=ANNOTATION_CHOICE_SUM,
848
+ divider=divider,
849
+ )
850
+
851
+ elif multi_value_type == MultiValueReportCell.MultiValueType.PERCENT:
852
+ numerator_filter = self.process_filters(search_filter_data=multi_value_report_cell.extra_query_data)
853
+ self._process_percentage(
854
+ numerator_filter=numerator_filter,
855
+ denominator_field=multi_value_report_cell.field,
856
+ numerator_field=multi_value_report_cell.numerator,
857
+ report_builder_class=report_builder_class,
858
+ decimal_places=multi_value_report_cell.decimal_places,
859
+ base_model=base_model,
860
+ fields=fields,
861
+ )
862
+ append_str = '%'
863
+ elif multi_value_type == MultiValueReportCell.MultiValueType.PERCENT_FROM_COUNT:
864
+ numerator_filter = self.process_filters(search_filter_data=multi_value_report_cell.extra_query_data)
865
+ self._process_percentage_from_count(
866
+ numerator_filter=numerator_filter,
867
+ decimal_places=multi_value_report_cell.decimal_places,
868
+ fields=fields,
869
+ )
870
+ append_str = '%'
871
+ elif multi_value_type == MultiValueReportCell.MultiValueType.EQUATION:
872
+ multi_value_report_equations.append((cell_name, multi_value_report_cell))
873
+ except ReportError as e:
874
+ value = e.value
875
+
876
+ if fields:
877
+ try:
878
+ value, raw_value = self.render_value(
879
+ base_model=base_model, fields=fields, multi_value_report_cell=multi_value_report_cell
880
+ )
881
+ except (AttributeError, TypeError) as e:
882
+ value = e
883
+ raw_value = None
884
+ if raw_value is not None:
885
+ with contextlib.suppress(ValueError):
886
+ raw_value = float(raw_value)
887
+ exp.add_to_global(name=cell_name, value=raw_value)
888
+ elif value is not None:
889
+ expression_value = value
890
+ with contextlib.suppress(ValueError):
891
+ expression_value = float(expression_value)
892
+ exp.add_to_global(name=cell_name, value=expression_value)
893
+
894
+ table_data[row][column] = {'value': value, 'cell': multi_value_report_cell, 'append_str': append_str}
895
+
896
+ if multi_value_report_cell.row_span > 1 or multi_value_report_cell.col_span > 1:
897
+ for row_offset in range(multi_value_report_cell.row_span):
898
+ for col_offset in range(multi_value_report_cell.col_span):
899
+ # skip the main (top-left) cell
900
+ if row_offset == 0 and col_offset == 0:
901
+ continue
902
+
903
+ table_data[row + row_offset][column + col_offset] = {'value': None}
904
+
905
+ unresolved = multi_value_report_equations[:] # initial list
906
+ previous_count = None
907
+ max_iterations = max(100, len(multi_value_report_equations) * 2)
908
+ iteration = 0
909
+
910
+ while (previous_count is None or len(unresolved) < previous_count) and iteration < max_iterations:
911
+ previous_count = len(unresolved)
912
+ iteration += 1
913
+ next_unresolved = []
914
+
915
+ for cell_name, equation in unresolved:
916
+ row = equation.row - 1
917
+ column = equation.column - 1
918
+
919
+ try:
920
+ value = exp.run_statement(equation.text)
921
+ exp.add_to_global(name=cell_name, value=value)
922
+ except ExpressionVariableError as e:
923
+ # Could not evaluate yet — keep it for later
924
+ next_unresolved.append((cell_name, equation))
925
+ value = e.value
926
+
927
+ table_data[row][column]['value'] = value
928
+
929
+ unresolved = next_unresolved
930
+
931
+ context['html'] = self.render_html(table_data=table_data)
932
+ return context
933
+
934
+ def render_html(self, table_data):
935
+ html = '<table class="table table-bordered kanban_summary">'
936
+
937
+ columns_data = {}
938
+ for multi_value_report_column in self.chart_report.multivaluereportcolumn_set.all():
939
+ columns_data[multi_value_report_column.column] = multi_value_report_column.get_td_style()
940
+
941
+ for row in table_data:
942
+ html += '<tr>'
943
+ for cols_index, cell in enumerate(row, start=1):
944
+ if cell is None:
945
+ html += '<td></td>'
946
+ elif cell['value'] is not None:
947
+ attrs = []
948
+ multi_value_report_cell = cell['cell']
949
+ col_span = multi_value_report_cell.col_span
950
+ row_span = multi_value_report_cell.row_span
951
+ if col_span > 1:
952
+ attrs.append(f'colspan="{col_span}"')
953
+ if row_span > 1:
954
+ attrs.append(f'rowspan="{row_span}"')
955
+ value = cell['value']
956
+ append_str = cell['append_str']
957
+ styles = []
958
+
959
+ if col_span == 1 and cols_index in columns_data:
960
+ styles.append(columns_data[cols_index])
961
+
962
+ if multi_value_report_cell.multi_cell_style is not None:
963
+ attrs.append('class="' + multi_value_report_cell.multi_cell_style.get_td_class() + '"')
964
+ styles.append(multi_value_report_cell.multi_cell_style.get_td_style())
965
+ link = self.get_breakdown_url(multi_value_report_cell=multi_value_report_cell)
966
+ if link is not None:
967
+ styles.append('cursor:pointer')
968
+ attrs.append(f'onclick="{link}"')
969
+
970
+ if len(styles) > 0:
971
+ attrs.append('style="' + ';'.join(styles) + '"')
972
+
973
+ attrs_html = ''
974
+ if len(attrs) > 0:
975
+ attrs_html = ' ' + ' '.join(attrs)
976
+
977
+ html += f'<td{attrs_html}>{value}{append_str}</td>'
978
+ html += '</tr>'
979
+
980
+ html += '</table>'
981
+ return html
982
+
983
+ def get_breakdown_url(self, multi_value_report_cell):
984
+ if multi_value_report_cell.show_breakdown:
985
+ enable_links = self.kwargs.get('enable_links')
986
+ link = show_modal(
987
+ 'advanced_report_builder:multi_value_breakdown_modal',
988
+ '',
989
+ f'pk-{multi_value_report_cell.id}-enable_links-{enable_links}',
990
+ href=True,
991
+ )
992
+ return link
993
+ return None
994
+
995
+ def pod_dashboard_edit_menu(self):
996
+ return [
997
+ MenuItem(
998
+ f'advanced_report_builder:dashboard_report_modal,pk-{self.dashboard_report.id}',
999
+ menu_display='Edit',
1000
+ font_awesome='fas fa-pencil-alt',
1001
+ css_classes=['btn-primary'],
1002
+ )
1003
+ ]
1004
+
1005
+ def extra_filters(self, query):
1006
+ query_data = self.current_multi_value_report_cell.query_data
1007
+ extra_filter_data = None
1008
+ if self.current_multi_value_report_cell.multi_value_held_query is not None:
1009
+ extra_filter_data = self.current_multi_value_report_cell.multi_value_held_query.query
1010
+ if query_data:
1011
+ query = self.process_query_filters(
1012
+ query=query, search_filter_data=query_data, extra_filter_data=extra_filter_data
1013
+ )
1014
+ return query
1015
+
1016
+ @staticmethod
1017
+ def set_prefix(table, multi_value_report_cell):
1018
+ if multi_value_report_cell.prefix:
1019
+ table.prefix = multi_value_report_cell.prefix
1020
+
1021
+ def render_value(self, base_model, fields, multi_value_report_cell):
1022
+ table = self.chart_js_table(model=base_model)
1023
+ self.set_prefix(table=table, multi_value_report_cell=multi_value_report_cell)
1024
+ table.add_columns(*fields)
1025
+ table.single_value = self.chart_report
1026
+
1027
+ self.current_multi_value_report_cell = multi_value_report_cell
1028
+
1029
+ table.extra_filters = self.extra_filters
1030
+ table.enable_links = self.kwargs.get('enable_links')
1031
+ table.datatable_template = 'advanced_report_builder/multi_values/middle.html'
1032
+ value = table.render()
1033
+ if len(table.raw_data) > 0 and len(table.raw_data[0]) > 0:
1034
+ return value, table.raw_data[0][0]
1035
+ return value, None
1036
+
1037
+
1038
+ class MultiValueShowBreakdownModal(TableUtilsMixin, Modal):
1039
+ button_container_class = 'text-center'
1040
+ size = 'xl'
1041
+
1042
+ def __init__(self, *args, **kwargs):
1043
+ self._held_multi_value_report_cell = None
1044
+ super().__init__(*args, **kwargs)
1045
+
1046
+ def modal_title(self):
1047
+ multi_value_report_cell = self.get_multi_value_report_cell()
1048
+ title = multi_value_report_cell.label
1049
+ if title is None:
1050
+ title = excel_column_name(multi_value_report_cell.column, row=multi_value_report_cell.row)
1051
+ return f'{self.table_report.multi_value_report.name} - {title}'
1052
+
1053
+ def add_table(self, base_model):
1054
+ return DatatableTable(view=self, model=base_model)
1055
+
1056
+ def get_multi_value_report_cell(self):
1057
+ if self._held_multi_value_report_cell is None:
1058
+ self._held_multi_value_report_cell = get_object_or_404(MultiValueReportCell, pk=self.slug['pk'])
1059
+ return self._held_multi_value_report_cell
1060
+
1061
+ def setup_table(self):
1062
+ multi_value_report_cell = self.get_multi_value_report_cell()
1063
+ self.kwargs['enable_links'] = self.slug['enable_links'] == 'True'
1064
+ self.table_report = multi_value_report_cell
1065
+ base_model = multi_value_report_cell.get_base_model()
1066
+ table = self.add_table(base_model=base_model)
1067
+ table.extra_filters = self.extra_filters
1068
+ table_fields = multi_value_report_cell.breakdown_fields
1069
+ report_builder_class = get_report_builder_class(model=base_model, report_type=self.table_report.report_type)
1070
+ fields_used = set()
1071
+ fields_map = {}
1072
+ try:
1073
+ self.process_query_results(
1074
+ report_builder_class=report_builder_class,
1075
+ table=table,
1076
+ base_model=base_model,
1077
+ fields_used=fields_used,
1078
+ fields_map=fields_map,
1079
+ table_fields=table_fields,
1080
+ )
1081
+ except (FieldError, FieldDoesNotExist) as e:
1082
+ raise ReportError(e)
1083
+ table.ajax_data = False
1084
+ table.table_options['pageLength'] = 25
1085
+ table.table_options['bStateSave'] = False
1086
+ return table
1087
+
1088
+ def modal_content(self):
1089
+ table = self.setup_table()
1090
+ return table.render()
1091
+
1092
+ def extra_filters(self, query):
1093
+ multi_value_report_cell = self.get_multi_value_report_cell()
1094
+ query = self.process_query_filters(query=query, search_filter_data=multi_value_report_cell.query_data)
1095
+ return query
1096
+
1097
+ def get_report_query(self, report):
1098
+ return self.get_multi_value_report_cell()
1099
+
1100
+
1101
+ class MultiValueCellCopyFromModal(FormModal):
1102
+ form_class = CrispyForm
1103
+ modal_title = 'Copy Cell From'
1104
+
1105
+ def __init__(self, *args, **kwargs):
1106
+ self._held_multi_value_report = None
1107
+ super().__init__(*args, **kwargs)
1108
+
1109
+ def get_multi_value_report(self):
1110
+ if self._held_multi_value_report is None:
1111
+ self._held_multi_value_report = get_object_or_404(MultiValueReport, pk=self.slug['pk'])
1112
+ return self._held_multi_value_report
1113
+
1114
+ def form_setup(self, form, *_args, **_kwargs):
1115
+ multi_value_report = self.get_multi_value_report()
1116
+ multi_value_report_cells = MultiValueReportCell.objects.filter(multi_value_report=multi_value_report)
1117
+ form.fields['copy_from'] = ModelChoiceField(queryset=multi_value_report_cells, widget=Select2())
1118
+ form.fields['copy_from'].label_from_instance = self.label_from_instance
1119
+
1120
+ @staticmethod
1121
+ def label_from_instance(obj):
1122
+ return excel_column_name(obj.column, row=obj.row)
1123
+
1124
+ def form_valid(self, form):
1125
+ original_cell = form.cleaned_data['copy_from']
1126
+ multi_value_report_cell = deepcopy(original_cell)
1127
+ multi_value_report_cell.pk = None
1128
+ multi_value_report_cell.id = None
1129
+ multi_value_report_cell.row = int(self.slug['row'])
1130
+ multi_value_report_cell.column = int(self.slug['column'])
1131
+ multi_value_report_cell.save()
1132
+ return self.command_response('reload')
1133
+
1134
+
1135
+ class MultiValueTableFieldForm(TableFieldForm):
1136
+ cancel_class = 'btn-secondary modal-cancel'
1137
+
1138
+ def cancel_button(self, css_class=cancel_class, **kwargs):
1139
+ commands = [
1140
+ {'function': 'save_query_builder_id_query_data'},
1141
+ {'function': 'save_query_builder_id_extra_query_data'},
1142
+ {'function': 'close'},
1143
+ ]
1144
+ return self.button('Cancel', commands, css_class, **kwargs)
1145
+
1146
+
1147
+ class MultiValueTableFieldModal(TableFieldModal):
1148
+ form_class = MultiValueTableFieldForm
1149
+
1150
+ def form_valid(self, form):
1151
+ selector = self.slug['selector']
1152
+
1153
+ _attr = form.get_additional_attributes()
1154
+ self.add_command({'function': 'set_attr', 'selector': f'#{selector}', 'attr': 'data-attr', 'val': _attr})
1155
+
1156
+ self.add_command({'function': 'html', 'selector': f'#{selector} span', 'html': form.cleaned_data['title']})
1157
+ self.add_command({'function': 'save_query_builder_id_query_data'})
1158
+ self.add_command({'function': 'save_query_builder_id_extra_query_data'})
1159
+ self.add_command({'function': 'update_selection'})
1160
+ return self.command_response('close')