@resolveio/server-lib 12.5.52 → 12.5.54

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 (400) hide show
  1. package/.nodemon.json +5 -0
  2. package/.vscode/settings.json +3 -0
  3. package/README.md +22 -0
  4. package/compileDTS.pl +64 -0
  5. package/gulpfile.js +127 -0
  6. package/mongodbensurers.js +2 -0
  7. package/mongostop.js +3 -0
  8. package/package.json +1 -1
  9. package/settings.development.json +13 -0
  10. package/src/client-server-app.ts +7 -0
  11. package/src/collections/app-status.collection.ts +51 -0
  12. package/src/collections/counter.collection.ts +54 -0
  13. package/src/collections/cron-job-history.collection.ts +82 -0
  14. package/src/collections/cron-job.collection.ts +85 -0
  15. package/src/collections/email-history.collection.ts +66 -0
  16. package/src/collections/email-verified.collection.ts +61 -0
  17. package/src/collections/file.collection.ts +73 -0
  18. package/src/collections/flag.collection.ts +56 -0
  19. package/src/collections/log-method-latency.collection.ts +64 -0
  20. package/src/collections/log-subscription.collection.ts +68 -0
  21. package/src/collections/log-ts.collection.ts +78 -0
  22. package/src/collections/log.collection.ts +77 -0
  23. package/src/collections/logged-in-users.collection.ts +65 -0
  24. package/src/collections/method-response.collection.ts +66 -0
  25. package/src/collections/monitor-cpu.collection.ts +63 -0
  26. package/src/collections/monitor-memory.collection.ts +75 -0
  27. package/src/collections/monitor-mongo.collection.ts +69 -0
  28. package/src/collections/notification.collection.ts +51 -0
  29. package/src/collections/report-builder-dashboard-builder.collection.ts +109 -0
  30. package/src/collections/report-builder-library.collection.ts +89 -0
  31. package/src/collections/report-builder-report.collection.ts +149 -0
  32. package/src/collections/user-group.collection.ts +90 -0
  33. package/src/collections/user-guide.collection.ts +57 -0
  34. package/src/collections/user.collection.ts +259 -0
  35. package/src/cron/cron.ts +188 -0
  36. package/src/fixtures/cron-jobs.ts +25 -0
  37. package/src/fixtures/init.ts +10 -0
  38. package/src/http/auth.ts +732 -0
  39. package/src/http/health.ts +7 -0
  40. package/src/http/home.ts +71 -0
  41. package/src/index.ts +71 -0
  42. package/src/managers/cron.manager.ts +208 -0
  43. package/src/managers/method.manager.ts +607 -0
  44. package/src/managers/mongo.manager.ts +2282 -0
  45. package/src/managers/monitor.manager.ts +323 -0
  46. package/src/managers/subscription.manager.ts +1196 -0
  47. package/{managers/subscription.performance.js → src/managers/subscription.performance.ts} +68 -33
  48. package/src/methods/accounts.ts +202 -0
  49. package/src/methods/aws.ts +507 -0
  50. package/src/methods/collections.ts +512 -0
  51. package/src/methods/counters.ts +75 -0
  52. package/src/methods/cron-jobs.ts +1454 -0
  53. package/src/methods/flags.ts +7 -0
  54. package/src/methods/logs.ts +327 -0
  55. package/src/methods/monitor.ts +548 -0
  56. package/src/methods/pdf.ts +615 -0
  57. package/src/methods/report-builder.ts +876 -0
  58. package/src/methods/support.ts +146 -0
  59. package/{models/app-status.model.d.ts → src/models/app-status.model.ts} +3 -2
  60. package/{models/billing-logged-in-users.model.d.ts → src/models/billing-logged-in-users.model.ts} +5 -4
  61. package/src/models/collection-document.model.ts +22 -0
  62. package/{models/counter.model.d.ts → src/models/counter.model.ts} +4 -3
  63. package/src/models/cron-job-history.model.ts +13 -0
  64. package/src/models/cron-job.model.ts +14 -0
  65. package/src/models/dialog.model.ts +25 -0
  66. package/{models/email-history.model.d.ts → src/models/email-history.model.ts} +8 -7
  67. package/{models/email-verified.model.d.ts → src/models/email-verified.model.ts} +6 -5
  68. package/{models/file.model.d.ts → src/models/file.model.ts} +8 -7
  69. package/{models/flag.model.d.ts → src/models/flag.model.ts} +4 -3
  70. package/{models/log-method-latency.model.d.ts → src/models/log-method-latency.model.ts} +5 -4
  71. package/{models/log-subscription.model.d.ts → src/models/log-subscription.model.ts} +8 -6
  72. package/{models/log.model.d.ts → src/models/log.model.ts} +12 -10
  73. package/{models/logged-in-users.model.d.ts → src/models/logged-in-users.model.ts} +6 -5
  74. package/{models/method-response.model.d.ts → src/models/method-response.model.ts} +7 -6
  75. package/src/models/method.model.ts +11 -0
  76. package/{models/monitor-cpu.model.d.ts → src/models/monitor-cpu.model.ts} +9 -7
  77. package/src/models/monitor-memory.model.ts +17 -0
  78. package/src/models/monitor-mongo.model.ts +15 -0
  79. package/{models/notification.model.d.ts → src/models/notification.model.ts} +3 -2
  80. package/src/models/pagination.model.ts +30 -0
  81. package/src/models/permission.model.ts +14 -0
  82. package/src/models/report-builder-dashboard-builder.model.ts +29 -0
  83. package/src/models/report-builder-library.model.ts +20 -0
  84. package/src/models/report-builder-report.model.ts +110 -0
  85. package/src/models/report-builder.model.ts +68 -0
  86. package/src/models/select-data-label.model.ts +9 -0
  87. package/src/models/server-response.model.ts +5 -0
  88. package/src/models/subscription.model.ts +64 -0
  89. package/src/models/support-ticket.model.ts +81 -0
  90. package/src/models/user-group.model.ts +23 -0
  91. package/{models/user-guide.model.d.ts → src/models/user-guide.model.ts} +5 -4
  92. package/src/models/user.model.ts +79 -0
  93. package/{public_api.d.ts → src/public_api.ts} +1 -1
  94. package/src/publications/app-status.ts +13 -0
  95. package/src/publications/cron-jobs.ts +30 -0
  96. package/src/publications/files.ts +34 -0
  97. package/src/publications/flags.ts +20 -0
  98. package/src/publications/logs.ts +164 -0
  99. package/src/publications/method-responses.ts +13 -0
  100. package/src/publications/notifications.ts +13 -0
  101. package/src/publications/report-builder-dashboard-builders.ts +39 -0
  102. package/src/publications/report-builder-libraries.ts +41 -0
  103. package/src/publications/report-builder-reports.ts +48 -0
  104. package/src/publications/super-admin.ts +13 -0
  105. package/src/publications/user-groups.ts +12 -0
  106. package/src/publications/user-guides.ts +12 -0
  107. package/src/server-app.ts +769 -0
  108. package/src/util/common.ts +519 -0
  109. package/src/util/schema-report-builder.ts +413 -0
  110. package/tsconfig.json +30 -0
  111. package/tslint.json +143 -0
  112. package/client-server-app.d.ts +0 -1
  113. package/client-server-app.js +0 -48
  114. package/client-server-app.js.map +0 -1
  115. package/collections/app-status.collection.d.ts +0 -3
  116. package/collections/app-status.collection.js +0 -51
  117. package/collections/app-status.collection.js.map +0 -1
  118. package/collections/counter.collection.d.ts +0 -3
  119. package/collections/counter.collection.js +0 -54
  120. package/collections/counter.collection.js.map +0 -1
  121. package/collections/cron-job-history.collection.d.ts +0 -3
  122. package/collections/cron-job-history.collection.js +0 -82
  123. package/collections/cron-job-history.collection.js.map +0 -1
  124. package/collections/cron-job.collection.d.ts +0 -3
  125. package/collections/cron-job.collection.js +0 -85
  126. package/collections/cron-job.collection.js.map +0 -1
  127. package/collections/email-history.collection.d.ts +0 -3
  128. package/collections/email-history.collection.js +0 -66
  129. package/collections/email-history.collection.js.map +0 -1
  130. package/collections/email-verified.collection.d.ts +0 -3
  131. package/collections/email-verified.collection.js +0 -61
  132. package/collections/email-verified.collection.js.map +0 -1
  133. package/collections/file.collection.d.ts +0 -3
  134. package/collections/file.collection.js +0 -73
  135. package/collections/file.collection.js.map +0 -1
  136. package/collections/flag.collection.d.ts +0 -3
  137. package/collections/flag.collection.js +0 -56
  138. package/collections/flag.collection.js.map +0 -1
  139. package/collections/log-method-latency.collection.d.ts +0 -3
  140. package/collections/log-method-latency.collection.js +0 -64
  141. package/collections/log-method-latency.collection.js.map +0 -1
  142. package/collections/log-subscription.collection.d.ts +0 -3
  143. package/collections/log-subscription.collection.js +0 -68
  144. package/collections/log-subscription.collection.js.map +0 -1
  145. package/collections/log-ts.collection.d.ts +0 -3
  146. package/collections/log-ts.collection.js +0 -78
  147. package/collections/log-ts.collection.js.map +0 -1
  148. package/collections/log.collection.d.ts +0 -3
  149. package/collections/log.collection.js +0 -77
  150. package/collections/log.collection.js.map +0 -1
  151. package/collections/logged-in-users.collection.d.ts +0 -3
  152. package/collections/logged-in-users.collection.js +0 -65
  153. package/collections/logged-in-users.collection.js.map +0 -1
  154. package/collections/method-response.collection.d.ts +0 -3
  155. package/collections/method-response.collection.js +0 -66
  156. package/collections/method-response.collection.js.map +0 -1
  157. package/collections/monitor-cpu.collection.d.ts +0 -3
  158. package/collections/monitor-cpu.collection.js +0 -63
  159. package/collections/monitor-cpu.collection.js.map +0 -1
  160. package/collections/monitor-memory.collection.d.ts +0 -3
  161. package/collections/monitor-memory.collection.js +0 -75
  162. package/collections/monitor-memory.collection.js.map +0 -1
  163. package/collections/monitor-mongo.collection.d.ts +0 -3
  164. package/collections/monitor-mongo.collection.js +0 -69
  165. package/collections/monitor-mongo.collection.js.map +0 -1
  166. package/collections/notification.collection.d.ts +0 -3
  167. package/collections/notification.collection.js +0 -51
  168. package/collections/notification.collection.js.map +0 -1
  169. package/collections/report-builder-dashboard-builder.collection.d.ts +0 -3
  170. package/collections/report-builder-dashboard-builder.collection.js +0 -109
  171. package/collections/report-builder-dashboard-builder.collection.js.map +0 -1
  172. package/collections/report-builder-library.collection.d.ts +0 -3
  173. package/collections/report-builder-library.collection.js +0 -87
  174. package/collections/report-builder-library.collection.js.map +0 -1
  175. package/collections/report-builder-report.collection.d.ts +0 -4
  176. package/collections/report-builder-report.collection.js +0 -149
  177. package/collections/report-builder-report.collection.js.map +0 -1
  178. package/collections/user-group.collection.d.ts +0 -4
  179. package/collections/user-group.collection.js +0 -90
  180. package/collections/user-group.collection.js.map +0 -1
  181. package/collections/user-guide.collection.d.ts +0 -3
  182. package/collections/user-guide.collection.js +0 -57
  183. package/collections/user-guide.collection.js.map +0 -1
  184. package/collections/user.collection.d.ts +0 -4
  185. package/collections/user.collection.js +0 -259
  186. package/collections/user.collection.js.map +0 -1
  187. package/cron/cron.d.ts +0 -5
  188. package/cron/cron.js +0 -162
  189. package/cron/cron.js.map +0 -1
  190. package/fixtures/cron-jobs.d.ts +0 -1
  191. package/fixtures/cron-jobs.js +0 -73
  192. package/fixtures/cron-jobs.js.map +0 -1
  193. package/fixtures/init.d.ts +0 -1
  194. package/fixtures/init.js +0 -59
  195. package/fixtures/init.js.map +0 -1
  196. package/http/auth.d.ts +0 -2
  197. package/http/auth.js +0 -763
  198. package/http/auth.js.map +0 -1
  199. package/http/health.d.ts +0 -1
  200. package/http/health.js +0 -12
  201. package/http/health.js.map +0 -1
  202. package/http/home.d.ts +0 -2
  203. package/http/home.js +0 -66
  204. package/http/home.js.map +0 -1
  205. package/index.d.ts +0 -23
  206. package/index.js +0 -127
  207. package/index.js.map +0 -1
  208. package/managers/cron.manager.d.ts +0 -17
  209. package/managers/cron.manager.js +0 -242
  210. package/managers/cron.manager.js.map +0 -1
  211. package/managers/method.manager.d.ts +0 -38
  212. package/managers/method.manager.js +0 -595
  213. package/managers/method.manager.js.map +0 -1
  214. package/managers/mongo.manager.d.ts +0 -178
  215. package/managers/mongo.manager.js +0 -2221
  216. package/managers/mongo.manager.js.map +0 -1
  217. package/managers/monitor.manager.d.ts +0 -59
  218. package/managers/monitor.manager.js +0 -351
  219. package/managers/monitor.manager.js.map +0 -1
  220. package/managers/subscription.manager.d.ts +0 -50
  221. package/managers/subscription.manager.js +0 -1091
  222. package/managers/subscription.manager.js.map +0 -1
  223. package/managers/subscription.performance.d.ts +0 -1
  224. package/managers/subscription.performance.js.map +0 -1
  225. package/methods/accounts.d.ts +0 -2
  226. package/methods/accounts.js +0 -274
  227. package/methods/accounts.js.map +0 -1
  228. package/methods/aws.d.ts +0 -2
  229. package/methods/aws.js +0 -617
  230. package/methods/aws.js.map +0 -1
  231. package/methods/collections.d.ts +0 -2
  232. package/methods/collections.js +0 -499
  233. package/methods/collections.js.map +0 -1
  234. package/methods/counters.d.ts +0 -2
  235. package/methods/counters.js +0 -122
  236. package/methods/counters.js.map +0 -1
  237. package/methods/cron-jobs.d.ts +0 -2
  238. package/methods/cron-jobs.js +0 -1315
  239. package/methods/cron-jobs.js.map +0 -1
  240. package/methods/flags.d.ts +0 -2
  241. package/methods/flags.js +0 -9
  242. package/methods/flags.js.map +0 -1
  243. package/methods/logs.d.ts +0 -2
  244. package/methods/logs.js +0 -371
  245. package/methods/logs.js.map +0 -1
  246. package/methods/monitor.d.ts +0 -2
  247. package/methods/monitor.js +0 -565
  248. package/methods/monitor.js.map +0 -1
  249. package/methods/pdf.d.ts +0 -2
  250. package/methods/pdf.js +0 -324
  251. package/methods/pdf.js.map +0 -1
  252. package/methods/report-builder.d.ts +0 -2
  253. package/methods/report-builder.js +0 -858
  254. package/methods/report-builder.js.map +0 -1
  255. package/methods/support.d.ts +0 -2
  256. package/methods/support.js +0 -246
  257. package/methods/support.js.map +0 -1
  258. package/models/app-status.model.js +0 -4
  259. package/models/app-status.model.js.map +0 -1
  260. package/models/billing-logged-in-users.model.js +0 -4
  261. package/models/billing-logged-in-users.model.js.map +0 -1
  262. package/models/collection-document.model.d.ts +0 -19
  263. package/models/collection-document.model.js +0 -4
  264. package/models/collection-document.model.js.map +0 -1
  265. package/models/counter.model.js +0 -4
  266. package/models/counter.model.js.map +0 -1
  267. package/models/cron-job-history.model.d.ts +0 -12
  268. package/models/cron-job-history.model.js +0 -4
  269. package/models/cron-job-history.model.js.map +0 -1
  270. package/models/cron-job.model.d.ts +0 -13
  271. package/models/cron-job.model.js +0 -4
  272. package/models/cron-job.model.js.map +0 -1
  273. package/models/dialog.model.d.ts +0 -23
  274. package/models/dialog.model.js +0 -4
  275. package/models/dialog.model.js.map +0 -1
  276. package/models/email-history.model.js +0 -4
  277. package/models/email-history.model.js.map +0 -1
  278. package/models/email-verified.model.js +0 -4
  279. package/models/email-verified.model.js.map +0 -1
  280. package/models/file.model.js +0 -4
  281. package/models/file.model.js.map +0 -1
  282. package/models/flag.model.js +0 -4
  283. package/models/flag.model.js.map +0 -1
  284. package/models/log-method-latency.model.js +0 -4
  285. package/models/log-method-latency.model.js.map +0 -1
  286. package/models/log-subscription.model.js +0 -4
  287. package/models/log-subscription.model.js.map +0 -1
  288. package/models/log.model.js +0 -4
  289. package/models/log.model.js.map +0 -1
  290. package/models/logged-in-users.model.js +0 -4
  291. package/models/logged-in-users.model.js.map +0 -1
  292. package/models/method-response.model.js +0 -4
  293. package/models/method-response.model.js.map +0 -1
  294. package/models/method.model.d.ts +0 -9
  295. package/models/method.model.js +0 -4
  296. package/models/method.model.js.map +0 -1
  297. package/models/monitor-cpu.model.js +0 -4
  298. package/models/monitor-cpu.model.js.map +0 -1
  299. package/models/monitor-memory.model.d.ts +0 -15
  300. package/models/monitor-memory.model.js +0 -4
  301. package/models/monitor-memory.model.js.map +0 -1
  302. package/models/monitor-mongo.model.d.ts +0 -13
  303. package/models/monitor-mongo.model.js +0 -4
  304. package/models/monitor-mongo.model.js.map +0 -1
  305. package/models/notification.model.js +0 -4
  306. package/models/notification.model.js.map +0 -1
  307. package/models/pagination.model.d.ts +0 -10
  308. package/models/pagination.model.js +0 -24
  309. package/models/pagination.model.js.map +0 -1
  310. package/models/permission.model.d.ts +0 -12
  311. package/models/permission.model.js +0 -4
  312. package/models/permission.model.js.map +0 -1
  313. package/models/report-builder-dashboard-builder.model.d.ts +0 -25
  314. package/models/report-builder-dashboard-builder.model.js +0 -4
  315. package/models/report-builder-dashboard-builder.model.js.map +0 -1
  316. package/models/report-builder-library.model.d.ts +0 -17
  317. package/models/report-builder-library.model.js +0 -4
  318. package/models/report-builder-library.model.js.map +0 -1
  319. package/models/report-builder-report.model.d.ts +0 -98
  320. package/models/report-builder-report.model.js +0 -4
  321. package/models/report-builder-report.model.js.map +0 -1
  322. package/models/report-builder.model.d.ts +0 -61
  323. package/models/report-builder.model.js +0 -4
  324. package/models/report-builder.model.js.map +0 -1
  325. package/models/select-data-label.model.d.ts +0 -9
  326. package/models/select-data-label.model.js +0 -4
  327. package/models/select-data-label.model.js.map +0 -1
  328. package/models/server-response.model.d.ts +0 -5
  329. package/models/server-response.model.js +0 -4
  330. package/models/server-response.model.js.map +0 -1
  331. package/models/subscription.model.d.ts +0 -23
  332. package/models/subscription.model.js +0 -4
  333. package/models/subscription.model.js.map +0 -1
  334. package/models/support-ticket.model.d.ts +0 -72
  335. package/models/support-ticket.model.js +0 -4
  336. package/models/support-ticket.model.js.map +0 -1
  337. package/models/user-group.model.d.ts +0 -19
  338. package/models/user-group.model.js +0 -4
  339. package/models/user-group.model.js.map +0 -1
  340. package/models/user-guide.model.js +0 -4
  341. package/models/user-guide.model.js.map +0 -1
  342. package/models/user.model.d.ts +0 -70
  343. package/models/user.model.js +0 -4
  344. package/models/user.model.js.map +0 -1
  345. package/public_api.js +0 -75
  346. package/public_api.js.map +0 -1
  347. package/publications/app-status.d.ts +0 -2
  348. package/publications/app-status.js +0 -17
  349. package/publications/app-status.js.map +0 -1
  350. package/publications/cron-jobs.d.ts +0 -2
  351. package/publications/cron-jobs.js +0 -33
  352. package/publications/cron-jobs.js.map +0 -1
  353. package/publications/files.d.ts +0 -2
  354. package/publications/files.js +0 -37
  355. package/publications/files.js.map +0 -1
  356. package/publications/flags.d.ts +0 -2
  357. package/publications/flags.js +0 -23
  358. package/publications/flags.js.map +0 -1
  359. package/publications/logs.d.ts +0 -2
  360. package/publications/logs.js +0 -165
  361. package/publications/logs.js.map +0 -1
  362. package/publications/method-responses.d.ts +0 -2
  363. package/publications/method-responses.js +0 -17
  364. package/publications/method-responses.js.map +0 -1
  365. package/publications/notifications.d.ts +0 -2
  366. package/publications/notifications.js +0 -17
  367. package/publications/notifications.js.map +0 -1
  368. package/publications/report-builder-dashboard-builders.d.ts +0 -2
  369. package/publications/report-builder-dashboard-builders.js +0 -43
  370. package/publications/report-builder-dashboard-builders.js.map +0 -1
  371. package/publications/report-builder-libraries.d.ts +0 -2
  372. package/publications/report-builder-libraries.js +0 -90
  373. package/publications/report-builder-libraries.js.map +0 -1
  374. package/publications/report-builder-reports.d.ts +0 -2
  375. package/publications/report-builder-reports.js +0 -51
  376. package/publications/report-builder-reports.js.map +0 -1
  377. package/publications/super-admin.d.ts +0 -2
  378. package/publications/super-admin.js +0 -17
  379. package/publications/super-admin.js.map +0 -1
  380. package/publications/user-groups.d.ts +0 -1
  381. package/publications/user-groups.js +0 -17
  382. package/publications/user-groups.js.map +0 -1
  383. package/publications/user-guides.d.ts +0 -1
  384. package/publications/user-guides.js +0 -17
  385. package/publications/user-guides.js.map +0 -1
  386. package/server-app.d.ts +0 -52
  387. package/server-app.js +0 -739
  388. package/server-app.js.map +0 -1
  389. package/util/common.d.ts +0 -25
  390. package/util/common.js +0 -524
  391. package/util/common.js.map +0 -1
  392. package/util/schema-report-builder.d.ts +0 -6
  393. package/util/schema-report-builder.js +0 -453
  394. package/util/schema-report-builder.js.map +0 -1
  395. /package/{private → src/private}/email-templates/enrollment.html +0 -0
  396. /package/{private → src/private}/email-templates/forgot-password.html +0 -0
  397. /package/{private → src/private}/email-templates/support-ticket-deleted.html +0 -0
  398. /package/{private → src/private}/email-templates/support-ticket-modified.html +0 -0
  399. /package/{private → src/private}/email-templates/support-ticket.html +0 -0
  400. /package/{private → src/private}/images/ResolveIO.png +0 -0
