@things-factory/kpi 9.0.22 → 9.0.24

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 (189) hide show
  1. package/client/pages/kpi/kpi-list-page.ts +180 -22
  2. package/client/pages/kpi/kpi-viz-editor.ts +1 -1
  3. package/client/pages/kpi-category/kpi-category-list-page.ts +76 -3
  4. package/client/pages/kpi-category/kpi-category-value-calculator.ts +233 -0
  5. package/client/pages/kpi-category-value/kpi-category-value-list-page.ts +404 -0
  6. package/client/pages/kpi-metric/kpi-metric-list-page.ts +13 -1
  7. package/client/pages/kpi-metric-value/kpi-metric-value-editor-page.ts +763 -0
  8. package/client/pages/kpi-metric-value/kpi-metric-value-list-page.ts +55 -1
  9. package/client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.ts +3 -13
  10. package/client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.ts +13 -1
  11. package/client/pages/kpi-value/kpi-value-editor-page.ts +774 -0
  12. package/client/pages/kpi-value/kpi-value-list-page.ts +58 -1
  13. package/client/route.ts +16 -0
  14. package/dist-client/pages/kpi/kpi-list-page.d.ts +2 -1
  15. package/dist-client/pages/kpi/kpi-list-page.js +180 -22
  16. package/dist-client/pages/kpi/kpi-list-page.js.map +1 -1
  17. package/dist-client/pages/kpi/kpi-viz-editor.d.ts +0 -1
  18. package/dist-client/pages/kpi/kpi-viz-editor.js +1 -1
  19. package/dist-client/pages/kpi/kpi-viz-editor.js.map +1 -1
  20. package/dist-client/pages/kpi-category/kpi-category-list-page.d.ts +3 -0
  21. package/dist-client/pages/kpi-category/kpi-category-list-page.js +71 -3
  22. package/dist-client/pages/kpi-category/kpi-category-list-page.js.map +1 -1
  23. package/dist-client/pages/kpi-category/kpi-category-value-calculator.d.ts +13 -0
  24. package/dist-client/pages/kpi-category/kpi-category-value-calculator.js +256 -0
  25. package/dist-client/pages/kpi-category/kpi-category-value-calculator.js.map +1 -0
  26. package/dist-client/pages/kpi-category-value/kpi-category-value-list-page.d.ts +63 -0
  27. package/dist-client/pages/kpi-category-value/kpi-category-value-list-page.js +393 -0
  28. package/dist-client/pages/kpi-category-value/kpi-category-value-list-page.js.map +1 -0
  29. package/dist-client/pages/kpi-metric/kpi-metric-list-page.js +13 -1
  30. package/dist-client/pages/kpi-metric/kpi-metric-list-page.js.map +1 -1
  31. package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.d.ts +58 -0
  32. package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.js +736 -0
  33. package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.js.map +1 -0
  34. package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.d.ts +5 -1
  35. package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js +50 -2
  36. package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js.map +1 -1
  37. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.js +3 -13
  38. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.js.map +1 -1
  39. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.js +13 -1
  40. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.js.map +1 -1
  41. package/dist-client/pages/kpi-value/kpi-value-editor-page.d.ts +55 -0
  42. package/dist-client/pages/kpi-value/kpi-value-editor-page.js +748 -0
  43. package/dist-client/pages/kpi-value/kpi-value-editor-page.js.map +1 -0
  44. package/dist-client/pages/kpi-value/kpi-value-list-page.d.ts +10 -2
  45. package/dist-client/pages/kpi-value/kpi-value-list-page.js +57 -1
  46. package/dist-client/pages/kpi-value/kpi-value-list-page.js.map +1 -1
  47. package/dist-client/route.d.ts +1 -1
  48. package/dist-client/route.js +12 -0
  49. package/dist-client/route.js.map +1 -1
  50. package/dist-client/tsconfig.tsbuildinfo +1 -1
  51. package/dist-server/calculator/evaluator.d.ts +8 -0
  52. package/dist-server/calculator/evaluator.js +42 -0
  53. package/dist-server/calculator/evaluator.js.map +1 -0
  54. package/dist-server/calculator/functions.d.ts +3 -0
  55. package/dist-server/calculator/functions.js +62 -0
  56. package/dist-server/calculator/functions.js.map +1 -0
  57. package/dist-server/calculator/index.d.ts +4 -0
  58. package/dist-server/calculator/index.js +8 -0
  59. package/dist-server/calculator/index.js.map +1 -0
  60. package/dist-server/calculator/parser.d.ts +21 -0
  61. package/dist-server/calculator/parser.js +121 -0
  62. package/dist-server/calculator/parser.js.map +1 -0
  63. package/dist-server/calculator/provider.d.ts +8 -0
  64. package/dist-server/calculator/provider.js +13 -0
  65. package/dist-server/calculator/provider.js.map +1 -0
  66. package/dist-server/controllers/kpi-metric-value-provider.d.ts +11 -0
  67. package/dist-server/controllers/kpi-metric-value-provider.js +63 -0
  68. package/dist-server/controllers/kpi-metric-value-provider.js.map +1 -0
  69. package/dist-server/controllers/kpi-value-provider.d.ts +11 -0
  70. package/dist-server/controllers/kpi-value-provider.js +46 -0
  71. package/dist-server/controllers/kpi-value-provider.js.map +1 -0
  72. package/dist-server/service/index.d.ts +4 -2
  73. package/dist-server/service/index.js +5 -0
  74. package/dist-server/service/index.js.map +1 -1
  75. package/dist-server/service/kpi/aggregate-kpi.js +4 -4
  76. package/dist-server/service/kpi/aggregate-kpi.js.map +1 -1
  77. package/dist-server/service/kpi/kpi-grade.types.d.ts +11 -10
  78. package/dist-server/service/kpi/kpi-grade.types.js.map +1 -1
  79. package/dist-server/service/kpi/kpi-history.d.ts +2 -2
  80. package/dist-server/service/kpi/kpi-history.js.map +1 -1
  81. package/dist-server/service/kpi/kpi-mutation.d.ts +2 -0
  82. package/dist-server/service/kpi/kpi-mutation.js +126 -4
  83. package/dist-server/service/kpi/kpi-mutation.js.map +1 -1
  84. package/dist-server/service/kpi/kpi-type.d.ts +8 -5
  85. package/dist-server/service/kpi/kpi-type.js +22 -8
  86. package/dist-server/service/kpi/kpi-type.js.map +1 -1
  87. package/dist-server/service/kpi/kpi.d.ts +6 -3
  88. package/dist-server/service/kpi/kpi.js +29 -9
  89. package/dist-server/service/kpi/kpi.js.map +1 -1
  90. package/dist-server/service/kpi-category/kpi-category-mutation.d.ts +3 -4
  91. package/dist-server/service/kpi-category/kpi-category-mutation.js +151 -80
  92. package/dist-server/service/kpi-category/kpi-category-mutation.js.map +1 -1
  93. package/dist-server/service/kpi-category/kpi-category-query.d.ts +5 -0
  94. package/dist-server/service/kpi-category/kpi-category-query.js +19 -1
  95. package/dist-server/service/kpi-category/kpi-category-query.js.map +1 -1
  96. package/dist-server/service/kpi-category/kpi-category-type.d.ts +3 -0
  97. package/dist-server/service/kpi-category/kpi-category-type.js +16 -1
  98. package/dist-server/service/kpi-category/kpi-category-type.js.map +1 -1
  99. package/dist-server/service/kpi-category/kpi-category.d.ts +2 -0
  100. package/dist-server/service/kpi-category/kpi-category.js +10 -1
  101. package/dist-server/service/kpi-category/kpi-category.js.map +1 -1
  102. package/dist-server/service/kpi-category-value/index.d.ts +6 -0
  103. package/dist-server/service/kpi-category-value/index.js +10 -0
  104. package/dist-server/service/kpi-category-value/index.js.map +1 -0
  105. package/dist-server/service/kpi-category-value/kpi-category-value-mutation.d.ts +8 -0
  106. package/dist-server/service/kpi-category-value/kpi-category-value-mutation.js +102 -0
  107. package/dist-server/service/kpi-category-value/kpi-category-value-mutation.js.map +1 -0
  108. package/dist-server/service/kpi-category-value/kpi-category-value-query.d.ts +13 -0
  109. package/dist-server/service/kpi-category-value/kpi-category-value-query.js +91 -0
  110. package/dist-server/service/kpi-category-value/kpi-category-value-query.js.map +1 -0
  111. package/dist-server/service/kpi-category-value/kpi-category-value-type.d.ts +19 -0
  112. package/dist-server/service/kpi-category-value/kpi-category-value-type.js +73 -0
  113. package/dist-server/service/kpi-category-value/kpi-category-value-type.js.map +1 -0
  114. package/dist-server/service/kpi-category-value/kpi-category-value.d.ts +19 -0
  115. package/dist-server/service/kpi-category-value/kpi-category-value.js +91 -0
  116. package/dist-server/service/kpi-category-value/kpi-category-value.js.map +1 -0
  117. package/dist-server/service/kpi-metric/kpi-metric-type.d.ts +5 -3
  118. package/dist-server/service/kpi-metric/kpi-metric-type.js +5 -3
  119. package/dist-server/service/kpi-metric/kpi-metric-type.js.map +1 -1
  120. package/dist-server/service/kpi-metric/kpi-metric.d.ts +2 -8
  121. package/dist-server/service/kpi-metric/kpi-metric.js +3 -14
  122. package/dist-server/service/kpi-metric/kpi-metric.js.map +1 -1
  123. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js +87 -45
  124. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js.map +1 -1
  125. package/dist-server/service/kpi-metric-value/kpi-metric-value.js +3 -2
  126. package/dist-server/service/kpi-metric-value/kpi-metric-value.js.map +1 -1
  127. package/dist-server/service/kpi-value/kpi-value-mutation.d.ts +3 -1
  128. package/dist-server/service/kpi-value/kpi-value-mutation.js +174 -6
  129. package/dist-server/service/kpi-value/kpi-value-mutation.js.map +1 -1
  130. package/dist-server/service/kpi-value/kpi-value-query.d.ts +0 -2
  131. package/dist-server/service/kpi-value/kpi-value-query.js +0 -12
  132. package/dist-server/service/kpi-value/kpi-value-query.js.map +1 -1
  133. package/dist-server/service/kpi-value/kpi-value-score.service.d.ts +26 -0
  134. package/dist-server/service/kpi-value/kpi-value-score.service.js +97 -0
  135. package/dist-server/service/kpi-value/kpi-value-score.service.js.map +1 -0
  136. package/dist-server/service/kpi-value/kpi-value-type.d.ts +2 -0
  137. package/dist-server/service/kpi-value/kpi-value-type.js +14 -0
  138. package/dist-server/service/kpi-value/kpi-value-type.js.map +1 -1
  139. package/dist-server/service/kpi-value/kpi-value.d.ts +1 -0
  140. package/dist-server/service/kpi-value/kpi-value.js +9 -1
  141. package/dist-server/service/kpi-value/kpi-value.js.map +1 -1
  142. package/dist-server/service/utils/value-date-util.d.ts +3 -0
  143. package/dist-server/service/utils/value-date-util.js +76 -0
  144. package/dist-server/service/utils/value-date-util.js.map +1 -0
  145. package/dist-server/tsconfig.tsbuildinfo +1 -1
  146. package/package.json +5 -5
  147. package/server/calculator/evaluator.ts +45 -0
  148. package/server/calculator/functions.ts +67 -0
  149. package/server/calculator/index.ts +4 -0
  150. package/server/calculator/parser.ts +128 -0
  151. package/server/calculator/provider.ts +10 -0
  152. package/server/controllers/kpi-metric-value-provider.ts +66 -0
  153. package/server/controllers/kpi-value-provider.ts +51 -0
  154. package/server/service/index.ts +5 -0
  155. package/server/service/kpi/aggregate-kpi.ts +4 -4
  156. package/server/service/kpi/kpi-grade.types.ts +11 -10
  157. package/server/service/kpi/kpi-history.ts +2 -2
  158. package/server/service/kpi/kpi-mutation.ts +128 -4
  159. package/server/service/kpi/kpi-type.ts +21 -9
  160. package/server/service/kpi/kpi.ts +32 -10
  161. package/server/service/kpi-category/kpi-category-mutation.ts +155 -82
  162. package/server/service/kpi-category/kpi-category-query.ts +21 -1
  163. package/server/service/kpi-category/kpi-category-type.ts +17 -6
  164. package/server/service/kpi-category/kpi-category.ts +10 -1
  165. package/server/service/kpi-category-value/index.ts +7 -0
  166. package/server/service/kpi-category-value/kpi-category-value-mutation.ts +88 -0
  167. package/server/service/kpi-category-value/kpi-category-value-query.ts +62 -0
  168. package/server/service/kpi-category-value/kpi-category-value-type.ts +48 -0
  169. package/server/service/kpi-category-value/kpi-category-value.ts +79 -0
  170. package/server/service/kpi-metric/kpi-metric-type.ts +7 -5
  171. package/server/service/kpi-metric/kpi-metric.ts +3 -15
  172. package/server/service/kpi-metric-value/kpi-metric-value-mutation.ts +95 -47
  173. package/server/service/kpi-metric-value/kpi-metric-value.ts +4 -2
  174. package/server/service/kpi-value/kpi-value-mutation.ts +176 -6
  175. package/server/service/kpi-value/kpi-value-query.ts +2 -8
  176. package/server/service/kpi-value/kpi-value-score.service.ts +112 -0
  177. package/server/service/kpi-value/kpi-value-type.ts +12 -0
  178. package/server/service/kpi-value/kpi-value.ts +8 -1
  179. package/server/service/utils/value-date-util.ts +72 -0
  180. package/things-factory.config.js +3 -0
  181. package/translations/en.json +3 -0
  182. package/translations/ja.json +3 -0
  183. package/translations/ko.json +3 -0
  184. package/translations/ms.json +3 -0
  185. package/translations/zh.json +3 -0
  186. package/dist-server/service/kpi-value/kpi-value-grade.service.d.ts +0 -34
  187. package/dist-server/service/kpi-value/kpi-value-grade.service.js +0 -117
  188. package/dist-server/service/kpi-value/kpi-value-grade.service.js.map +0 -1
  189. package/server/service/kpi-value/kpi-value-grade.service.ts +0 -127
