@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
@@ -1,9 +1,11 @@
1
1
  import { getRepository } from '@things-factory/shell'
2
+ import type ResolverContext from '@things-factory/auth-base'
2
3
  import { DataSummary } from '@things-factory/dataset'
3
4
  import { finalizeLatestDataCollection } from '@things-factory/dataset/dist-server/controllers/finalize-data-collection'
4
5
  import { KpiMetric } from './kpi-metric'
5
6
  import { KpiValue, KpiValueInputType } from '../kpi-value/kpi-value'
6
7
  import { Kpi } from '../kpi/kpi'
8
+ import { KpiOrgScope } from '../kpi-org-scope/kpi-org-scope'
7
9
  import { KpiFormulaService } from '../kpi/kpi-formula.service'
8
10
 
9
11
  /**
@@ -38,7 +40,7 @@ export async function aggregateKpiMetricValue(metricId: string, domainId: string
38
40
  date: summary.date,
39
41
  period: summary.period,
40
42
  value: summary.summary[metric.fieldName],
41
- group: {
43
+ org: {
42
44
  key01: summary.key01,
43
45
  key02: summary.key02,
44
46
  key03: summary.key03,
@@ -56,32 +58,74 @@ export async function aggregateKpiMetricValue(metricId: string, domainId: string
56
58
  const kpi = await getRepository(Kpi).findOne({ where: { name: metric.name, domain: { id: domainId } } })
57
59
  if (!kpi) throw new Error('KPI 정보 없음 (metric.name과 동일한 KPI name 기준, 실제 연동 구조에 맞게 보완 필요)')
58
60
 
59
- // KPI Value version, valueDate, group 등 매핑
61
+ // KPI Value version, valueDate, org 등 매핑
60
62
  const savedValues = []
63
+ const kpiOrgScopeRepo = getRepository(KpiOrgScope, context.state?.tx)
64
+ const kpiValueRepo = getRepository(KpiValue, context.state?.tx)
65
+
61
66
  for (const v of values) {
62
67
  const valueDate = v.date
63
- const group = v.group
68
+ const orgData = v.org
64
69
  const version = kpi.version || 1
65
70
  const value = v.value
66
71
  if (value == null || isNaN(value)) continue
67
- // upsert(동일 KPI, valueDate, group, version) 기준으로 저장
68
- const repo = getRepository(KpiValue, context.state?.tx)
69
- const existing = await repo.findOne({
70
- where: { kpi: { id: kpi.id }, valueDate, group, version, domain: { id: domainId } }
72
+
73
+ // KpiOrgScope 찾기 또는 생성
74
+ let kpiOrgScope: KpiOrgScope | null = null
75
+
76
+ // key들로 조합된 org 식별자 생성
77
+ const orgIdentifier =
78
+ [orgData.key01, orgData.key02, orgData.key03, orgData.key04, orgData.key05].filter(Boolean).join('-') ||
79
+ 'unknown-org'
80
+
81
+ // 기존 KpiOrgScope 조회 (entityName 기준)
82
+ kpiOrgScope = await kpiOrgScopeRepo.findOne({
83
+ where: { entityName: orgIdentifier, domain: { id: domainId } }
71
84
  })
72
- let entity = existing || repo.create()
85
+
86
+ // 없으면 새로 생성
87
+ if (!kpiOrgScope) {
88
+ kpiOrgScope = await kpiOrgScopeRepo.save({
89
+ entityType: 'DataSummary', // DataSummary에서 온 데이터임을 표시
90
+ entityId: `datasummary-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
91
+ entityName: orgIdentifier,
92
+ org: orgIdentifier, // legacy field
93
+ scope01: orgData.key01,
94
+ scope02: orgData.key02,
95
+ scope03: orgData.key03,
96
+ scope04: orgData.key04,
97
+ scope05: orgData.key05,
98
+ domain: kpi.domain,
99
+ creator: context.state?.user,
100
+ updater: context.state?.user
101
+ })
102
+ }
103
+
104
+ // upsert KpiValue (동일 KPI, valueDate, kpiOrgScope, version 기준)
105
+ const existing = await kpiValueRepo.findOne({
106
+ where: {
107
+ kpi: { id: kpi.id },
108
+ valueDate,
109
+ kpiOrgScope: { id: kpiOrgScope.id },
110
+ version,
111
+ domain: { id: domainId }
112
+ }
113
+ })
114
+
115
+ let entity = existing || kpiValueRepo.create()
73
116
  entity.kpi = kpi
74
117
  entity.kpiId = kpi.id
75
118
  entity.version = version
76
119
  entity.valueDate = valueDate
77
120
  entity.value = value
78
- entity.group = group
121
+ entity.kpiOrgScope = kpiOrgScope
122
+ entity.kpiOrgScopeId = kpiOrgScope.id
79
123
  entity.inputType = KpiValueInputType.AUTO
80
- entity.source = 'AUTO'
124
+ entity.source = 'AUTO-AGGREGATE'
81
125
  entity.domain = kpi.domain
82
126
  entity.creator = context.state?.user
83
127
  entity.updater = context.state?.user
84
- entity = await repo.save(entity)
128
+ entity = await kpiValueRepo.save(entity)
85
129
  savedValues.push(entity)
86
130
  }
87
131
  return savedValues
@@ -47,7 +47,7 @@ export class KpiMetricValueMutation {
47
47
  valueDate,
48
48
  periodType,
49
49
  value: metricValue.value,
50
- group: metricValue.group,
50
+ org: metricValue.org,
51
51
  unit: metricValue.unit,
52
52
  meta: metricValue.meta,
53
53
  domain: domain,
@@ -60,14 +60,14 @@ export class KpiMetricValueMutation {
60
60
 
61
61
  @Directive('@transaction')
62
62
  @Directive('@privilege(category: "kpi", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)')
63
- @Mutation(returns => KpiMetricValue, { description: 'Record a metric value by metric name, value, meta, and group.' })
63
+ @Mutation(returns => KpiMetricValue, { description: 'Record a metric value by metric name, value, meta, and org.' })
64
64
  async recordKpiMetricValue(
65
65
  @Arg('metricName', { description: 'Metric code/name.' }) metricName: string,
66
66
  @Arg('value', type => Float, { nullable: true, description: 'Metric value (number).' }) value: number | null,
67
67
  @Arg('meta', type => ScalarObject, { nullable: true, description: 'Extended or non-numeric information (JSON).' })
68
68
  meta: any,
69
- @Arg('group', { nullable: true, description: 'Group key for this value (organization, line, user, etc.)' })
70
- group: string | null,
69
+ @Arg('org', { nullable: true, description: 'Organizational unit for this value (project, department, company, employee, etc.)' })
70
+ org: string | null,
71
71
  @Ctx() context: ResolverContext
72
72
  ): Promise<KpiMetricValue> {
73
73
  const { domain, user, tx } = context.state
@@ -84,7 +84,7 @@ export class KpiMetricValueMutation {
84
84
  metric: { id: metric.id },
85
85
  valueDate,
86
86
  periodType,
87
- group,
87
+ org,
88
88
  domain: { id: domain.id }
89
89
  }
90
90
  })
@@ -100,7 +100,7 @@ export class KpiMetricValueMutation {
100
100
  meta,
101
101
  valueDate,
102
102
  periodType,
103
- group,
103
+ org,
104
104
  domain,
105
105
  creator: user,
106
106
  updater: user
@@ -29,8 +29,8 @@ export class NewKpiMetricValue {
29
29
  })
30
30
  meta?: any
31
31
 
32
- @Field({ nullable: true, description: 'Group key for this value (organization, line, user, etc.)' })
33
- group?: string
32
+ @Field({ nullable: true, description: 'Organizational unit for this value (project, department, company, employee, etc.)' })
33
+ org?: string
34
34
  }
35
35
 
36
36
  @InputType({
@@ -65,8 +65,8 @@ export class KpiMetricValuePatch {
65
65
  })
66
66
  meta?: any
67
67
 
68
- @Field({ nullable: true, description: 'Group key for this value (organization, line, user, etc.)' })
69
- group?: string
68
+ @Field({ nullable: true, description: 'Organizational unit for this value (project, department, company, employee, etc.)' })
69
+ org?: string
70
70
 
71
71
  @Field({ nullable: true, description: 'Custom flag for update operations (internal use).' })
72
72
  cuFlag?: string
@@ -16,7 +16,7 @@ import { KpiPeriodType } from '../kpi/kpi'
16
16
  import { User } from '@things-factory/auth-base'
17
17
 
18
18
  @Entity()
19
- @Index('ix_kpi_metric_value_latest', ['domain', 'metric', 'valueDate', 'group'], { unique: true })
19
+ @Index('ix_kpi_metric_value_latest', ['domain', 'metric', 'valueDate', 'org'], { unique: true })
20
20
  @ObjectType({ description: 'Current value for each KPI metric (can be used for both state and history).' })
21
21
  export class KpiMetricValue {
22
22
  @PrimaryGeneratedColumn('uuid')
@@ -60,8 +60,8 @@ export class KpiMetricValue {
60
60
  periodType: KpiPeriodType
61
61
 
62
62
  @Column({ default: '' })
63
- @Field({ nullable: true, description: 'Group key for this value (organization, line, user, etc.)' })
64
- group?: string
63
+ @Field({ nullable: true, description: 'Organizational unit for this value (project, department, company, employee, etc.)' })
64
+ org?: string
65
65
 
66
66
  @Column({ type: 'simple-json', nullable: true })
67
67
  @Field(type => ScalarObject, { nullable: true })
@@ -0,0 +1,6 @@
1
+ import { KpiOrgScope } from './kpi-org-scope'
2
+ import { KpiOrgScopeQuery } from './kpi-org-scope-query'
3
+ import { KpiOrgScopeMutation } from './kpi-org-scope-mutation'
4
+
5
+ export const entities = [KpiOrgScope]
6
+ export const resolvers = [KpiOrgScopeQuery, KpiOrgScopeMutation]
@@ -0,0 +1,173 @@
1
+ import { Resolver, Mutation, Arg, Ctx, Directive } from 'type-graphql'
2
+ import { In } from 'typeorm'
3
+ import { getRepository } from '@things-factory/shell'
4
+
5
+ import { KpiOrgScope } from './kpi-org-scope'
6
+ import { NewKpiOrgScope, KpiOrgScopePatch } from './kpi-org-scope-type'
7
+
8
+ @Resolver(KpiOrgScope)
9
+ export class KpiOrgScopeMutation {
10
+ @Directive('@privilege(category: "kpi", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)')
11
+ @Directive('@transaction')
12
+ @Mutation(returns => KpiOrgScope, { description: 'Create a new KPI org-scope mapping with the provided details.' })
13
+ async createKpiOrgScope(
14
+ @Arg('kpiOrgScope', { description: 'Input object containing details for the new org-scope mapping.' })
15
+ kpiOrgScope: NewKpiOrgScope,
16
+ @Ctx() context: ResolverContext
17
+ ): Promise<KpiOrgScope> {
18
+ const { domain, user, tx } = context.state
19
+
20
+ // Check if org already exists for this domain
21
+ const existingOrgScope = await getRepository(KpiOrgScope, tx).findOne({
22
+ where: { domain: { id: domain.id }, org: kpiOrgScope.org }
23
+ })
24
+
25
+ if (existingOrgScope) {
26
+ throw new Error(`Organization '${kpiOrgScope.org}' already has a scope mapping in this domain`)
27
+ }
28
+
29
+ const entity: Partial<KpiOrgScope> = {
30
+ ...kpiOrgScope,
31
+ domain,
32
+ creator: user,
33
+ updater: user
34
+ }
35
+
36
+ return await getRepository(KpiOrgScope, tx).save(entity)
37
+ }
38
+
39
+ @Directive('@privilege(category: "kpi", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)')
40
+ @Directive('@transaction')
41
+ @Mutation(returns => [KpiOrgScope], {
42
+ description: 'Update multiple KPI org-scope mappings with the provided patches.'
43
+ })
44
+ async updateMultipleKpiOrgScope(
45
+ @Arg('patches', type => [KpiOrgScopePatch], {
46
+ description: 'Array of patch objects for updating org-scope mappings.'
47
+ })
48
+ patches: KpiOrgScopePatch[],
49
+ @Ctx() context: ResolverContext
50
+ ): Promise<KpiOrgScope[]> {
51
+ const { domain, user, tx } = context.state
52
+
53
+ const ids = patches.map(patch => patch.id)
54
+ const existingOrgScopes = await getRepository(KpiOrgScope, tx).find({
55
+ where: {
56
+ domain: { id: domain.id },
57
+ id: In(ids)
58
+ }
59
+ })
60
+
61
+ if (existingOrgScopes.length !== patches.length) {
62
+ throw new Error('Some org-scope mappings not found or not accessible')
63
+ }
64
+
65
+ const updatedOrgScopes: KpiOrgScope[] = []
66
+
67
+ for (const patch of patches) {
68
+ const existingOrgScope = existingOrgScopes.find(os => os.id === patch.id)
69
+ if (!existingOrgScope) continue
70
+
71
+ // Check if org is being changed and if new org already exists
72
+ if (patch.org && patch.org !== existingOrgScope.org) {
73
+ const duplicateOrgScope = await getRepository(KpiOrgScope, tx).findOne({
74
+ where: {
75
+ domain: { id: domain.id },
76
+ org: patch.org,
77
+ id: In(ids.filter(id => id !== patch.id))
78
+ }
79
+ })
80
+ if (duplicateOrgScope) {
81
+ throw new Error(`Organization '${patch.org}' already has a scope mapping in this domain`)
82
+ }
83
+ }
84
+
85
+ const updatedEntity: Partial<KpiOrgScope> = {
86
+ ...existingOrgScope,
87
+ ...patch,
88
+ updater: user,
89
+ updatedAt: new Date()
90
+ }
91
+
92
+ const savedOrgScope = await getRepository(KpiOrgScope, tx).save(updatedEntity)
93
+ updatedOrgScopes.push(savedOrgScope)
94
+ }
95
+
96
+ return updatedOrgScopes
97
+ }
98
+
99
+ @Directive('@privilege(category: "kpi", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)')
100
+ @Directive('@transaction')
101
+ @Mutation(returns => Boolean, { description: 'Delete KPI org-scope mappings by their IDs.' })
102
+ async deleteKpiOrgScopes(
103
+ @Arg('ids', type => [String], { description: 'Array of org-scope mapping IDs to delete.' }) ids: string[],
104
+ @Ctx() context: ResolverContext
105
+ ): Promise<boolean> {
106
+ const { domain, tx } = context.state
107
+
108
+ const existingOrgScopes = await getRepository(KpiOrgScope, tx).find({
109
+ where: {
110
+ domain: { id: domain.id },
111
+ id: In(ids)
112
+ }
113
+ })
114
+
115
+ if (existingOrgScopes.length === 0) {
116
+ throw new Error('No org-scope mappings found to delete')
117
+ }
118
+
119
+ // Soft delete
120
+ await getRepository(KpiOrgScope, tx).softDelete(existingOrgScopes.map(os => os.id))
121
+
122
+ return true
123
+ }
124
+
125
+ @Directive('@privilege(category: "kpi", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)')
126
+ @Directive('@transaction')
127
+ @Mutation(returns => [KpiOrgScope], { description: 'Bulk create or update KPI org-scope mappings.' })
128
+ async bulkUpsertKpiOrgScopes(
129
+ @Arg('orgScopes', type => [NewKpiOrgScope], { description: 'Array of org-scope mapping data for bulk upsert.' })
130
+ orgScopes: NewKpiOrgScope[],
131
+ @Ctx() context: ResolverContext
132
+ ): Promise<KpiOrgScope[]> {
133
+ const { domain, user, tx } = context.state
134
+
135
+ const orgs = orgScopes.map(os => os.org)
136
+ const existingOrgScopes = await getRepository(KpiOrgScope, tx).find({
137
+ where: {
138
+ domain: { id: domain.id },
139
+ org: In(orgs)
140
+ }
141
+ })
142
+
143
+ const results: KpiOrgScope[] = []
144
+
145
+ for (const orgScopeData of orgScopes) {
146
+ const existing = existingOrgScopes.find(os => os.org === orgScopeData.org)
147
+
148
+ if (existing) {
149
+ // Update existing
150
+ const updatedEntity: Partial<KpiOrgScope> = {
151
+ ...existing,
152
+ ...orgScopeData,
153
+ updater: user,
154
+ updatedAt: new Date()
155
+ }
156
+ const updated = await getRepository(KpiOrgScope, tx).save(updatedEntity)
157
+ results.push(updated)
158
+ } else {
159
+ // Create new
160
+ const newEntity: Partial<KpiOrgScope> = {
161
+ ...orgScopeData,
162
+ domain,
163
+ creator: user,
164
+ updater: user
165
+ }
166
+ const saved = await getRepository(KpiOrgScope, tx).save(newEntity)
167
+ results.push(saved)
168
+ }
169
+ }
170
+
171
+ return results
172
+ }
173
+ }
@@ -0,0 +1,127 @@
1
+ import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx, Directive } from 'type-graphql'
2
+ import { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'
3
+ import { User } from '@things-factory/auth-base'
4
+
5
+ import { KpiOrgScope } from './kpi-org-scope'
6
+ import { KpiOrgScopeList } from './kpi-org-scope-type'
7
+
8
+ @Resolver(KpiOrgScope)
9
+ export class KpiOrgScopeQuery {
10
+ @Directive('@privilege(category: "kpi", privilege: "query", domainOwnerGranted: true, superUserGranted: true)')
11
+ @Query(returns => KpiOrgScope!, {
12
+ nullable: true,
13
+ description: 'Fetch a single KPI org-scope mapping by its unique identifier.'
14
+ })
15
+ async kpiOrgScope(
16
+ @Arg('id', { description: 'Unique identifier of the org-scope mapping to fetch.' }) id: string,
17
+ @Ctx() context: ResolverContext
18
+ ): Promise<KpiOrgScope> {
19
+ const { domain } = context.state
20
+
21
+ return await getRepository(KpiOrgScope).findOne({
22
+ where: { domain: { id: domain.id }, id }
23
+ })
24
+ }
25
+
26
+ @Directive('@privilege(category: "kpi", privilege: "query", domainOwnerGranted: true, superUserGranted: true)')
27
+ @Query(returns => KpiOrgScopeList, {
28
+ description: 'Fetch multiple KPI org-scope mappings with filters and pagination'
29
+ })
30
+ async kpiOrgScopes(
31
+ @Args(type => ListParam) params: ListParam,
32
+ @Ctx() context: ResolverContext
33
+ ): Promise<KpiOrgScopeList> {
34
+ const { domain } = context.state
35
+
36
+ const queryBuilder = getQueryBuilderFromListParams({
37
+ domain,
38
+ params,
39
+ repository: await getRepository(KpiOrgScope),
40
+ searchables: ['org', 'scope01', 'scope02', 'scope03', 'scope04', 'scope05']
41
+ })
42
+
43
+ const [items, total] = await queryBuilder.getManyAndCount()
44
+
45
+ return { items, total }
46
+ }
47
+
48
+ @Directive('@privilege(category: "kpi", privilege: "query", domainOwnerGranted: true, superUserGranted: true)')
49
+ @Query(returns => [String], { description: 'Get distinct values for a specific scope field' })
50
+ async kpiOrgScopeValues(
51
+ @Arg('scopeField', { description: 'Scope field to get distinct values from' })
52
+ scopeField: 'scope01' | 'scope02' | 'scope03' | 'scope04' | 'scope05',
53
+ @Ctx() context: ResolverContext,
54
+ @Arg('searchTerm', { nullable: true, description: 'Optional search term to filter values' }) searchTerm?: string
55
+ ): Promise<string[]> {
56
+ const { domain } = context.state
57
+
58
+ const queryBuilder = getRepository(KpiOrgScope)
59
+ .createQueryBuilder('orgScope')
60
+ .select(`DISTINCT orgScope.${scopeField}`, 'value')
61
+ .where('orgScope.domain_id = :domainId', { domainId: domain.id })
62
+ .andWhere(`orgScope.${scopeField} IS NOT NULL`)
63
+ .andWhere(`orgScope.${scopeField} != ''`)
64
+ .andWhere('orgScope.active = true')
65
+
66
+ if (searchTerm) {
67
+ queryBuilder.andWhere(`orgScope.${scopeField} ILIKE :searchTerm`, {
68
+ searchTerm: `%${searchTerm}%`
69
+ })
70
+ }
71
+
72
+ const results = await queryBuilder.getRawMany()
73
+ return results.map(r => r.value).filter(v => v)
74
+ }
75
+
76
+ @Directive('@privilege(category: "kpi", privilege: "query", domainOwnerGranted: true, superUserGranted: true)')
77
+ @Query(returns => [String], { description: 'Get distinct org values' })
78
+ async kpiOrgValues(
79
+ @Ctx() context: ResolverContext,
80
+ @Arg('searchTerm', { nullable: true, description: 'Optional search term to filter org values' }) searchTerm?: string
81
+ ): Promise<string[]> {
82
+ const { domain } = context.state
83
+
84
+ const queryBuilder = getRepository(KpiOrgScope)
85
+ .createQueryBuilder('orgScope')
86
+ .select('DISTINCT orgScope.org', 'value')
87
+ .where('orgScope.domain_id = :domainId', { domainId: domain.id })
88
+ .andWhere('orgScope.active = true')
89
+
90
+ if (searchTerm) {
91
+ queryBuilder.andWhere('orgScope.org ILIKE :searchTerm', {
92
+ searchTerm: `%${searchTerm}%`
93
+ })
94
+ }
95
+
96
+ const results = await queryBuilder.getRawMany()
97
+ return results.map(r => r.value)
98
+ }
99
+
100
+ @Directive('@privilege(category: "kpi", privilege: "query", domainOwnerGranted: true, superUserGranted: true)')
101
+ @Query(returns => KpiOrgScope, { nullable: true, description: 'Find org-scope mapping by org identifier' })
102
+ async kpiOrgScopeByOrg(
103
+ @Arg('org', { description: 'Organization identifier to search for' }) org: string,
104
+ @Ctx() context: ResolverContext
105
+ ): Promise<KpiOrgScope | undefined> {
106
+ const { domain } = context.state
107
+
108
+ return await getRepository(KpiOrgScope).findOne({
109
+ where: { domain: { id: domain.id }, org }
110
+ })
111
+ }
112
+
113
+ @FieldResolver(type => Domain)
114
+ async domain(@Root() kpiOrgScope: KpiOrgScope): Promise<Domain> {
115
+ return kpiOrgScope.domainId && (await getRepository(Domain).findOneBy({ id: kpiOrgScope.domainId }))
116
+ }
117
+
118
+ @FieldResolver(type => User)
119
+ async creator(@Root() kpiOrgScope: KpiOrgScope): Promise<User> {
120
+ return kpiOrgScope.creatorId && (await getRepository(User).findOneBy({ id: kpiOrgScope.creatorId }))
121
+ }
122
+
123
+ @FieldResolver(type => User)
124
+ async updater(@Root() kpiOrgScope: KpiOrgScope): Promise<User> {
125
+ return kpiOrgScope.updaterId && (await getRepository(User).findOneBy({ id: kpiOrgScope.updaterId }))
126
+ }
127
+ }
@@ -0,0 +1,68 @@
1
+ import { InputType, Field, ID, ObjectType, Int } from 'type-graphql'
2
+ import { KpiOrgScope } from './kpi-org-scope'
3
+
4
+ @InputType({ description: 'Input type for creating a new KPI org-scope mapping' })
5
+ export class NewKpiOrgScope {
6
+ @Field({ description: 'Organizational unit identifier' })
7
+ org: string
8
+
9
+ @Field({ nullable: true, description: 'First scope dimension' })
10
+ scope01?: string
11
+
12
+ @Field({ nullable: true, description: 'Second scope dimension' })
13
+ scope02?: string
14
+
15
+ @Field({ nullable: true, description: 'Third scope dimension' })
16
+ scope03?: string
17
+
18
+ @Field({ nullable: true, description: 'Fourth scope dimension' })
19
+ scope04?: string
20
+
21
+ @Field({ nullable: true, description: 'Fifth scope dimension' })
22
+ scope05?: string
23
+
24
+ @Field({ nullable: true, description: 'Human-readable name or description' })
25
+ displayName?: string
26
+
27
+ @Field({ nullable: true, description: 'Active status' })
28
+ active?: boolean
29
+ }
30
+
31
+ @InputType({ description: 'Input type for updating an existing KPI org-scope mapping' })
32
+ export class KpiOrgScopePatch {
33
+ @Field(type => ID, { description: 'ID of the org-scope mapping to update' })
34
+ id: string
35
+
36
+ @Field({ nullable: true, description: 'Organizational unit identifier' })
37
+ org?: string
38
+
39
+ @Field({ nullable: true, description: 'First scope dimension' })
40
+ scope01?: string
41
+
42
+ @Field({ nullable: true, description: 'Second scope dimension' })
43
+ scope02?: string
44
+
45
+ @Field({ nullable: true, description: 'Third scope dimension' })
46
+ scope03?: string
47
+
48
+ @Field({ nullable: true, description: 'Fourth scope dimension' })
49
+ scope04?: string
50
+
51
+ @Field({ nullable: true, description: 'Fifth scope dimension' })
52
+ scope05?: string
53
+
54
+ @Field({ nullable: true, description: 'Human-readable name or description' })
55
+ displayName?: string
56
+
57
+ @Field({ nullable: true, description: 'Active status' })
58
+ active?: boolean
59
+ }
60
+
61
+ @ObjectType({ description: 'List of KPI org-scope mappings with pagination' })
62
+ export class KpiOrgScopeList {
63
+ @Field(type => [KpiOrgScope], { description: 'Array of KPI org-scope mappings' })
64
+ items: KpiOrgScope[]
65
+
66
+ @Field(type => Int, { description: 'Total count of items' })
67
+ total: number
68
+ }