@things-factory/kpi 9.0.31 → 9.0.33

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 (365) hide show
  1. package/README.md +1 -2
  2. package/client/charts/kpi-boxplot-chart.ts +182 -42
  3. package/client/charts/kpi-radar-chart.ts +9 -9
  4. package/client/pages/kpi/kpi-list-page.ts +196 -32
  5. package/client/pages/kpi/kpi-overview.ts +9 -11
  6. package/client/pages/kpi/kpi-tree-page.ts +409 -0
  7. package/client/pages/kpi/kpi-view.ts +187 -0
  8. package/client/pages/kpi-dashboard/cards/kpi-level1-card.ts +1 -1
  9. package/client/pages/kpi-dashboard/cards/kpi-level2-comparison.ts +1 -1
  10. package/client/pages/kpi-dashboard/cards/kpi-level3-comparison.ts +1 -1
  11. package/client/pages/kpi-dashboard/components/kpi-left-panel.ts +198 -160
  12. package/client/pages/kpi-dashboard/components/kpi-map-panel.ts +133 -0
  13. package/client/pages/kpi-dashboard/components/kpi-region-popup.ts +3 -2
  14. package/client/pages/kpi-dashboard/kpi-dashboard-map.ts +291 -48
  15. package/client/pages/kpi-dashboard/kpi-dashboard.ts +28 -30
  16. package/client/pages/kpi-history/kpi-history-list-page.ts +11 -11
  17. package/client/pages/kpi-metric/kpi-metric-list-page.ts +10 -2
  18. package/client/pages/kpi-metric-value/kpi-metric-value-editor-page.ts +7 -7
  19. package/client/pages/kpi-metric-value/kpi-metric-value-importer.ts +2 -2
  20. package/client/pages/kpi-metric-value/kpi-metric-value-list-page.ts +16 -8
  21. package/client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.ts +5 -5
  22. package/client/pages/kpi-statistic/kpi-statistic-editor-page.ts +1 -2
  23. package/client/pages/kpi-statistic/kpi-statistic-list-page.ts +10 -2
  24. package/client/pages/kpi-value/kpi-value-editor-page.ts +11 -7
  25. package/client/pages/kpi-value/kpi-value-list-page.ts +31 -7
  26. package/client/route.ts +2 -9
  27. package/design-entities.md +8 -12
  28. package/dist-client/charts/kpi-boxplot-chart.d.ts +2 -0
  29. package/dist-client/charts/kpi-boxplot-chart.js +168 -42
  30. package/dist-client/charts/kpi-boxplot-chart.js.map +1 -1
  31. package/dist-client/charts/kpi-radar-chart.js +9 -9
  32. package/dist-client/charts/kpi-radar-chart.js.map +1 -1
  33. package/dist-client/pages/kpi/kpi-list-page.d.ts +19 -3
  34. package/dist-client/pages/kpi/kpi-list-page.js +188 -32
  35. package/dist-client/pages/kpi/kpi-list-page.js.map +1 -1
  36. package/dist-client/pages/kpi/kpi-overview.js +9 -11
  37. package/dist-client/pages/kpi/kpi-overview.js.map +1 -1
  38. package/dist-client/pages/kpi/kpi-tree-page.d.ts +59 -0
  39. package/dist-client/pages/kpi/kpi-tree-page.js +403 -0
  40. package/dist-client/pages/kpi/kpi-tree-page.js.map +1 -0
  41. package/dist-client/pages/kpi/kpi-view.d.ts +12 -0
  42. package/dist-client/pages/kpi/kpi-view.js +191 -0
  43. package/dist-client/pages/kpi/kpi-view.js.map +1 -0
  44. package/dist-client/pages/kpi-dashboard/cards/kpi-level1-card.js +1 -1
  45. package/dist-client/pages/kpi-dashboard/cards/kpi-level1-card.js.map +1 -1
  46. package/dist-client/pages/kpi-dashboard/cards/kpi-level2-comparison.js +1 -1
  47. package/dist-client/pages/kpi-dashboard/cards/kpi-level2-comparison.js.map +1 -1
  48. package/dist-client/pages/kpi-dashboard/cards/kpi-level3-comparison.js +1 -1
  49. package/dist-client/pages/kpi-dashboard/cards/kpi-level3-comparison.js.map +1 -1
  50. package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.d.ts +3 -1
  51. package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.js +197 -161
  52. package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.js.map +1 -1
  53. package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.d.ts +5 -0
  54. package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js +146 -0
  55. package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js.map +1 -1
  56. package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.js +3 -2
  57. package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.js.map +1 -1
  58. package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.d.ts +3 -1
  59. package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js +268 -46
  60. package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js.map +1 -1
  61. package/dist-client/pages/kpi-dashboard/kpi-dashboard.js +28 -30
  62. package/dist-client/pages/kpi-dashboard/kpi-dashboard.js.map +1 -1
  63. package/dist-client/pages/kpi-history/kpi-history-list-page.d.ts +6 -1
  64. package/dist-client/pages/kpi-history/kpi-history-list-page.js +11 -11
  65. package/dist-client/pages/kpi-history/kpi-history-list-page.js.map +1 -1
  66. package/dist-client/pages/kpi-metric/kpi-metric-list-page.d.ts +5 -0
  67. package/dist-client/pages/kpi-metric/kpi-metric-list-page.js +10 -2
  68. package/dist-client/pages/kpi-metric/kpi-metric-list-page.js.map +1 -1
  69. package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.d.ts +1 -1
  70. package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.js +8 -8
  71. package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.js.map +1 -1
  72. package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.js +2 -2
  73. package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.js.map +1 -1
  74. package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.d.ts +5 -0
  75. package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js +16 -8
  76. package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js.map +1 -1
  77. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.d.ts +1 -1
  78. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.js +6 -6
  79. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.js.map +1 -1
  80. package/dist-client/pages/kpi-statistic/kpi-statistic-editor-page.js +1 -2
  81. package/dist-client/pages/kpi-statistic/kpi-statistic-editor-page.js.map +1 -1
  82. package/dist-client/pages/kpi-statistic/kpi-statistic-list-page.d.ts +5 -0
  83. package/dist-client/pages/kpi-statistic/kpi-statistic-list-page.js +10 -2
  84. package/dist-client/pages/kpi-statistic/kpi-statistic-list-page.js.map +1 -1
  85. package/dist-client/pages/kpi-value/kpi-value-editor-page.d.ts +2 -1
  86. package/dist-client/pages/kpi-value/kpi-value-editor-page.js +16 -8
  87. package/dist-client/pages/kpi-value/kpi-value-editor-page.js.map +1 -1
  88. package/dist-client/pages/kpi-value/kpi-value-list-page.d.ts +5 -0
  89. package/dist-client/pages/kpi-value/kpi-value-list-page.js +31 -7
  90. package/dist-client/pages/kpi-value/kpi-value-list-page.js.map +1 -1
  91. package/dist-client/route.d.ts +1 -1
  92. package/dist-client/route.js +2 -8
  93. package/dist-client/route.js.map +1 -1
  94. package/dist-client/tsconfig.tsbuildinfo +1 -1
  95. package/dist-server/controllers/kpi-metric-value-provider.d.ts +1 -1
  96. package/dist-server/controllers/kpi-metric-value-provider.js +4 -4
  97. package/dist-server/controllers/kpi-metric-value-provider.js.map +1 -1
  98. package/dist-server/controllers/kpi-value-provider.d.ts +1 -1
  99. package/dist-server/controllers/kpi-value-provider.js +3 -3
  100. package/dist-server/controllers/kpi-value-provider.js.map +1 -1
  101. package/dist-server/migrations/1752190849680-seed-kpi-metrics.d.ts +6 -0
  102. package/dist-server/migrations/1752190849680-seed-kpi-metrics.js +101 -0
  103. package/dist-server/migrations/1752190849680-seed-kpi-metrics.js.map +1 -0
  104. package/dist-server/migrations/1752190849681-seed-kpi.d.ts +5 -0
  105. package/dist-server/migrations/1752190849681-seed-kpi.js +315 -0
  106. package/dist-server/migrations/1752190849681-seed-kpi.js.map +1 -0
  107. package/dist-server/migrations/1752192090123-add-grades-to-kpi.d.ts +7 -0
  108. package/dist-server/migrations/1752192090123-add-grades-to-kpi.js +51 -0
  109. package/dist-server/migrations/1752192090123-add-grades-to-kpi.js.map +1 -0
  110. package/dist-server/migrations/1752192090124-add-kpi-statistics.d.ts +5 -0
  111. package/dist-server/migrations/1752192090124-add-kpi-statistics.js +710 -0
  112. package/dist-server/migrations/1752192090124-add-kpi-statistics.js.map +1 -0
  113. package/dist-server/migrations/1752192090128-seed-kpi-org-scope.d.ts +6 -0
  114. package/dist-server/migrations/1752192090128-seed-kpi-org-scope.js +111 -0
  115. package/dist-server/migrations/1752192090128-seed-kpi-org-scope.js.map +1 -0
  116. package/dist-server/migrations/1752192090129-seed-kpi-values.d.ts +6 -0
  117. package/dist-server/migrations/1752192090129-seed-kpi-values.js +187 -0
  118. package/dist-server/migrations/1752192090129-seed-kpi-values.js.map +1 -0
  119. package/dist-server/migrations/grade-data/x11-performance-table.json +962 -0
  120. package/dist-server/migrations/grade-data/x12-performance-table.json +611 -0
  121. package/dist-server/migrations/grade-data/x14-performance-table.json +42 -0
  122. package/dist-server/migrations/grade-data/x21-performance-table.json +889 -0
  123. package/dist-server/migrations/grade-data/x22-performance-table.json +1064 -0
  124. package/dist-server/migrations/grade-data/x23-performance-table.json +42 -0
  125. package/dist-server/migrations/grade-data/x31-performance-table.json +644 -0
  126. package/dist-server/migrations/grade-data/x32-performance-table.json +993 -0
  127. package/dist-server/migrations/grade-data/x33-performance-table.json +195 -0
  128. package/dist-server/migrations/grade-data/x34-performance-table.json +12 -0
  129. package/dist-server/migrations/grade-data/x35-performance-table.json +42 -0
  130. package/dist-server/migrations/grade-data/x41-performance-table.json +825 -0
  131. package/dist-server/migrations/grade-data/x42-performance-table.json +786 -0
  132. package/dist-server/migrations/grade-data/x43-performance-table.json +12 -0
  133. package/dist-server/migrations/grade-data/x44-performance-table.json +42 -0
  134. package/dist-server/migrations/grade-data/x51-performance-table.json +924 -0
  135. package/dist-server/migrations/grade-data/x52-performance-table.json +42 -0
  136. package/dist-server/migrations/grade-data/x61-performance-table.json +261 -0
  137. package/dist-server/migrations/grade-data/x62-performance-table.json +42 -0
  138. package/dist-server/migrations/seed-data/kpi-metrics-seed.json +454 -0
  139. package/dist-server/migrations/seed-data/kpi-org-scope-seed.json +1676 -0
  140. package/dist-server/migrations/seed-data/kpi-scopes-seed.json +121 -0
  141. package/dist-server/migrations/seed-data/kpi-values-seed.json +402 -0
  142. package/dist-server/migrations/seed-data/kpis-seed.json +488 -0
  143. package/dist-server/migrations/seed-data/scope-definitions-seed.json +90 -0
  144. package/dist-server/service/index.d.ts +4 -7
  145. package/dist-server/service/index.js +10 -13
  146. package/dist-server/service/index.js.map +1 -1
  147. package/dist-server/service/kpi/aggregate-kpi.js +30 -13
  148. package/dist-server/service/kpi/aggregate-kpi.js.map +1 -1
  149. package/dist-server/service/kpi/kpi-formula.service.d.ts +15 -0
  150. package/dist-server/service/kpi/kpi-formula.service.js +90 -0
  151. package/dist-server/service/kpi/kpi-formula.service.js.map +1 -1
  152. package/dist-server/service/kpi/kpi-history.d.ts +0 -3
  153. package/dist-server/service/kpi/kpi-history.js +0 -10
  154. package/dist-server/service/kpi/kpi-history.js.map +1 -1
  155. package/dist-server/service/kpi/kpi-mutation.d.ts +1 -1
  156. package/dist-server/service/kpi/kpi-mutation.js +57 -20
  157. package/dist-server/service/kpi/kpi-mutation.js.map +1 -1
  158. package/dist-server/service/kpi/kpi-query.d.ts +7 -3
  159. package/dist-server/service/kpi/kpi-query.js +126 -10
  160. package/dist-server/service/kpi/kpi-query.js.map +1 -1
  161. package/dist-server/service/kpi/kpi-type.d.ts +4 -2
  162. package/dist-server/service/kpi/kpi-type.js +12 -4
  163. package/dist-server/service/kpi/kpi-type.js.map +1 -1
  164. package/dist-server/service/kpi/kpi.d.ts +4 -3
  165. package/dist-server/service/kpi/kpi.js +20 -8
  166. package/dist-server/service/kpi/kpi.js.map +1 -1
  167. package/dist-server/service/kpi-metric/aggregate-kpi-metric.js +46 -11
  168. package/dist-server/service/kpi-metric/aggregate-kpi-metric.js.map +1 -1
  169. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.d.ts +1 -1
  170. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js +6 -6
  171. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js.map +1 -1
  172. package/dist-server/service/kpi-metric-value/kpi-metric-value-type.d.ts +2 -2
  173. package/dist-server/service/kpi-metric-value/kpi-metric-value-type.js +4 -4
  174. package/dist-server/service/kpi-metric-value/kpi-metric-value-type.js.map +1 -1
  175. package/dist-server/service/kpi-metric-value/kpi-metric-value.d.ts +1 -1
  176. package/dist-server/service/kpi-metric-value/kpi-metric-value.js +3 -3
  177. package/dist-server/service/kpi-metric-value/kpi-metric-value.js.map +1 -1
  178. package/dist-server/service/kpi-org-scope/index.d.ts +5 -0
  179. package/dist-server/service/kpi-org-scope/index.js +9 -0
  180. package/dist-server/service/kpi-org-scope/index.js.map +1 -0
  181. package/dist-server/service/kpi-org-scope/kpi-org-scope-mutation.d.ts +8 -0
  182. package/dist-server/service/kpi-org-scope/kpi-org-scope-mutation.js +170 -0
  183. package/dist-server/service/kpi-org-scope/kpi-org-scope-mutation.js.map +1 -0
  184. package/dist-server/service/kpi-org-scope/kpi-org-scope-query.d.ts +14 -0
  185. package/dist-server/service/kpi-org-scope/kpi-org-scope-query.js +152 -0
  186. package/dist-server/service/kpi-org-scope/kpi-org-scope-query.js.map +1 -0
  187. package/dist-server/service/kpi-org-scope/kpi-org-scope-type.d.ts +26 -0
  188. package/dist-server/service/kpi-org-scope/kpi-org-scope-type.js +101 -0
  189. package/dist-server/service/kpi-org-scope/kpi-org-scope-type.js.map +1 -0
  190. package/dist-server/service/kpi-org-scope/kpi-org-scope.d.ts +26 -0
  191. package/dist-server/service/kpi-org-scope/kpi-org-scope.js +135 -0
  192. package/dist-server/service/kpi-org-scope/kpi-org-scope.js.map +1 -0
  193. package/dist-server/service/kpi-scope/index.d.ts +9 -0
  194. package/dist-server/service/kpi-scope/index.js +14 -0
  195. package/dist-server/service/kpi-scope/index.js.map +1 -0
  196. package/dist-server/service/kpi-scope/kpi-scope-mutation.d.ts +9 -0
  197. package/dist-server/service/kpi-scope/kpi-scope-mutation.js +135 -0
  198. package/dist-server/service/kpi-scope/kpi-scope-mutation.js.map +1 -0
  199. package/dist-server/service/kpi-scope/kpi-scope-query.d.ts +11 -0
  200. package/dist-server/service/kpi-scope/kpi-scope-query.js +89 -0
  201. package/dist-server/service/kpi-scope/kpi-scope-query.js.map +1 -0
  202. package/dist-server/service/kpi-scope/kpi-scope-type.d.ts +35 -0
  203. package/dist-server/service/kpi-scope/kpi-scope-type.js +138 -0
  204. package/dist-server/service/kpi-scope/kpi-scope-type.js.map +1 -0
  205. package/dist-server/service/kpi-scope/kpi-scope.d.ts +38 -0
  206. package/dist-server/service/kpi-scope/kpi-scope.js +144 -0
  207. package/dist-server/service/kpi-scope/kpi-scope.js.map +1 -0
  208. package/dist-server/service/kpi-statistic/kpi-statistic-batch.service.d.ts +43 -0
  209. package/dist-server/service/kpi-statistic/kpi-statistic-batch.service.js +181 -0
  210. package/dist-server/service/kpi-statistic/kpi-statistic-batch.service.js.map +1 -0
  211. package/dist-server/service/kpi-statistic/kpi-statistic-calculation.service.d.ts +50 -0
  212. package/dist-server/service/kpi-statistic/kpi-statistic-calculation.service.js +324 -0
  213. package/dist-server/service/kpi-statistic/kpi-statistic-calculation.service.js.map +1 -0
  214. package/dist-server/service/kpi-statistic/kpi-statistic-mutation.d.ts +4 -0
  215. package/dist-server/service/kpi-statistic/kpi-statistic-mutation.js +76 -0
  216. package/dist-server/service/kpi-statistic/kpi-statistic-mutation.js.map +1 -1
  217. package/dist-server/service/kpi-statistic/kpi-statistic-query.d.ts +5 -1
  218. package/dist-server/service/kpi-statistic/kpi-statistic-query.js +92 -1
  219. package/dist-server/service/kpi-statistic/kpi-statistic-query.js.map +1 -1
  220. package/dist-server/service/kpi-statistic/kpi-statistic.d.ts +4 -0
  221. package/dist-server/service/kpi-statistic/kpi-statistic.js +33 -0
  222. package/dist-server/service/kpi-statistic/kpi-statistic.js.map +1 -1
  223. package/dist-server/service/kpi-value/kpi-value-mutation.js +71 -7
  224. package/dist-server/service/kpi-value/kpi-value-mutation.js.map +1 -1
  225. package/dist-server/service/kpi-value/kpi-value-type.d.ts +4 -2
  226. package/dist-server/service/kpi-value/kpi-value-type.js +12 -4
  227. package/dist-server/service/kpi-value/kpi-value-type.js.map +1 -1
  228. package/dist-server/service/kpi-value/kpi-value.d.ts +3 -1
  229. package/dist-server/service/kpi-value/kpi-value.js +11 -5
  230. package/dist-server/service/kpi-value/kpi-value.js.map +1 -1
  231. package/dist-server/service/utils/value-date-util.d.ts +1 -0
  232. package/dist-server/service/utils/value-date-util.js +41 -0
  233. package/dist-server/service/utils/value-date-util.js.map +1 -1
  234. package/dist-server/tsconfig.json +10 -0
  235. package/dist-server/tsconfig.tsbuildinfo +1 -1
  236. package/package.json +7 -6
  237. package/server/@types/index.d.ts +11 -0
  238. package/server/controllers/kpi-metric-value-provider.ts +5 -5
  239. package/server/controllers/kpi-value-provider.ts +4 -4
  240. package/server/migrations/1752190849680-seed-kpi-metrics.ts +124 -0
  241. package/server/migrations/1752190849681-seed-kpi.ts +356 -0
  242. package/server/migrations/1752192090123-add-grades-to-kpi.ts +67 -0
  243. package/server/migrations/1752192090124-add-kpi-statistics.ts +719 -0
  244. package/server/migrations/1752192090128-seed-kpi-org-scope.ts +132 -0
  245. package/server/migrations/1752192090129-seed-kpi-values.ts +207 -0
  246. package/server/migrations/grade-data/x11-performance-table.json +962 -0
  247. package/server/migrations/grade-data/x12-performance-table.json +611 -0
  248. package/server/migrations/grade-data/x14-performance-table.json +42 -0
  249. package/server/migrations/grade-data/x21-performance-table.json +889 -0
  250. package/server/migrations/grade-data/x22-performance-table.json +1064 -0
  251. package/server/migrations/grade-data/x23-performance-table.json +42 -0
  252. package/server/migrations/grade-data/x31-performance-table.json +644 -0
  253. package/server/migrations/grade-data/x32-performance-table.json +993 -0
  254. package/server/migrations/grade-data/x33-performance-table.json +195 -0
  255. package/server/migrations/grade-data/x34-performance-table.json +12 -0
  256. package/server/migrations/grade-data/x35-performance-table.json +42 -0
  257. package/server/migrations/grade-data/x41-performance-table.json +825 -0
  258. package/server/migrations/grade-data/x42-performance-table.json +786 -0
  259. package/server/migrations/grade-data/x43-performance-table.json +12 -0
  260. package/server/migrations/grade-data/x44-performance-table.json +42 -0
  261. package/server/migrations/grade-data/x51-performance-table.json +924 -0
  262. package/server/migrations/grade-data/x52-performance-table.json +42 -0
  263. package/server/migrations/grade-data/x61-performance-table.json +261 -0
  264. package/server/migrations/grade-data/x62-performance-table.json +42 -0
  265. package/server/migrations/seed-data/kpi-metrics-seed.json +454 -0
  266. package/server/migrations/seed-data/kpi-org-scope-seed.json +1676 -0
  267. package/server/migrations/seed-data/kpi-scopes-seed.json +121 -0
  268. package/server/migrations/seed-data/kpi-values-seed.json +402 -0
  269. package/server/migrations/seed-data/kpis-seed.json +488 -0
  270. package/server/migrations/seed-data/scope-definitions-seed.json +90 -0
  271. package/server/service/index.ts +10 -13
  272. package/server/service/kpi/aggregate-kpi.ts +31 -13
  273. package/server/service/kpi/kpi-formula.service.ts +101 -0
  274. package/server/service/kpi/kpi-history.ts +0 -8
  275. package/server/service/kpi/kpi-mutation.ts +59 -19
  276. package/server/service/kpi/kpi-query.ts +119 -8
  277. package/server/service/kpi/kpi-type.ts +10 -4
  278. package/server/service/kpi/kpi.ts +17 -7
  279. package/server/service/kpi-metric/aggregate-kpi-metric.ts +55 -11
  280. package/server/service/kpi-metric-value/kpi-metric-value-mutation.ts +6 -6
  281. package/server/service/kpi-metric-value/kpi-metric-value-type.ts +4 -4
  282. package/server/service/kpi-metric-value/kpi-metric-value.ts +3 -3
  283. package/server/service/kpi-org-scope/index.ts +6 -0
  284. package/server/service/kpi-org-scope/kpi-org-scope-mutation.ts +173 -0
  285. package/server/service/kpi-org-scope/kpi-org-scope-query.ts +127 -0
  286. package/server/service/kpi-org-scope/kpi-org-scope-type.ts +68 -0
  287. package/server/service/kpi-org-scope/kpi-org-scope.ts +123 -0
  288. package/server/service/kpi-scope/index.ts +11 -0
  289. package/server/service/kpi-scope/kpi-scope-mutation.ts +129 -0
  290. package/server/service/kpi-scope/kpi-scope-query.ts +63 -0
  291. package/server/service/kpi-scope/kpi-scope-type.ts +96 -0
  292. package/server/service/kpi-scope/kpi-scope.ts +143 -0
  293. package/server/service/kpi-statistic/kpi-statistic-batch.service.ts +231 -0
  294. package/server/service/kpi-statistic/kpi-statistic-calculation.service.ts +410 -0
  295. package/server/service/kpi-statistic/kpi-statistic-mutation.ts +97 -0
  296. package/server/service/kpi-statistic/kpi-statistic-query.ts +89 -2
  297. package/server/service/kpi-statistic/kpi-statistic.ts +32 -0
  298. package/server/service/kpi-value/kpi-value-mutation.ts +73 -7
  299. package/server/service/kpi-value/kpi-value-type.ts +10 -4
  300. package/server/service/kpi-value/kpi-value.ts +10 -5
  301. package/server/service/utils/value-date-util.ts +47 -0
  302. package/server/types/global.d.ts +8 -0
  303. package/things-factory.config.js +1 -0
  304. package/translations/en.json +15 -3
  305. package/translations/ja.json +13 -3
  306. package/translations/ko.json +15 -3
  307. package/translations/ms.json +13 -3
  308. package/translations/zh.json +13 -3
  309. package/client/pages/kpi-category/kpi-category-importer.ts +0 -90
  310. package/client/pages/kpi-category/kpi-category-list-page.ts +0 -537
  311. package/client/pages/kpi-category/kpi-category-value-calculator.ts +0 -233
  312. package/client/pages/kpi-category-value/kpi-category-value-list-page.ts +0 -404
  313. package/dist-client/pages/kpi-category/kpi-category-importer.d.ts +0 -23
  314. package/dist-client/pages/kpi-category/kpi-category-importer.js +0 -92
  315. package/dist-client/pages/kpi-category/kpi-category-importer.js.map +0 -1
  316. package/dist-client/pages/kpi-category/kpi-category-list-page.d.ts +0 -74
  317. package/dist-client/pages/kpi-category/kpi-category-list-page.js +0 -517
  318. package/dist-client/pages/kpi-category/kpi-category-list-page.js.map +0 -1
  319. package/dist-client/pages/kpi-category/kpi-category-value-calculator.d.ts +0 -13
  320. package/dist-client/pages/kpi-category/kpi-category-value-calculator.js +0 -256
  321. package/dist-client/pages/kpi-category/kpi-category-value-calculator.js.map +0 -1
  322. package/dist-client/pages/kpi-category-value/kpi-category-value-list-page.d.ts +0 -63
  323. package/dist-client/pages/kpi-category-value/kpi-category-value-list-page.js +0 -393
  324. package/dist-client/pages/kpi-category-value/kpi-category-value-list-page.js.map +0 -1
  325. package/dist-server/service/kpi-category/index.d.ts +0 -6
  326. package/dist-server/service/kpi-category/index.js +0 -10
  327. package/dist-server/service/kpi-category/index.js.map +0 -1
  328. package/dist-server/service/kpi-category/kpi-category-mutation.d.ts +0 -9
  329. package/dist-server/service/kpi-category/kpi-category-mutation.js +0 -221
  330. package/dist-server/service/kpi-category/kpi-category-mutation.js.map +0 -1
  331. package/dist-server/service/kpi-category/kpi-category-query.d.ts +0 -18
  332. package/dist-server/service/kpi-category/kpi-category-query.js +0 -115
  333. package/dist-server/service/kpi-category/kpi-category-query.js.map +0 -1
  334. package/dist-server/service/kpi-category/kpi-category-type.d.ts +0 -24
  335. package/dist-server/service/kpi-category/kpi-category-type.js +0 -100
  336. package/dist-server/service/kpi-category/kpi-category-type.js.map +0 -1
  337. package/dist-server/service/kpi-category/kpi-category.d.ts +0 -22
  338. package/dist-server/service/kpi-category/kpi-category.js +0 -106
  339. package/dist-server/service/kpi-category/kpi-category.js.map +0 -1
  340. package/dist-server/service/kpi-category-value/index.d.ts +0 -6
  341. package/dist-server/service/kpi-category-value/index.js +0 -10
  342. package/dist-server/service/kpi-category-value/index.js.map +0 -1
  343. package/dist-server/service/kpi-category-value/kpi-category-value-mutation.d.ts +0 -8
  344. package/dist-server/service/kpi-category-value/kpi-category-value-mutation.js +0 -102
  345. package/dist-server/service/kpi-category-value/kpi-category-value-mutation.js.map +0 -1
  346. package/dist-server/service/kpi-category-value/kpi-category-value-query.d.ts +0 -13
  347. package/dist-server/service/kpi-category-value/kpi-category-value-query.js +0 -91
  348. package/dist-server/service/kpi-category-value/kpi-category-value-query.js.map +0 -1
  349. package/dist-server/service/kpi-category-value/kpi-category-value-type.d.ts +0 -19
  350. package/dist-server/service/kpi-category-value/kpi-category-value-type.js +0 -73
  351. package/dist-server/service/kpi-category-value/kpi-category-value-type.js.map +0 -1
  352. package/dist-server/service/kpi-category-value/kpi-category-value.d.ts +0 -19
  353. package/dist-server/service/kpi-category-value/kpi-category-value.js +0 -91
  354. package/dist-server/service/kpi-category-value/kpi-category-value.js.map +0 -1
  355. package/helps/kpi/kpi-category.md +0 -160
  356. package/server/service/kpi-category/index.ts +0 -7
  357. package/server/service/kpi-category/kpi-category-mutation.ts +0 -217
  358. package/server/service/kpi-category/kpi-category-query.ts +0 -87
  359. package/server/service/kpi-category/kpi-category-type.ts +0 -73
  360. package/server/service/kpi-category/kpi-category.ts +0 -95
  361. package/server/service/kpi-category-value/index.ts +0 -7
  362. package/server/service/kpi-category-value/kpi-category-value-mutation.ts +0 -88
  363. package/server/service/kpi-category-value/kpi-category-value-query.ts +0 -62
  364. package/server/service/kpi-category-value/kpi-category-value-type.ts +0 -48
  365. package/server/service/kpi-category-value/kpi-category-value.ts +0 -79
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kpi-scope-type.js","sourceRoot":"","sources":["../../../server/service/kpi-scope/kpi-scope-type.ts"],"names":[],"mappings":"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","sourcesContent":["import { ScalarObject } from '@things-factory/shell'\nimport { ObjectType, Field, InputType, ID, Int } from 'type-graphql'\nimport { KpiScope, ScopeType } from './kpi-scope'\n\n@InputType()\nexport class NewKpiScope {\n @Field(type => Int, { description: 'Scope level (1-5) corresponding to scope01-scope05 in KpiOrgScope' })\n level: number\n\n @Field({ description: 'Display name for this scope dimension (e.g., \"지역\", \"회사\", \"프로젝트규모\")' })\n name: string\n\n @Field({ nullable: true, description: 'Detailed description of what this scope dimension represents' })\n description?: string\n\n @Field(type => ScopeType, { description: 'Type category of this scope dimension' })\n scopeType: ScopeType\n\n @Field(type => Int, { nullable: true, description: 'Parent scope level if this forms a hierarchy' })\n parentLevel?: number\n\n @Field(type => Int, { description: 'Order/priority for display and processing', defaultValue: 1 })\n displayOrder: number\n\n @Field(type => [String], { nullable: true, description: 'List of valid values for this scope' })\n validValues?: string[]\n\n @Field({ nullable: true, description: 'Regex pattern for validating values in this scope dimension' })\n validationPattern?: string\n\n @Field({ description: 'Whether this scope definition is active and should be used', defaultValue: true })\n active: boolean\n\n @Field({ description: 'Whether this scope should be included in statistical calculations', defaultValue: true })\n includeInStatistics: boolean\n\n @Field({ description: 'Whether this scope should be displayed in dashboard visualizations', defaultValue: false })\n showInDashboard: boolean\n\n @Field(type => ScalarObject, { nullable: true, description: 'Additional metadata for this scope dimension' })\n metadata?: any\n}\n\n@InputType()\nexport class KpiScopePatch {\n @Field(type => ID, { nullable: true })\n id?: string\n\n @Field(type => Int, { description: 'Scope level (1-5) corresponding to scope01-scope05 in KpiOrgScope' })\n level: number\n\n @Field({ description: 'Display name for this scope dimension (e.g., \"지역\", \"회사\", \"프로젝트규모\")' })\n name: string\n\n @Field({ nullable: true, description: 'Detailed description of what this scope dimension represents' })\n description?: string\n\n @Field(type => ScopeType, { description: 'Type category of this scope dimension' })\n scopeType: ScopeType\n\n @Field(type => Int, { nullable: true, description: 'Parent scope level if this forms a hierarchy' })\n parentLevel?: number\n\n @Field(type => Int, { description: 'Order/priority for display and processing', defaultValue: 1 })\n displayOrder: number\n\n @Field(type => [String], { nullable: true, description: 'List of valid values for this scope' })\n validValues?: string[]\n\n @Field({ nullable: true, description: 'Regex pattern for validating values in this scope dimension' })\n validationPattern?: string\n\n @Field({ description: 'Whether this scope definition is active and should be used', defaultValue: true })\n active: boolean\n\n @Field({ description: 'Whether this scope should be included in statistical calculations', defaultValue: true })\n includeInStatistics: boolean\n\n @Field({ description: 'Whether this scope should be displayed in dashboard visualizations', defaultValue: false })\n showInDashboard: boolean\n\n @Field(type => ScalarObject, { nullable: true, description: 'Additional metadata for this scope dimension' })\n metadata?: any\n\n @Field({ nullable: true })\n cuFlag?: string\n}\n\n@ObjectType()\nexport class KpiScopeList {\n @Field(type => [KpiScope])\n items: KpiScope[]\n\n @Field()\n total: number\n}\n"]}
@@ -0,0 +1,38 @@
1
+ import { Domain } from '@things-factory/shell';
2
+ import { User } from '@things-factory/auth-base';
3
+ export declare enum ScopeType {
4
+ GEOGRAPHIC = "GEOGRAPHIC",// 지리적 차원 (지역, 시도, 구군)
5
+ ORGANIZATIONAL = "ORGANIZATIONAL",// 조직 차원 (회사, 부서, 팀)
6
+ BUSINESS = "BUSINESS",// 비즈니스 차원 (규모, 유형, 등급)
7
+ TECHNICAL = "TECHNICAL",// 기술적 차원 (공종, 기술, 방법)
8
+ TEMPORAL = "TEMPORAL",// 시간적 차원 (분기, 년도, 기간)
9
+ CUSTOM = "CUSTOM"
10
+ }
11
+ export declare class KpiScope {
12
+ readonly id: string;
13
+ level: number;
14
+ name: string;
15
+ description?: string;
16
+ scopeType: ScopeType;
17
+ parentLevel?: number;
18
+ displayOrder: number;
19
+ validValues?: string[];
20
+ validationPattern?: string;
21
+ active: boolean;
22
+ includeInStatistics: boolean;
23
+ showInDashboard: boolean;
24
+ metadata?: {
25
+ color?: string;
26
+ icon?: string;
27
+ unit?: string;
28
+ [key: string]: any;
29
+ };
30
+ domain?: Domain;
31
+ domainId?: string;
32
+ createdAt?: Date;
33
+ updatedAt?: Date;
34
+ creator?: User;
35
+ creatorId?: string;
36
+ updater?: User;
37
+ updaterId?: string;
38
+ }
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KpiScope = exports.ScopeType = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const typeorm_1 = require("typeorm");
6
+ const type_graphql_1 = require("type-graphql");
7
+ const shell_1 = require("@things-factory/shell");
8
+ const auth_base_1 = require("@things-factory/auth-base");
9
+ var ScopeType;
10
+ (function (ScopeType) {
11
+ ScopeType["GEOGRAPHIC"] = "GEOGRAPHIC";
12
+ ScopeType["ORGANIZATIONAL"] = "ORGANIZATIONAL";
13
+ ScopeType["BUSINESS"] = "BUSINESS";
14
+ ScopeType["TECHNICAL"] = "TECHNICAL";
15
+ ScopeType["TEMPORAL"] = "TEMPORAL";
16
+ ScopeType["CUSTOM"] = "CUSTOM"; // 사용자 정의
17
+ })(ScopeType || (exports.ScopeType = ScopeType = {}));
18
+ (0, type_graphql_1.registerEnumType)(ScopeType, {
19
+ name: 'ScopeType',
20
+ description: 'Types of organizational scope dimensions'
21
+ });
22
+ let KpiScope = class KpiScope {
23
+ };
24
+ exports.KpiScope = KpiScope;
25
+ tslib_1.__decorate([
26
+ (0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
27
+ (0, type_graphql_1.Field)(type => type_graphql_1.ID),
28
+ tslib_1.__metadata("design:type", String)
29
+ ], KpiScope.prototype, "id", void 0);
30
+ tslib_1.__decorate([
31
+ (0, typeorm_1.Column)({ type: 'int' }),
32
+ (0, type_graphql_1.Field)(type => type_graphql_1.Int, { description: 'Scope level (1-5) corresponding to scope01-scope05 in KpiOrgScope' }),
33
+ tslib_1.__metadata("design:type", Number)
34
+ ], KpiScope.prototype, "level", void 0);
35
+ tslib_1.__decorate([
36
+ (0, typeorm_1.Column)(),
37
+ (0, type_graphql_1.Field)({ description: 'Display name for this scope dimension (e.g., "지역", "회사", "프로젝트규모")' }),
38
+ tslib_1.__metadata("design:type", String)
39
+ ], KpiScope.prototype, "name", void 0);
40
+ tslib_1.__decorate([
41
+ (0, typeorm_1.Column)({ nullable: true }),
42
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Detailed description of what this scope dimension represents' }),
43
+ tslib_1.__metadata("design:type", String)
44
+ ], KpiScope.prototype, "description", void 0);
45
+ tslib_1.__decorate([
46
+ (0, typeorm_1.Column)(),
47
+ (0, type_graphql_1.Field)(type => ScopeType, { description: 'Type category of this scope dimension' }),
48
+ tslib_1.__metadata("design:type", String)
49
+ ], KpiScope.prototype, "scopeType", void 0);
50
+ tslib_1.__decorate([
51
+ (0, typeorm_1.Column)({ nullable: true }),
52
+ (0, type_graphql_1.Field)(type => type_graphql_1.Int, { nullable: true, description: 'Parent scope level if this forms a hierarchy' }),
53
+ tslib_1.__metadata("design:type", Number)
54
+ ], KpiScope.prototype, "parentLevel", void 0);
55
+ tslib_1.__decorate([
56
+ (0, typeorm_1.Column)({ default: 1 }),
57
+ (0, type_graphql_1.Field)(type => type_graphql_1.Int, { description: 'Order/priority for display and processing' }),
58
+ tslib_1.__metadata("design:type", Number)
59
+ ], KpiScope.prototype, "displayOrder", void 0);
60
+ tslib_1.__decorate([
61
+ (0, typeorm_1.Column)('simple-json', { nullable: true }),
62
+ (0, type_graphql_1.Field)(type => shell_1.ScalarObject, {
63
+ nullable: true,
64
+ description: 'List of valid values for this scope (e.g., ["서울", "부산", "대구"] for regions)'
65
+ }),
66
+ tslib_1.__metadata("design:type", Array)
67
+ ], KpiScope.prototype, "validValues", void 0);
68
+ tslib_1.__decorate([
69
+ (0, typeorm_1.Column)({ nullable: true }),
70
+ (0, type_graphql_1.Field)({
71
+ nullable: true,
72
+ description: 'Regex pattern for validating values in this scope dimension'
73
+ }),
74
+ tslib_1.__metadata("design:type", String)
75
+ ], KpiScope.prototype, "validationPattern", void 0);
76
+ tslib_1.__decorate([
77
+ (0, typeorm_1.Column)({ default: true }),
78
+ (0, type_graphql_1.Field)({ description: 'Whether this scope definition is active and should be used' }),
79
+ tslib_1.__metadata("design:type", Boolean)
80
+ ], KpiScope.prototype, "active", void 0);
81
+ tslib_1.__decorate([
82
+ (0, typeorm_1.Column)({ default: true }),
83
+ (0, type_graphql_1.Field)({ description: 'Whether this scope should be included in statistical calculations' }),
84
+ tslib_1.__metadata("design:type", Boolean)
85
+ ], KpiScope.prototype, "includeInStatistics", void 0);
86
+ tslib_1.__decorate([
87
+ (0, typeorm_1.Column)({ default: false }),
88
+ (0, type_graphql_1.Field)({ description: 'Whether this scope should be displayed in dashboard visualizations' }),
89
+ tslib_1.__metadata("design:type", Boolean)
90
+ ], KpiScope.prototype, "showInDashboard", void 0);
91
+ tslib_1.__decorate([
92
+ (0, typeorm_1.Column)('simple-json', { nullable: true }),
93
+ (0, type_graphql_1.Field)(type => shell_1.ScalarObject, {
94
+ nullable: true,
95
+ description: 'Additional metadata for this scope dimension (colors, icons, etc.)'
96
+ }),
97
+ tslib_1.__metadata("design:type", Object)
98
+ ], KpiScope.prototype, "metadata", void 0);
99
+ tslib_1.__decorate([
100
+ (0, typeorm_1.ManyToOne)(type => shell_1.Domain),
101
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Domain this scope definition belongs to' }),
102
+ tslib_1.__metadata("design:type", shell_1.Domain)
103
+ ], KpiScope.prototype, "domain", void 0);
104
+ tslib_1.__decorate([
105
+ (0, typeorm_1.RelationId)((kpiScope) => kpiScope.domain),
106
+ tslib_1.__metadata("design:type", String)
107
+ ], KpiScope.prototype, "domainId", void 0);
108
+ tslib_1.__decorate([
109
+ (0, typeorm_1.CreateDateColumn)(),
110
+ (0, type_graphql_1.Field)({ nullable: true }),
111
+ tslib_1.__metadata("design:type", Date)
112
+ ], KpiScope.prototype, "createdAt", void 0);
113
+ tslib_1.__decorate([
114
+ (0, typeorm_1.UpdateDateColumn)(),
115
+ (0, type_graphql_1.Field)({ nullable: true }),
116
+ tslib_1.__metadata("design:type", Date)
117
+ ], KpiScope.prototype, "updatedAt", void 0);
118
+ tslib_1.__decorate([
119
+ (0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
120
+ (0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true }),
121
+ tslib_1.__metadata("design:type", auth_base_1.User)
122
+ ], KpiScope.prototype, "creator", void 0);
123
+ tslib_1.__decorate([
124
+ (0, typeorm_1.RelationId)((kpiScope) => kpiScope.creator),
125
+ tslib_1.__metadata("design:type", String)
126
+ ], KpiScope.prototype, "creatorId", void 0);
127
+ tslib_1.__decorate([
128
+ (0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
129
+ (0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true }),
130
+ tslib_1.__metadata("design:type", auth_base_1.User)
131
+ ], KpiScope.prototype, "updater", void 0);
132
+ tslib_1.__decorate([
133
+ (0, typeorm_1.RelationId)((kpiScope) => kpiScope.updater),
134
+ tslib_1.__metadata("design:type", String)
135
+ ], KpiScope.prototype, "updaterId", void 0);
136
+ exports.KpiScope = KpiScope = tslib_1.__decorate([
137
+ (0, typeorm_1.Entity)(),
138
+ (0, typeorm_1.Index)('ix_kpi_scope_domain', (kpiScope) => [kpiScope.domain]),
139
+ (0, typeorm_1.Index)('ix_kpi_scope_level', (kpiScope) => [kpiScope.domain, kpiScope.level]),
140
+ (0, type_graphql_1.ObjectType)({
141
+ description: 'Defines the meaning and metadata for each scope level (scope01~05) in KpiOrgScope'
142
+ })
143
+ ], KpiScope);
144
+ //# sourceMappingURL=kpi-scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kpi-scope.js","sourceRoot":"","sources":["../../../server/service/kpi-scope/kpi-scope.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n CreateDateColumn,\n UpdateDateColumn,\n Entity,\n Index,\n Column,\n RelationId,\n ManyToOne,\n PrimaryGeneratedColumn\n} from 'typeorm'\nimport { ObjectType, Field, ID, registerEnumType, Int } from 'type-graphql'\n\nimport { Domain, ScalarObject } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\n\nexport enum ScopeType {\n GEOGRAPHIC = 'GEOGRAPHIC', // 지리적 차원 (지역, 시도, 구군)\n ORGANIZATIONAL = 'ORGANIZATIONAL', // 조직 차원 (회사, 부서, 팀)\n BUSINESS = 'BUSINESS', // 비즈니스 차원 (규모, 유형, 등급)\n TECHNICAL = 'TECHNICAL', // 기술적 차원 (공종, 기술, 방법)\n TEMPORAL = 'TEMPORAL', // 시간적 차원 (분기, 년도, 기간)\n CUSTOM = 'CUSTOM' // 사용자 정의\n}\n\nregisterEnumType(ScopeType, {\n name: 'ScopeType',\n description: 'Types of organizational scope dimensions'\n})\n\n@Entity()\n@Index('ix_kpi_scope_domain', (kpiScope: KpiScope) => [kpiScope.domain])\n@Index('ix_kpi_scope_level', (kpiScope: KpiScope) => [kpiScope.domain, kpiScope.level])\n@ObjectType({\n description: 'Defines the meaning and metadata for each scope level (scope01~05) in KpiOrgScope'\n})\nexport class KpiScope {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID)\n readonly id: string\n\n // 스코프 레벨 (1-5)\n @Column({ type: 'int' })\n @Field(type => Int, { description: 'Scope level (1-5) corresponding to scope01-scope05 in KpiOrgScope' })\n level: number\n\n // 스코프 차원 이름\n @Column()\n @Field({ description: 'Display name for this scope dimension (e.g., \"지역\", \"회사\", \"프로젝트규모\")' })\n name: string\n\n // 스코프 차원 설명\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Detailed description of what this scope dimension represents' })\n description?: string\n\n // 스코프 타입 (지리적, 조직적, 비즈니스 등)\n @Column()\n @Field(type => ScopeType, { description: 'Type category of this scope dimension' })\n scopeType: ScopeType\n\n // 계층 정보\n @Column({ nullable: true })\n @Field(type => Int, { nullable: true, description: 'Parent scope level if this forms a hierarchy' })\n parentLevel?: number\n\n @Column({ default: 1 })\n @Field(type => Int, { description: 'Order/priority for display and processing' })\n displayOrder: number\n\n // 유효한 값들 (선택사항)\n @Column('simple-json', { nullable: true })\n @Field(type => ScalarObject, {\n nullable: true,\n description: 'List of valid values for this scope (e.g., [\"서울\", \"부산\", \"대구\"] for regions)'\n })\n validValues?: string[]\n\n // 정규표현식 검증 (선택사항)\n @Column({ nullable: true })\n @Field({\n nullable: true,\n description: 'Regex pattern for validating values in this scope dimension'\n })\n validationPattern?: string\n\n // 활성화 여부\n @Column({ default: true })\n @Field({ description: 'Whether this scope definition is active and should be used' })\n active: boolean\n\n // 통계 계산에 사용 여부\n @Column({ default: true })\n @Field({ description: 'Whether this scope should be included in statistical calculations' })\n includeInStatistics: boolean\n\n // 대시보드에 표시 여부\n @Column({ default: false })\n @Field({ description: 'Whether this scope should be displayed in dashboard visualizations' })\n showInDashboard: boolean\n\n // 메타데이터\n @Column('simple-json', { nullable: true })\n @Field(type => ScalarObject, {\n nullable: true,\n description: 'Additional metadata for this scope dimension (colors, icons, etc.)'\n })\n metadata?: {\n color?: string\n icon?: string\n unit?: string\n [key: string]: any\n }\n\n // === 표준 필드들 ===\n @ManyToOne(type => Domain)\n @Field({ nullable: true, description: 'Domain this scope definition belongs to' })\n domain?: Domain\n\n @RelationId((kpiScope: KpiScope) => kpiScope.domain)\n domainId?: string\n\n @CreateDateColumn()\n @Field({ nullable: true })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true })\n updatedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true })\n creator?: User\n\n @RelationId((kpiScope: KpiScope) => kpiScope.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true })\n updater?: User\n\n @RelationId((kpiScope: KpiScope) => kpiScope.updater)\n updaterId?: string\n}\n"]}
@@ -0,0 +1,43 @@
1
+ import { KpiPeriodType } from '../kpi/kpi';
2
+ /**
3
+ * KPI 통계 배치 계산 서비스
4
+ * 정기적으로 실행하여 KpiValue 데이터를 집계해서 KpiStatistic을 생성/업데이트
5
+ */
6
+ export declare class KpiStatisticBatchService {
7
+ /**
8
+ * 일일 배치: 어제 날짜의 모든 통계 계산
9
+ */
10
+ static runDailyBatch(domainId?: string): Promise<void>;
11
+ /**
12
+ * 월간 배치: 지난 달의 모든 통계 계산
13
+ */
14
+ static runMonthlyBatch(domainId?: string): Promise<void>;
15
+ /**
16
+ * 분기 배치: 지난 분기의 모든 통계 계산
17
+ */
18
+ static runQuarterlyBatch(domainId?: string): Promise<void>;
19
+ /**
20
+ * 연간 배치: 작년의 모든 통계 계산
21
+ */
22
+ static runYearlyBatch(domainId?: string): Promise<void>;
23
+ /**
24
+ * 대시보드용 지역별 통계 계산
25
+ */
26
+ static runDashboardBatch(periodType?: KpiPeriodType, valueDate?: string, domainId?: string): Promise<void>;
27
+ /**
28
+ * 모든 도메인에 대해 통계 계산
29
+ */
30
+ private static calculateForAllDomains;
31
+ /**
32
+ * 특정 도메인에 대해 통계 계산
33
+ */
34
+ private static calculateForDomain;
35
+ /**
36
+ * 배치 실행 결과 로깅
37
+ */
38
+ private static logBatchResult;
39
+ /**
40
+ * 배치 작업 스케줄링 설정 예시
41
+ */
42
+ static setupBatchSchedule(): void;
43
+ }
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KpiStatisticBatchService = void 0;
4
+ const shell_1 = require("@things-factory/shell");
5
+ const kpi_statistic_calculation_service_1 = require("./kpi-statistic-calculation.service");
6
+ const kpi_1 = require("../kpi/kpi");
7
+ const shell_2 = require("@things-factory/shell");
8
+ /**
9
+ * KPI 통계 배치 계산 서비스
10
+ * 정기적으로 실행하여 KpiValue 데이터를 집계해서 KpiStatistic을 생성/업데이트
11
+ */
12
+ class KpiStatisticBatchService {
13
+ /**
14
+ * 일일 배치: 어제 날짜의 모든 통계 계산
15
+ */
16
+ static async runDailyBatch(domainId) {
17
+ console.log('[KPI Statistics] Starting daily batch calculation...');
18
+ const yesterday = new Date();
19
+ yesterday.setDate(yesterday.getDate() - 1);
20
+ const valueDate = yesterday.toISOString().split('T')[0]; // YYYY-MM-DD
21
+ await this.calculateForAllDomains(kpi_1.KpiPeriodType.DAY, valueDate, domainId);
22
+ console.log(`[KPI Statistics] Daily batch completed for ${valueDate}`);
23
+ }
24
+ /**
25
+ * 월간 배치: 지난 달의 모든 통계 계산
26
+ */
27
+ static async runMonthlyBatch(domainId) {
28
+ console.log('[KPI Statistics] Starting monthly batch calculation...');
29
+ const lastMonth = new Date();
30
+ lastMonth.setMonth(lastMonth.getMonth() - 1);
31
+ const valueDate = lastMonth.toISOString().substring(0, 7); // YYYY-MM
32
+ await this.calculateForAllDomains(kpi_1.KpiPeriodType.MONTH, valueDate, domainId);
33
+ console.log(`[KPI Statistics] Monthly batch completed for ${valueDate}`);
34
+ }
35
+ /**
36
+ * 분기 배치: 지난 분기의 모든 통계 계산
37
+ */
38
+ static async runQuarterlyBatch(domainId) {
39
+ console.log('[KPI Statistics] Starting quarterly batch calculation...');
40
+ const now = new Date();
41
+ const currentQuarter = Math.floor(now.getMonth() / 3) + 1;
42
+ const lastQuarter = currentQuarter === 1 ? 4 : currentQuarter - 1;
43
+ const year = currentQuarter === 1 ? now.getFullYear() - 1 : now.getFullYear();
44
+ const valueDate = `${year}-Q${lastQuarter}`;
45
+ await this.calculateForAllDomains(kpi_1.KpiPeriodType.QUARTER, valueDate, domainId);
46
+ console.log(`[KPI Statistics] Quarterly batch completed for ${valueDate}`);
47
+ }
48
+ /**
49
+ * 연간 배치: 작년의 모든 통계 계산
50
+ */
51
+ static async runYearlyBatch(domainId) {
52
+ console.log('[KPI Statistics] Starting yearly batch calculation...');
53
+ const lastYear = new Date().getFullYear() - 1;
54
+ const valueDate = lastYear.toString();
55
+ await this.calculateForAllDomains(kpi_1.KpiPeriodType.YEAR, valueDate, domainId);
56
+ console.log(`[KPI Statistics] Yearly batch completed for ${valueDate}`);
57
+ }
58
+ /**
59
+ * 대시보드용 지역별 통계 계산
60
+ */
61
+ static async runDashboardBatch(periodType = kpi_1.KpiPeriodType.MONTH, valueDate, domainId) {
62
+ console.log('[KPI Statistics] Starting dashboard batch calculation...');
63
+ if (!valueDate) {
64
+ const now = new Date();
65
+ if (periodType === kpi_1.KpiPeriodType.MONTH) {
66
+ now.setMonth(now.getMonth() - 1);
67
+ valueDate = now.toISOString().substring(0, 7); // YYYY-MM
68
+ }
69
+ else {
70
+ now.setDate(now.getDate() - 1);
71
+ valueDate = now.toISOString().split('T')[0]; // YYYY-MM-DD
72
+ }
73
+ }
74
+ await this.calculateForAllDomains(periodType, valueDate, domainId);
75
+ console.log(`[KPI Statistics] Dashboard batch completed for ${valueDate} (${periodType})`);
76
+ }
77
+ /**
78
+ * 모든 도메인에 대해 통계 계산
79
+ */
80
+ static async calculateForAllDomains(periodType, valueDate, domainId) {
81
+ try {
82
+ const domains = domainId
83
+ ? await (0, shell_1.getRepository)(shell_2.Domain).find({ where: { id: domainId } })
84
+ : await (0, shell_1.getRepository)(shell_2.Domain).find();
85
+ for (const domain of domains) {
86
+ try {
87
+ await this.calculateForDomain(domain, periodType, valueDate);
88
+ }
89
+ catch (error) {
90
+ console.error(`[KPI Statistics] Domain ${domain.name} calculation failed, continuing with next domain:`, error);
91
+ // 개별 도메인 실패가 전체 배치를 중단시키지 않도록 계속 진행
92
+ continue;
93
+ }
94
+ }
95
+ }
96
+ catch (error) {
97
+ console.error('[KPI Statistics] Batch calculation failed:', error);
98
+ throw error;
99
+ }
100
+ }
101
+ /**
102
+ * 특정 도메인에 대해 통계 계산
103
+ */
104
+ static async calculateForDomain(domain, periodType, valueDate) {
105
+ console.log(`[KPI Statistics] Calculating for domain: ${domain.name} (${domain.id})`);
106
+ // 가짜 ResolverContext 생성 (배치 작업용)
107
+ const context = {
108
+ state: {
109
+ domain,
110
+ user: { id: 'system', name: 'System Batch' }, // 시스템 사용자
111
+ tx: null // 트랜잭션 없음 (각 계산마다 개별 트랜잭션)
112
+ }
113
+ };
114
+ try {
115
+ const statistics = await kpi_statistic_calculation_service_1.KpiStatisticCalculationService.calculateAllStatistics(periodType, valueDate, context);
116
+ console.log(`[KPI Statistics] Generated ${statistics.length} statistics for domain ${domain.name}`);
117
+ // 성공 로깅
118
+ this.logBatchResult(domain.id, periodType, valueDate, statistics.length, 'SUCCESS');
119
+ }
120
+ catch (error) {
121
+ console.error(`[KPI Statistics] Failed to calculate for domain ${domain.name}:`, error);
122
+ // 실패 로깅
123
+ this.logBatchResult(domain.id, periodType, valueDate, 0, 'FAILED', error.message);
124
+ // 에러를 던져서 상위에서 처리
125
+ throw error;
126
+ }
127
+ }
128
+ /**
129
+ * 배치 실행 결과 로깅
130
+ */
131
+ static logBatchResult(domainId, periodType, valueDate, statisticsCount, status, errorMessage) {
132
+ const logData = {
133
+ timestamp: new Date().toISOString(),
134
+ domainId,
135
+ periodType,
136
+ valueDate,
137
+ statisticsCount,
138
+ status,
139
+ errorMessage
140
+ };
141
+ // 실제 운영에서는 로깅 시스템에 저장
142
+ console.log('[KPI Statistics Batch Log]', JSON.stringify(logData));
143
+ }
144
+ /**
145
+ * 배치 작업 스케줄링 설정 예시
146
+ */
147
+ static setupBatchSchedule() {
148
+ // 실제 구현시에는 cron 등의 스케줄러 사용
149
+ console.log('[KPI Statistics] Batch schedule setup example:');
150
+ console.log('Daily batch: Run at 02:00 AM every day');
151
+ console.log('Monthly batch: Run at 03:00 AM on 1st of every month');
152
+ console.log('Quarterly batch: Run at 04:00 AM on 1st of every quarter');
153
+ console.log('Yearly batch: Run at 05:00 AM on January 1st');
154
+ /*
155
+ // Node-cron 사용 예시:
156
+ import cron from 'node-cron'
157
+
158
+ // 매일 새벽 2시
159
+ cron.schedule('0 2 * * *', () => {
160
+ this.runDailyBatch()
161
+ })
162
+
163
+ // 매월 1일 새벽 3시
164
+ cron.schedule('0 3 1 * *', () => {
165
+ this.runMonthlyBatch()
166
+ })
167
+
168
+ // 매 분기 첫날 새벽 4시 (1, 4, 7, 10월)
169
+ cron.schedule('0 4 1 1,4,7,10 *', () => {
170
+ this.runQuarterlyBatch()
171
+ })
172
+
173
+ // 매년 1월 1일 새벽 5시
174
+ cron.schedule('0 5 1 1 *', () => {
175
+ this.runYearlyBatch()
176
+ })
177
+ */
178
+ }
179
+ }
180
+ exports.KpiStatisticBatchService = KpiStatisticBatchService;
181
+ //# sourceMappingURL=kpi-statistic-batch.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kpi-statistic-batch.service.js","sourceRoot":"","sources":["../../../server/service/kpi-statistic/kpi-statistic-batch.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { getRepository } from '@things-factory/shell'\nimport type ResolverContext from '@things-factory/auth-base'\nimport { KpiStatisticCalculationService } from './kpi-statistic-calculation.service'\nimport { KpiPeriodType } from '../kpi/kpi'\nimport { Domain } from '@things-factory/shell'\n\n/**\n * KPI 통계 배치 계산 서비스\n * 정기적으로 실행하여 KpiValue 데이터를 집계해서 KpiStatistic을 생성/업데이트\n */\nexport class KpiStatisticBatchService {\n \n /**\n * 일일 배치: 어제 날짜의 모든 통계 계산\n */\n static async runDailyBatch(domainId?: string): Promise<void> {\n console.log('[KPI Statistics] Starting daily batch calculation...')\n \n const yesterday = new Date()\n yesterday.setDate(yesterday.getDate() - 1)\n const valueDate = yesterday.toISOString().split('T')[0] // YYYY-MM-DD\n \n await this.calculateForAllDomains(KpiPeriodType.DAY, valueDate, domainId)\n \n console.log(`[KPI Statistics] Daily batch completed for ${valueDate}`)\n }\n \n /**\n * 월간 배치: 지난 달의 모든 통계 계산\n */\n static async runMonthlyBatch(domainId?: string): Promise<void> {\n console.log('[KPI Statistics] Starting monthly batch calculation...')\n \n const lastMonth = new Date()\n lastMonth.setMonth(lastMonth.getMonth() - 1)\n const valueDate = lastMonth.toISOString().substring(0, 7) // YYYY-MM\n \n await this.calculateForAllDomains(KpiPeriodType.MONTH, valueDate, domainId)\n \n console.log(`[KPI Statistics] Monthly batch completed for ${valueDate}`)\n }\n \n /**\n * 분기 배치: 지난 분기의 모든 통계 계산\n */\n static async runQuarterlyBatch(domainId?: string): Promise<void> {\n console.log('[KPI Statistics] Starting quarterly batch calculation...')\n \n const now = new Date()\n const currentQuarter = Math.floor(now.getMonth() / 3) + 1\n const lastQuarter = currentQuarter === 1 ? 4 : currentQuarter - 1\n const year = currentQuarter === 1 ? now.getFullYear() - 1 : now.getFullYear()\n const valueDate = `${year}-Q${lastQuarter}`\n \n await this.calculateForAllDomains(KpiPeriodType.QUARTER, valueDate, domainId)\n \n console.log(`[KPI Statistics] Quarterly batch completed for ${valueDate}`)\n }\n \n /**\n * 연간 배치: 작년의 모든 통계 계산\n */\n static async runYearlyBatch(domainId?: string): Promise<void> {\n console.log('[KPI Statistics] Starting yearly batch calculation...')\n \n const lastYear = new Date().getFullYear() - 1\n const valueDate = lastYear.toString()\n \n await this.calculateForAllDomains(KpiPeriodType.YEAR, valueDate, domainId)\n \n console.log(`[KPI Statistics] Yearly batch completed for ${valueDate}`)\n }\n \n /**\n * 대시보드용 지역별 통계 계산\n */\n static async runDashboardBatch(\n periodType: KpiPeriodType = KpiPeriodType.MONTH,\n valueDate?: string,\n domainId?: string\n ): Promise<void> {\n console.log('[KPI Statistics] Starting dashboard batch calculation...')\n \n if (!valueDate) {\n const now = new Date()\n if (periodType === KpiPeriodType.MONTH) {\n now.setMonth(now.getMonth() - 1)\n valueDate = now.toISOString().substring(0, 7) // YYYY-MM\n } else {\n now.setDate(now.getDate() - 1)\n valueDate = now.toISOString().split('T')[0] // YYYY-MM-DD\n }\n }\n \n await this.calculateForAllDomains(periodType, valueDate, domainId)\n \n console.log(`[KPI Statistics] Dashboard batch completed for ${valueDate} (${periodType})`)\n }\n \n /**\n * 모든 도메인에 대해 통계 계산\n */\n private static async calculateForAllDomains(\n periodType: KpiPeriodType,\n valueDate: string,\n domainId?: string\n ): Promise<void> {\n try {\n const domains = domainId \n ? await getRepository(Domain).find({ where: { id: domainId } })\n : await getRepository(Domain).find()\n \n for (const domain of domains) {\n try {\n await this.calculateForDomain(domain, periodType, valueDate)\n } catch (error) {\n console.error(`[KPI Statistics] Domain ${domain.name} calculation failed, continuing with next domain:`, error)\n // 개별 도메인 실패가 전체 배치를 중단시키지 않도록 계속 진행\n continue\n }\n }\n } catch (error) {\n console.error('[KPI Statistics] Batch calculation failed:', error)\n throw error\n }\n }\n \n /**\n * 특정 도메인에 대해 통계 계산\n */\n private static async calculateForDomain(\n domain: Domain,\n periodType: KpiPeriodType,\n valueDate: string\n ): Promise<void> {\n console.log(`[KPI Statistics] Calculating for domain: ${domain.name} (${domain.id})`)\n \n // 가짜 ResolverContext 생성 (배치 작업용)\n const context: ResolverContext = {\n state: {\n domain,\n user: { id: 'system', name: 'System Batch' }, // 시스템 사용자\n tx: null // 트랜잭션 없음 (각 계산마다 개별 트랜잭션)\n }\n } as any\n \n try {\n const statistics = await KpiStatisticCalculationService.calculateAllStatistics(\n periodType,\n valueDate,\n context\n )\n \n console.log(`[KPI Statistics] Generated ${statistics.length} statistics for domain ${domain.name}`)\n \n // 성공 로깅\n this.logBatchResult(domain.id, periodType, valueDate, statistics.length, 'SUCCESS')\n \n } catch (error) {\n console.error(`[KPI Statistics] Failed to calculate for domain ${domain.name}:`, error)\n \n // 실패 로깅\n this.logBatchResult(domain.id, periodType, valueDate, 0, 'FAILED', error.message)\n \n // 에러를 던져서 상위에서 처리\n throw error\n }\n }\n \n /**\n * 배치 실행 결과 로깅\n */\n private static logBatchResult(\n domainId: string,\n periodType: KpiPeriodType,\n valueDate: string,\n statisticsCount: number,\n status: 'SUCCESS' | 'FAILED',\n errorMessage?: string\n ): void {\n const logData = {\n timestamp: new Date().toISOString(),\n domainId,\n periodType,\n valueDate,\n statisticsCount,\n status,\n errorMessage\n }\n \n // 실제 운영에서는 로깅 시스템에 저장\n console.log('[KPI Statistics Batch Log]', JSON.stringify(logData))\n }\n \n /**\n * 배치 작업 스케줄링 설정 예시\n */\n static setupBatchSchedule(): void {\n // 실제 구현시에는 cron 등의 스케줄러 사용\n console.log('[KPI Statistics] Batch schedule setup example:')\n console.log('Daily batch: Run at 02:00 AM every day')\n console.log('Monthly batch: Run at 03:00 AM on 1st of every month') \n console.log('Quarterly batch: Run at 04:00 AM on 1st of every quarter')\n console.log('Yearly batch: Run at 05:00 AM on January 1st')\n \n /*\n // Node-cron 사용 예시:\n import cron from 'node-cron'\n \n // 매일 새벽 2시\n cron.schedule('0 2 * * *', () => {\n this.runDailyBatch()\n })\n \n // 매월 1일 새벽 3시\n cron.schedule('0 3 1 * *', () => {\n this.runMonthlyBatch()\n })\n \n // 매 분기 첫날 새벽 4시 (1, 4, 7, 10월)\n cron.schedule('0 4 1 1,4,7,10 *', () => {\n this.runQuarterlyBatch()\n })\n \n // 매년 1월 1일 새벽 5시\n cron.schedule('0 5 1 1 *', () => {\n this.runYearlyBatch()\n })\n */\n }\n}"]}
@@ -0,0 +1,50 @@
1
+ import { KpiStatistic } from './kpi-statistic';
2
+ import { KpiPeriodType } from '../kpi/kpi';
3
+ import { KpiOrgScope } from '../kpi-org-scope/kpi-org-scope';
4
+ import { KpiScope } from '../kpi-scope/kpi-scope';
5
+ /**
6
+ * KPI 통계 계산 서비스
7
+ * KpiValue 데이터로부터 통계값을 계산하여 KpiStatistic에 저장
8
+ */
9
+ export declare class KpiStatisticCalculationService {
10
+ /**
11
+ * 전체 KPI에 대해 통계를 계산
12
+ */
13
+ static calculateAllStatistics(periodType: KpiPeriodType, valueDate: string, context: ResolverContext): Promise<KpiStatistic[]>;
14
+ /**
15
+ * 특정 KPI의 통계를 계산
16
+ */
17
+ static calculateKpiStatistics(kpiId: string, periodType: KpiPeriodType, valueDate: string, kpiOrgScope: KpiOrgScope | null, context: ResolverContext): Promise<KpiStatistic | null>;
18
+ /**
19
+ * 스코프별 통계 계산 (KpiScope 기반)
20
+ */
21
+ static calculateScopedStatistics(kpiId: string, periodType: KpiPeriodType, valueDate: string, context: ResolverContext): Promise<KpiStatistic[]>;
22
+ /**
23
+ * 특정 스코프 차원별 통계 계산
24
+ */
25
+ static calculateStatisticsByScope(kpiId: string, periodType: KpiPeriodType, valueDate: string, kpiScope: KpiScope, context: ResolverContext): Promise<KpiStatistic[]>;
26
+ /**
27
+ * 스코프 값별 집계 통계 계산 (예: 서울 전체 평균)
28
+ */
29
+ private static calculateAggregatedScopeStatistics;
30
+ /**
31
+ * 특정 스코프 필드의 유니크한 값들 조회
32
+ */
33
+ private static getDistinctScopeValues;
34
+ /**
35
+ * 통계값 계산 로직
36
+ */
37
+ private static calculateStatistics;
38
+ /**
39
+ * 왜도 계산
40
+ */
41
+ private static calculateSkewness;
42
+ /**
43
+ * 첨도 계산
44
+ */
45
+ private static calculateKurtosis;
46
+ /**
47
+ * 기간 타입에 따른 날짜 필터 생성
48
+ */
49
+ private static buildDateFilter;
50
+ }