@@ -1 +1 @@
1
- {"version":3,"file":"kpi-metric-value.js","sourceRoot":"","sources":["../../../server/service/kpi-metric-value/kpi-metric-value.ts"],"names":[],"mappings":";;;;AAAA,qCASgB;AAChB,+CAA2D;AAC3D,iDAA4D;AAC5D,yDAAoD;AACpD,oCAA0C;AAC1C,yDAAgD;AAIzC,IAAM,cAAc,GAApB,MAAM,cAAc;CAwE1B,CAAA;AAxEY,wCAAc;AAGzB;IAFC,IAAA,gCAAsB,EAAC,MAAM,CAAC;IAC9B,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAE,CAAC;;0CACR;AAIV;IAFC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,cAAM,CAAC;IACvB,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;sCACjC,cAAM;8CAAA;AAIf;IAFC,IAAA,oBAAU,EAAC,CAAC,MAAsB,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;IACrD,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;gDACT;AAKjB;IAHC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,sBAAS,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IACpE,IAAA,oBAAU,EAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IAChC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,sBAAS,CAAC;sCACjB,sBAAS;8CAAA;AAIjB;IAFC,IAAA,oBAAU,EAAC,CAAC,MAAsB,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;IACrD,IAAA,oBAAK,GAAE;;gDACQ;AAIhB;IAFC,IAAA,gBAAM,EAAC,OAAO,CAAC;IACf,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAK,CAAC;;6CACR;AAIb;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;4CACb;AAOb;IALC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACvC,IAAA,oBAAK,EAAC;QACL,WAAW,EACT,+HAA+H;KAClI,CAAC;;iDACe;AAIjB;IAFC,IAAA,gBAAM,EAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,mBAAa,CAAC;;kDACJ;AAIzB;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,2DAA2D,EAAE,CAAC;;6CACtF;AAId;IAFC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC/C,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;4CACtC;AAIV;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;sCACd,IAAI;iDAAA;AAIhB;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;sCACd,IAAI;iDAAA;AAIhB;IAFC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACzC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;sCAC9B,gBAAI;+CAAA;AAId;IAFC,IAAA,oBAAU,EAAC,CAAC,MAAsB,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC;IACtD,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;iDACR;AAIlB;IAFC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACzC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;sCAC9B,gBAAI;+CAAA;AAId;IAFC,IAAA,oBAAU,EAAC,CAAC,MAAsB,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC;IACtD,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;iDACR;yBAvEP,cAAc;IAF1B,IAAA,gBAAM,GAAE;IACR,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,6EAA6E,EAAE,CAAC;GAC9F,cAAc,CAwE1B","sourcesContent":["import {\n Entity,\n PrimaryGeneratedColumn,\n Column,\n ManyToOne,\n JoinColumn,\n CreateDateColumn,\n UpdateDateColumn,\n RelationId\n} from 'typeorm'\nimport { ObjectType, Field, ID, Float } from 'type-graphql'\nimport { Domain, ScalarObject } from '@things-factory/shell'\nimport { KpiMetric } from '../kpi-metric/kpi-metric'\nimport { KpiPeriodType } from '../kpi/kpi'\nimport { User } from '@things-factory/auth-base'\n\n@Entity()\n@ObjectType({ description: 'Current value for each KPI metric (can be used for both state and history).' })\nexport class KpiMetricValue {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID)\n id: string\n\n @ManyToOne(() => Domain)\n @Field(type => Domain, { nullable: true })\n domain?: Domain\n\n @RelationId((entity: KpiMetricValue) => entity.domain)\n @Field({ nullable: true })\n domainId?: string\n\n @ManyToOne(() => KpiMetric, { nullable: false, onDelete: 'CASCADE' })\n @JoinColumn({ name: 'metricId' })\n @Field(type => KpiMetric)\n metric: KpiMetric\n\n @RelationId((entity: KpiMetricValue) => entity.metric)\n @Field()\n metricId: string\n\n @Column('float')\n @Field(type => Float)\n value: number\n\n @Column({ nullable: true })\n @Field({ nullable: true })\n unit?: string\n\n @Column({ type: 'varchar', length: 20 })\n @Field({\n description:\n 'Date or period for which this metric value is recorded (e.g., day: YYYY-MM-DD, month: YYYY-MM, range: YYYY-MM-DD~YYYY-MM-DD).'\n })\n valueDate: string\n\n @Column({ default: 'DAY' })\n @Field(type => KpiPeriodType)\n periodType: KpiPeriodType\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Group key for this value (organization, line, user, etc.)' })\n group?: string\n\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, { nullable: true })\n meta?: any\n\n @CreateDateColumn()\n @Field({ nullable: true })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true })\n updatedAt?: Date\n\n @ManyToOne(() => User, { nullable: true })\n @Field(type => User, { nullable: true })\n creator?: User\n\n @RelationId((entity: KpiMetricValue) => entity.creator)\n @Field({ nullable: true })\n creatorId?: string\n\n @ManyToOne(() => User, { nullable: true })\n @Field(type => User, { nullable: true })\n updater?: User\n\n @RelationId((entity: KpiMetricValue) => entity.updater)\n @Field({ nullable: true })\n updaterId?: string\n}\n"]}
1
+ {"version":3,"file":"kpi-metric-value.js","sourceRoot":"","sources":["../../../server/service/kpi-metric-value/kpi-metric-value.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Entity,\n PrimaryGeneratedColumn,\n Column,\n ManyToOne,\n Index,\n JoinColumn,\n CreateDateColumn,\n UpdateDateColumn,\n RelationId\n} from 'typeorm'\nimport { ObjectType, Field, ID, Float } from 'type-graphql'\nimport { Domain, ScalarObject } from '@things-factory/shell'\nimport { KpiMetric } from '../kpi-metric/kpi-metric'\nimport { KpiPeriodType } from '../kpi/kpi'\nimport { User } from '@things-factory/auth-base'\n\n@Entity()\n@Index('ix_kpi_metric_value_latest', ['domain', 'metric', 'valueDate', 'group'], { unique: true })\n@ObjectType({ description: 'Current value for each KPI metric (can be used for both state and history).' })\nexport class KpiMetricValue {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID)\n id: string\n\n @ManyToOne(() => Domain)\n @Field(type => Domain, { nullable: true })\n domain?: Domain\n\n @RelationId((entity: KpiMetricValue) => entity.domain)\n @Field({ nullable: true })\n domainId?: string\n\n @ManyToOne(() => KpiMetric, { nullable: false, onDelete: 'CASCADE' })\n @JoinColumn({ name: 'metricId' })\n @Field(type => KpiMetric)\n metric: KpiMetric\n\n @RelationId((entity: KpiMetricValue) => entity.metric)\n @Field()\n metricId: string\n\n @Column('float')\n @Field(type => Float)\n value: number\n\n @Column({ nullable: true })\n @Field({ nullable: true })\n unit?: string\n\n @Column()\n @Field({\n description:\n 'Date or period for which this metric value is recorded (e.g., day: YYYY-MM-DD, month: YYYY-MM, range: YYYY-MM-DD~YYYY-MM-DD).'\n })\n valueDate: string\n\n @Column({ default: 'DAY' })\n @Field(type => KpiPeriodType)\n periodType: KpiPeriodType\n\n @Column({ default: '' })\n @Field({ nullable: true, description: 'Group key for this value (organization, line, user, etc.)' })\n group?: string\n\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, { nullable: true })\n meta?: any\n\n @CreateDateColumn()\n @Field({ nullable: true })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true })\n updatedAt?: Date\n\n @ManyToOne(() => User, { nullable: true })\n @Field(type => User, { nullable: true })\n creator?: User\n\n @RelationId((entity: KpiMetricValue) => entity.creator)\n @Field({ nullable: true })\n creatorId?: string\n\n @ManyToOne(() => User, { nullable: true })\n @Field(type => User, { nullable: true })\n updater?: User\n\n @RelationId((entity: KpiMetricValue) => entity.updater)\n @Field({ nullable: true })\n updaterId?: string\n}\n"]}
@@ -2,10 +2,12 @@ import { KpiValue } from './kpi-value';
2
2
  import { NewKpiValue, KpiValuePatch } from './kpi-value-type';
