@things-factory/kpi 1.0.0-alpha.5 → 9.0.9

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 (309) hide show
  1. package/README.md +74 -0
  2. package/client/pages/kpi/kpi-list-page.ts +97 -47
  3. package/client/pages/kpi/kpi-overview-sample.ts +260 -0
  4. package/client/pages/kpi/kpi-overview.ts +271 -0
  5. package/client/pages/kpi-category/kpi-category-list-page.ts +39 -50
  6. package/client/pages/kpi-dashboard/kpi-alert-panel.ts +114 -0
  7. package/client/pages/kpi-dashboard/kpi-dashboard.ts +285 -0
  8. package/client/pages/kpi-dashboard/kpi-grade-visualization.ts +75 -0
  9. package/client/pages/kpi-dashboard/kpi-history-viewer.ts +58 -0
  10. package/client/pages/kpi-dashboard/kpi-list-summary.ts +100 -0
  11. package/client/pages/kpi-dashboard/kpi-performance-summary.ts +124 -0
  12. package/client/pages/kpi-dashboard/kpi-value-entry.ts +78 -0
  13. package/client/pages/kpi-grade/kpi-grade-list-page.ts +58 -68
  14. package/client/pages/kpi-history/kpi-history-list-page.ts +146 -0
  15. package/client/pages/kpi-metric/kpi-metric-list-page.ts +67 -63
  16. package/client/pages/kpi-value/kpi-value-list-page.ts +73 -72
  17. package/client/pages/kpi-value/kpi-value-manual-entry-form.ts +168 -0
  18. package/client/pages/kpi-value/kpi-value-manual-entry-page.ts +173 -0
  19. package/client/route.ts +35 -0
  20. package/dist-client/pages/kpi/kpi-importer.js +16 -17
  21. package/dist-client/pages/kpi/kpi-importer.js.map +1 -1
  22. package/dist-client/pages/kpi/kpi-list-page.js +128 -68
  23. package/dist-client/pages/kpi/kpi-list-page.js.map +1 -1
  24. package/dist-client/pages/kpi/kpi-overview-sample.d.ts +36 -0
  25. package/dist-client/pages/kpi/kpi-overview-sample.js +264 -0
  26. package/dist-client/pages/kpi/kpi-overview-sample.js.map +1 -0
  27. package/dist-client/pages/kpi/kpi-overview.d.ts +14 -0
  28. package/dist-client/pages/kpi/kpi-overview.js +290 -0
  29. package/dist-client/pages/kpi/kpi-overview.js.map +1 -0
  30. package/dist-client/pages/kpi-category/kpi-category-importer.js +16 -17
  31. package/dist-client/pages/kpi-category/kpi-category-importer.js.map +1 -1
  32. package/dist-client/pages/kpi-category/kpi-category-list-page.js +70 -71
  33. package/dist-client/pages/kpi-category/kpi-category-list-page.js.map +1 -1
  34. package/dist-client/pages/kpi-dashboard/kpi-alert-panel.d.ts +18 -0
  35. package/dist-client/pages/kpi-dashboard/kpi-alert-panel.js +128 -0
  36. package/dist-client/pages/kpi-dashboard/kpi-alert-panel.js.map +1 -0
  37. package/dist-client/pages/kpi-dashboard/kpi-dashboard.d.ts +24 -0
  38. package/dist-client/pages/kpi-dashboard/kpi-dashboard.js +305 -0
  39. package/dist-client/pages/kpi-dashboard/kpi-dashboard.js.map +1 -0
  40. package/dist-client/pages/kpi-dashboard/kpi-grade-visualization.d.ts +12 -0
  41. package/dist-client/pages/kpi-dashboard/kpi-grade-visualization.js +82 -0
  42. package/dist-client/pages/kpi-dashboard/kpi-grade-visualization.js.map +1 -0
  43. package/dist-client/pages/kpi-dashboard/kpi-history-viewer.d.ts +11 -0
  44. package/dist-client/pages/kpi-dashboard/kpi-history-viewer.js +65 -0
  45. package/dist-client/pages/kpi-dashboard/kpi-history-viewer.js.map +1 -0
  46. package/dist-client/pages/kpi-dashboard/kpi-list-summary.d.ts +13 -0
  47. package/dist-client/pages/kpi-dashboard/kpi-list-summary.js +115 -0
  48. package/dist-client/pages/kpi-dashboard/kpi-list-summary.js.map +1 -0
  49. package/dist-client/pages/kpi-dashboard/kpi-performance-summary.d.ts +15 -0
  50. package/dist-client/pages/kpi-dashboard/kpi-performance-summary.js +139 -0
  51. package/dist-client/pages/kpi-dashboard/kpi-performance-summary.js.map +1 -0
  52. package/dist-client/pages/kpi-dashboard/kpi-value-entry.d.ts +7 -0
  53. package/dist-client/pages/kpi-dashboard/kpi-value-entry.js +86 -0
  54. package/dist-client/pages/kpi-dashboard/kpi-value-entry.js.map +1 -0
  55. package/dist-client/pages/kpi-grade/kpi-grade-importer.js +16 -17
  56. package/dist-client/pages/kpi-grade/kpi-grade-importer.js.map +1 -1
  57. package/dist-client/pages/kpi-grade/kpi-grade-list-page.js +89 -89
  58. package/dist-client/pages/kpi-grade/kpi-grade-list-page.js.map +1 -1
  59. package/dist-client/pages/kpi-history/kpi-history-list-page.d.ts +16 -0
  60. package/dist-client/pages/kpi-history/kpi-history-list-page.js +155 -0
  61. package/dist-client/pages/kpi-history/kpi-history-list-page.js.map +1 -0
  62. package/dist-client/pages/kpi-metric/kpi-metric-importer.js +16 -17
  63. package/dist-client/pages/kpi-metric/kpi-metric-importer.js.map +1 -1
  64. package/dist-client/pages/kpi-metric/kpi-metric-list-page.js +98 -84
  65. package/dist-client/pages/kpi-metric/kpi-metric-list-page.js.map +1 -1
  66. package/dist-client/pages/kpi-value/kpi-value-importer.js +16 -17
  67. package/dist-client/pages/kpi-value/kpi-value-importer.js.map +1 -1
  68. package/dist-client/pages/kpi-value/kpi-value-list-page.js +104 -93
  69. package/dist-client/pages/kpi-value/kpi-value-list-page.js.map +1 -1
  70. package/dist-client/pages/kpi-value/kpi-value-manual-entry-form.d.ts +14 -0
  71. package/dist-client/pages/kpi-value/kpi-value-manual-entry-form.js +201 -0
  72. package/dist-client/pages/kpi-value/kpi-value-manual-entry-form.js.map +1 -0
  73. package/dist-client/pages/kpi-value/kpi-value-manual-entry-page.d.ts +41 -0
  74. package/dist-client/pages/kpi-value/kpi-value-manual-entry-page.js +180 -0
  75. package/dist-client/pages/kpi-value/kpi-value-manual-entry-page.js.map +1 -0
  76. package/dist-client/route.d.ts +1 -1
  77. package/dist-client/route.js +27 -0
  78. package/dist-client/route.js.map +1 -1
  79. package/dist-client/tsconfig.tsbuildinfo +1 -1
  80. package/dist-server/index.d.ts +2 -1
  81. package/dist-server/index.js +2 -1
  82. package/dist-server/index.js.map +1 -1
  83. package/dist-server/migrations/1752188906708-SeedKpiCategory.d.ts +5 -0
  84. package/dist-server/migrations/1752188906708-SeedKpiCategory.js +56 -0
  85. package/dist-server/migrations/1752188906708-SeedKpiCategory.js.map +1 -0
  86. package/dist-server/migrations/1752190849681-SeedKpi.d.ts +5 -0
  87. package/dist-server/migrations/1752190849681-SeedKpi.js +107 -0
  88. package/dist-server/migrations/1752190849681-SeedKpi.js.map +1 -0
  89. package/dist-server/migrations/1752191090459-SeedKpiGrade.d.ts +5 -0
  90. package/dist-server/migrations/1752191090459-SeedKpiGrade.js +271 -0
  91. package/dist-server/migrations/1752191090459-SeedKpiGrade.js.map +1 -0
  92. package/dist-server/migrations/index.d.ts +1 -0
  93. package/dist-server/migrations/index.js +12 -0
  94. package/dist-server/migrations/index.js.map +1 -0
  95. package/dist-server/routes.d.ts +1 -0
  96. package/dist-server/routes.js +48 -0
  97. package/dist-server/routes.js.map +1 -1
  98. package/dist-server/service/index.d.ts +3 -4
  99. package/dist-server/service/index.js +4 -6
  100. package/dist-server/service/index.js.map +1 -1
  101. package/dist-server/service/kpi/aggregate-kpi.d.ts +8 -0
  102. package/dist-server/service/kpi/aggregate-kpi.js +88 -0
  103. package/dist-server/service/kpi/aggregate-kpi.js.map +1 -0
  104. package/dist-server/service/kpi/event-subscriber.d.ts +2 -0
  105. package/dist-server/service/kpi/event-subscriber.js +10 -0
  106. package/dist-server/service/kpi/event-subscriber.js.map +1 -1
  107. package/dist-server/service/kpi/index.d.ts +2 -1
  108. package/dist-server/service/kpi/kpi-formula.service.d.ts +24 -0
  109. package/dist-server/service/kpi/kpi-formula.service.js +64 -0
  110. package/dist-server/service/kpi/kpi-formula.service.js.map +1 -0
  111. package/dist-server/service/kpi/kpi-history.d.ts +6 -2
  112. package/dist-server/service/kpi/kpi-history.js +29 -11
  113. package/dist-server/service/kpi/kpi-history.js.map +1 -1
  114. package/dist-server/service/kpi/kpi-mutation.d.ts +2 -0
  115. package/dist-server/service/kpi/kpi-mutation.js +215 -10
  116. package/dist-server/service/kpi/kpi-mutation.js.map +1 -1
  117. package/dist-server/service/kpi/kpi-query.d.ts +10 -0
  118. package/dist-server/service/kpi/kpi-query.js +87 -3
  119. package/dist-server/service/kpi/kpi-query.js.map +1 -1
  120. package/dist-server/service/kpi/kpi-type.d.ts +14 -3
  121. package/dist-server/service/kpi/kpi-type.js +81 -18
  122. package/dist-server/service/kpi/kpi-type.js.map +1 -1
  123. package/dist-server/service/kpi/kpi.d.ts +14 -3
  124. package/dist-server/service/kpi/kpi.js +96 -19
  125. package/dist-server/service/kpi/kpi.js.map +1 -1
  126. package/dist-server/service/kpi-alert/index.d.ts +2 -0
  127. package/dist-server/service/kpi-alert/index.js +6 -0
  128. package/dist-server/service/kpi-alert/index.js.map +1 -0
  129. package/dist-server/service/kpi-alert/kpi-alert-query.d.ts +4 -0
  130. package/dist-server/service/kpi-alert/kpi-alert-query.js +71 -0
  131. package/dist-server/service/kpi-alert/kpi-alert-query.js.map +1 -0
  132. package/dist-server/service/kpi-alert/kpi-alert-type.d.ts +8 -0
  133. package/dist-server/service/kpi-alert/kpi-alert-type.js +33 -0
  134. package/dist-server/service/kpi-alert/kpi-alert-type.js.map +1 -0
  135. package/dist-server/service/kpi-category/kpi-category-mutation.d.ts +1 -1
  136. package/dist-server/service/kpi-category/kpi-category-mutation.js +36 -10
  137. package/dist-server/service/kpi-category/kpi-category-mutation.js.map +1 -1
  138. package/dist-server/service/kpi-category/kpi-category-query.d.ts +2 -0
  139. package/dist-server/service/kpi-category/kpi-category-query.js +18 -2
  140. package/dist-server/service/kpi-category/kpi-category-query.js.map +1 -1
  141. package/dist-server/service/kpi-category/kpi-category-type.d.ts +3 -5
  142. package/dist-server/service/kpi-category/kpi-category-type.js +16 -20
  143. package/dist-server/service/kpi-category/kpi-category-type.js.map +1 -1
  144. package/dist-server/service/kpi-category/kpi-category.d.ts +7 -9
  145. package/dist-server/service/kpi-category/kpi-category.js +40 -38
  146. package/dist-server/service/kpi-category/kpi-category.js.map +1 -1
  147. package/dist-server/service/kpi-grade/index.d.ts +1 -2
  148. package/dist-server/service/kpi-grade/index.js +2 -4
  149. package/dist-server/service/kpi-grade/index.js.map +1 -1
  150. package/dist-server/service/kpi-grade/kpi-grade-mutation.d.ts +1 -1
  151. package/dist-server/service/kpi-grade/kpi-grade-mutation.js +33 -10
  152. package/dist-server/service/kpi-grade/kpi-grade-mutation.js.map +1 -1
  153. package/dist-server/service/kpi-grade/kpi-grade-query.js +2 -2
  154. package/dist-server/service/kpi-grade/kpi-grade-query.js.map +1 -1
  155. package/dist-server/service/kpi-grade/kpi-grade-type.d.ts +13 -4
  156. package/dist-server/service/kpi-grade/kpi-grade-type.js +54 -18
  157. package/dist-server/service/kpi-grade/kpi-grade-type.js.map +1 -1
  158. package/dist-server/service/kpi-grade/kpi-grade.d.ts +8 -8
  159. package/dist-server/service/kpi-grade/kpi-grade.js +48 -40
  160. package/dist-server/service/kpi-grade/kpi-grade.js.map +1 -1
  161. package/dist-server/service/kpi-metric/aggregate-kpi-metric.d.ts +8 -0
  162. package/dist-server/service/kpi-metric/aggregate-kpi-metric.js +134 -0
  163. package/dist-server/service/kpi-metric/aggregate-kpi-metric.js.map +1 -0
  164. package/dist-server/service/kpi-metric/index.d.ts +1 -2
  165. package/dist-server/service/kpi-metric/index.js +2 -4
  166. package/dist-server/service/kpi-metric/index.js.map +1 -1
  167. package/dist-server/service/kpi-metric/kpi-metric-mutation.d.ts +1 -1
  168. package/dist-server/service/kpi-metric/kpi-metric-mutation.js +139 -13
  169. package/dist-server/service/kpi-metric/kpi-metric-mutation.js.map +1 -1
  170. package/dist-server/service/kpi-metric/kpi-metric-query.js +3 -3
  171. package/dist-server/service/kpi-metric/kpi-metric-query.js.map +1 -1
  172. package/dist-server/service/kpi-metric/kpi-metric-type.d.ts +17 -4
  173. package/dist-server/service/kpi-metric/kpi-metric-type.js +69 -11
  174. package/dist-server/service/kpi-metric/kpi-metric-type.js.map +1 -1
  175. package/dist-server/service/kpi-metric/kpi-metric.d.ts +11 -8
  176. package/dist-server/service/kpi-metric/kpi-metric.js +62 -37
  177. package/dist-server/service/kpi-metric/kpi-metric.js.map +1 -1
  178. package/dist-server/service/kpi-value/kpi-value-mutation.js +66 -11
  179. package/dist-server/service/kpi-value/kpi-value-mutation.js.map +1 -1
  180. package/dist-server/service/kpi-value/kpi-value-query.d.ts +2 -0
  181. package/dist-server/service/kpi-value/kpi-value-query.js +15 -2
  182. package/dist-server/service/kpi-value/kpi-value-query.js.map +1 -1
  183. package/dist-server/service/kpi-value/kpi-value-type.d.ts +19 -10
  184. package/dist-server/service/kpi-value/kpi-value-type.js +87 -24
  185. package/dist-server/service/kpi-value/kpi-value-type.js.map +1 -1
  186. package/dist-server/service/kpi-value/kpi-value.d.ts +15 -9
  187. package/dist-server/service/kpi-value/kpi-value.js +86 -32
  188. package/dist-server/service/kpi-value/kpi-value.js.map +1 -1
  189. package/dist-server/tsconfig.tsbuildinfo +1 -1
  190. package/implement-plan/01-entity-type-resolver.md +57 -0
  191. package/implement-plan/02-dataset-integration.md +35 -0
  192. package/implement-plan/03-kpivalue-automation.md +34 -0
  193. package/implement-plan/04-version-history.md +33 -0
  194. package/implement-plan/05-grade-visualization.md +33 -0
  195. package/implement-plan/06-graphql-frontend.md +30 -0
  196. package/implement-plan/07-test-docs.md +35 -0
  197. package/implement-plan/TODO.md +41 -0
  198. package/package.json +18 -6
  199. package/server/index.ts +2 -1
  200. package/server/migrations/1752188906708-SeedKpiCategory.ts +61 -0
  201. package/server/migrations/1752190849681-SeedKpi.ts +112 -0
  202. package/server/migrations/1752191090459-SeedKpiGrade.ts +270 -0
  203. package/server/migrations/index.ts +9 -0
  204. package/server/routes.ts +55 -0
  205. package/server/service/index.ts +4 -6
  206. package/server/service/kpi/aggregate-kpi.ts +82 -0
  207. package/server/service/kpi/event-subscriber.ts +12 -0
  208. package/server/service/kpi/kpi-formula.service.ts +63 -0
  209. package/server/service/kpi/kpi-history.ts +29 -21
  210. package/server/service/kpi/kpi-mutation.ts +194 -12
  211. package/server/service/kpi/kpi-query.ts +57 -2
  212. package/server/service/kpi/kpi-type.ts +72 -19
  213. package/server/service/kpi/kpi.ts +96 -20
  214. package/server/service/kpi-alert/index.ts +3 -0
  215. package/server/service/kpi-alert/kpi-alert-query.ts +59 -0
  216. package/server/service/kpi-alert/kpi-alert-type.ts +20 -0
  217. package/server/service/kpi-category/kpi-category-mutation.ts +17 -4
  218. package/server/service/kpi-category/kpi-category-query.ts +20 -3
  219. package/server/service/kpi-category/kpi-category-type.ts +17 -19
  220. package/server/service/kpi-category/kpi-category.ts +39 -37
  221. package/server/service/kpi-grade/index.ts +2 -4
  222. package/server/service/kpi-grade/kpi-grade-mutation.ts +13 -4
  223. package/server/service/kpi-grade/kpi-grade-query.ts +5 -2
  224. package/server/service/kpi-grade/kpi-grade-type.ts +46 -19
  225. package/server/service/kpi-grade/kpi-grade.ts +44 -38
  226. package/server/service/kpi-metric/aggregate-kpi-metric.ts +128 -0
  227. package/server/service/kpi-metric/index.ts +2 -4
  228. package/server/service/kpi-metric/kpi-metric-mutation.ts +123 -7
  229. package/server/service/kpi-metric/kpi-metric-query.ts +9 -3
  230. package/server/service/kpi-metric/kpi-metric-type.ts +56 -13
  231. package/server/service/kpi-metric/kpi-metric.ts +55 -35
  232. package/server/service/kpi-value/kpi-value-mutation.ts +52 -14
  233. package/server/service/kpi-value/kpi-value-query.ts +12 -2
  234. package/server/service/kpi-value/kpi-value-type.ts +80 -25
  235. package/server/service/kpi-value/kpi-value.ts +81 -29
  236. package/things-factory.config.js +12 -4
  237. package/translations/en.json +12 -1
  238. package/translations/ja.json +12 -1
  239. package/translations/ko.json +12 -1
  240. package/translations/ms.json +12 -1
  241. package/translations/zh.json +12 -1
  242. package/client/pages/kpe-metric/kpe-metric-importer.ts +0 -90
  243. package/client/pages/kpe-metric/kpe-metric-list-page.ts +0 -398
  244. package/client/pages/kpi-formula/kpi-formula-importer.ts +0 -90
  245. package/client/pages/kpi-formula/kpi-formula-list-page.ts +0 -398
  246. package/client/pages/metric/metric-importer.ts +0 -90
  247. package/client/pages/metric/metric-list-page.ts +0 -398
  248. package/dist-client/pages/kpe-metric/kpe-metric-importer.d.ts +0 -23
  249. package/dist-client/pages/kpe-metric/kpe-metric-importer.js +0 -93
  250. package/dist-client/pages/kpe-metric/kpe-metric-importer.js.map +0 -1
  251. package/dist-client/pages/kpe-metric/kpe-metric-list-page.d.ts +0 -66
  252. package/dist-client/pages/kpe-metric/kpe-metric-list-page.js +0 -370
  253. package/dist-client/pages/kpe-metric/kpe-metric-list-page.js.map +0 -1
  254. package/dist-client/pages/kpi-formula/kpi-formula-importer.d.ts +0 -23
  255. package/dist-client/pages/kpi-formula/kpi-formula-importer.js +0 -93
  256. package/dist-client/pages/kpi-formula/kpi-formula-importer.js.map +0 -1
  257. package/dist-client/pages/kpi-formula/kpi-formula-list-page.d.ts +0 -66
  258. package/dist-client/pages/kpi-formula/kpi-formula-list-page.js +0 -370
  259. package/dist-client/pages/kpi-formula/kpi-formula-list-page.js.map +0 -1
  260. package/dist-client/pages/metric/metric-importer.d.ts +0 -23
  261. package/dist-client/pages/metric/metric-importer.js +0 -93
  262. package/dist-client/pages/metric/metric-importer.js.map +0 -1
  263. package/dist-client/pages/metric/metric-list-page.d.ts +0 -66
  264. package/dist-client/pages/metric/metric-list-page.js +0 -370
  265. package/dist-client/pages/metric/metric-list-page.js.map +0 -1
  266. package/dist-server/service/kpi-formula/event-subscriber.d.ts +0 -7
  267. package/dist-server/service/kpi-formula/event-subscriber.js +0 -21
  268. package/dist-server/service/kpi-formula/event-subscriber.js.map +0 -1
  269. package/dist-server/service/kpi-formula/index.d.ts +0 -7
  270. package/dist-server/service/kpi-formula/index.js +0 -12
  271. package/dist-server/service/kpi-formula/index.js.map +0 -1
  272. package/dist-server/service/kpi-formula/kpi-formula-history.d.ts +0 -25
  273. package/dist-server/service/kpi-formula/kpi-formula-history.js +0 -128
  274. package/dist-server/service/kpi-formula/kpi-formula-history.js.map +0 -1
  275. package/dist-server/service/kpi-formula/kpi-formula-mutation.d.ts +0 -10
  276. package/dist-server/service/kpi-formula/kpi-formula-mutation.js +0 -128
  277. package/dist-server/service/kpi-formula/kpi-formula-mutation.js.map +0 -1
  278. package/dist-server/service/kpi-formula/kpi-formula-query.d.ts +0 -11
  279. package/dist-server/service/kpi-formula/kpi-formula-query.js +0 -79
  280. package/dist-server/service/kpi-formula/kpi-formula-query.js.map +0 -1
  281. package/dist-server/service/kpi-formula/kpi-formula-type.d.ts +0 -20
  282. package/dist-server/service/kpi-formula/kpi-formula-type.js +0 -77
  283. package/dist-server/service/kpi-formula/kpi-formula-type.js.map +0 -1
  284. package/dist-server/service/kpi-formula/kpi-formula.d.ts +0 -24
  285. package/dist-server/service/kpi-formula/kpi-formula.js +0 -109
  286. package/dist-server/service/kpi-formula/kpi-formula.js.map +0 -1
  287. package/dist-server/service/kpi-grade/event-subscriber.d.ts +0 -7
  288. package/dist-server/service/kpi-grade/event-subscriber.js +0 -21
  289. package/dist-server/service/kpi-grade/event-subscriber.js.map +0 -1
  290. package/dist-server/service/kpi-grade/kpi-grade-history.d.ts +0 -25
  291. package/dist-server/service/kpi-grade/kpi-grade-history.js +0 -128
  292. package/dist-server/service/kpi-grade/kpi-grade-history.js.map +0 -1
  293. package/dist-server/service/kpi-metric/event-subscriber.d.ts +0 -7
  294. package/dist-server/service/kpi-metric/event-subscriber.js +0 -21
  295. package/dist-server/service/kpi-metric/event-subscriber.js.map +0 -1
  296. package/dist-server/service/kpi-metric/kpi-metric-history.d.ts +0 -25
  297. package/dist-server/service/kpi-metric/kpi-metric-history.js +0 -128
  298. package/dist-server/service/kpi-metric/kpi-metric-history.js.map +0 -1
  299. package/server/service/kpi-formula/event-subscriber.ts +0 -17
  300. package/server/service/kpi-formula/index.ts +0 -9
  301. package/server/service/kpi-formula/kpi-formula-history.ts +0 -116
  302. package/server/service/kpi-formula/kpi-formula-mutation.ts +0 -137
  303. package/server/service/kpi-formula/kpi-formula-query.ts +0 -48
  304. package/server/service/kpi-formula/kpi-formula-type.ts +0 -55
  305. package/server/service/kpi-formula/kpi-formula.ts +0 -95
  306. package/server/service/kpi-grade/event-subscriber.ts +0 -17
  307. package/server/service/kpi-grade/kpi-grade-history.ts +0 -116
  308. package/server/service/kpi-metric/event-subscriber.ts +0 -17
  309. package/server/service/kpi-metric/kpi-metric-history.ts +0 -116