@@ -0,0 +1,1454 @@
1
+ import { MethodManager } from '../managers/method.manager';
2
+ import { ReportBuilderReports } from '../collections/report-builder-report.collection';
3
+ import SimpleSchema from 'simpl-schema';
4
+ import { mergeDeep, deepCopy, toTitleCase } from '../util/common';
5
+ import { PaginationOptions } from '../models/pagination.model';
6
+ import * as moment from 'moment';
7
+ import * as XLSX from 'xlsx';
8
+ import * as Excel from 'exceljs';
9
+ import { Files } from '../collections/file.collection';
10
+
11
+ export function loadCronJobMethods(methodManager: MethodManager) {
12
+ methodManager.methods({
13
+ cronEmailMergedDocsCleanUp: {
14
+ function: function() {
15
+ return new Promise(async (resolve, reject) => {
16
+ let files = await Files.find({$and: [{type: 'Email Merged Docs'}, {createdAt: {$lte: moment().subtract(1, 'day').toDate()}}]});
17
+
18
+ if (files.length) {
19
+ this.callMethodInternal('deleteFiles');
20
+ Files.deleteMany({_id: {$in: files.map(a => a._id)}});
21
+ }
22
+
23
+ resolve(true);
24
+ });
25
+ }
26
+ },
27
+ reportbuilderCronJob: {
28
+ check: new SimpleSchema({
29
+ data: {
30
+ type: Object,
31
+ blackbox: true
32
+ }
33
+ }),
34
+ function: function(data: Object) {
35
+ return new Promise(async (resolve, reject) => {
36
+ let report = await ReportBuilderReports.findById(data['id_report']);
37
+
38
+ report.fields_selected.forEach((field: any) => {
39
+ let dotPath = field.fieldPath.replace(/\.\$/g, '');
40
+ let fieldData = dotPath.split('.');
41
+ field.fieldPathObj = null;
42
+ for (let i = fieldData.length - 1; i >= 0; i--) {
43
+ if (!field.fieldPathObj) {
44
+ field.fieldPathObj = {[fieldData[i]]: 1};
45
+ }
46
+ else {
47
+ field.fieldPathObj = {[fieldData[i]]: field.fieldPathObj};
48
+ }
49
+ }
50
+ });
51
+
52
+ if ((report.fields_selected && report.fields_selected.length) || (report.groups_row && report.groups_row.length)) {
53
+ let fieldsObj = {};
54
+
55
+ let count = 0;
56
+
57
+ report.fields_selected.forEach((field: any) => {
58
+ if (field.collection_name === report.collection_root) {
59
+ fieldsObj = mergeDeep(fieldsObj, field.fieldPathObj);
60
+ }
61
+
62
+ let sortIndex = report.fields_sort.findIndex(a => a.field === field['id']);
63
+
64
+ if (sortIndex >= 0) {
65
+ report.fields_sort[sortIndex].field = ('f_' + count);
66
+ }
67
+
68
+ field['id'] = 'f_' + count;
69
+
70
+ count += 1;
71
+ });
72
+
73
+ let sortObj = {};
74
+ if (report.fields_sort.length) {
75
+ report.fields_sort.forEach(sortField => {
76
+ if (sortField.field.startsWith('gr_')) {
77
+ sortObj['_id.' + sortField.field] = (sortField.order === 'asc' ? 1 : -1);
78
+ }
79
+ else {
80
+ sortObj[sortField.field] = (sortField.order === 'asc' ? 1 : -1);
81
+ }
82
+ });
83
+ }
84
+ else {
85
+ sortObj = null;
86
+ }
87
+
88
+ let rootOptions: PaginationOptions = {
89
+ limit: 0,
90
+ skip: 0,
91
+ fields: fieldsObj,
92
+ sort: sortObj
93
+ };
94
+
95
+ let filters = [];
96
+ report.fields_filter.forEach(filterAnd => {
97
+ let ors = [];
98
+ filterAnd.ors.filter(a => !a.field.includes('.$.')).forEach(filter => {
99
+ if (filter.condition && filter.field && ((filter.value !== null && (!Array.isArray(filter.value) || filter.value.length)) || filter.condition === 'null' || filter.condition === 'nnull')) {
100
+ if (filter.condition === 'bw') {
101
+ if (filter.fieldType === 'Date' && filter.is_rolling) {
102
+ let startDate = null;
103
+ let endDate = null;
104
+
105
+ if (filter.rolling_interval === 'Q1') {
106
+ startDate = moment().startOf('year').toDate();
107
+ endDate = moment().startOf('year').quarter(2).subtract(1, 'days').toDate();
108
+ }
109
+ else if (filter.rolling_interval === 'Q2') {
110
+ startDate = moment().startOf('year').quarter(2).toDate();
111
+ endDate = moment().startOf('year').quarter(3).subtract(1, 'days').toDate();
112
+ }
113
+ else if (filter.rolling_interval === 'Q3') {
114
+ startDate = moment().startOf('year').quarter(3).toDate();
115
+ endDate = moment().startOf('year').quarter(4).subtract(1, 'days').toDate();
116
+ }
117
+ else if (filter.rolling_interval === 'Q4') {
118
+ startDate = moment().startOf('year').quarter(4).toDate();
119
+ endDate = moment().endOf('year').toDate();
120
+ }
121
+ else if (filter.rolling_interval === 'Today') {
122
+ startDate = moment().startOf('day').toDate();
123
+ endDate = moment().endOf('day').toDate();
124
+ }
125
+ else if (filter.rolling_interval === 'Yesterday') {
126
+ startDate = moment().subtract(1, 'days').startOf('day').toDate();
127
+ endDate = moment().subtract(1, 'days').endOf('day').toDate();
128
+ }
129
+ else if (filter.rolling_interval === 'Week') {
130
+ startDate = moment().startOf('isoWeek').toDate();
131
+ endDate = moment().endOf('day').toDate();
132
+ }
133
+ else if (filter.rolling_interval === 'Last Week') {
134
+ endDate = moment().startOf('isoWeek').subtract(1, 'days').toDate();
135
+ startDate = moment(endDate).startOf('isoWeek').toDate();
136
+ }
137
+ else if (filter.rolling_interval === 'Month') {
138
+ startDate = moment().startOf('month').toDate();
139
+ endDate = moment().endOf('day').toDate();
140
+ }
141
+ else if (filter.rolling_interval === 'Last Month') {
142
+ endDate = moment().startOf('month').subtract(1, 'days').endOf('day').toDate();
143
+ startDate = moment(endDate).startOf('month').toDate();
144
+ }
145
+ else if (filter.rolling_interval === 'Last 30 Days') {
146
+ endDate = moment().endOf('day').toDate();
147
+ startDate = moment().subtract(30, 'days').startOf('day').toDate();
148
+ }
149
+ else if (filter.rolling_interval === 'Quarter') {
150
+ startDate = moment().startOf('year').quarter(moment().quarter()).toDate();
151
+ endDate = moment().endOf('day').toDate();
152
+ }
153
+ else if (filter.rolling_interval === 'Last Quarter') {
154
+ endDate = moment().startOf('year').quarter(moment().quarter()).subtract(1, 'days').endOf('day').toDate();
155
+ startDate = moment(endDate).startOf('quarter').toDate();
156
+ }
157
+ else if (filter.rolling_interval === 'Year') {
158
+ startDate = moment().startOf('year').toDate();
159
+ endDate = moment().endOf('day').toDate();
160
+ }
161
+ else if (filter.rolling_interval === 'Last Year') {
162
+ endDate = moment().startOf('year').subtract(1, 'days').endOf('day').toDate();
163
+ startDate = moment(endDate).startOf('year').toDate();
164
+ }
165
+ else if (filter.rolling_interval === 'All') {
166
+ startDate = new Date(2017, 0, 1, 0, 0, 0, 0);
167
+ endDate = moment().endOf('day').toDate();
168
+ }
169
+
170
+ endDate.setHours(23);
171
+ endDate.setMinutes(59);
172
+ endDate.setSeconds(59);
173
+ endDate.setMilliseconds(999);
174
+
175
+ ors.push({$and: [{[filter.field]: {'$gte': startDate}}, {[filter.field]: {'$lte': endDate}}]});
176
+ }
177
+ else {
178
+ ors.push({$and: [{[filter.field]: {'$gte': filter.value}}, {[filter.field]: {'$lte': filter.highValue}}]});
179
+ }
180
+ }
181
+ else if (filter.condition === 'nnull') {
182
+ let and = [];
183
+ and.push({[filter.field]: {'$exists': true}});
184
+ and.push({[filter.field]: {'$ne': null}});
185
+
186
+ if (filter.fieldType === 'String') {
187
+ and.push({[filter.field]: {'$ne': ''}});
188
+ }
189
+
190
+ ors.push({$and: and});
191
+ }
192
+ else if (filter.condition === 'null') {
193
+ ors.push({[filter.field]: {'$eq': null}});
194
+ }
195
+ else {
196
+ if (Array.isArray(filter.value)) {
197
+ if (filter.condition === 'ne') {
198
+ let and = [];
199
+ filter.value.forEach(filt => {
200
+ and.push({[filter.field]: {['$' + filter.condition]: (Array.isArray(filt) ? filt[0] : filt)}});
201
+ });
202
+
203
+ if (and.length > 1) {
204
+ ors.push({$and: and});
205
+ }
206
+ else {
207
+ ors.push(and[0]);
208
+ }
209
+ }
210
+ else {
211
+ let or = [];
212
+
213
+ filter.value.forEach(filt => {
214
+ or.push({[filter.field]: {['$' + filter.condition]: (Array.isArray(filt) ? filt[0] : filt)}});
215
+ });
216
+
217
+ if (or.length > 1) {
218
+ ors.push({$or: or});
219
+ }
220
+ else {
221
+ ors.push(or[0]);
222
+ }
223
+ }
224
+ }
225
+ else {
226
+ ors.push({[filter.field]: {['$' + filter.condition]: filter.value}});
227
+ }
228
+ }
229
+ }
230
+ });
231
+
232
+ if (ors.length) {
233
+ filters.push({$or: ors});
234
+ }
235
+ });
236
+
237
+ this.callMethodInternal('reportBuilderBuildTree', report.collection_root, (errCollTree, collectionTree) => {
238
+ if (collectionTree) {
239
+ collectionTree.layers = [collectionTree];
240
+
241
+ let treeLeaves = [];
242
+ let allLeaves = [];
243
+ getTreeLeaves(collectionTree.children, treeLeaves);
244
+ getTreeLeaves(collectionTree.children, allLeaves, true);
245
+
246
+ let filterArrayFields = [];
247
+ let filterArrays = [];
248
+ report.fields_filter.forEach(filterAnd => {
249
+ let ors = [];
250
+ filterAnd.ors.filter(a => a.field.includes('.$.')).forEach(filter => {
251
+ if (allLeaves.filter(a => a.fieldPath === filter.field)[0]) {
252
+ filterArrayFields.push(allLeaves.filter(a => a.fieldPath === filter.field)[0]);
253
+ }
254
+
255
+ if (filter.condition && filter.field && ((filter.value !== null && (!Array.isArray(filter.value) || filter.value.length)) || filter.condition === 'null' || filter.condition === 'nnull')) {
256
+ if (filter.condition === 'bw') {
257
+ if (filter.fieldType === 'Date' && filter.is_rolling) {
258
+ let startDate = null;
259
+ let endDate = null;
260
+
261
+ if (filter.rolling_interval === 'Q1') {
262
+ startDate = moment().startOf('year').toDate();
263
+ endDate = moment().startOf('year').quarter(2).subtract(1, 'days').toDate();
264
+ }
265
+ else if (filter.rolling_interval === 'Q2') {
266
+ startDate = moment().startOf('year').quarter(2).toDate();
267
+ endDate = moment().startOf('year').quarter(3).subtract(1, 'days').toDate();
268
+ }
269
+ else if (filter.rolling_interval === 'Q3') {
270
+ startDate = moment().startOf('year').quarter(3).toDate();
271
+ endDate = moment().startOf('year').quarter(4).subtract(1, 'days').toDate();
272
+ }
273
+ else if (filter.rolling_interval === 'Q4') {
274
+ startDate = moment().startOf('year').quarter(4).toDate();
275
+ endDate = moment().endOf('year').toDate();
276
+ }
277
+ else if (filter.rolling_interval === 'Today') {
278
+ startDate = moment().startOf('day').toDate();
279
+ endDate = moment().endOf('day').toDate();
280
+ }
281
+ else if (filter.rolling_interval === 'Yesterday') {
282
+ startDate = moment().subtract(1, 'days').startOf('day').toDate();
283
+ endDate = moment().subtract(1, 'days').endOf('day').toDate();
284
+ }
285
+ else if (filter.rolling_interval === 'Week') {
286
+ startDate = moment().startOf('isoWeek').toDate();
287
+ endDate = moment().endOf('day').toDate();
288
+ }
289
+ else if (filter.rolling_interval === 'Last Week') {
290
+ endDate = moment().startOf('isoWeek').subtract(1, 'days').toDate();
291
+ startDate = moment(endDate).startOf('isoWeek').toDate();
292
+ }
293
+ else if (filter.rolling_interval === 'Month') {
294
+ startDate = moment().startOf('month').toDate();
295
+ endDate = moment().endOf('day').toDate();
296
+ }
297
+ else if (filter.rolling_interval === 'Last Month') {
298
+ endDate = moment().startOf('month').subtract(1, 'days').endOf('day').toDate();
299
+ startDate = moment(endDate).startOf('month').toDate();
300
+ }
301
+ else if (filter.rolling_interval === 'Last 30 Days') {
302
+ endDate = moment().endOf('day').toDate();
303
+ startDate = moment().subtract(30, 'days').startOf('day').toDate();
304
+ }
305
+ else if (filter.rolling_interval === 'Quarter') {
306
+ startDate = moment().startOf('year').quarter(moment().quarter()).toDate();
307
+ endDate = moment().endOf('day').toDate();
308
+ }
309
+ else if (filter.rolling_interval === 'Last Quarter') {
310
+ endDate = moment().startOf('year').quarter(moment().quarter()).subtract(1, 'days').endOf('day').toDate();
311
+ startDate = moment(endDate).startOf('quarter').toDate();
312
+ }
313
+ else if (filter.rolling_interval === 'Year') {
314
+ startDate = moment().startOf('year').toDate();
315
+ endDate = moment().endOf('day').toDate();
316
+ }
317
+ else if (filter.rolling_interval === 'Last Year') {
318
+ endDate = moment().startOf('year').subtract(1, 'days').endOf('day').toDate();
319
+ startDate = moment(endDate).startOf('year').toDate();
320
+ }
321
+ else if (filter.rolling_interval === 'All') {
322
+ startDate = new Date(2017, 0, 1, 0, 0, 0, 0);
323
+ endDate = moment().endOf('day').toDate();
324
+ }
325
+ endDate.setHours(23);
326
+ endDate.setMinutes(59);
327
+ endDate.setSeconds(59);
328
+ endDate.setMilliseconds(999);
329
+
330
+ ors.push({$and: [{[filter.field.replace(/\.\$/g, '')]: {'$gte': startDate}}, {[filter.field.replace(/\.\$/g, '')]: {'$lte': endDate}}]});
331
+ }
332
+ else {
333
+ filterArrays.push({$and: [{[filter.field.replace(/\.\$/g, '')]: {'$gte': filter.value}}, {[filter.field.replace(/\.\$/g, '')]: {'$lte': filter.highValue}}]});
334
+ }
335
+ }
336
+ else if (filter.condition === 'nnull') {
337
+ let and = [];
338
+ and.push({[filter.field.replace(/\.\$/g, '')]: {'$exists': true}});
339
+ and.push({[filter.field.replace(/\.\$/g, '')]: {'$ne': null}});
340
+
341
+ if (filter.fieldType === 'String') {
342
+ and.push({[filter.field.replace(/\.\$/g, '')]: {'$ne': ''}});
343
+ }
344
+
345
+ ors.push({$and: and});
346
+ }
347
+ else if (filter.condition === 'null') {
348
+ ors.push({[filter.field.replace(/\.\$/g, '')]: {'$eq': null}});
349
+ }
350
+ else {
351
+ if (Array.isArray(filter.value)) {
352
+ if (filter.condition === 'ne') {
353
+ let and = [];
354
+ filter.value.forEach(filt => {
355
+ and.push({[filter.field.replace(/\.\$/g, '')]: {['$' + filter.condition]: (Array.isArray(filt) ? filt[0] : filt)}});
356
+ });
357
+
358
+ if (and.length > 1) {
359
+ ors.push({$and: and});
360
+ }
361
+ else {
362
+ ors.push(and[0]);
363
+ }
364
+ }
365
+ else {
366
+ let or = [];
367
+
368
+ filter.value.forEach(filt => {
369
+ or.push({[filter.field.replace(/\.\$/g, '')]: {['$' + filter.condition]: (Array.isArray(filt) ? filt[0] : filt)}});
370
+ });
371
+
372
+ if (or.length > 1) {
373
+ ors.push({$or: or});
374
+ }
375
+ else {
376
+ ors.push(or[0]);
377
+ }
378
+ }
379
+ }
380
+ else {
381
+ ors.push({[filter.field.replace(/\.\$/g, '')]: {['$' + filter.condition]: filter.value}});
382
+ }
383
+ }
384
+ }
385
+ });
386
+
387
+ if (ors.length) {
388
+ filterArrays.push({$or: ors});
389
+ }
390
+ });
391
+
392
+ this.callMethodInternal('reportBuilderGetResults', report.type, report.collection_root, rootOptions, filters, filterArrays, filterArrayFields, report.fields_selected, report.fields_custom, report.groups_row, report.fields_total, report.fields_link, report.id_date_field || null, report.date_interval || null, report.group_type, (err, res) => {
393
+ if (res && res[0]) {
394
+ let results = res[0].results;
395
+ let reportTotals = res[0].totals;
396
+
397
+ if (report.type === 'List') {
398
+ report.fields_selected.filter(a => a.show).forEach(field => {
399
+ if ((field.fieldType === 'Number' || field.leafValueType === 'Count') && field.leafFormatType === 'Number') {
400
+ results.filter(a => a[field.id] !== null && a[field.id] !== undefined ).forEach(result => {
401
+ result[field.id] = result[field.id].toLocaleString();
402
+ });
403
+ }
404
+ else if ((field.fieldType === 'Number' || field.leafValueType === 'Count') && field.leafFormatType === 'String') {
405
+ results.filter(a => a[field.id] !== null && a[field.id] !== undefined).forEach(result => {
406
+ result[field.id] = result[field.id].toLocaleString('en-US', { style: 'currency', currency: 'USD' });
407
+ });
408
+ }
409
+ else if ((field.fieldType === 'Number' || field.leafValueType === 'Count') && field.leafFormatType === 'Currency') {
410
+ results.filter(a => a[field.id] !== null && a[field.id] !== undefined).forEach(result => {
411
+ result[field.id] = result[field.id].toLocaleString('en-US', { style: 'currency', currency: 'USD' });
412
+ });
413
+ }
414
+ else if (field.fieldType === 'Boolean' && (!field.leafFormatType || field.leafFormatType === 'Boolean')) {
415
+ results.filter(a => a[field.id] !== null && a[field.id] !== undefined).forEach(result => {
416
+ result[field.id] = result[field.id] === true ? 'True' : 'False';
417
+ });
418
+ }
419
+ else if (field.fieldType === 'Boolean' && field.leafFormatType === 'String') {
420
+ results.filter(a => a[field.id] !== null && a[field.id] !== undefined).forEach(result => {
421
+ result[field.id] = result[field.id] === true ? 'Yes' : 'No';
422
+ });
423
+ }
424
+ else if (field.fieldType === 'Boolean' && field.leafFormatType === 'Boolean_Number') {
425
+ results.filter(a => a[field.id] !== null && a[field.id] !== undefined).forEach(result => {
426
+ result[field.id] = result[field.id] === true ? 1 : 0;
427
+ });
428
+ }
429
+ else if (field.fieldType === 'Date' && (field.leafFormatType === 'Date')) {
430
+ results.filter(a => a[field.id] !== null && a[field.id] !== undefined).forEach(result => {
431
+ result[field.id] = moment(result[field.id]).format('L');
432
+ });
433
+ }
434
+ else if (field.fieldType === 'Date' && field.leafFormatType === 'Time') {
435
+ results.filter(a => a[field.id] !== null && a[field.id] !== undefined).forEach(result => {
436
+ result[field.id] = moment(result[field.id]).format('LT');
437
+ });
438
+ }
439
+ else if (field.fieldType === 'Date' && field.leafFormatType === 'DateTime') {
440
+ results.filter(a => a[field.id] !== null && a[field.id] !== undefined).forEach(result => {
441
+ result[field.id] = moment(result[field.id]).format('MM/DD/YYYY h:mm A');
442
+ });
443
+ }
444
+ else if (field.fieldType === 'Date' && field.leafFormatType === 'Date_long') {
445
+ results.filter(a => a[field.id] !== null && a[field.id] !== undefined).forEach(result => {
446
+ result[field.id] = moment(result[field.id]).format('LL');
447
+ });
448
+ }
449
+ else if (field.fieldType === 'Date' && field.leafFormatType === 'DateTime_long') {
450
+ results.filter(a => a[field.id] !== null && a[field.id] !== undefined).forEach(result => {
451
+ result[field.id] = moment(result[field.id]).format('LLL');
452
+ });
453
+ }
454
+ else if (field.fieldType === 'Date' && field.leafFormatType === 'Timestamp') {
455
+ results.filter(a => a[field.id] !== null && a[field.id] !== undefined).forEach(result => {
456
+ result[field.id] = moment(result[field.id]).toDate().getTime();
457
+ });
458
+ }
459
+ });
460
+
461
+ let lines: any = [];
462
+
463
+ let tmpHeaders = {};
464
+
465
+ report.groups_row.forEach(group => {
466
+ tmpHeaders[group.id] = group.columnName;
467
+ });
468
+
469
+ report.fields_selected.filter(a => a.show).forEach(header => {
470
+ tmpHeaders[header.columnName] = header.columnName;
471
+ });
472
+
473
+ let wb = XLSX.utils.book_new();
474
+
475
+ results.forEach(result => {
476
+ let tmp = {};
477
+ report.groups_row.forEach(group => {
478
+ if (Array.isArray(result._id[group.id])) {
479
+ tmp[group.columnName] = result._id[group.id].join(',');
480
+ }
481
+ else {
482
+ if (group.treeItem.fieldType === 'Number') {
483
+ tmp[group.columnName] = result._id[group.id] ? (typeof(result._id[group.id]) === 'string' ? parseFloat(result._id[group.id].replace(/,/g, '').replace(/\$/g, '')) : result._id[group.id]) : '';
484
+ }
485
+ else {
486
+ tmp[group.columnName] = result._id[group.id] || '';
487
+ }
488
+ }
489
+ });
490
+ report.fields_selected.filter(a => a.show).forEach(header => {
491
+ if (Array.isArray(result[header.id])) {
492
+ tmp[header.columnName] = result[header.id].join(',');
493
+ }
494
+ else {
495
+ if (header.fieldType === 'Number' || header.leafValueType === 'Count') {
496
+ tmp[header.columnName] = result[header.id] ? (typeof(result[header.id]) === 'string' ? parseFloat(result[header.id].replace(/,/g, '').replace(/\$/g, '')) : result[header.id]) : '';
497
+ }
498
+ else {
499
+ tmp[header.columnName] = result[header.id] || '';
500
+ }
501
+ }
502
+ });
503
+
504
+ lines.push(tmp);
505
+ });
506
+
507
+ let ws = XLSX.utils.json_to_sheet(lines);
508
+ XLSX.utils.book_append_sheet(wb, ws, 'RB Data');
509
+
510
+ let wbout = XLSX.write(wb, {bookType: 'xlsx', type: 'base64'});
511
+
512
+ data['emails'].forEach(email => {
513
+ this.sendEmail(email,
514
+ this.serverConfig['CLIENT_NAME'] + ' Scheduled Report - ' + report.report_name,
515
+ '',
516
+ `
517
+ <b>` + this.serverConfig['CLIENT_NAME'] + ` Automated Report</b><br>
518
+ <b>Report Name: </b>` + report.report_name + `<br>
519
+ <b>Prepared By: </b>` + data['user'] + `<br><br>
520
+ Attached are the results of this automated report.<br><br>
521
+ ResolveIO<br><br>`,
522
+ [
523
+ {
524
+ filename: report.report_name + '-' + moment().format('MM-DD-YYYY-hh-mm-A') + '.xlsx',
525
+ content: wbout,
526
+ encoding: 'base64'
527
+ }
528
+ ],
529
+ this.serverConfig['MAIL_FROM_REPORTS'],
530
+ ''
531
+ );
532
+ });
533
+ }
534
+ else if (report.type === 'Group') {
535
+ report.fields_selected.filter(a => a.show).forEach(field => {
536
+ results.forEach(result => {
537
+ modifyDataTypeField(report, result, field, 1);
538
+ });
539
+ });
540
+
541
+ let wb = new Excel.Workbook();
542
+ let ws = wb.addWorksheet('RB_1', {views: [{showGridLines: false}]});
543
+ wb.properties.date1904 = false;
544
+ wb.calcProperties.fullCalcOnLoad = true;
545
+
546
+ let currentRow = 1;
547
+ let row = ws.getRow(currentRow);
548
+
549
+ row.getCell(2).font = {
550
+ name: 'Arial',
551
+ bold: true,
552
+ size: 14
553
+ };
554
+ row.getCell(4).font = {
555
+ name: 'Arial',
556
+ size: 14
557
+ };
558
+ row.getCell(2).value = 'Report Name:';
559
+ row.getCell(4).value = report.report_name;
560
+
561
+ currentRow += 1;
562
+ row = ws.getRow(currentRow);
563
+
564
+ row.getCell(2).font = {
565
+ name: 'Arial',
566
+ bold: true,
567
+ size: 14
568
+ };
569
+ row.getCell(4).font = {
570
+ name: 'Arial',
571
+ size: 14
572
+ };
573
+ row.getCell(2).value = 'Run Date:';
574
+ row.getCell(4).value = moment().format('LLL');
575
+
576
+ currentRow += 2;
577
+
578
+ let copy = deepCopy(results);
579
+ let widths = [];
580
+ copy.forEach(res => {
581
+ currentRow = tabGroupExcelRecursive(report, ws, currentRow, 1, res);
582
+ tabGroupExcelWidthRecursive(report, 1, res, widths);
583
+ });
584
+
585
+ for (let i = 1; i < ws.columns.length; i++) {
586
+ ws.columns[i].width = widths[i - 1];
587
+ }
588
+
589
+ let now = new Date();
590
+
591
+ wb.xlsx.writeBuffer().then(buffer => {
592
+ data['emails'].forEach(email => {
593
+ this.sendEmail(email,
594
+ this.serverConfig['CLIENT_NAME'] + ' Scheduled Report - ' + report.report_name,
595
+ '',
596
+ `
597
+ <b>` + this.serverConfig['CLIENT_NAME'] + ` Automated Report</b><br>
598
+ <b>Report Name: </b>` + report.report_name + `<br>
599
+ <b>Prepared By: </b>` + data['user'] + `<br><br>
600
+ Attached are the results of this automated report.<br><br>
601
+ Have a great day!<br><br>
602
+ ResolveIO<br><br>`,
603
+ [
604
+ {
605
+ filename: 'Group_Report_' + report.report_name + '_' + now.getFullYear() + '_' + (now.getMonth() + 1) + '_' + now.getDate() + '.xlsx',
606
+ content: buffer
607
+ }
608
+ ],
609
+ this.serverConfig['MAIL_FROM_REPORTS'],
610
+ ''
611
+ );
612
+ });
613
+ }).catch(err => console.log('Error writing excel export', err));
614
+ }
615
+ else if (report.type === 'Dated') {
616
+ let lines: any = [];
617
+
618
+ let tmpHeaders = {};
619
+
620
+ report.groups_row.forEach(group => {
621
+ tmpHeaders[group.id] = group.columnName;
622
+ });
623
+
624
+ tmpHeaders[''] = '';
625
+
626
+ let datedUniqueDates = [];
627
+ let datedUniqueGroups = [];
628
+
629
+ if (report.date_interval === 'Quarterly') {
630
+ results.forEach(dataPt => {
631
+ if (dataPt._id.month < 4) {
632
+ dataPt._id.quarter = 1;
633
+ }
634
+ else if (dataPt._id.month < 7) {
635
+ dataPt._id.quarter = 2;
636
+ }
637
+ else if (dataPt._id.month < 10) {
638
+ dataPt._id.quarter = 3;
639
+ }
640
+ else {
641
+ dataPt._id.quarter = 4;
642
+ }
643
+
644
+ delete dataPt._id.month;
645
+ });
646
+
647
+ for (let i = results.length - 1; i >= 1; i--) {
648
+ let dataPt = results[i];
649
+
650
+ if (results.filter(a => JSON.stringify(a._id) === JSON.stringify(dataPt._id)).length > 1) {
651
+ let tmpData = results.filter(a => JSON.stringify(a._id) === JSON.stringify(dataPt._id))[0];
652
+
653
+ Object.keys(tmpData).filter(a => a !== '_id').forEach(key => {
654
+
655
+ tmpData[key] += dataPt[key];
656
+ });
657
+
658
+ results.splice(i, 1);
659
+ }
660
+ }
661
+ }
662
+
663
+ let tmpResults = deepCopy(results);
664
+ tmpResults.forEach(result => {
665
+ delete result._id.day;
666
+ delete result._id.week;
667
+ delete result._id.month;
668
+ delete result._id.quarter;
669
+ delete result._id.year;
670
+
671
+ let tmp = {};
672
+
673
+ Object.keys(result._id).forEach(key => {
674
+ tmp[key] = result._id[key];
675
+ });
676
+
677
+ if (!datedUniqueGroups.filter(a => JSON.stringify(a) === JSON.stringify(tmp)).length) {
678
+ datedUniqueGroups.push(tmp);
679
+ }
680
+ });
681
+
682
+ tmpResults = deepCopy(results);
683
+
684
+ tmpResults.forEach(result => {
685
+ Object.keys(result._id).filter(a => a !== 'second' && a !== 'hour' && a !== 'minute' && a !== 'day' && a !== 'week' && a !== 'month' && a !== 'quarter' && a !== 'year').forEach(key => {
686
+ delete result._id[key];
687
+ });
688
+
689
+ let tmp = {};
690
+
691
+ Object.keys(result._id).forEach(key => {
692
+ tmp[key] = result._id[key];
693
+ });
694
+
695
+ if (!datedUniqueDates.filter(a => JSON.stringify(a) === JSON.stringify(tmp)).length) {
696
+ datedUniqueDates.push(tmp);
697
+ }
698
+ });
699
+
700
+ datedUniqueDates.forEach(result => {
701
+ if (!result.year) {
702
+ result.dateString = 'No Date';
703
+ }
704
+ else {
705
+ if (report.date_interval === 'Seconds') {
706
+ result.date = new Date(result.year, result.month - 1, result.day, result.hour, result.minute, result.second, 0);
707
+ result.dateString = moment(result.date).format('MMM DD YYYY HH:mm:ss');
708
+ }
709
+ else if (report.date_interval === 'Minutes') {
710
+ result.date = new Date(result.year, result.month - 1, result.day, result.hour, result.minute, 0, 0);
711
+ result.dateString = moment(result.date).format('MMM DD YYYY HH:mm');
712
+ }
713
+ else if (report.date_interval === 'Hours') {
714
+ result.date = new Date(result.year, result.month - 1, result.day, result.hour, 0, 0, 0);
715
+ result.dateString = moment(result.date).format('MMM DD YYYY HH');
716
+ }
717
+ else if (report.date_interval === 'Daily') {
718
+ result.date = new Date(result.year, result.month - 1, result.day, 0, 0, 0, 0);
719
+ result.dateString = moment(result.date).format('MMM DD YYYY');
720
+ }
721
+ else if (report.date_interval === 'Weekly') {
722
+ result.date = moment().day('Monday').isoWeekYear(result.year).isoWeek(result.week).toDate();
723
+ result.dateLast = moment().day('Sunday').isoWeekYear(result.year).isoWeek(result.week).toDate();
724
+ result.dateString = 'Week #' + result.week + ' ' + result.year + '(' + moment(result.date).format('MM/DD/YY') + ' - ' + moment(result.dateLast).format('MM/DD/YY') + ')';
725
+ }
726
+ else if (report.date_interval === 'Monthly') {
727
+ result.date = new Date(result.year, result.month - 1, 1, 0, 0, 0, 0);
728
+ result.dateString = moment(result.date).format('MMM YYYY');
729
+ }
730
+ else if (report.date_interval === 'Quarterly') {
731
+ result.date = moment().quarter(result.quarter).year(result.year).toDate();
732
+ result.dateString = 'Q' + result.quarter + ' ' + result.year;
733
+ }
734
+ else if (report.date_interval === 'Yearly') {
735
+ result.date = new Date(result.year);
736
+ result.dateString = result.year.toString();
737
+ }
738
+ }
739
+ });
740
+
741
+ datedUniqueDates = datedUniqueDates.filter(a => !a.date).concat(datedUniqueDates.filter(a => a.date).sort((a, b) => a.date.getTime() - b.date.getTime()));
742
+
743
+ let reportTotalGroups = [];
744
+ let reportTotalDates = [];
745
+ let datedData = [];
746
+
747
+ datedUniqueDates.forEach(date => {
748
+ let tmpData = [];
749
+ let tmpTotalDated = {};
750
+ let tmpTotalCnt = {};
751
+ let tmpTotalType = {};
752
+
753
+ datedUniqueGroups.forEach(group => {
754
+ let result = results.filter(a => {
755
+ let res = true;
756
+
757
+ Object.keys(date).filter(a => a !== 'date' && a !== 'dateLast' && a !== 'dateString').forEach(key => {
758
+ if (a._id[key] !== date[key]) {
759
+ res = false;
760
+ }
761
+ });
762
+
763
+ Object.keys(group).forEach(key => {
764
+ if (a._id[key] !== group[key]) {
765
+ res = false;
766
+ }
767
+ });
768
+
769
+ return res;
770
+ })[0];
771
+
772
+ if (result) {
773
+ tmpData.push(result);
774
+
775
+ Object.keys(result._id).filter(a => a).forEach(key => {
776
+ if (report.fields_total.filter(a => a.fields.includes(key)).length) {
777
+ if (!tmpTotalDated[key]) {
778
+ tmpTotalDated[key] = result._id[key];
779
+ }
780
+ else {
781
+ tmpTotalDated[key] += result._id[key];
782
+ }
783
+
784
+ if (!tmpTotalCnt[key]) {
785
+ tmpTotalCnt[key] = 1;
786
+ }
787
+ else {
788
+ tmpTotalCnt[key] += 1;
789
+ }
790
+
791
+ tmpTotalType[key] = report.fields_total.filter(a => a.fields.includes(key))[0].type;
792
+ }
793
+ });
794
+
795
+ Object.keys(result).filter(a => a && a !== '_id').forEach(key => {
796
+ if (report.fields_total.filter(a => a.fields.includes(key)).length) {
797
+ if (!tmpTotalDated[key]) {
798
+ tmpTotalDated[key] = result[key];
799
+ }
800
+ else {
801
+ tmpTotalDated[key] += result[key];
802
+ }
803
+
804
+ if (!tmpTotalCnt[key]) {
805
+ tmpTotalCnt[key] = 1;
806
+ }
807
+ else {
808
+ tmpTotalCnt[key] += 1;
809
+ }
810
+
811
+ tmpTotalType[key] = report.fields_total.filter(a => a.fields.includes(key))[0].type;
812
+ }
813
+ });
814
+ }
815
+ else {
816
+ tmpData.push(null);
817
+ }
818
+ });
819
+
820
+ Object.keys(tmpTotalType).forEach(totalKey => {
821
+ if (tmpTotalType[totalKey] === 'avg') {
822
+ tmpTotalDated[totalKey] = tmpTotalDated[totalKey] / tmpTotalCnt[totalKey];
823
+ }
824
+
825
+ tmpTotalDated[totalKey] = Math.round(tmpTotalDated[totalKey] * 100) / 100;
826
+ });
827
+
828
+ reportTotalDates.push(tmpTotalDated);
829
+ datedData.push(tmpData);
830
+ });
831
+
832
+ datedUniqueGroups.forEach(group => {
833
+ let tmpTotalGroup = {};
834
+ let filteredData = results.filter(a => {
835
+ let res = (!Object.keys(group).length || group._id === null) ? false : true;
836
+
837
+ Object.keys(group).filter(a => a !== 'date' && a !== 'dateLast' && a !== 'dateString' && a !== 'second' && a !== 'minute' && a !== 'hour' && a !== 'day' && a !== 'week' && a !== 'month' && a !== 'quarter' && a !== 'year').forEach(key => {
838
+ if (a._id[key] !== group[key]) {
839
+ res = false;
840
+ }
841
+ });
842
+
843
+ return res;
844
+ });
845
+
846
+ report.fields_total.forEach(total => {
847
+ total.fields.forEach(field => {
848
+ if (filteredData.length) {
849
+ tmpTotalGroup[field] = filteredData.filter(a => a && a[field]).map(a => a[field]).reduce((a, b) => a + b, 0);
850
+
851
+ if (total.type === 'avg') {
852
+ tmpTotalGroup[field] = Math.round(tmpTotalGroup[field] / filteredData.length * 100) / 100;
853
+ }
854
+ }
855
+ else {
856
+ tmpTotalGroup[field] = 0;
857
+ }
858
+ });
859
+ });
860
+
861
+ reportTotalGroups.push(tmpTotalGroup);
862
+ });
863
+
864
+ datedUniqueDates.forEach(date => {
865
+ tmpHeaders[date.dateString] = date.dateString;
866
+ });
867
+
868
+ report.fields_total.forEach(total => {
869
+ tmpHeaders['Totals - ' + total.type.toUpperCase()] = 'Totals - ' + toTitleCase(total.type);
870
+ });
871
+
872
+ lines.push(tmpHeaders);
873
+
874
+ let selectedFields = deepCopy(report.fields_selected);
875
+ //add custom
876
+ report.fields_custom.forEach(customField => {
877
+ selectedFields.push({
878
+ collection_name : '',
879
+ columnName : customField.columnName,
880
+ fieldName : customField.selFieldId,
881
+ fieldType : 'Number',
882
+ fieldTypeName : 'Number',
883
+ distinctFieldValues : [],
884
+ fieldPath : customField.selFieldId,
885
+ fieldPathName : 'Custom Field',
886
+ lookup_collection : '',
887
+ lookup_local_key : '',
888
+ lookup_foreign_key : '',
889
+ lookup_as : '',
890
+ text : '',
891
+ value : '',
892
+ isLeaf : true,
893
+ isActive : true,
894
+ isSelected : true,
895
+ depth : 0,
896
+ leafValueType : customField.leafValueType,
897
+ leafValueTypes : [],
898
+ leafFormatType : 'Number',
899
+ leafFormatTypes : [],
900
+ id : customField.selFieldId,
901
+ show: true
902
+ });
903
+ });
904
+
905
+ for (let i = 0; i < datedUniqueGroups.length; i++) {
906
+ let group = datedUniqueGroups[i];
907
+
908
+ const fieldsSelectedArr = selectedFields.filter(a => a.show);
909
+ for (let j = 0; j < fieldsSelectedArr.length; j++) {
910
+ let field = fieldsSelectedArr[j];
911
+
912
+ let tmp = {};
913
+
914
+ for (let k = 0; k <= report.groups_row.length - 1; k++) {
915
+ let groupRow = report.groups_row[k];
916
+
917
+ if (j === 0) {
918
+ tmp[group[groupRow.id]] = group[groupRow.id];
919
+ }
920
+ else {
921
+ tmp[group[groupRow.id]] = '';
922
+ }
923
+ }
924
+
925
+ tmp[field.columnName] = field.columnName;
926
+
927
+ for (let k = 0; k <= datedData.length - 1; k++) {
928
+ let result = datedData[k];
929
+
930
+ if (result[i]) {
931
+ if (allLeaves.filter(a => a.id === field.id)[0] && allLeaves.filter(a => a.id === field.id)[0].fieldType === 'Number') {
932
+ tmp[i + ' ' + j + ' ' + k] = result[i][field.id] ? (typeof(result[i][field.id]) === 'string' ? parseInt(result[i][field.id].replace(/,/g, '')) : result[i][field.id]) : '';
933
+ }
934
+ else {
935
+ tmp[i + ' ' + j + ' ' + k] = result[i][field.id] ? (typeof(result[i][field.id]) === 'string' ? result[i][field.id].replace(/,/g, '') : result[i][field.id]) : '';
936
+ }
937
+ }
938
+ else {
939
+ tmp[i + ' ' + j + ' ' + k] = '';
940
+ }
941
+ }
942
+
943
+ for (let k = 0; k <= report.fields_total.length - 1; k++) {
944
+ let total = report.fields_total[k];
945
+
946
+ if (total.fields.includes(field.id)) {
947
+ tmp['total' + i + ' ' + j + ' ' + k] = reportTotalGroups[i][field.id] ? (typeof(reportTotalGroups[i][field.id]) === 'string' ? parseInt(reportTotalGroups[i][field.id].replace(/,/g, '')) : reportTotalGroups[i][field.id]) : '';
948
+ }
949
+ else {
950
+ tmp['total' + i + ' ' + j + ' ' + k] = '';
951
+ }
952
+ }
953
+
954
+ lines.push(tmp);
955
+ }
956
+ }
957
+
958
+ if (reportTotals) {
959
+ for (let i = 0; i < report.fields_total.length; i++) {
960
+ let total = report.fields_total[i];
961
+ let tmp = {};
962
+
963
+ tmp[total.type] = toTitleCase(total.type) + ' Totals';
964
+
965
+ for (let j = 0; j < report.groups_row.length - 1; j++) {
966
+ tmp['total_gr_j'] = '';
967
+ }
968
+
969
+ tmp['Total - Fields'] = '';
970
+
971
+ for (let j = 0; j < datedData.length; j++) {
972
+ tmp['Total - Dated ' + j] = '';
973
+ }
974
+
975
+ for (let j = 0; j <= report.fields_selected.filter(a => a.show).length - 1; j++) {
976
+ let field = report.fields_selected.filter(a => a.show)[j];
977
+
978
+ if (total.fields.includes(field.id)) {
979
+ tmp['totalreportTotals' + j] = reportTotals[total.id + '_' + field.id];
980
+ }
981
+ else {
982
+ tmp['totalreportTotals' + j] = '';
983
+ }
984
+ }
985
+
986
+ lines.push(tmp);
987
+ }
988
+ }
989
+
990
+ let newCSV = '';
991
+
992
+ lines.forEach((row, index) => {
993
+ Object.keys(row).forEach((key, keyIndex) => {
994
+ if (row[key] && typeof(row[key]) === 'string') {
995
+ row[key] = row[key].replace(new RegExp(/,/g), '');
996
+ }
997
+
998
+ newCSV += row[key];
999
+
1000
+ if (keyIndex < Object.keys(row).length - 1) {
1001
+ newCSV += ',';
1002
+ }
1003
+ });
1004
+
1005
+ if (index < lines.length - 1) {
1006
+ newCSV += '\r\n';
1007
+ }
1008
+ });
1009
+
1010
+ data['emails'].forEach(email => {
1011
+ this.sendEmail(email,
1012
+ this.serverConfig['CLIENT_NAME'] + ' Scheduled Report - ' + report.report_name,
1013
+ '',
1014
+ `
1015
+ <b>` + this.serverConfig['CLIENT_NAME'] + ` Automated Report</b><br>
1016
+ <b>Report Name: </b>` + report.report_name + `<br>
1017
+ <b>Prepared By: </b>` + data['user'] + `<br><br>
1018
+ Attached are the results of this automated report.<br><br>
1019
+ Have a great day!<br><br>
1020
+ ResolveIO<br><br>`,
1021
+ [
1022
+ {
1023
+ filename: report.report_name + '-' + moment().format('MM-DD-YYYY-hh-mm-A') + '.csv',
1024
+ content: newCSV
1025
+ }
1026
+ ],
1027
+ this.serverConfig['MAIL_FROM_REPORTS'],
1028
+ ''
1029
+ );
1030
+ });
1031
+
1032
+ resolve(true);
1033
+ }
1034
+ }
1035
+ else {
1036
+ this.callMethodInternal('insertErrorLog', 'Report Builder Cron Job - Report Builder Get Results', [
1037
+ err
1038
+ ]);
1039
+
1040
+ reject(err);
1041
+ }
1042
+ });
1043
+ }
1044
+ });
1045
+ }
1046
+ });
1047
+ }
1048
+ }
1049
+ });
1050
+ }
1051
+
1052
+ function getTreeLeaves(items, resArray, allowLookups = false) {
1053
+ items.forEach(item => {
1054
+ if (item.isLeaf) {
1055
+ resArray.push(item);
1056
+ }
1057
+ else {
1058
+ if (!item.lookup_collection || allowLookups) {
1059
+ getTreeLeaves(item.children, resArray, allowLookups);
1060
+ }
1061
+ }
1062
+ });
1063
+ }
1064
+
1065
+ function modifyDataTypeField(report, result, field, index) {
1066
+ if (index < report.groups_row.length) {
1067
+ result = result['gr_' + (index + 1)];
1068
+ result.forEach((tDataRes, tIndex) => {
1069
+ modifyDataTypeField(report, tDataRes, field, index + 1)
1070
+ });
1071
+ }
1072
+ else {
1073
+ if (Array.isArray(result[field.id])) {
1074
+ result[field.id].forEach((arr, arrIndex) => {
1075
+ if ((field.fieldType === 'Number' || field.leafValueType === 'Count') && field.leafFormatType === 'Number') {
1076
+ result[field.id].splice(arrIndex, 1, arr.toLocaleString());
1077
+ }
1078
+ else if ((field.fieldType === 'Number' || field.leafValueType === 'Count') && field.leafFormatType === 'String') {
1079
+ result[field.id].splice(arrIndex, 1, arr.toString());
1080
+ }
1081
+ else if ((field.fieldType === 'Number' || field.leafValueType === 'Count') && field.leafFormatType === 'Currency') {
1082
+ result[field.id].splice(arrIndex, 1, arr.toLocaleString('en-US', { style: 'currency', currency: 'USD' }));
1083
+ }
1084
+ else if (field.fieldType === 'Boolean' && (!field.leafFormatType || field.leafFormatType === 'Boolean')) {
1085
+ result[field.id].splice(arrIndex, 1, arr === true ? 'True' : 'False');
1086
+ }
1087
+ else if (field.fieldType === 'Boolean' && field.leafFormatType === 'String') {
1088
+ result[field.id].splice(arrIndex, 1, arr === true ? 'Yes' : 'No');
1089
+ }
1090
+ else if (field.fieldType === 'Boolean' && field.leafFormatType === 'Boolean_Number') {
1091
+ result[field.id].splice(arrIndex, 1, arr === true ? 1 : 0);
1092
+ }
1093
+ else if (field.fieldType === 'Date' && (field.leafFormatType === 'Date')) {
1094
+ result[field.id].splice(arrIndex, 1, moment(arr).format('L'));
1095
+ }
1096
+ else if (field.fieldType === 'Date' && field.leafFormatType === 'Time') {
1097
+ result[field.id].splice(arrIndex, 1, moment(arr).format('LT'));
1098
+ }
1099
+ else if (field.fieldType === 'Date' && field.leafFormatType === 'DateTime') {
1100
+ result[field.id].splice(arrIndex, 1, moment(arr).format('MM/DD/YYYY h:mm A'));
1101
+ }
1102
+ else if (field.fieldType === 'Date' && field.leafFormatType === 'Date_long') {
1103
+ result[field.id].splice(arrIndex, 1, moment(arr).format('LL'));
1104
+ }
1105
+ else if (field.fieldType === 'Date' && field.leafFormatType === 'DateTime_long') {
1106
+ result[field.id].splice(arrIndex, 1, moment(arr).format('LLL'));
1107
+ }
1108
+ else if (field.fieldType === 'Date' && field.leafFormatType === 'Timestamp') {
1109
+ result[field.id].splice(arrIndex, 1, moment(arr).toDate().getTime());
1110
+ }
1111
+ });
1112
+ }
1113
+ else {
1114
+ if ((field.fieldType === 'Number' || field.leafValueType === 'Count') && field.leafFormatType === 'Number') {
1115
+ result[field.id] = result[field.id].toLocaleString();
1116
+ }
1117
+ else if ((field.fieldType === 'Number' || field.leafValueType === 'Count') && field.leafFormatType === 'String') {
1118
+ result[field.id] = result[field.id].toString();
1119
+ }
1120
+ else if ((field.fieldType === 'Number' || field.leafValueType === 'Count') && field.leafFormatType === 'Currency') {
1121
+ result[field.id] = result[field.id].toLocaleString('en-US', { style: 'currency', currency: 'USD' });
1122
+ }
1123
+ else if (field.fieldType === 'Boolean' && (!field.leafFormatType || field.leafFormatType === 'Boolean')) {
1124
+ result[field.id] = result[field.id] === true ? 'True' : 'False';
1125
+ }
1126
+ else if (field.fieldType === 'Boolean' && field.leafFormatType === 'String') {
1127
+ result[field.id] = result[field.id] === true ? 'Yes' : 'No';
1128
+ }
1129
+ else if (field.fieldType === 'Boolean' && field.leafFormatType === 'Boolean_Number') {
1130
+ result[field.id] = result[field.id] === true ? 1 : 0;
1131
+ }
1132
+ else if (field.fieldType === 'Date' && (field.leafFormatType === 'Date')) {
1133
+ result[field.id] = moment(result[field.id]).format('L');
1134
+ }
1135
+ else if (field.fieldType === 'Date' && field.leafFormatType === 'Time') {
1136
+ result[field.id] = moment(result[field.id]).format('LT');
1137
+ }
1138
+ else if (field.fieldType === 'Date' && field.leafFormatType === 'DateTime') {
1139
+ result[field.id] = moment(result[field.id]).format('MM/DD/YYYY h:mm A');
1140
+ }
1141
+ else if (field.fieldType === 'Date' && field.leafFormatType === 'Date_long') {
1142
+ result[field.id] = moment(result[field.id]).format('LL');
1143
+ }
1144
+ else if (field.fieldType === 'Date' && field.leafFormatType === 'DateTime_long') {
1145
+ result[field.id] = moment(result[field.id]).format('LLL');
1146
+ }
1147
+ else if (field.fieldType === 'Date' && field.leafFormatType === 'Timestamp') {
1148
+ result[field.id] = moment(result[field.id]).toDate().getTime();
1149
+ }
1150
+ }
1151
+ }
1152
+ }
1153
+
1154
+ function tabGroupExcelRecursive(report, ws: Excel.Worksheet, currentRow, level, result) {
1155
+ let row = ws.getRow(currentRow);
1156
+
1157
+ if (level < report.groups_row.length) {
1158
+ row.getCell(2).fill = {
1159
+ fgColor: {argb: report.groups_row[level - 1].fill_color ? report.groups_row[level - 1].fill_color.replace('#', '') : 'ffffff'},
1160
+ type: 'pattern',
1161
+ pattern: 'solid'
1162
+ };
1163
+ row.getCell(2).font = {
1164
+ color: {argb: report.groups_row[level - 1].font_color ? report.groups_row[level - 1].font_color.replace('#', '') : '000000'},
1165
+ name: 'Arial',
1166
+ bold: true,
1167
+ size: 14
1168
+ };
1169
+
1170
+ row.getCell(2).value = report.groups_row[level - 1].columnName + ': ' + result._id['gr_' + level];
1171
+ ws.mergeCells(row.getCell(2).$col$row + ':' + row.getCell(report.fields_selected.filter(a => a.show).length + 1).$col$row);
1172
+
1173
+ row.getCell(2).border = {
1174
+ top: {style:'thick'},
1175
+ left: {style:'thick'},
1176
+ right: {style: 'thick'}
1177
+ };
1178
+
1179
+ if (report.fields_total.length) {
1180
+ report.fields_total.forEach(total => {
1181
+ currentRow += 1;
1182
+ row = ws.getRow(currentRow);
1183
+
1184
+ report.fields_selected.filter(a => a.show).forEach((field, fieldIndex) => {
1185
+ if (total.fields.includes(field.id)) {
1186
+ row.getCell(fieldIndex + 2).value = field.columnName;
1187
+
1188
+ row.getCell(fieldIndex + 2).font = {
1189
+ name: 'Arial',
1190
+ bold: true,
1191
+ size: 10
1192
+ };
1193
+ }
1194
+
1195
+ if (field.leafFormatType === 'Currency') {
1196
+ row.getCell(fieldIndex + 2).numFmt = '"$"#,##0.00';
1197
+ }
1198
+ else if (field.leafFormatType === 'Number') {
1199
+ row.getCell(fieldIndex + 2).numFmt = '#,##0';
1200
+ }
1201
+
1202
+ if (fieldIndex === 0) {
1203
+ row.getCell(fieldIndex + 2).border = {
1204
+ left: {style:'thick'}
1205
+ };
1206
+ }
1207
+ else if (fieldIndex === report.fields_selected.filter(a => a.show).length - 1) {
1208
+ row.getCell(fieldIndex + 2).border = {
1209
+ right: {style:'thick'}
1210
+ };
1211
+ }
1212
+ });
1213
+ });
1214
+ }
1215
+
1216
+ // Totals
1217
+ report.fields_total.forEach(total => {
1218
+ currentRow += 1;
1219
+ row = ws.getRow(currentRow);
1220
+
1221
+ report.fields_selected.filter(a => a.show).forEach((field, fieldIndex) => {
1222
+ if (total.fields.includes(field.id)) {
1223
+ row.getCell(fieldIndex + 2).value = result[total.id + '_' + field.id];
1224
+
1225
+ row.getCell(fieldIndex + 2).font = {
1226
+ name: 'Arial',
1227
+ bold: true,
1228
+ size: 10
1229
+ };
1230
+
1231
+ if (field.leafFormatType === 'Currency') {
1232
+ row.getCell(fieldIndex + 2).numFmt = '"$"#,##0.00';
1233
+ }
1234
+ else if (field.leafFormatType === 'Number') {
1235
+ row.getCell(fieldIndex + 2).numFmt = '#,##0';
1236
+ }
1237
+ }
1238
+
1239
+ if (fieldIndex === 0) {
1240
+ row.getCell(fieldIndex + 2).border = {
1241
+ top: {style:'thin'},
1242
+ left: {style:'thick'},
1243
+ bottom: {style:'thick'}
1244
+ };
1245
+ }
1246
+ else if (fieldIndex === report.fields_selected.filter(a => a.show).length - 1) {
1247
+ row.getCell(fieldIndex + 2).border = {
1248
+ top: {style:'thin'},
1249
+ bottom: {style:'thick'},
1250
+ right: {style:'thick'}
1251
+ };
1252
+ }
1253
+ else {
1254
+ row.getCell(fieldIndex + 2).border = {
1255
+ top: {style:'thin'},
1256
+ bottom: {style:'thick'}
1257
+ };
1258
+ }
1259
+ });
1260
+ });
1261
+
1262
+ currentRow += 1;
1263
+
1264
+ result = result['gr_' + (level + 1)];
1265
+ result.forEach((tDataRes, tIndex) => {
1266
+ currentRow = tabGroupExcelRecursive(report, ws, currentRow, level + 1, tDataRes);
1267
+ });
1268
+ }
1269
+ else {
1270
+ row.getCell(2).fill = {
1271
+ fgColor: {argb: report.groups_row[level - 1].fill_color ? report.groups_row[level - 1].fill_color.replace('#', '') : 'ffffff'},
1272
+ type: 'pattern',
1273
+ pattern: 'solid'
1274
+ };
1275
+ row.getCell(2).font = {
1276
+ color: {argb: report.groups_row[level - 1].font_color ? report.groups_row[level - 1].font_color.replace('#', '') : '000000'},
1277
+ name: 'Arial',
1278
+ bold: true,
1279
+ size: 12
1280
+ };
1281
+
1282
+ row.getCell(2).value = report.groups_row[level - 1].columnName + ': ' + result._id['gr_' + level];
1283
+ ws.mergeCells(row.getCell(2).$col$row + ':' + row.getCell(report.fields_selected.filter(a => a.show).length + 1).$col$row);
1284
+
1285
+ row.getCell(2).border = {
1286
+ top: {style:'thick'},
1287
+ left: {style:'thick'},
1288
+ right: {style: 'thick'}
1289
+ };
1290
+
1291
+ currentRow += 1;
1292
+ row = ws.getRow(currentRow);
1293
+ // Headers
1294
+ report.fields_selected.filter(a => a.show).forEach((field, fieldIndex) => {
1295
+ row.getCell(fieldIndex + 2).value = field.columnName;
1296
+ row.getCell(fieldIndex + 2).font = {
1297
+ name: 'Arial',
1298
+ bold: true,
1299
+ size: 10
1300
+ };
1301
+
1302
+ if (field.leafFormatType === 'Currency') {
1303
+ row.getCell(fieldIndex + 2).numFmt = '"$"#,##0.00';
1304
+ }
1305
+ else if (field.leafFormatType === 'Number') {
1306
+ row.getCell(fieldIndex + 2).numFmt = '#,##0';
1307
+ }
1308
+
1309
+ if (fieldIndex === 0) {
1310
+ row.getCell(fieldIndex + 2).border = {
1311
+ left: {style:'thick'}
1312
+ };
1313
+ }
1314
+ else if (fieldIndex === report.fields_selected.filter(a => a.show).length - 1) {
1315
+ row.getCell(fieldIndex + 2).border = {
1316
+ right: {style:'thick'}
1317
+ };
1318
+ }
1319
+ });
1320
+
1321
+ // Data
1322
+ result['f_0'].forEach((res, resIndex) => {
1323
+ currentRow += 1;
1324
+ row = ws.getRow(currentRow);
1325
+
1326
+ report.fields_selected.filter(a => a.show).forEach((field, fieldIndex) => {
1327
+ if (field.fieldType === 'Number' && typeof(result[field.id][resIndex] === 'string') && result[field.id][resIndex]) {
1328
+ row.getCell(fieldIndex + 2).value = parseFloat(result[field.id][resIndex].replace(new RegExp(/\,/g), '').replace(new RegExp(/\$/g), ''));
1329
+ }
1330
+ else {
1331
+ row.getCell(fieldIndex + 2).value = result[field.id][resIndex];
1332
+ }
1333
+
1334
+ if (field.leafFormatType === 'Currency') {
1335
+ row.getCell(fieldIndex + 2).numFmt = '"$"#,##0.00';
1336
+ }
1337
+ else if (field.leafFormatType === 'Number') {
1338
+ row.getCell(fieldIndex + 2).numFmt = '#,##0';
1339
+ }
1340
+
1341
+ row.getCell(fieldIndex + 2).font = {
1342
+ name: 'Arial',
1343
+ size: 10
1344
+ };
1345
+
1346
+ if (fieldIndex === 0) {
1347
+ row.getCell(fieldIndex + 2).border = {
1348
+ left: {style:'thick'}
1349
+ };
1350
+ }
1351
+ else if (fieldIndex === report.fields_selected.filter(a => a.show).length - 1) {
1352
+ row.getCell(fieldIndex + 2).border = {
1353
+ right: {style:'thick'}
1354
+ };
1355
+ }
1356
+ });
1357
+ });
1358
+
1359
+ // Totals
1360
+ report.fields_total.forEach(total => {
1361
+ currentRow += 1;
1362
+ row = ws.getRow(currentRow);
1363
+
1364
+ report.fields_selected.filter(a => a.show).forEach((field, fieldIndex) => {
1365
+ if (total.fields.includes(field.id)) {
1366
+ row.getCell(fieldIndex + 2).value = result[total.id + '_' + field.id];
1367
+
1368
+ row.getCell(fieldIndex + 2).font = {
1369
+ name: 'Arial',
1370
+ bold: true,
1371
+ size: 10
1372
+ };
1373
+
1374
+ if (field.leafFormatType === 'Currency') {
1375
+ row.getCell(fieldIndex + 2).numFmt = '"$"#,##0.00';
1376
+ }
1377
+ else if (field.leafFormatType === 'Number') {
1378
+ row.getCell(fieldIndex + 2).numFmt = '#,##0';
1379
+ }
1380
+ }
1381
+
1382
+ if (fieldIndex === 0) {
1383
+ row.getCell(fieldIndex + 2).border = {
1384
+ top: {style:'thin'},
1385
+ left: {style:'thick'},
1386
+ bottom: {style:'thick'}
1387
+ };
1388
+ }
1389
+ else if (fieldIndex === report.fields_selected.filter(a => a.show).length - 1) {
1390
+ row.getCell(fieldIndex + 2).border = {
1391
+ top: {style:'thin'},
1392
+ bottom: {style:'thick'},
1393
+ right: {style:'thick'}
1394
+ };
1395
+ }
1396
+ else {
1397
+ row.getCell(fieldIndex + 2).border = {
1398
+ top: {style:'thin'},
1399
+ bottom: {style:'thick'}
1400
+ };
1401
+ }
1402
+ });
1403
+ });
1404
+ }
1405
+
1406
+ return currentRow + 1;
1407
+ }
1408
+
1409
+ function tabGroupExcelWidthRecursive(report, level, result, cols) {
1410
+ if (level < report.groups_row.length) {
1411
+ result = result['gr_' + (level + 1)];
1412
+ result.forEach((tDataRes, tIndex) => {
1413
+ cols = tabGroupExcelWidthRecursive(report, level + 1, tDataRes, cols);
1414
+ });
1415
+ }
1416
+ else {
1417
+ report.fields_selected.filter(a => a.show).forEach((field, fieldIndex) => {
1418
+ if (Array.isArray(result[field.id])) {
1419
+ result[field.id].forEach(res => {
1420
+ let length = 10;
1421
+
1422
+ if (res) {
1423
+ length = res.length + 3;
1424
+ }
1425
+
1426
+ if (!cols[fieldIndex]) {
1427
+ cols[fieldIndex] = Math.max(10, field.columnName.length);
1428
+ }
1429
+
1430
+ if (length > cols[fieldIndex]) {
1431
+ cols[fieldIndex] = length;
1432
+ }
1433
+ });
1434
+ }
1435
+ else {
1436
+ let res = result[field.id];
1437
+
1438
+ if (res) {
1439
+ length = res.length + 3;
1440
+ }
1441
+
1442
+ if (!cols[fieldIndex]) {
1443
+ cols[fieldIndex] = Math.max(10, field.columnName.length);
1444
+ }
1445
+
1446
+ if (length > cols[fieldIndex]) {
1447
+ cols[fieldIndex] = length;
1448
+ }
1449
+ }
1450
+ });
1451
+ }
1452
+
1453
+ return cols;
1454
+ }