3
3
  export declare class KpiValueMutation {
4
4
  createKpiValue(kpiValue: NewKpiValue, context: ResolverContext): Promise<KpiValue>;
5
+ createMultipleKpiValue(values: NewKpiValue[], context: ResolverContext): Promise<KpiValue[]>;
5
6
  updateKpiValue(id: string, patch: KpiValuePatch, context: ResolverContext): Promise<KpiValue>;
6
7
  updateMultipleKpiValue(patches: KpiValuePatch[], context: ResolverContext): Promise<KpiValue[]>;
7
8
  deleteKpiValue(id: string, context: ResolverContext): Promise<boolean>;
8
9
  deleteKpiValues(ids: string[], context: ResolverContext): Promise<boolean>;
9
10
  importKpiValues(kpiValues: KpiValuePatch[], context: ResolverContext): Promise<boolean>;
10
- recalculateGradesForKpi(kpiId: string, context: ResolverContext): Promise<boolean>;
11
+ recalculateScoresForKpi(kpiId: string, context: ResolverContext): Promise<boolean>;
12
+ recalculateKpiValue(id: string, context: ResolverContext): Promise<KpiValue>;
11
13
  }
@@ -8,8 +8,15 @@ const shell_1 = require("@things-factory/shell");
8
8
  const kpi_value_1 = require("./kpi-value");
9
9
  const kpi_value_type_1 = require("./kpi-value-type");
10
10
  const kpi_1 = require("../kpi/kpi");
11
+ const kpi_metric_1 = require("../kpi-metric/kpi-metric");
12
+ const kpi_metric_value_1 = require("../kpi-metric-value/kpi-metric-value");
13
+ const kpi_2 = require("../kpi/kpi");
11
14
  const kpi_value_2 = require("./kpi-value");