@@ -0,0 +1,59 @@
1
+ import { Resolver, Query, Ctx } from 'type-graphql'
2
+ import { getRepository } from '@things-factory/shell'
3
+ import { Kpi } from '../kpi/kpi'
4
+ import { KpiValue } from '../kpi-value/kpi-value'
5
+ import { KpiGrade } from '../kpi-grade/kpi-grade'
6
+ import { KpiAlert } from './kpi-alert-type'
7
+
8
+ @Resolver()
9
+ export class KpiAlertQuery {
10
+ @Query(returns => [KpiAlert], { description: 'KPI 실적/등급/목표 미달 등 경고/알림 리스트 반환' })
11
+ async kpiAlerts(@Ctx() context): Promise<KpiAlert[]> {
12
+ const { domain } = context.state
13
+ // 1. KPI 전체 조회
14
+ const kpis = await getRepository(Kpi).find({ where: { domain: { id: domain.id } }, relations: ['grades'] })
15
+ // 2. KPI별 최신 실적값 조회
16
+ const alerts: KpiAlert[] = []
17
+ for (const kpi of kpis) {
18
+ const value = await getRepository(KpiValue).findOne({
19
+ where: { domain: { id: domain.id }, kpi: { id: kpi.id } },
20
+ order: { valueDate: 'DESC' }
21
+ })
22
+ if (!value) {
23
+ alerts.push({
24
+ id: `${kpi.id}-no-value`,
25
+ kpi,
26
+ message: `${kpi.name} 실적값 미입력`,
27
+ level: 'info',
28
+ createdAt: new Date()
29
+ })
30
+ continue
31
+ }
32
+ // 목표값(예: kpi.vizMeta?.targetValue) 기준 경고
33
+ const target = kpi.vizMeta?.targetValue
34
+ if (target !== undefined && value.value < target) {
35
+ alerts.push({
36
+ id: `${kpi.id}-target-miss`,
37
+ kpi,
38
+ message: `${kpi.name} 실적(${value.value})이 목표(${target}) 미달`,
39
+ level: 'warning',
40
+ createdAt: new Date()
41
+ })
42
+ }
43
+ // 등급 기준 경고(예: 최하위 등급)
44
+ if (kpi.grades?.length) {
45
+ const grade = kpi.grades.find(g => value.value >= g.minValue && value.value <= g.maxValue)
46
+ if (grade && grade.score !== undefined && grade.score <= 2) {
47
+ alerts.push({
48
+ id: `${kpi.id}-grade-low`,
49
+ kpi,
50
+ message: `${kpi.name} 등급(${grade.name})(${grade.score}점)`,
51
+ level: 'critical',
52
+ createdAt: new Date()
53
+ })
54
+ }
55
+ }
56
+ }
57
+ return alerts
58
+ }
59
+ }
@@ -0,0 +1,20 @@
1
+ import { ObjectType, Field, ID } from 'type-graphql'
2
+ import { Kpi } from '../kpi/kpi'
3
+
4
+ @ObjectType({ description: 'KPI 경고/알림 엔티티. KPI 실적, 등급, 목표 미달 등 경고/알림 정보를 제공.' })
5
+ export class KpiAlert {
6
+ @Field(type => ID)
7
+ id: string
8
+
9
+ @Field(type => Kpi, { nullable: true, description: '경고/알림이 발생한 KPI.' })
10
+ kpi?: Kpi
11
+
12
+ @Field({ description: '경고/알림 메시지.' })
13
+ message: string
14
+
15
+ @Field({ description: '경고 레벨(예: warning, critical, info 등).' })
16
+ level: string
17
+
18
+ @Field({ description: '경고/알림 발생 시각.' })
19
+ createdAt: Date
20
+ }
@@ -8,12 +8,21 @@ import { NewKpiCategory, KpiCategoryPatch } from './kpi-category-type'
8
8
  @Resolver(KpiCategory)