12
- const kpi_value_grade_service_1 = require("./kpi-value-grade.service");
15
+ const kpi_value_score_service_1 = require("./kpi-value-score.service");
16
+ const parser_1 = require("../../calculator/parser");
17
+ const evaluator_1 = require("../../calculator/evaluator");
18
+ const functions_1 = require("../../calculator/functions");
19
+ const kpi_metric_value_provider_1 = require("../../controllers/kpi-metric-value-provider");
13
20
  let KpiValueMutation = class KpiValueMutation {
14
21
  async createKpiValue(kpiValue, context) {
15
22
  const { domain, user, tx } = context.state;
@@ -39,6 +46,45 @@ let KpiValueMutation = class KpiValueMutation {
39
46
  entity.inputType = inputType;
40
47
  return await (0, shell_1.getRepository)(kpi_value_1.KpiValue, tx).save(entity);
41
48
  }
49
+ async createMultipleKpiValue(values, context) {
50
+ const { domain, user, tx } = context.state;
51
+ const repository = (0, shell_1.getRepository)(kpi_value_1.KpiValue, tx);
52
+ const scoreService = new kpi_value_score_service_1.KpiValueScoreService();
53
+ const entities = [];
54
+ for (const kpiValue of values) {
55
+ let kpi = kpiValue.kpiId ? await (0, shell_1.getRepository)(kpi_1.Kpi).findOne({ where: { id: kpiValue.kpiId } }) : undefined;
56
+ let inputType = undefined;
57
+ if (kpiValue.inputType) {
58
+ if (typeof kpiValue.inputType === 'string') {
59
+ inputType = kpi_value_2.KpiValueInputType[kpiValue.inputType];
60
+ }
61
+ else {
62
+ inputType = kpiValue.inputType;
63
+ }
64
+ }
65
+ const entity = {
66
+ kpi,
67
+ kpiId: kpiValue.kpiId,
68
+ version: kpiValue.version || 1,
69
+ valueDate: kpiValue.valueDate,
70
+ value: kpiValue.value,
71
+ group: kpiValue.group || '',
72
+ source: kpiValue.source || 'MANUAL',
73
+ domain: domain,
74
+ creator: user,
75
+ updater: user
76
+ };
77
+ if (inputType)
78
+ entity.inputType = inputType;
79
+ const savedEntity = await repository.save(entity);
80
+ // 성과 점수 자동 계산 및 저장
81
+ if (kpi) {
82
+ await scoreService.calculateAndSaveScore(savedEntity, kpi);
83
+ }
84
+ entities.push(savedEntity);
85
+ }
86
+ return entities;
87
+ }
42
88
  async updateKpiValue(id, patch, context) {
43
89
  const { domain, user, tx } = context.state;
44
90
  const repository = (0, shell_1.getRepository)(kpi_value_1.KpiValue, tx);
@@ -77,8 +123,13 @@ let KpiValueMutation = class KpiValueMutation {
77
123
  if (_createRecords.length > 0) {
78
124
  for (let i = 0; i < _createRecords.length; i++) {
79
125
  const newRecord = _createRecords[i];
126
+ const kpi = await (0, shell_1.getRepository)(kpi_1.Kpi, tx).findOne({
127
+ where: { domain: { id: domain.id }, id: newRecord.kpiId }
128
+ });
80
129
  const result = await kpiValueRepo.save({
81
130
  ...newRecord,
131
+ kpi,
132
+ version: newRecord.version || kpi.version,
82
133
  domain,
83
134
  creator: user,
84
135
  updater: user
@@ -90,9 +141,14 @@ let KpiValueMutation = class KpiValueMutation {
90
141
  for (let i = 0; i < _updateRecords.length; i++) {
91
142
  const updateRecord = _updateRecords[i];
92
143
  const kpiValue = await kpiValueRepo.findOneBy({ id: updateRecord.id });
144
+ const kpi = await (0, shell_1.getRepository)(kpi_1.Kpi, tx).findOne({
145
+ where: { domain: { id: domain.id }, id: updateRecord.kpiId }
146
+ });
93
147
  const result = await kpiValueRepo.save({
94
148
  ...kpiValue,
95
149
  ...updateRecord,
150
+ kpi,
151
+ version: updateRecord.version || kpi.version,
96
152
  updater: user
97
153
  });
98
154
  results.push({ ...result, cuFlag: 'M' });
@@ -120,11 +176,103 @@ let KpiValueMutation = class KpiValueMutation {
120
176
  }));
121
177
  return true;
122
178
  }
123
- async recalculateGradesForKpi(kpiId, context) {
124
- const gradeService = new kpi_value_grade_service_1.KpiValueGradeService();
125
- await gradeService.recalculateGradesForKpi(kpiId, context);
179
+ async recalculateScoresForKpi(kpiId, context) {
180
+ const scoreService = new kpi_value_score_service_1.KpiValueScoreService();
181
+ await scoreService.recalculateScoresForKpi(kpiId, context);
126
182
  return true;
127
183
  }
184
+ async recalculateKpiValue(id, context) {
185
+ const { domain, user, tx } = context.state;
186
+ const kpiValueRepo = (0, shell_1.getRepository)(kpi_value_1.KpiValue, tx);
187
+ const kpiRepo = (0, shell_1.getRepository)(kpi_1.Kpi, tx);
188
+ const metricRepo = (0, shell_1.getRepository)(kpi_metric_1.KpiMetric, tx);
189
+ const metricValueRepo = (0, shell_1.getRepository)(kpi_metric_value_1.KpiMetricValue, tx);
190
+ // 1. 기존 KPI Value 인스턴스 조회
191
+ const kpiValue = await kpiValueRepo.findOne({
192
+ where: { id, domain: { id: domain.id } },
193
+ relations: ['kpi']
194
+ });
195
+ if (!kpiValue)
196
+ throw new Error('KPI Value not found');
197
+ const kpi = kpiValue.kpi || (await kpiRepo.findOne({ where: { id: kpiValue.kpiId, domain: { id: domain.id } } }));
198
+ if (!kpi)
199
+ throw new Error('KPI 정보 없음');
200
+ if (!kpi.formula)
201
+ throw new Error('KPI formula 없음');
202
+ const periodType = kpi.periodType || kpi_2.KpiPeriodType.DAY;
203
+ const valueDate = kpiValue.valueDate;
204
+ const group = kpiValue.group;
205
+ const version = kpiValue.version;
206
+ // 2. formula에서 metric code 추출
207
+ const metricCodes = (kpi.formula.match(/[a-zA-Z_][a-zA-Z0-9_]*/g) || []).filter(code => code !== 'null' && code !== 'undefined');
208
+ const metricMap = {};
209
+ for (const code of metricCodes) {
210
+ const metric = await metricRepo.findOne({ where: { name: code, domain: { id: domain.id } } });
211
+ if (!metric)
212
+ throw new Error(`KPI formula metric '${code}' not found`);
213
+ metricMap[code] = metric;
214
+ }
215
+ // 3. metric 값 집계 (periodType 변환/집계)
216
+ const metricValues = {};
217
+ for (const code of metricCodes) {
218
+ const metric = metricMap[code];
219
+ let value = null;
220
+ if (metric.periodType === periodType) {
221
+ const mv = await metricValueRepo.findOne({
222
+ where: {
223
+ metric: { id: metric.id },
224
+ valueDate,
225
+ periodType,
226
+ group: group ?? '',
227
+ domain: { id: domain.id }
228
+ }
229
+ });
230
+ value = mv?.value ?? null;
231
+ }
232
+ else {
233
+ let startDate, endDate;
234
+ if (periodType === kpi_2.KpiPeriodType.MONTH && metric.periodType === kpi_2.KpiPeriodType.DAY) {
235
+ startDate = valueDate + '-01';
236
+ endDate = valueDate + '-31';
237
+ const mvs = await metricValueRepo.find({
238
+ where: {
239
+ metric: { id: metric.id },
240
+ valueDate: (0, typeorm_1.Between)(startDate, endDate),
241
+ periodType: metric.periodType,
242
+ group: group ?? '',
243
+ domain: { id: domain.id }
244
+ }
245
+ });
246
+ value = mvs.reduce((sum, mv) => sum + (mv.value ?? 0), 0);
247
+ }
248
+ else {
249
+ throw new Error('KPI/Metric periodType 조합 집계 미지원');
250
+ }
251
+ }
252
+ if (value == null)
253
+ throw new Error(`Metric '${code}' 값 없음`);
254
+ metricValues[code] = value;
255
+ }
256
+ // 4. formula 계산 (calculator 기반)
257
+ const ast = (0, parser_1.parseFormula)(kpi.formula);
258
+ const provider = new kpi_metric_value_provider_1.KpiMetricValueProvider({
259
+ valueDate,
260
+ group,
261
+ domainId: domain.id,
262
+ tx
263
+ });
264
+ const evalContext = { functions: functions_1.builtinFunctions, provider };
265
+ const kpiValueResult = await (0, evaluator_1.evaluateFormula)(ast, evalContext);
266
+ if (kpiValueResult == null || isNaN(kpiValueResult))
267
+ throw new Error('KPI formula 결과값 없음');
268
+ // 5. KPI Value 업데이트
269
+ kpiValue.value = kpiValueResult;
270
+ kpiValue.updater = user;
271
+ // 6. 성과 점수 자동 계산 및 저장
272
+ const scoreService = new kpi_value_score_service_1.KpiValueScoreService();
273
+ await scoreService.calculateAndSaveScore(kpiValue, kpi);
274
+ return await kpiValueRepo.save(kpiValue);
275
+ }
128
276
  };
129
277
  exports.KpiValueMutation = KpiValueMutation;
130
278
  tslib_1.__decorate([
@@ -136,6 +284,17 @@ tslib_1.__decorate([
136
284
  tslib_1.__metadata("design:paramtypes", [kpi_value_type_1.NewKpiValue, Object]),
137
285
  tslib_1.__metadata("design:returntype", Promise)
138
286
  ], KpiValueMutation.prototype, "createKpiValue", null);
287
+ tslib_1.__decorate([
288
+ (0, type_graphql_1.Directive)('@transaction'),
289
+ (0, type_graphql_1.Mutation)(returns => [kpi_value_1.KpiValue], { description: 'Create multiple KPI values with the provided details.' }),
290
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('values', type => [kpi_value_type_1.NewKpiValue], {
291
+ description: 'Array of input objects containing details for the new KPI values.'
292
+ })),
293
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
294
+ tslib_1.__metadata("design:type", Function),
295
+ tslib_1.__metadata("design:paramtypes", [Array, Object]),
296
+ tslib_1.__metadata("design:returntype", Promise)
297
+ ], KpiValueMutation.prototype, "createMultipleKpiValue", null);
139
298
  tslib_1.__decorate([
140
299
  (0, type_graphql_1.Directive)('@transaction'),
141
300
  (0, type_graphql_1.Mutation)(returns => kpi_value_1.KpiValue, { description: 'To modify KpiValue information' }),
@@ -184,13 +343,22 @@ tslib_1.__decorate([
184
343
  ], KpiValueMutation.prototype, "importKpiValues", null);
185
344
  tslib_1.__decorate([
186
345
  (0, type_graphql_1.Directive)('@transaction'),
187
- (0, type_graphql_1.Mutation)(returns => Boolean, { description: 'Recalculate grades for all KpiValues of a specific KPI' }),
346
+ (0, type_graphql_1.Mutation)(returns => Boolean, { description: 'Recalculate scores for all KpiValues of a specific KPI' }),
188
347
  tslib_1.__param(0, (0, type_graphql_1.Arg)('kpiId')),
189
348
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
190
349
  tslib_1.__metadata("design:type", Function),
191
350
  tslib_1.__metadata("design:paramtypes", [String, Object]),
192
351
  tslib_1.__metadata("design:returntype", Promise)
193
- ], KpiValueMutation.prototype, "recalculateGradesForKpi", null);
352
+ ], KpiValueMutation.prototype, "recalculateScoresForKpi", null);
353
+ tslib_1.__decorate([
354
+ (0, type_graphql_1.Directive)('@transaction'),
355
+ (0, type_graphql_1.Mutation)(returns => kpi_value_1.KpiValue, { description: '기존 KPI Value 인스턴스를 현재 formula/metric 값으로 재계산' }),
356
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
357
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
358
+ tslib_1.__metadata("design:type", Function),
359
+ tslib_1.__metadata("design:paramtypes", [String, Object]),
360
+ tslib_1.__metadata("design:returntype", Promise)
361
+ ], KpiValueMutation.prototype, "recalculateKpiValue", null);
194
362
  exports.KpiValueMutation = KpiValueMutation = tslib_1.__decorate([
195
363
  (0, type_graphql_1.Resolver)(kpi_value_1.KpiValue)
196
364
  ], KpiValueMutation);
@@ -1 +1 @@
1
- {"version":3,"file":"kpi-value-mutation.js","sourceRoot":"","sources":["../../../server/service/kpi-value/kpi-value-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Resolver, Mutation, Arg, Ctx, Directive } from 'type-graphql'\nimport { In } from 'typeorm'\nimport { getRepository } from '@things-factory/shell'\n\nimport { KpiValue } from './kpi-value'\nimport { NewKpiValue, KpiValuePatch } from './kpi-value-type'\nimport { Kpi } from '../kpi/kpi'\nimport { KpiValueInputType } from './kpi-value'\nimport { KpiValueGradeService } from './kpi-value-grade.service'\n\n@Resolver(KpiValue)\nexport class KpiValueMutation {\n @Directive('@transaction')\n @Mutation(returns => KpiValue, { description: 'Create a new KPI value with the provided details.' })\n async createKpiValue(\n @Arg('kpiValue', { description: 'Input object containing details for the new KPI value.' }) kpiValue: NewKpiValue,\n @Ctx() context: ResolverContext\n ): Promise<KpiValue> {\n const { domain, user, tx } = context.state\n\n let kpi = kpiValue.kpiId ? await getRepository(Kpi).findOne({ where: { id: kpiValue.kpiId } }) : undefined\n\n let inputType: KpiValueInputType | undefined = undefined\n if (kpiValue.inputType) {\n if (typeof kpiValue.inputType === 'string') {\n inputType = KpiValueInputType[kpiValue.inputType as keyof typeof KpiValueInputType]\n } else {\n inputType = kpiValue.inputType\n }\n }\n\n const entity: Partial<KpiValue> = {\n kpi,\n kpiId: kpiValue.kpiId,\n version: kpiValue.version,\n valueDate: kpiValue.valueDate,\n value: kpiValue.value,\n group: kpiValue.group,\n source: kpiValue.source,\n domain: domain,\n creator: user,\n updater: user\n }\n if (inputType) entity.inputType = inputType\n\n return await getRepository(KpiValue, tx).save(entity)\n }\n\n @Directive('@transaction')\n @Mutation(returns => KpiValue, { description: 'To modify KpiValue information' })\n async updateKpiValue(\n @Arg('id') id: string,\n @Arg('patch') patch: KpiValuePatch,\n @Ctx() context: ResolverContext\n ): Promise<KpiValue> {\n const { domain, user, tx } = context.state\n\n const repository = getRepository(KpiValue, tx)\n const kpiValue = await repository.findOne({\n where: { domain: { id: domain.id }, id }\n })\n\n let kpi = patch.kpiId ? await getRepository(Kpi).findOne({ where: { id: patch.kpiId } }) : kpiValue.kpi\n\n let inputType: KpiValueInputType | undefined = undefined\n if (patch.inputType) {\n if (typeof patch.inputType === 'string') {\n inputType = KpiValueInputType[patch.inputType as keyof typeof KpiValueInputType]\n } else {\n inputType = patch.inputType\n }\n } else {\n inputType = kpiValue.inputType\n }\n\n const entity: any = {\n ...kpiValue,\n ...patch,\n kpi,\n updater: user\n }\n if (inputType) entity.inputType = inputType\n\n return await repository.save(entity)\n }\n\n @Directive('@transaction')\n @Mutation(returns => [KpiValue], { description: \"To modify multiple KpiValues' information\" })\n async updateMultipleKpiValue(\n @Arg('patches', type => [KpiValuePatch]) patches: KpiValuePatch[],\n @Ctx() context: ResolverContext\n ): Promise<KpiValue[]> {\n const { domain, user, tx } = context.state\n\n let results = []\n const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')\n const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')\n const kpiValueRepo = getRepository(KpiValue, tx)\n\n if (_createRecords.length > 0) {\n for (let i = 0; i < _createRecords.length; i++) {\n const newRecord = _createRecords[i]\n\n const result = await kpiValueRepo.save({\n ...newRecord,\n domain,\n creator: user,\n updater: user\n } as any)\n\n results.push({ ...result, cuFlag: '+' })\n }\n }\n\n if (_updateRecords.length > 0) {\n for (let i = 0; i < _updateRecords.length; i++) {\n const updateRecord = _updateRecords[i]\n const kpiValue = await kpiValueRepo.findOneBy({ id: updateRecord.id })\n\n const result = await kpiValueRepo.save({\n ...kpiValue,\n ...updateRecord,\n updater: user\n } as any)\n\n results.push({ ...result, cuFlag: 'M' })\n }\n }\n\n return results\n }\n\n @Directive('@transaction')\n @Mutation(returns => Boolean, { description: 'To delete KpiValue' })\n async deleteKpiValue(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const { domain, tx } = context.state\n\n await getRepository(KpiValue, tx).delete({ domain: { id: domain.id }, id })\n\n return true\n }\n\n @Directive('@transaction')\n @Mutation(returns => Boolean, { description: 'To delete multiple KpiValues' })\n async deleteKpiValues(\n @Arg('ids', type => [String]) ids: string[],\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, tx } = context.state\n\n await getRepository(KpiValue, tx).delete({\n domain: { id: domain.id },\n id: In(ids)\n })\n\n return true\n }\n\n @Directive('@transaction')\n @Mutation(returns => Boolean, { description: 'To import multiple KpiValues' })\n async importKpiValues(\n @Arg('kpiValues', type => [KpiValuePatch]) kpiValues: KpiValuePatch[],\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, tx } = context.state\n\n await Promise.all(\n kpiValues.map(async (kpiValue: KpiValuePatch) => {\n const createdKpiValue: KpiValue = await getRepository(KpiValue, tx).save({ domain, ...kpiValue } as any)\n })\n )\n\n return true\n }\n\n @Directive('@transaction')\n @Mutation(returns => Boolean, { description: 'Recalculate grades for all KpiValues of a specific KPI' })\n async recalculateGradesForKpi(@Arg('kpiId') kpiId: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const gradeService = new KpiValueGradeService()\n await gradeService.recalculateGradesForKpi(kpiId, context)\n return true\n }\n}\n"]}
1
+ {"version":3,"file":"kpi-value-mutation.js","sourceRoot":"","sources":["../../../server/service/kpi-value/kpi-value-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Resolver, Mutation, Arg, Ctx, Directive } from 'type-graphql'\nimport { In, Between } from 'typeorm'\nimport { getRepository } from '@things-factory/shell'\n\nimport { KpiValue } from './kpi-value'\nimport { NewKpiValue, KpiValuePatch } from './kpi-value-type'\nimport { Kpi } from '../kpi/kpi'\nimport { KpiMetric } from '../kpi-metric/kpi-metric'\nimport { KpiMetricValue } from '../kpi-metric-value/kpi-metric-value'\nimport { KpiPeriodType } from '../kpi/kpi'\nimport { getDefaultValueDate } from '../utils/value-date-util'\nimport { KpiValueInputType } from './kpi-value'\nimport { KpiValueScoreService } from './kpi-value-score.service'\nimport { parseFormula } from '../../calculator/parser'\nimport { evaluateFormula } from '../../calculator/evaluator'\nimport { builtinFunctions } from '../../calculator/functions'\nimport { KpiMetricValueProvider } from '../../controllers/kpi-metric-value-provider'\n\n@Resolver(KpiValue)\nexport class KpiValueMutation {\n @Directive('@transaction')\n @Mutation(returns => KpiValue, { description: 'Create a new KPI value with the provided details.' })\n async createKpiValue(\n @Arg('kpiValue', { description: 'Input object containing details for the new KPI value.' }) kpiValue: NewKpiValue,\n @Ctx() context: ResolverContext\n ): Promise<KpiValue> {\n const { domain, user, tx } = context.state\n\n let kpi = kpiValue.kpiId ? await getRepository(Kpi).findOne({ where: { id: kpiValue.kpiId } }) : undefined\n\n let inputType: KpiValueInputType | undefined = undefined\n if (kpiValue.inputType) {\n if (typeof kpiValue.inputType === 'string') {\n inputType = KpiValueInputType[kpiValue.inputType as keyof typeof KpiValueInputType]\n } else {\n inputType = kpiValue.inputType\n }\n }\n\n const entity: Partial<KpiValue> = {\n kpi,\n kpiId: kpiValue.kpiId,\n version: kpiValue.version,\n valueDate: kpiValue.valueDate,\n value: kpiValue.value,\n group: kpiValue.group,\n source: kpiValue.source,\n domain: domain,\n creator: user,\n updater: user\n }\n if (inputType) entity.inputType = inputType\n\n return await getRepository(KpiValue, tx).save(entity)\n }\n\n @Directive('@transaction')\n @Mutation(returns => [KpiValue], { description: 'Create multiple KPI values with the provided details.' })\n async createMultipleKpiValue(\n @Arg('values', type => [NewKpiValue], {\n description: 'Array of input objects containing details for the new KPI values.'\n })\n values: NewKpiValue[],\n @Ctx() context: ResolverContext\n ): Promise<KpiValue[]> {\n const { domain, user, tx } = context.state\n const repository = getRepository(KpiValue, tx)\n const scoreService = new KpiValueScoreService()\n\n const entities: KpiValue[] = []\n\n for (const kpiValue of values) {\n let kpi = kpiValue.kpiId ? await getRepository(Kpi).findOne({ where: { id: kpiValue.kpiId } }) : undefined\n\n let inputType: KpiValueInputType | undefined = undefined\n if (kpiValue.inputType) {\n if (typeof kpiValue.inputType === 'string') {\n inputType = KpiValueInputType[kpiValue.inputType as keyof typeof KpiValueInputType]\n } else {\n inputType = kpiValue.inputType\n }\n }\n\n const entity: Partial<KpiValue> = {\n kpi,\n kpiId: kpiValue.kpiId,\n version: kpiValue.version || 1,\n valueDate: kpiValue.valueDate,\n value: kpiValue.value,\n group: kpiValue.group || '',\n source: kpiValue.source || 'MANUAL',\n domain: domain,\n creator: user,\n updater: user\n }\n if (inputType) entity.inputType = inputType\n\n const savedEntity = await repository.save(entity)\n\n // 성과 점수 자동 계산 및 저장\n if (kpi) {\n await scoreService.calculateAndSaveScore(savedEntity, kpi)\n }\n\n entities.push(savedEntity)\n }\n\n return entities\n }\n\n @Directive('@transaction')\n @Mutation(returns => KpiValue, { description: 'To modify KpiValue information' })\n async updateKpiValue(\n @Arg('id') id: string,\n @Arg('patch') patch: KpiValuePatch,\n @Ctx() context: ResolverContext\n ): Promise<KpiValue> {\n const { domain, user, tx } = context.state\n\n const repository = getRepository(KpiValue, tx)\n const kpiValue = await repository.findOne({\n where: { domain: { id: domain.id }, id }\n })\n\n let kpi = patch.kpiId ? await getRepository(Kpi).findOne({ where: { id: patch.kpiId } }) : kpiValue.kpi\n\n let inputType: KpiValueInputType | undefined = undefined\n if (patch.inputType) {\n if (typeof patch.inputType === 'string') {\n inputType = KpiValueInputType[patch.inputType as keyof typeof KpiValueInputType]\n } else {\n inputType = patch.inputType\n }\n } else {\n inputType = kpiValue.inputType\n }\n\n const entity: any = {\n ...kpiValue,\n ...patch,\n kpi,\n updater: user\n }\n if (inputType) entity.inputType = inputType\n\n return await repository.save(entity)\n }\n\n @Directive('@transaction')\n @Mutation(returns => [KpiValue], { description: \"To modify multiple KpiValues' information\" })\n async updateMultipleKpiValue(\n @Arg('patches', type => [KpiValuePatch]) patches: KpiValuePatch[],\n @Ctx() context: ResolverContext\n ): Promise<KpiValue[]> {\n const { domain, user, tx } = context.state\n\n let results = []\n const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')\n const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')\n const kpiValueRepo = getRepository(KpiValue, tx)\n\n if (_createRecords.length > 0) {\n for (let i = 0; i < _createRecords.length; i++) {\n const newRecord = _createRecords[i]\n\n const kpi = await getRepository(Kpi, tx).findOne({\n where: { domain: { id: domain.id }, id: newRecord.kpiId }\n })\n\n const result = await kpiValueRepo.save({\n ...newRecord,\n kpi,\n version: newRecord.version || kpi.version,\n domain,\n creator: user,\n updater: user\n } as any)\n\n results.push({ ...result, cuFlag: '+' })\n }\n }\n\n if (_updateRecords.length > 0) {\n for (let i = 0; i < _updateRecords.length; i++) {\n const updateRecord = _updateRecords[i]\n const kpiValue = await kpiValueRepo.findOneBy({ id: updateRecord.id })\n\n const kpi = await getRepository(Kpi, tx).findOne({\n where: { domain: { id: domain.id }, id: updateRecord.kpiId }\n })\n\n const result = await kpiValueRepo.save({\n ...kpiValue,\n ...updateRecord,\n kpi,\n version: updateRecord.version || kpi.version,\n updater: user\n } as any)\n\n results.push({ ...result, cuFlag: 'M' })\n }\n }\n\n return results\n }\n\n @Directive('@transaction')\n @Mutation(returns => Boolean, { description: 'To delete KpiValue' })\n async deleteKpiValue(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const { domain, tx } = context.state\n\n await getRepository(KpiValue, tx).delete({ domain: { id: domain.id }, id })\n\n return true\n }\n\n @Directive('@transaction')\n @Mutation(returns => Boolean, { description: 'To delete multiple KpiValues' })\n async deleteKpiValues(\n @Arg('ids', type => [String]) ids: string[],\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, tx } = context.state\n\n await getRepository(KpiValue, tx).delete({\n domain: { id: domain.id },\n id: In(ids)\n })\n\n return true\n }\n\n @Directive('@transaction')\n @Mutation(returns => Boolean, { description: 'To import multiple KpiValues' })\n async importKpiValues(\n @Arg('kpiValues', type => [KpiValuePatch]) kpiValues: KpiValuePatch[],\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, tx } = context.state\n\n await Promise.all(\n kpiValues.map(async (kpiValue: KpiValuePatch) => {\n const createdKpiValue: KpiValue = await getRepository(KpiValue, tx).save({ domain, ...kpiValue } as any)\n })\n )\n\n return true\n }\n\n @Directive('@transaction')\n @Mutation(returns => Boolean, { description: 'Recalculate scores for all KpiValues of a specific KPI' })\n async recalculateScoresForKpi(@Arg('kpiId') kpiId: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const scoreService = new KpiValueScoreService()\n await scoreService.recalculateScoresForKpi(kpiId, context)\n return true\n }\n\n @Directive('@transaction')\n @Mutation(returns => KpiValue, { description: '기존 KPI Value 인스턴스를 현재 formula/metric 값으로 재계산' })\n async recalculateKpiValue(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<KpiValue> {\n const { domain, user, tx } = context.state\n const kpiValueRepo = getRepository(KpiValue, tx)\n const kpiRepo = getRepository(Kpi, tx)\n const metricRepo = getRepository(KpiMetric, tx)\n const metricValueRepo = getRepository(KpiMetricValue, tx)\n\n // 1. 기존 KPI Value 인스턴스 조회\n const kpiValue = await kpiValueRepo.findOne({\n where: { id, domain: { id: domain.id } },\n relations: ['kpi']\n })\n if (!kpiValue) throw new Error('KPI Value not found')\n const kpi = kpiValue.kpi || (await kpiRepo.findOne({ where: { id: kpiValue.kpiId, domain: { id: domain.id } } }))\n if (!kpi) throw new Error('KPI 정보 없음')\n if (!kpi.formula) throw new Error('KPI formula 없음')\n const periodType = kpi.periodType || KpiPeriodType.DAY\n const valueDate = kpiValue.valueDate\n const group = kpiValue.group\n const version = kpiValue.version\n\n // 2. formula에서 metric code 추출\n const metricCodes = (kpi.formula.match(/[a-zA-Z_][a-zA-Z0-9_]*/g) || []).filter(\n code => code !== 'null' && code !== 'undefined'\n )\n const metricMap: Record<string, KpiMetric> = {}\n for (const code of metricCodes) {\n const metric = await metricRepo.findOne({ where: { name: code, domain: { id: domain.id } } })\n if (!metric) throw new Error(`KPI formula metric '${code}' not found`)\n metricMap[code] = metric\n }\n\n // 3. metric 값 집계 (periodType 변환/집계)\n const metricValues: Record<string, number> = {}\n for (const code of metricCodes) {\n const metric = metricMap[code]\n let value = null\n if (metric.periodType === periodType) {\n const mv = await metricValueRepo.findOne({\n where: {\n metric: { id: metric.id },\n valueDate,\n periodType,\n group: group ?? '',\n domain: { id: domain.id }\n }\n })\n value = mv?.value ?? null\n } else {\n let startDate: string, endDate: string\n if (periodType === KpiPeriodType.MONTH && metric.periodType === KpiPeriodType.DAY) {\n startDate = valueDate + '-01'\n endDate = valueDate + '-31'\n const mvs = await metricValueRepo.find({\n where: {\n metric: { id: metric.id },\n valueDate: Between(startDate, endDate),\n periodType: metric.periodType,\n group: group ?? '',\n domain: { id: domain.id }\n }\n })\n value = mvs.reduce((sum, mv) => sum + (mv.value ?? 0), 0)\n } else {\n throw new Error('KPI/Metric periodType 조합 집계 미지원')\n }\n }\n if (value == null) throw new Error(`Metric '${code}' 값 없음`)\n metricValues[code] = value\n }\n\n // 4. formula 계산 (calculator 기반)\n const ast = parseFormula(kpi.formula)\n const provider = new KpiMetricValueProvider({\n valueDate,\n group,\n domainId: domain.id,\n tx\n })\n const evalContext = { functions: builtinFunctions, provider }\n const kpiValueResult = await evaluateFormula(ast, evalContext)\n if (kpiValueResult == null || isNaN(kpiValueResult)) throw new Error('KPI formula 결과값 없음')\n\n // 5. KPI Value 업데이트\n kpiValue.value = kpiValueResult\n kpiValue.updater = user\n\n // 6. 성과 점수 자동 계산 및 저장\n const scoreService = new KpiValueScoreService()\n await scoreService.calculateAndSaveScore(kpiValue, kpi)\n\n return await kpiValueRepo.save(kpiValue)\n }\n}\n"]}
@@ -3,7 +3,6 @@ import { User } from '@things-factory/auth-base';
3
3
  import { KpiValue } from './kpi-value';
4
4
  import { KpiValueList } from './kpi-value-type';
5
5
  import { Kpi } from '../kpi/kpi';
6
- import { GradeInfo } from './kpi-value-grade.service';
7
6
  export declare class KpiValueQuery {
8
7
  kpiValue(id: string, context: ResolverContext): Promise<KpiValue>;
9
8
  kpiValues(params: ListParam, context: ResolverContext): Promise<KpiValueList>;
@@ -11,5 +10,4 @@ export declare class KpiValueQuery {
11
10
  updater(kpiValue: KpiValue): Promise<User>;
12
11
  creator(kpiValue: KpiValue): Promise<User>;
13
12
  kpi(kpiValue: KpiValue): Promise<Kpi | null>;
14
- grade(kpiValue: KpiValue): Promise<GradeInfo | null>;
15
13
  }
@@ -8,7 +8,6 @@ const auth_base_1 = require("@things-factory/auth-base");
8
8
  const kpi_value_1 = require("./kpi-value");
9
9
  const kpi_value_type_1 = require("./kpi-value-type");
10
10
  const kpi_1 = require("../kpi/kpi");
11
- const kpi_value_grade_service_1 = require("./kpi-value-grade.service");
12
11
  let KpiValueQuery = class KpiValueQuery {
13
12
  async kpiValue(id, context) {
14
13
  const { domain } = context.state;
@@ -41,10 +40,6 @@ let KpiValueQuery = class KpiValueQuery {
41
40
  return null;
42
41
  return await (0, shell_1.getRepository)(kpi_1.Kpi).findOneBy({ id: kpiValue.kpiId });
43
42
  }
44
- async grade(kpiValue) {
45
- const gradeService = new kpi_value_grade_service_1.KpiValueGradeService();
46
- return await gradeService.getGradeForKpiValue(kpiValue);
47
- }
48
43
  };
49
44
  exports.KpiValueQuery = KpiValueQuery;
50
45
  tslib_1.__decorate([
@@ -91,13 +86,6 @@ tslib_1.__decorate([
91
86
  tslib_1.__metadata("design:paramtypes", [kpi_value_1.KpiValue]),
92
87
  tslib_1.__metadata("design:returntype", Promise)
93
88
  ], KpiValueQuery.prototype, "kpi", null);
94
- tslib_1.__decorate([
95
- (0, type_graphql_1.FieldResolver)(type => kpi_value_grade_service_1.GradeInfo, { nullable: true }),
96
- tslib_1.__param(0, (0, type_graphql_1.Root)()),
97
- tslib_1.__metadata("design:type", Function),
98
- tslib_1.__metadata("design:paramtypes", [kpi_value_1.KpiValue]),
99
- tslib_1.__metadata("design:returntype", Promise)
100
- ], KpiValueQuery.prototype, "grade", null);
101
89
  exports.KpiValueQuery = KpiValueQuery = tslib_1.__decorate([
102
90
  (0, type_graphql_1.Resolver)(kpi_value_1.KpiValue)
103
91
  ], KpiValueQuery);
@@ -1 +1 @@
1
- {"version":3,"file":"kpi-value-query.js","sourceRoot":"","sources":["../../../server/service/kpi-value/kpi-value-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx, Directive } from 'type-graphql'\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\nimport { KpiValue } from './kpi-value'\nimport { KpiValueList } from './kpi-value-type'\nimport { Kpi } from '../kpi/kpi'\nimport { KpiValueGradeService, GradeInfo } from './kpi-value-grade.service'\n\n@Resolver(KpiValue)\nexport class KpiValueQuery {\n @Query(returns => KpiValue!, { nullable: true, description: 'Fetch a single KPI value by its unique identifier.' })\n async kpiValue(\n @Arg('id', { description: 'Unique identifier of the KPI value to fetch.' }) id: string,\n @Ctx() context: ResolverContext\n ): Promise<KpiValue> {\n const { domain } = context.state\n\n return await getRepository(KpiValue).findOne({\n where: { domain: { id: domain.id }, id }\n })\n }\n\n @Query(returns => KpiValueList, { description: 'To fetch multiple KpiValues' })\n async kpiValues(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<KpiValueList> {\n const { domain } = context.state\n\n const queryBuilder = getQueryBuilderFromListParams({\n domain,\n params,\n repository: await getRepository(KpiValue),\n searchables: ['kpi', 'group', 'valueDate']\n })\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n @FieldResolver(type => Domain)\n async domain(@Root() kpiValue: KpiValue): Promise<Domain> {\n return kpiValue.domainId && (await getRepository(Domain).findOneBy({ id: kpiValue.domainId }))\n }\n\n @FieldResolver(type => User)\n async updater(@Root() kpiValue: KpiValue): Promise<User> {\n return kpiValue.updaterId && (await getRepository(User).findOneBy({ id: kpiValue.updaterId }))\n }\n\n @FieldResolver(type => User)\n async creator(@Root() kpiValue: KpiValue): Promise<User> {\n return kpiValue.creatorId && (await getRepository(User).findOneBy({ id: kpiValue.creatorId }))\n }\n\n @FieldResolver(type => Kpi)\n async kpi(@Root() kpiValue: KpiValue): Promise<Kpi | null> {\n if (!kpiValue.kpiId) return null\n return await getRepository(Kpi).findOneBy({ id: kpiValue.kpiId })\n }\n\n @FieldResolver(type => GradeInfo, { nullable: true })\n async grade(@Root() kpiValue: KpiValue): Promise<GradeInfo | null> {\n const gradeService = new KpiValueGradeService()\n return await gradeService.getGradeForKpiValue(kpiValue)\n }\n}\n"]}
1
+ {"version":3,"file":"kpi-value-query.js","sourceRoot":"","sources":["../../../server/service/kpi-value/kpi-value-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx, Directive, Float } from 'type-graphql'\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\nimport { KpiValue } from './kpi-value'\nimport { KpiValueList } from './kpi-value-type'\nimport { Kpi } from '../kpi/kpi'\nimport { KpiValueScoreService } from './kpi-value-score.service'\n\n@Resolver(KpiValue)\nexport class KpiValueQuery {\n @Query(returns => KpiValue!, { nullable: true, description: 'Fetch a single KPI value by its unique identifier.' })\n async kpiValue(\n @Arg('id', { description: 'Unique identifier of the KPI value to fetch.' }) id: string,\n @Ctx() context: ResolverContext\n ): Promise<KpiValue> {\n const { domain } = context.state\n\n return await getRepository(KpiValue).findOne({\n where: { domain: { id: domain.id }, id }\n })\n }\n\n @Query(returns => KpiValueList, { description: 'To fetch multiple KpiValues' })\n async kpiValues(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<KpiValueList> {\n const { domain } = context.state\n\n const queryBuilder = getQueryBuilderFromListParams({\n domain,\n params,\n repository: await getRepository(KpiValue),\n searchables: ['kpi', 'group', 'valueDate']\n })\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n @FieldResolver(type => Domain)\n async domain(@Root() kpiValue: KpiValue): Promise<Domain> {\n return kpiValue.domainId && (await getRepository(Domain).findOneBy({ id: kpiValue.domainId }))\n }\n\n @FieldResolver(type => User)\n async updater(@Root() kpiValue: KpiValue): Promise<User> {\n return kpiValue.updaterId && (await getRepository(User).findOneBy({ id: kpiValue.updaterId }))\n }\n\n @FieldResolver(type => User)\n async creator(@Root() kpiValue: KpiValue): Promise<User> {\n return kpiValue.creatorId && (await getRepository(User).findOneBy({ id: kpiValue.creatorId }))\n }\n\n @FieldResolver(type => Kpi)\n async kpi(@Root() kpiValue: KpiValue): Promise<Kpi | null> {\n if (!kpiValue.kpiId) return null\n return await getRepository(Kpi).findOneBy({ id: kpiValue.kpiId })\n }\n}\n"]}
@@ -0,0 +1,26 @@
1
+ import { Kpi } from '../kpi/kpi';
2
+ import { KpiValue } from './kpi-value';
3
+ export interface ScoreResult {
4
+ score: number;
5
+ calculationMethod?: 'formula' | 'lookup';
6
+ }
7
+ export declare class KpiValueScoreService {
8
+ /**
9
+ * scoreFormula를 사용한 성과 점수 계산
10
+ */
11
+ calculateScoreFromFormula(kpi: Kpi, value: number): Promise<ScoreResult | null>;
12
+ /**
13
+ * KPI의 grades lookup table을 이용한 성과 점수 변환
14
+ * 복잡한 성과 점수 변환을 수식으로 표현하기 어려운 경우 사용
15
+ * @deprecated 향후 grades 필드 제거 예정. scoreFormula로 대체 권장
16
+ */
17
+ calculateScoreFromLookup(kpi: Kpi, value: number): ScoreResult | null;
18
+ /**
19
+ * KpiValue 생성/수정 시 성과 점수 자동 계산 및 저장
20
+ */
21
+ calculateAndSaveScore(kpiValue: KpiValue, kpi: Kpi): Promise<void>;
22
+ /**
23
+ * 기존 KpiValue들의 성과 점수 재계산 (배치 처리)
24
+ */
25
+ recalculateScoresForKpi(kpiId: string, context: ResolverContext): Promise<void>;
26
+ }
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KpiValueScoreService = void 0;
4
+ const shell_1 = require("@things-factory/shell");
5
+ const kpi_1 = require("../kpi/kpi");
6
+ const kpi_value_1 = require("./kpi-value");
7
+ const parser_1 = require("../../calculator/parser");
8
+ const evaluator_1 = require("../../calculator/evaluator");
9
+ const functions_1 = require("../../calculator/functions");
10
+ class KpiValueScoreService {
11
+ /**
12
+ * scoreFormula를 사용한 성과 점수 계산
13
+ */
14
+ async calculateScoreFromFormula(kpi, value) {
15
+ if (!kpi.scoreFormula) {
16
+ return null;
17
+ }
18
+ try {
19
+ const ast = (0, parser_1.parseFormula)(kpi.scoreFormula);
20
+ const provider = {
21
+ get: async (name) => {
22
+ if (name === 'value')
23
+ return value;
24
+ return null;
25
+ }
26
+ };
27
+ const evalContext = { functions: functions_1.builtinFunctions, provider };
28
+ const result = await (0, evaluator_1.evaluateFormula)(ast, evalContext);
29
+ if (result !== null && result !== undefined && !isNaN(result)) {
30
+ const performanceScore = Number(result);
31
+ // score를 0~1 범위로 제한
32
+ const clampedScore = Math.max(0, Math.min(1, performanceScore));
33
+ return {
34
+ score: clampedScore,
35
+ calculationMethod: 'formula'
36
+ };
37
+ }
38
+ }
39
+ catch (error) {
40
+ console.error('Score formula evaluation error:', error);
41
+ }
42
+ return null;
43
+ }
44
+ /**
45
+ * KPI의 grades lookup table을 이용한 성과 점수 변환
46
+ * 복잡한 성과 점수 변환을 수식으로 표현하기 어려운 경우 사용
47
+ * @deprecated 향후 grades 필드 제거 예정. scoreFormula로 대체 권장
48
+ */
49
+ calculateScoreFromLookup(kpi, value) {
50
+ if (!kpi.grades || kpi.grades.length === 0) {
51
+ return null;
52
+ }
53
+ // grades lookup table에서 해당 값의 범위에 맞는 성과 점수 찾기
54
+ const grade = kpi.grades.find(g => value >= g.minValue && value <= g.maxValue);
55
+ if (!grade) {
56
+ return null;
57
+ }
58
+ // score를 0~1 범위로 제한
59
+ const clampedScore = Math.max(0, Math.min(1, grade.score));
60
+ return {
61
+ score: clampedScore,
62
+ calculationMethod: 'lookup'
63
+ };
64
+ }
65
+ /**
66
+ * KpiValue 생성/수정 시 성과 점수 자동 계산 및 저장
67
+ */
68
+ async calculateAndSaveScore(kpiValue, kpi) {
69
+ // 1. scoreFormula 우선 시도
70
+ let scoreResult = await this.calculateScoreFromFormula(kpi, kpiValue.value);
71
+ // 2. scoreFormula가 없거나 실패하면 grades lookup table 사용 (deprecated)
72
+ if (!scoreResult) {
73
+ scoreResult = this.calculateScoreFromLookup(kpi, kpiValue.value);
74
+ }
75
+ if (scoreResult) {
76
+ // KpiValue의 score 필드에 성과 점수 저장
77
+ kpiValue.score = scoreResult.score;
78
+ }
79
+ }
80
+ /**
81
+ * 기존 KpiValue들의 성과 점수 재계산 (배치 처리)
82
+ */
83
+ async recalculateScoresForKpi(kpiId, context) {
84
+ const kpi = await (0, shell_1.getRepository)(kpi_1.Kpi).findOne({ where: { id: kpiId } });
85
+ if (!kpi)
86
+ return;
87
+ const kpiValues = await (0, shell_1.getRepository)(kpi_value_1.KpiValue).find({
88
+ where: { kpiId, version: kpi.version }
89
+ });
90
+ for (const kpiValue of kpiValues) {
91
+ await this.calculateAndSaveScore(kpiValue, kpi);
92
+ }
93
+ await (0, shell_1.getRepository)(kpi_value_1.KpiValue).save(kpiValues);
94
+ }
95
+ }
96
+ exports.KpiValueScoreService = KpiValueScoreService;
97
+ //# sourceMappingURL=kpi-value-score.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kpi-value-score.service.js","sourceRoot":"","sources":["../../../server/service/kpi-value/kpi-value-score.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { getRepository } from '@things-factory/shell'\nimport { Kpi } from '../kpi/kpi'\nimport { KpiValue } from './kpi-value'\nimport { parseFormula } from '../../calculator/parser'\nimport { evaluateFormula } from '../../calculator/evaluator'\nimport { builtinFunctions } from '../../calculator/functions'\n\nexport interface ScoreResult {\n score: number\n calculationMethod?: 'formula' | 'lookup'\n}\n\nexport class KpiValueScoreService {\n /**\n * scoreFormula를 사용한 성과 점수 계산\n */\n async calculateScoreFromFormula(kpi: Kpi, value: number): Promise<ScoreResult | null> {\n if (!kpi.scoreFormula) {\n return null\n }\n\n try {\n const ast = parseFormula(kpi.scoreFormula)\n const provider = {\n get: async (name: string) => {\n if (name === 'value') return value\n return null\n }\n }\n const evalContext = { functions: builtinFunctions, provider }\n const result = await evaluateFormula(ast, evalContext)\n\n if (result !== null && result !== undefined && !isNaN(result)) {\n const performanceScore = Number(result)\n\n // score를 0~1 범위로 제한\n const clampedScore = Math.max(0, Math.min(1, performanceScore))\n\n return {\n score: clampedScore,\n calculationMethod: 'formula'\n }\n }\n } catch (error) {\n console.error('Score formula evaluation error:', error)\n }\n\n return null\n }\n\n /**\n * KPI의 grades lookup table을 이용한 성과 점수 변환\n * 복잡한 성과 점수 변환을 수식으로 표현하기 어려운 경우 사용\n * @deprecated 향후 grades 필드 제거 예정. scoreFormula로 대체 권장\n */\n calculateScoreFromLookup(kpi: Kpi, value: number): ScoreResult | null {\n if (!kpi.grades || kpi.grades.length === 0) {\n return null\n }\n\n // grades lookup table에서 해당 값의 범위에 맞는 성과 점수 찾기\n const grade = kpi.grades.find(g => value >= g.minValue && value <= g.maxValue)\n\n if (!grade) {\n return null\n }\n\n // score를 0~1 범위로 제한\n const clampedScore = Math.max(0, Math.min(1, grade.score))\n\n return {\n score: clampedScore,\n calculationMethod: 'lookup'\n }\n }\n\n /**\n * KpiValue 생성/수정 시 성과 점수 자동 계산 및 저장\n */\n async calculateAndSaveScore(kpiValue: KpiValue, kpi: Kpi): Promise<void> {\n // 1. scoreFormula 우선 시도\n let scoreResult = await this.calculateScoreFromFormula(kpi, kpiValue.value)\n\n // 2. scoreFormula가 없거나 실패하면 grades lookup table 사용 (deprecated)\n if (!scoreResult) {\n scoreResult = this.calculateScoreFromLookup(kpi, kpiValue.value)\n }\n\n if (scoreResult) {\n // KpiValue의 score 필드에 성과 점수 저장\n kpiValue.score = scoreResult.score\n }\n }\n\n /**\n * 기존 KpiValue들의 성과 점수 재계산 (배치 처리)\n */\n async recalculateScoresForKpi(kpiId: string, context: ResolverContext): Promise<void> {\n const kpi = await getRepository(Kpi).findOne({ where: { id: kpiId } })\n if (!kpi) return\n\n const kpiValues = await getRepository(KpiValue).find({\n where: { kpiId, version: kpi.version }\n })\n\n for (const kpiValue of kpiValues) {\n await this.calculateAndSaveScore(kpiValue, kpi)\n }\n\n await getRepository(KpiValue).save(kpiValues)\n }\n}\n"]}
@@ -4,6 +4,7 @@ export declare class NewKpiValue {
4
4
  version: number;
5
5
  valueDate: string;
6
6
  value: number;
7
+ score?: number;
7
8
  meta?: any;
8
9
  group?: string;
9
10
  inputType?: KpiValueInputType;
@@ -15,6 +16,7 @@ export declare class KpiValuePatch {
15
16
  version?: number;
16
17
  valueDate?: string;
17
18
  value?: number;
19
+ score?: number;
18
20
  meta?: any;
19
21
  group?: string;
20
22
  inputType?: KpiValueInputType;
@@ -24,6 +24,13 @@ tslib_1.__decorate([
24
24
  (0, type_graphql_1.Field)(type => type_graphql_1.Float, { description: 'The calculated numeric value for this KPI and period.' }),
25
25
  tslib_1.__metadata("design:type", Number)
26
26
  ], NewKpiValue.prototype, "value", void 0);
27
+ tslib_1.__decorate([
28
+ (0, type_graphql_1.Field)(type => type_graphql_1.Float, {
29
+ nullable: true,
30
+ description: 'Performance score calculated from KPI value using scoreFormula or grades lookup table. Range: 0-1.'
31
+ }),
32
+ tslib_1.__metadata("design:type", Number)
33
+ ], NewKpiValue.prototype, "score", void 0);
27
34
  tslib_1.__decorate([
28
35
  (0, type_graphql_1.Field)(type => shell_1.ScalarObject, {
29
36
  nullable: true,
@@ -78,6 +85,13 @@ tslib_1.__decorate([
78
85
  (0, type_graphql_1.Field)(type => type_graphql_1.Float, { nullable: true, description: 'The calculated numeric value for this KPI and period.' }),
79
86
  tslib_1.__metadata("design:type", Number)
80
87
  ], KpiValuePatch.prototype, "value", void 0);
88
+ tslib_1.__decorate([
89
+ (0, type_graphql_1.Field)(type => type_graphql_1.Float, {
90
+ nullable: true,
91
+ description: 'Performance score calculated from KPI value using scoreFormula or grades lookup table. Range: 0-1.'
92
+ }),
93
+ tslib_1.__metadata("design:type", Number)
94
+ ], KpiValuePatch.prototype, "score", void 0);
81
95
  tslib_1.__decorate([
82
96
  (0, type_graphql_1.Field)(type => shell_1.ScalarObject, {
83
97
  nullable: true,