9
9
  export class KpiCategoryMutation {
10
10
  @Directive('@transaction')
11
- @Mutation(returns => KpiCategory, { description: 'To create new KpiCategory' })
12
- async createKpiCategory(@Arg('kpiCategory') kpiCategory: NewKpiCategory, @Ctx() context: ResolverContext): Promise<KpiCategory> {
11
+ @Mutation(returns => KpiCategory, { description: 'Create a new KPI category with the provided details.' })
12
+ async createKpiCategory(
13
+ @Arg('category', { description: 'Input object containing details for the new KPI category.' })
14
+ category: NewKpiCategory,
15
+ @Ctx() context: ResolverContext
16
+ ): Promise<KpiCategory> {
13
17
  const { domain, user, tx } = context.state
14
18
 
19
+ let parent = category.parentId
20
+ ? await getRepository(KpiCategory).findOne({ where: { id: category.parentId } })
21
+ : undefined
22
+
15
23
  const result = await getRepository(KpiCategory, tx).save({
16
- ...kpiCategory,
24
+ ...category,
25
+ parent,
17
26
  domain,
18
27
  creator: user,
19
28
  updater: user
@@ -36,9 +45,14 @@ export class KpiCategoryMutation {
36
45
  where: { domain: { id: domain.id }, id }
37
46
  })
38
47
 
48
+ let parent = patch.parentId
49
+ ? await getRepository(KpiCategory).findOne({ where: { id: patch.parentId } })
50
+ : kpiCategory.parent
51
+
39
52
  const result = await repository.save({
40
53
  ...kpiCategory,
41
54
  ...patch,
55
+ parent,
42
56
  updater: user
43
57
  })
44
58
 
@@ -114,7 +128,6 @@ export class KpiCategoryMutation {
114
128
  id: In(ids)
115
129
  })
116
130
 
117
-
118
131
  return true
119
132
  }
120
133
 
@@ -3,11 +3,18 @@ import { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from
3
3
  import { User } from '@things-factory/auth-base'
4
4
  import { KpiCategory } from './kpi-category'
5
5
  import { KpiCategoryList } from './kpi-category-type'
6
+ import { Kpi } from '../kpi/kpi'
6
7
 
7
8
  @Resolver(KpiCategory)
8
9
  export class KpiCategoryQuery {
9
- @Query(returns => KpiCategory!, { nullable: true, description: 'To fetch a KpiCategory' })
10
- async kpiCategory(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<KpiCategory> {
10
+ @Query(returns => KpiCategory!, {
11
+ nullable: true,
12
+ description: 'Fetch a single KPI category by its unique identifier.'
13
+ })
14
+ async kpiCategory(
15
+ @Arg('id', { description: 'Unique identifier of the KPI category to fetch.' }) id: string,
16
+ @Ctx() context: ResolverContext
17
+ ): Promise<KpiCategory> {
11
18
  const { domain } = context.state
12
19
 
13
20
  return await getRepository(KpiCategory).findOne({
@@ -16,7 +23,10 @@ export class KpiCategoryQuery {
16
23
  }
17
24
 
18
25
  @Query(returns => KpiCategoryList, { description: 'To fetch multiple KpiCategories' })
19
- async kpiCategories(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<KpiCategoryList> {
26
+ async kpiCategories(
27
+ @Args(type => ListParam) params: ListParam,
28
+ @Ctx() context: ResolverContext
29
+ ): Promise<KpiCategoryList> {
20
30
  const { domain } = context.state
21
31
 
22
32
  const queryBuilder = getQueryBuilderFromListParams({
@@ -31,6 +41,13 @@ export class KpiCategoryQuery {
31
41
  return { items, total }
32
42
  }
33
43
 
44
+ @FieldResolver(type => [Kpi])
45
+ async kpis(@Root() kpiCategory: KpiCategory): Promise<Kpi[]> {
46
+ return await getRepository(Kpi).find({
47
+ where: { domain: { id: kpiCategory.domainId }, category: { id: kpiCategory.id } }
48
+ })
49
+ }
50
+
34
51
  @FieldResolver(type => Domain)
35
52
  async domain(@Root() kpiCategory: KpiCategory): Promise<Domain> {
36
53
  return kpiCategory.domainId && (await getRepository(Domain).findOneBy({ id: kpiCategory.domainId }))
@@ -4,44 +4,42 @@ import { ObjectType, Field, InputType, Int, ID, registerEnumType } from 'type-gr
4
4
 
5
5
  import { ObjectRef, ScalarObject } from '@things-factory/shell'
6
6
 
7
- import { KpiCategory, KpiCategoryStatus } from './kpi-category'
7
+ import { KpiCategory } from './kpi-category'
8
8
 
9
- @InputType()
9
+ @InputType({
10
+ description: 'Input type for creating a new KPI category. Used in mutations to provide category details.'
11
+ })
10
12
  export class NewKpiCategory {
11
- @Field()
13
+ @Field({ description: 'Name of the KPI category.' })
12
14
  name: string
13
15
 
14
- @Field({ nullable: true })
16
+ @Field({ nullable: true, description: 'Detailed description of this KPI category.' })
15
17
  description?: string
16
18
 
17
- @Field(type => KpiCategoryStatus, { nullable: true })
18
- state?: KpiCategoryStatus
19
+ @Field(type => ID, { nullable: true, description: 'ID of the parent category, if any.' })
20
+ parentId?: string
19
21
 
20
22
  @Field({ nullable: true })
21
23
  active?: boolean
22
-
23
- @Field({ nullable: true })
24
- params?: string
25
24
  }
26
25
 
27
- @InputType()
26
+ @InputType({
27
+ description: 'Input type for updating an existing KPI category. Used in mutations to patch category details.'
28
+ })
28
29
  export class KpiCategoryPatch {
29
- @Field(type => ID, { nullable: true })
30
+ @Field(type => ID, { nullable: true, description: 'ID of the KPI category to update.' })
30
31
  id?: string
31
32
 
32
- @Field({ nullable: true })
33
+ @Field({ nullable: true, description: 'Name of the KPI category.' })
33
34
  name?: string
34
35
 
35
- @Field({ nullable: true })
36
+ @Field({ nullable: true, description: 'Detailed description of this KPI category.' })
36
37
  description?: string
37
38
 
38
- @Field(type => KpiCategoryStatus, { nullable: true })
39
- state?: KpiCategoryStatus
39
+ @Field(type => ID, { nullable: true, description: 'ID of the parent category, if any.' })
40
+ parentId?: string
40
41
 
41
- @Field({ nullable: true })
42
- active?: boolean
43
-
44
- @Field({ nullable: true })
42
+ @Field({ nullable: true, description: 'Custom flag for update operations (internal use).' })
45
43
  cuFlag?: string
46
44
  }
47
45
 
@@ -6,79 +6,81 @@ import {
6
6
  Column,
7
7
  RelationId,
8
8
  ManyToOne,
9
+ OneToMany,
9
10
  PrimaryGeneratedColumn
10
11
  } from 'typeorm'
11
- import { ObjectType, Field, Int, ID, registerEnumType } from 'type-graphql'
12
+ import { ObjectType, Field, Int, ID } from 'type-graphql'
12
13
 
13
14
  import { Domain } from '@things-factory/shell'
14
15
  import { User } from '@things-factory/auth-base'
15
-
16
- export enum KpiCategoryStatus {
17
- STATUS_A = 'STATUS_A',
18
- STATUS_B = 'STATUS_B'
19
- }
20
-
21
- registerEnumType(KpiCategoryStatus, {
22
- name: 'KpiCategoryStatus',
23
- description: 'state enumeration of a kpiCategory'
24
- })
16
+ import { Kpi } from '../kpi/kpi'
25
17
 
26
18
  @Entity()
27
19
  @Index('ix_kpi_category_0', (kpiCategory: KpiCategory) => [kpiCategory.domain, kpiCategory.name], {
28
20
  unique: true
29
21
  })
30
- @ObjectType({ description: 'Entity for KpiCategory' })
22
+ @ObjectType({
23
+ description:
24
+ 'KPI category entity. Represents a classification or group for KPIs. Supports hierarchical (tree) structure.'
25
+ })
31
26
  export class KpiCategory {
32
27
  @PrimaryGeneratedColumn('uuid')
33
- @Field(type => ID)
28
+ @Field(type => ID, { description: 'Unique identifier for this KPI category.' })
34
29
  readonly id: string
35
30
 
36
31
  @ManyToOne(type => Domain)
37
- @Field({ nullable: true })
32
+ @Field({ nullable: true, description: 'Domain (tenant) to which this KPI category belongs.' })
38
33
  domain?: Domain
39
34
 
40
- @RelationId((kpiCategory: KpiCategory) => kpiCategory.domain)
35
+ @RelationId((category: KpiCategory) => category.domain)
36
+ @Field({ nullable: true, description: 'ID of the domain (tenant) for this KPI category.' })
41
37
  domainId?: string
42
38
 
43
39
  @Column()
44
- @Field({ nullable: true })
45
- name?: string
40
+ @Field({ description: 'Name of the KPI category.' })
41
+ name: string
46
42
 
47
43
  @Column({ nullable: true })
48
- @Field({ nullable: true })
44
+ @Field({ nullable: true, description: 'Detailed description of this KPI category.' })
49
45
  description?: string
50
46
 
51
47
  @Column({ nullable: false, default: false })
52
- @Field({ nullable: true })
48
+ @Field({ nullable: true, description: 'Whether this category is active (usable) or not.' })
53
49
  active?: boolean
54
50
 
55
- @Column({ nullable: true })
56
- @Field({ nullable: true })
57
- state?: KpiCategoryStatus
58
-
59
- @Column({ nullable: true })
60
- @Field({ nullable: true })
61
- params?: string
62
-
63
- @CreateDateColumn()
64
- @Field({ nullable: true })
65
- createdAt?: Date
51
+ @ManyToOne(type => KpiCategory, { nullable: true })
52
+ @Field(type => KpiCategory, { nullable: true, description: 'Parent category for hierarchical category structure.' })
53
+ parent?: KpiCategory
66
54
 
67
- @UpdateDateColumn()
68
- @Field({ nullable: true })
69
- updatedAt?: Date
55
+ @RelationId((category: KpiCategory) => category.parent)
56
+ @Field({ nullable: true, description: 'ID of the parent category, if any.' })
57
+ parentId?: string
70
58
 
71
59
  @ManyToOne(type => User, { nullable: true })
72
- @Field(type => User, { nullable: true })
60
+ @Field(type => User, { nullable: true, description: 'User who created this KPI category.' })
73
61
  creator?: User
74
62
 
75
- @RelationId((kpiCategory: KpiCategory) => kpiCategory.creator)
63
+ @RelationId((category: KpiCategory) => category.creator)
64
+ @Field({ nullable: true, description: 'ID of the user who created this KPI category.' })
76
65
  creatorId?: string
77
66
 
78
67
  @ManyToOne(type => User, { nullable: true })
79
- @Field(type => User, { nullable: true })
68
+ @Field(type => User, { nullable: true, description: 'User who last updated this KPI category.' })
80
69
  updater?: User
81
70
 
82
- @RelationId((kpiCategory: KpiCategory) => kpiCategory.updater)
71
+ @RelationId((category: KpiCategory) => category.updater)
72
+ @Field({ nullable: true, description: 'ID of the user who last updated this KPI category.' })
83
73
  updaterId?: string
74
+
75
+ @CreateDateColumn()
76
+ @Field({ nullable: true, description: 'Timestamp when this KPI category was created.' })
77
+ createdAt?: Date
78
+
79
+ @UpdateDateColumn()
80
+ @Field({ nullable: true, description: 'Timestamp when this KPI category was last updated.' })
81
+ updatedAt?: Date
82
+
83
+ @OneToMany(type => Kpi, kpi => kpi.category)
84
+ @Field(type => [Kpi], { nullable: true, description: 'List of KPIs belonging to this category.' })
85
+ kpis?: Kpi[]
84
86
  }
@@ -1,9 +1,7 @@
1
1
  import { KpiGrade } from './kpi-grade'
2
- import { KpiGradeHistory } from './kpi-grade-history'
3
- import { KpiGradeHistoryEntitySubscriber } from './event-subscriber'
4
2
  import { KpiGradeQuery } from './kpi-grade-query'
5
3
  import { KpiGradeMutation } from './kpi-grade-mutation'
6
4
 
7
- export const entities = [KpiGrade, KpiGradeHistory]
5
+ export const entities = [KpiGrade]
8
6
  export const resolvers = [KpiGradeQuery, KpiGradeMutation]
9
- export const subscribers = [KpiGradeHistoryEntitySubscriber]
7
+ export const subscribers = []
@@ -4,16 +4,23 @@ import { getRepository } from '@things-factory/shell'
4
4
 
5
5
  import { KpiGrade } from './kpi-grade'
6
6
  import { NewKpiGrade, KpiGradePatch } from './kpi-grade-type'
7
+ import { Kpi } from '../kpi/kpi'
7
8
 
8
9
  @Resolver(KpiGrade)
9
10
  export class KpiGradeMutation {
10
11
  @Directive('@transaction')
11
- @Mutation(returns => KpiGrade, { description: 'To create new KpiGrade' })
12
- async createKpiGrade(@Arg('kpiGrade') kpiGrade: NewKpiGrade, @Ctx() context: ResolverContext): Promise<KpiGrade> {
12
+ @Mutation(returns => KpiGrade, { description: 'Create a new KPI grade with the provided details.' })
13
+ async createKpiGrade(
14
+ @Arg('grade', { description: 'Input object containing details for the new KPI grade.' }) grade: NewKpiGrade,
15
+ @Ctx() context: ResolverContext
16
+ ): Promise<KpiGrade> {
13
17
  const { domain, user, tx } = context.state
14
18
 
19
+ let kpi = grade.kpiId ? await getRepository(Kpi).findOne({ where: { id: grade.kpiId } }) : undefined
20
+
15
21
  const result = await getRepository(KpiGrade, tx).save({
16
- ...kpiGrade,
22
+ ...grade,
23
+ kpi,
17
24
  domain,
18
25
  creator: user,
19
26
  updater: user
@@ -36,9 +43,12 @@ export class KpiGradeMutation {
36
43
  where: { domain: { id: domain.id }, id }
37
44
  })
38
45
 
46
+ let kpi = patch.kpiId ? await getRepository(Kpi).findOne({ where: { id: patch.kpiId } }) : kpiGrade.kpi
47
+
39
48
  const result = await repository.save({
40
49
  ...kpiGrade,
41
50
  ...patch,
51
+ kpi,
42
52
  updater: user
43
53
  })
44
54
 
@@ -114,7 +124,6 @@ export class KpiGradeMutation {
114
124
  id: In(ids)
115
125
  })
116
126
 
117
-
118
127
  return true
119
128
  }
120
129
 
@@ -6,8 +6,11 @@ import { KpiGradeList } from './kpi-grade-type'
6
6
 
7
7
  @Resolver(KpiGrade)
8
8
  export class KpiGradeQuery {
9
- @Query(returns => KpiGrade!, { nullable: true, description: 'To fetch a KpiGrade' })
10
- async kpiGrade(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<KpiGrade> {
9
+ @Query(returns => KpiGrade!, { nullable: true, description: 'Fetch a single KPI grade by its unique identifier.' })
10
+ async kpiGrade(
11
+ @Arg('id', { description: 'Unique identifier of the KPI grade to fetch.' }) id: string,
12
+ @Ctx() context: ResolverContext
13
+ ): Promise<KpiGrade> {
11
14
  const { domain } = context.state
12
15
 
13
16
  return await getRepository(KpiGrade).findOne({
@@ -4,44 +4,71 @@ import { ObjectType, Field, InputType, Int, ID, registerEnumType } from 'type-gr
4
4
 
5
5
  import { ObjectRef, ScalarObject } from '@things-factory/shell'
6
6
 
7
- import { KpiGrade, KpiGradeStatus } from './kpi-grade'
7
+ import { KpiGrade } from './kpi-grade'
8
8
 
9
- @InputType()
9
+ @InputType({ description: 'Input type for creating a new KPI grade. Used in mutations to provide grade details.' })
10
10
  export class NewKpiGrade {
11
- @Field()
11
+ @Field({ description: 'Name of the grade or section for this KPI.' })
12
12
  name: string
13
13
 
14
- @Field({ nullable: true })
14
+ @Field({ nullable: true, description: 'Detailed description of this KPI grade.' })
15
15
  description?: string
16
16
 
17
- @Field(type => KpiGradeStatus, { nullable: true })
18
- state?: KpiGradeStatus
17
+ @Field(type => ID, { description: 'ID of the KPI to which this grade belongs.' })
18
+ kpiId: string
19
19
 
20
- @Field({ nullable: true })
21
- active?: boolean
20
+ @Field(type => Int, { description: 'Version of the KPI definition to which this grade belongs.' })
21
+ version: number
22
+
23
+ @Field(type => Int, { description: 'Minimum value for this grade section.' })
24
+ minValue: number
25
+
26
+ @Field(type => Int, { description: 'Maximum value for this grade section.' })
27
+ maxValue: number
22
28
 
23
- @Field({ nullable: true })
24
- params?: string
29
+ @Field(type => Int, { nullable: true, description: 'Score or weight for this grade (optional).' })
30
+ score?: number
31
+
32
+ @Field({ nullable: true, description: 'Color code for this grade (for visualization purposes).' })
33
+ color?: string
34
+
35
+ @Field({ nullable: true, description: 'Indicates whether this KPI grade is active and usable.' })
36
+ active?: boolean
25
37
  }
26
38
 
27
- @InputType()
39
+ @InputType({ description: 'Input type for updating an existing KPI grade. Used in mutations to patch grade details.' })
28
40
  export class KpiGradePatch {
29
- @Field(type => ID, { nullable: true })
41
+ @Field(type => ID, { nullable: true, description: 'ID of the KPI grade to update.' })
30
42
  id?: string
31
43
 
32
- @Field({ nullable: true })
44
+ @Field({ nullable: true, description: 'Name of the grade or section for this KPI.' })
33
45
  name?: string
34
46
 
35
- @Field({ nullable: true })
47
+ @Field({ nullable: true, description: 'Detailed description of this KPI grade.' })
36
48
  description?: string
37
49
 
38
- @Field(type => KpiGradeStatus, { nullable: true })
39
- state?: KpiGradeStatus
50
+ @Field(type => ID, { nullable: true, description: 'ID of the KPI to which this grade belongs.' })
51
+ kpiId?: string
40
52
 
41
- @Field({ nullable: true })
53
+ @Field(type => Int, { nullable: true, description: 'Version of the KPI definition to which this grade belongs.' })
54
+ version?: number
55
+
56
+ @Field(type => Int, { nullable: true, description: 'Minimum value for this grade section.' })
57
+ minValue?: number
58
+
59
+ @Field(type => Int, { nullable: true, description: 'Maximum value for this grade section.' })
60
+ maxValue?: number
61
+
62
+ @Field(type => Int, { nullable: true, description: 'Score or weight for this grade (optional).' })
63
+ score?: number
64
+
65
+ @Field({ nullable: true, description: 'Color code for this grade (for visualization purposes).' })
66
+ color?: string
67
+
68
+ @Field({ nullable: true, description: 'Indicates whether this KPI grade is active and usable.' })
42
69
  active?: boolean
43
-
44
- @Field({ nullable: true })
70
+
71
+ @Field({ nullable: true, description: 'Custom flag for update operations (internal use).' })
45
72
  cuFlag?: string
46
73
  }
47
74
 
@@ -1,95 +1,101 @@
1
1
  import {
2
2
  CreateDateColumn,
3
3
  UpdateDateColumn,
4
- DeleteDateColumn,
5
4
  Entity,
6
5
  Index,
7
6
  Column,
8
7
  RelationId,
9
8
  ManyToOne,
10
- VersionColumn,
11
9
  PrimaryGeneratedColumn
12
10
  } from 'typeorm'
13
- import { ObjectType, Field, Int, ID, registerEnumType } from 'type-graphql'
11
+ import { ObjectType, Field, Int, ID, registerEnumType, Float } from 'type-graphql'
14
12
 
15
13
  import { Domain } from '@things-factory/shell'
16
14
  import { User } from '@things-factory/auth-base'
17
-
18
- export enum KpiGradeStatus {
19
- STATUS_A = 'STATUS_A',
20
- STATUS_B = 'STATUS_B'
21
- }
22
-
23
- registerEnumType(KpiGradeStatus, {
24
- name: 'KpiGradeStatus',
25
- description: 'state enumeration of a kpiGrade'
26
- })
15
+ import { Kpi } from '../kpi/kpi'
27
16
 
28
17
  @Entity()
29
- @Index('ix_kpi_grade_0', (kpiGrade: KpiGrade) => [kpiGrade.domain, kpiGrade.name], {
30
- where: '"deleted_at" IS NULL',
18
+ @Index('ix_kpi_grade_0', (kpiGrade: KpiGrade) => [kpiGrade.domain, kpiGrade.kpi, kpiGrade.version, kpiGrade.name], {
31
19
  unique: true
32
20
  })
33
- @ObjectType({ description: 'Entity for KpiGrade' })
21
+ @ObjectType({
22
+ description:
23
+ 'KPI grade entity. Represents a grade/section for a KPI version, with value range, score, color, and description.'
24
+ })
34
25
  export class KpiGrade {
35
26
  @PrimaryGeneratedColumn('uuid')
36
- @Field(type => ID)
27
+ @Field(type => ID, { description: 'Unique identifier for this KPI grade.' })
37
28
  readonly id: string
38
-
39
- @VersionColumn()
40
- @Field({ nullable: true })
41
- version?: number = 1
42
29
 
43
30
  @ManyToOne(type => Domain)
44
- @Field({ nullable: true })
31
+ @Field({ nullable: true, description: 'Domain (tenant) to which this KPI grade belongs.' })
45
32
  domain?: Domain
46
33
 
47
34
  @RelationId((kpiGrade: KpiGrade) => kpiGrade.domain)
35
+ @Field({ nullable: true, description: 'ID of the domain (tenant) for this KPI grade.' })
48
36
  domainId?: string
49
37
 
50
38
  @Column()
51
- @Field({ nullable: true })
39
+ @Field({ nullable: true, description: 'Name of the grade or section for this KPI.' })
52
40
  name?: string
53
41
 
54
42
  @Column({ nullable: true })
55
- @Field({ nullable: true })
43
+ @Field({ nullable: true, description: 'Detailed description of this KPI grade.' })
56
44
  description?: string
57
45
 
58
46
  @Column({ nullable: false, default: false })
59
- @Field({ nullable: true })
47
+ @Field({ nullable: true, description: 'Indicates whether this KPI grade is active and usable.' })
60
48
  active?: boolean
61
49
 
62
- @Column({ nullable: true })
63
- @Field({ nullable: true })
64
- state?: KpiGradeStatus
50
+ @ManyToOne(() => Kpi)
51
+ @Field(type => Kpi, { description: 'Reference to the KPI to which this grade belongs.' })
52
+ kpi: Kpi
53
+
54
+ @RelationId((kpiGrade: KpiGrade) => kpiGrade.kpi)
55
+ @Field({ description: 'ID of the referenced KPI.' })
56
+ kpiId: string
57
+
58
+ @Column('int')
59
+ @Field(type => Int, { description: 'Version of the KPI definition to which this grade belongs.' })
60
+ version: number
61
+
62
+ @Column('float')
63
+ @Field(type => Float, { description: 'Minimum value for this grade section.' })
64
+ minValue: number
65
+
66
+ @Column('float')
67
+ @Field(type => Float, { description: 'Maximum value for this grade section.' })
68
+ maxValue: number
69
+
70
+ @Column({ nullable: true, type: 'float' })
71
+ @Field(type => Float, { nullable: true, description: 'Score or weight for this grade (optional).' })
72
+ score?: number
65
73
 
66
74
  @Column({ nullable: true })
67
- @Field({ nullable: true })
68
- params?: string
75
+ @Field({ nullable: true, description: 'Color code for this grade (for visualization purposes).' })
76
+ color?: string
69
77
 
70
78
  @CreateDateColumn()
71
- @Field({ nullable: true })
79
+ @Field({ nullable: true, description: 'Timestamp when this KPI grade was created.' })
72
80
  createdAt?: Date
73
81
 
74
82
  @UpdateDateColumn()
75
- @Field({ nullable: true })
83
+ @Field({ nullable: true, description: 'Timestamp when this KPI grade was last updated.' })
76
84
  updatedAt?: Date
77
85
 
78
- @DeleteDateColumn()
79
- @Field({ nullable: true })
80
- deletedAt?: Date
81
-
82
86
  @ManyToOne(type => User, { nullable: true })
83
- @Field(type => User, { nullable: true })
87
+ @Field(type => User, { nullable: true, description: 'User who created this KPI grade.' })
84
88
  creator?: User
85
89
 
86
90
  @RelationId((kpiGrade: KpiGrade) => kpiGrade.creator)
91
+ @Field({ nullable: true, description: 'ID of the user who created this KPI grade.' })
87
92
  creatorId?: string
88
93
 
89
94
  @ManyToOne(type => User, { nullable: true })
90
- @Field(type => User, { nullable: true })
95
+ @Field(type => User, { nullable: true, description: 'User who last updated this KPI grade.' })
91
96
  updater?: User
92
97
 
93
98
  @RelationId((kpiGrade: KpiGrade) => kpiGrade.updater)
99
+ @Field({ nullable: true, description: 'ID of the user who last updated this KPI grade.' })
94
100
  updaterId?: string
95
101
  }