@things-factory/kpi 9.0.31 → 9.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- package/client/charts/kpi-boxplot-chart.ts +182 -42
- package/client/charts/kpi-radar-chart.ts +9 -9
- package/client/pages/kpi/kpi-list-page.ts +196 -32
- package/client/pages/kpi/kpi-overview.ts +9 -11
- package/client/pages/kpi/kpi-tree-page.ts +409 -0
- package/client/pages/kpi/kpi-view.ts +187 -0
- package/client/pages/kpi-dashboard/cards/kpi-level1-card.ts +1 -1
- package/client/pages/kpi-dashboard/cards/kpi-level2-comparison.ts +1 -1
- package/client/pages/kpi-dashboard/cards/kpi-level3-comparison.ts +1 -1
- package/client/pages/kpi-dashboard/components/kpi-left-panel.ts +198 -160
- package/client/pages/kpi-dashboard/components/kpi-map-panel.ts +133 -0
- package/client/pages/kpi-dashboard/components/kpi-region-popup.ts +3 -2
- package/client/pages/kpi-dashboard/kpi-dashboard-map.ts +291 -48
- package/client/pages/kpi-dashboard/kpi-dashboard.ts +28 -30
- package/client/pages/kpi-history/kpi-history-list-page.ts +11 -11
- package/client/pages/kpi-metric/kpi-metric-list-page.ts +10 -2
- package/client/pages/kpi-metric-value/kpi-metric-value-editor-page.ts +7 -7
- package/client/pages/kpi-metric-value/kpi-metric-value-importer.ts +2 -2
- package/client/pages/kpi-metric-value/kpi-metric-value-list-page.ts +16 -8
- package/client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.ts +5 -5
- package/client/pages/kpi-statistic/kpi-statistic-editor-page.ts +1 -2
- package/client/pages/kpi-statistic/kpi-statistic-list-page.ts +10 -2
- package/client/pages/kpi-value/kpi-value-editor-page.ts +11 -7
- package/client/pages/kpi-value/kpi-value-list-page.ts +31 -7
- package/client/route.ts +2 -9
- package/design-entities.md +8 -12
- package/dist-client/charts/kpi-boxplot-chart.d.ts +2 -0
- package/dist-client/charts/kpi-boxplot-chart.js +168 -42
- package/dist-client/charts/kpi-boxplot-chart.js.map +1 -1
- package/dist-client/charts/kpi-radar-chart.js +9 -9
- package/dist-client/charts/kpi-radar-chart.js.map +1 -1
- package/dist-client/pages/kpi/kpi-list-page.d.ts +19 -3
- package/dist-client/pages/kpi/kpi-list-page.js +188 -32
- package/dist-client/pages/kpi/kpi-list-page.js.map +1 -1
- package/dist-client/pages/kpi/kpi-overview.js +9 -11
- package/dist-client/pages/kpi/kpi-overview.js.map +1 -1
- package/dist-client/pages/kpi/kpi-tree-page.d.ts +59 -0
- package/dist-client/pages/kpi/kpi-tree-page.js +403 -0
- package/dist-client/pages/kpi/kpi-tree-page.js.map +1 -0
- package/dist-client/pages/kpi/kpi-view.d.ts +12 -0
- package/dist-client/pages/kpi/kpi-view.js +191 -0
- package/dist-client/pages/kpi/kpi-view.js.map +1 -0
- package/dist-client/pages/kpi-dashboard/cards/kpi-level1-card.js +1 -1
- package/dist-client/pages/kpi-dashboard/cards/kpi-level1-card.js.map +1 -1
- package/dist-client/pages/kpi-dashboard/cards/kpi-level2-comparison.js +1 -1
- package/dist-client/pages/kpi-dashboard/cards/kpi-level2-comparison.js.map +1 -1
- package/dist-client/pages/kpi-dashboard/cards/kpi-level3-comparison.js +1 -1
- package/dist-client/pages/kpi-dashboard/cards/kpi-level3-comparison.js.map +1 -1
- package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.d.ts +3 -1
- package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.js +197 -161
- package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.js.map +1 -1
- package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.d.ts +5 -0
- package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js +146 -0
- package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js.map +1 -1
- package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.js +3 -2
- package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.js.map +1 -1
- package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.d.ts +3 -1
- package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js +268 -46
- package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js.map +1 -1
- package/dist-client/pages/kpi-dashboard/kpi-dashboard.js +28 -30
- package/dist-client/pages/kpi-dashboard/kpi-dashboard.js.map +1 -1
- package/dist-client/pages/kpi-history/kpi-history-list-page.d.ts +6 -1
- package/dist-client/pages/kpi-history/kpi-history-list-page.js +11 -11
- package/dist-client/pages/kpi-history/kpi-history-list-page.js.map +1 -1
- package/dist-client/pages/kpi-metric/kpi-metric-list-page.d.ts +5 -0
- package/dist-client/pages/kpi-metric/kpi-metric-list-page.js +10 -2
- package/dist-client/pages/kpi-metric/kpi-metric-list-page.js.map +1 -1
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.d.ts +1 -1
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.js +8 -8
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.js.map +1 -1
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.js +2 -2
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.js.map +1 -1
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.d.ts +5 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js +16 -8
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js.map +1 -1
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.d.ts +1 -1
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.js +6 -6
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.js.map +1 -1
- package/dist-client/pages/kpi-statistic/kpi-statistic-editor-page.js +1 -2
- package/dist-client/pages/kpi-statistic/kpi-statistic-editor-page.js.map +1 -1
- package/dist-client/pages/kpi-statistic/kpi-statistic-list-page.d.ts +5 -0
- package/dist-client/pages/kpi-statistic/kpi-statistic-list-page.js +10 -2
- package/dist-client/pages/kpi-statistic/kpi-statistic-list-page.js.map +1 -1
- package/dist-client/pages/kpi-value/kpi-value-editor-page.d.ts +2 -1
- package/dist-client/pages/kpi-value/kpi-value-editor-page.js +16 -8
- package/dist-client/pages/kpi-value/kpi-value-editor-page.js.map +1 -1
- package/dist-client/pages/kpi-value/kpi-value-list-page.d.ts +5 -0
- package/dist-client/pages/kpi-value/kpi-value-list-page.js +31 -7
- package/dist-client/pages/kpi-value/kpi-value-list-page.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/route.js +2 -8
- package/dist-client/route.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/controllers/kpi-metric-value-provider.d.ts +1 -1
- package/dist-server/controllers/kpi-metric-value-provider.js +4 -4
- package/dist-server/controllers/kpi-metric-value-provider.js.map +1 -1
- package/dist-server/controllers/kpi-value-provider.d.ts +1 -1
- package/dist-server/controllers/kpi-value-provider.js +3 -3
- package/dist-server/controllers/kpi-value-provider.js.map +1 -1
- package/dist-server/migrations/1752190849680-seed-kpi-metrics.d.ts +6 -0
- package/dist-server/migrations/1752190849680-seed-kpi-metrics.js +101 -0
- package/dist-server/migrations/1752190849680-seed-kpi-metrics.js.map +1 -0
- package/dist-server/migrations/1752190849681-seed-kpi.d.ts +5 -0
- package/dist-server/migrations/1752190849681-seed-kpi.js +315 -0
- package/dist-server/migrations/1752190849681-seed-kpi.js.map +1 -0
- package/dist-server/migrations/1752192090123-add-grades-to-kpi.d.ts +7 -0
- package/dist-server/migrations/1752192090123-add-grades-to-kpi.js +51 -0
- package/dist-server/migrations/1752192090123-add-grades-to-kpi.js.map +1 -0
- package/dist-server/migrations/1752192090124-add-kpi-statistics.d.ts +5 -0
- package/dist-server/migrations/1752192090124-add-kpi-statistics.js +710 -0
- package/dist-server/migrations/1752192090124-add-kpi-statistics.js.map +1 -0
- package/dist-server/migrations/1752192090128-seed-kpi-org-scope.d.ts +6 -0
- package/dist-server/migrations/1752192090128-seed-kpi-org-scope.js +111 -0
- package/dist-server/migrations/1752192090128-seed-kpi-org-scope.js.map +1 -0
- package/dist-server/migrations/1752192090129-seed-kpi-values.d.ts +6 -0
- package/dist-server/migrations/1752192090129-seed-kpi-values.js +187 -0
- package/dist-server/migrations/1752192090129-seed-kpi-values.js.map +1 -0
- package/dist-server/migrations/grade-data/x11-performance-table.json +962 -0
- package/dist-server/migrations/grade-data/x12-performance-table.json +611 -0
- package/dist-server/migrations/grade-data/x14-performance-table.json +42 -0
- package/dist-server/migrations/grade-data/x21-performance-table.json +889 -0
- package/dist-server/migrations/grade-data/x22-performance-table.json +1064 -0
- package/dist-server/migrations/grade-data/x23-performance-table.json +42 -0
- package/dist-server/migrations/grade-data/x31-performance-table.json +644 -0
- package/dist-server/migrations/grade-data/x32-performance-table.json +993 -0
- package/dist-server/migrations/grade-data/x33-performance-table.json +195 -0
- package/dist-server/migrations/grade-data/x34-performance-table.json +12 -0
- package/dist-server/migrations/grade-data/x35-performance-table.json +42 -0
- package/dist-server/migrations/grade-data/x41-performance-table.json +825 -0
- package/dist-server/migrations/grade-data/x42-performance-table.json +786 -0
- package/dist-server/migrations/grade-data/x43-performance-table.json +12 -0
- package/dist-server/migrations/grade-data/x44-performance-table.json +42 -0
- package/dist-server/migrations/grade-data/x51-performance-table.json +924 -0
- package/dist-server/migrations/grade-data/x52-performance-table.json +42 -0
- package/dist-server/migrations/grade-data/x61-performance-table.json +261 -0
- package/dist-server/migrations/grade-data/x62-performance-table.json +42 -0
- package/dist-server/migrations/seed-data/kpi-metrics-seed.json +454 -0
- package/dist-server/migrations/seed-data/kpi-org-scope-seed.json +1676 -0
- package/dist-server/migrations/seed-data/kpi-scopes-seed.json +121 -0
- package/dist-server/migrations/seed-data/kpi-values-seed.json +402 -0
- package/dist-server/migrations/seed-data/kpis-seed.json +488 -0
- package/dist-server/migrations/seed-data/scope-definitions-seed.json +90 -0
- package/dist-server/service/index.d.ts +4 -7
- package/dist-server/service/index.js +10 -13
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/kpi/aggregate-kpi.js +30 -13
- package/dist-server/service/kpi/aggregate-kpi.js.map +1 -1
- package/dist-server/service/kpi/kpi-formula.service.d.ts +15 -0
- package/dist-server/service/kpi/kpi-formula.service.js +90 -0
- package/dist-server/service/kpi/kpi-formula.service.js.map +1 -1
- package/dist-server/service/kpi/kpi-history.d.ts +0 -3
- package/dist-server/service/kpi/kpi-history.js +0 -10
- package/dist-server/service/kpi/kpi-history.js.map +1 -1
- package/dist-server/service/kpi/kpi-mutation.d.ts +1 -1
- package/dist-server/service/kpi/kpi-mutation.js +57 -20
- package/dist-server/service/kpi/kpi-mutation.js.map +1 -1
- package/dist-server/service/kpi/kpi-query.d.ts +7 -3
- package/dist-server/service/kpi/kpi-query.js +126 -10
- package/dist-server/service/kpi/kpi-query.js.map +1 -1
- package/dist-server/service/kpi/kpi-type.d.ts +4 -2
- package/dist-server/service/kpi/kpi-type.js +12 -4
- package/dist-server/service/kpi/kpi-type.js.map +1 -1
- package/dist-server/service/kpi/kpi.d.ts +4 -3
- package/dist-server/service/kpi/kpi.js +20 -8
- package/dist-server/service/kpi/kpi.js.map +1 -1
- package/dist-server/service/kpi-metric/aggregate-kpi-metric.js +46 -11
- package/dist-server/service/kpi-metric/aggregate-kpi-metric.js.map +1 -1
- package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.d.ts +1 -1
- package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js +6 -6
- package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js.map +1 -1
- package/dist-server/service/kpi-metric-value/kpi-metric-value-type.d.ts +2 -2
- package/dist-server/service/kpi-metric-value/kpi-metric-value-type.js +4 -4
- package/dist-server/service/kpi-metric-value/kpi-metric-value-type.js.map +1 -1
- package/dist-server/service/kpi-metric-value/kpi-metric-value.d.ts +1 -1
- package/dist-server/service/kpi-metric-value/kpi-metric-value.js +3 -3
- package/dist-server/service/kpi-metric-value/kpi-metric-value.js.map +1 -1
- package/dist-server/service/kpi-org-scope/index.d.ts +5 -0
- package/dist-server/service/kpi-org-scope/index.js +9 -0
- package/dist-server/service/kpi-org-scope/index.js.map +1 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope-mutation.d.ts +8 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope-mutation.js +170 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope-mutation.js.map +1 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope-query.d.ts +14 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope-query.js +152 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope-query.js.map +1 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope-type.d.ts +26 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope-type.js +101 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope-type.js.map +1 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope.d.ts +26 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope.js +135 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope.js.map +1 -0
- package/dist-server/service/kpi-scope/index.d.ts +9 -0
- package/dist-server/service/kpi-scope/index.js +14 -0
- package/dist-server/service/kpi-scope/index.js.map +1 -0
- package/dist-server/service/kpi-scope/kpi-scope-mutation.d.ts +9 -0
- package/dist-server/service/kpi-scope/kpi-scope-mutation.js +135 -0
- package/dist-server/service/kpi-scope/kpi-scope-mutation.js.map +1 -0
- package/dist-server/service/kpi-scope/kpi-scope-query.d.ts +11 -0
- package/dist-server/service/kpi-scope/kpi-scope-query.js +89 -0
- package/dist-server/service/kpi-scope/kpi-scope-query.js.map +1 -0
- package/dist-server/service/kpi-scope/kpi-scope-type.d.ts +35 -0
- package/dist-server/service/kpi-scope/kpi-scope-type.js +138 -0
- package/dist-server/service/kpi-scope/kpi-scope-type.js.map +1 -0
- package/dist-server/service/kpi-scope/kpi-scope.d.ts +38 -0
- package/dist-server/service/kpi-scope/kpi-scope.js +144 -0
- package/dist-server/service/kpi-scope/kpi-scope.js.map +1 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-batch.service.d.ts +43 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-batch.service.js +181 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-batch.service.js.map +1 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-calculation.service.d.ts +50 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-calculation.service.js +324 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-calculation.service.js.map +1 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-mutation.d.ts +4 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-mutation.js +76 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-mutation.js.map +1 -1
- package/dist-server/service/kpi-statistic/kpi-statistic-query.d.ts +5 -1
- package/dist-server/service/kpi-statistic/kpi-statistic-query.js +92 -1
- package/dist-server/service/kpi-statistic/kpi-statistic-query.js.map +1 -1
- package/dist-server/service/kpi-statistic/kpi-statistic.d.ts +4 -0
- package/dist-server/service/kpi-statistic/kpi-statistic.js +33 -0
- package/dist-server/service/kpi-statistic/kpi-statistic.js.map +1 -1
- package/dist-server/service/kpi-value/kpi-value-mutation.js +71 -7
- package/dist-server/service/kpi-value/kpi-value-mutation.js.map +1 -1
- package/dist-server/service/kpi-value/kpi-value-type.d.ts +4 -2
- package/dist-server/service/kpi-value/kpi-value-type.js +12 -4
- package/dist-server/service/kpi-value/kpi-value-type.js.map +1 -1
- package/dist-server/service/kpi-value/kpi-value.d.ts +3 -1
- package/dist-server/service/kpi-value/kpi-value.js +11 -5
- package/dist-server/service/kpi-value/kpi-value.js.map +1 -1
- package/dist-server/service/utils/value-date-util.d.ts +1 -0
- package/dist-server/service/utils/value-date-util.js +41 -0
- package/dist-server/service/utils/value-date-util.js.map +1 -1
- package/dist-server/tsconfig.json +10 -0
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -6
- package/server/@types/index.d.ts +11 -0
- package/server/controllers/kpi-metric-value-provider.ts +5 -5
- package/server/controllers/kpi-value-provider.ts +4 -4
- package/server/migrations/1752190849680-seed-kpi-metrics.ts +124 -0
- package/server/migrations/1752190849681-seed-kpi.ts +356 -0
- package/server/migrations/1752192090123-add-grades-to-kpi.ts +67 -0
- package/server/migrations/1752192090124-add-kpi-statistics.ts +719 -0
- package/server/migrations/1752192090128-seed-kpi-org-scope.ts +132 -0
- package/server/migrations/1752192090129-seed-kpi-values.ts +207 -0
- package/server/migrations/grade-data/x11-performance-table.json +962 -0
- package/server/migrations/grade-data/x12-performance-table.json +611 -0
- package/server/migrations/grade-data/x14-performance-table.json +42 -0
- package/server/migrations/grade-data/x21-performance-table.json +889 -0
- package/server/migrations/grade-data/x22-performance-table.json +1064 -0
- package/server/migrations/grade-data/x23-performance-table.json +42 -0
- package/server/migrations/grade-data/x31-performance-table.json +644 -0
- package/server/migrations/grade-data/x32-performance-table.json +993 -0
- package/server/migrations/grade-data/x33-performance-table.json +195 -0
- package/server/migrations/grade-data/x34-performance-table.json +12 -0
- package/server/migrations/grade-data/x35-performance-table.json +42 -0
- package/server/migrations/grade-data/x41-performance-table.json +825 -0
- package/server/migrations/grade-data/x42-performance-table.json +786 -0
- package/server/migrations/grade-data/x43-performance-table.json +12 -0
- package/server/migrations/grade-data/x44-performance-table.json +42 -0
- package/server/migrations/grade-data/x51-performance-table.json +924 -0
- package/server/migrations/grade-data/x52-performance-table.json +42 -0
- package/server/migrations/grade-data/x61-performance-table.json +261 -0
- package/server/migrations/grade-data/x62-performance-table.json +42 -0
- package/server/migrations/seed-data/kpi-metrics-seed.json +454 -0
- package/server/migrations/seed-data/kpi-org-scope-seed.json +1676 -0
- package/server/migrations/seed-data/kpi-scopes-seed.json +121 -0
- package/server/migrations/seed-data/kpi-values-seed.json +402 -0
- package/server/migrations/seed-data/kpis-seed.json +488 -0
- package/server/migrations/seed-data/scope-definitions-seed.json +90 -0
- package/server/service/index.ts +10 -13
- package/server/service/kpi/aggregate-kpi.ts +31 -13
- package/server/service/kpi/kpi-formula.service.ts +101 -0
- package/server/service/kpi/kpi-history.ts +0 -8
- package/server/service/kpi/kpi-mutation.ts +59 -19
- package/server/service/kpi/kpi-query.ts +119 -8
- package/server/service/kpi/kpi-type.ts +10 -4
- package/server/service/kpi/kpi.ts +17 -7
- package/server/service/kpi-metric/aggregate-kpi-metric.ts +55 -11
- package/server/service/kpi-metric-value/kpi-metric-value-mutation.ts +6 -6
- package/server/service/kpi-metric-value/kpi-metric-value-type.ts +4 -4
- package/server/service/kpi-metric-value/kpi-metric-value.ts +3 -3
- package/server/service/kpi-org-scope/index.ts +6 -0
- package/server/service/kpi-org-scope/kpi-org-scope-mutation.ts +173 -0
- package/server/service/kpi-org-scope/kpi-org-scope-query.ts +127 -0
- package/server/service/kpi-org-scope/kpi-org-scope-type.ts +68 -0
- package/server/service/kpi-org-scope/kpi-org-scope.ts +123 -0
- package/server/service/kpi-scope/index.ts +11 -0
- package/server/service/kpi-scope/kpi-scope-mutation.ts +129 -0
- package/server/service/kpi-scope/kpi-scope-query.ts +63 -0
- package/server/service/kpi-scope/kpi-scope-type.ts +96 -0
- package/server/service/kpi-scope/kpi-scope.ts +143 -0
- package/server/service/kpi-statistic/kpi-statistic-batch.service.ts +231 -0
- package/server/service/kpi-statistic/kpi-statistic-calculation.service.ts +410 -0
- package/server/service/kpi-statistic/kpi-statistic-mutation.ts +97 -0
- package/server/service/kpi-statistic/kpi-statistic-query.ts +89 -2
- package/server/service/kpi-statistic/kpi-statistic.ts +32 -0
- package/server/service/kpi-value/kpi-value-mutation.ts +73 -7
- package/server/service/kpi-value/kpi-value-type.ts +10 -4
- package/server/service/kpi-value/kpi-value.ts +10 -5
- package/server/service/utils/value-date-util.ts +47 -0
- package/server/types/global.d.ts +8 -0
- package/things-factory.config.js +1 -0
- package/translations/en.json +15 -3
- package/translations/ja.json +13 -3
- package/translations/ko.json +15 -3
- package/translations/ms.json +13 -3
- package/translations/zh.json +13 -3
- package/client/pages/kpi-category/kpi-category-importer.ts +0 -90
- package/client/pages/kpi-category/kpi-category-list-page.ts +0 -537
- package/client/pages/kpi-category/kpi-category-value-calculator.ts +0 -233
- package/client/pages/kpi-category-value/kpi-category-value-list-page.ts +0 -404
- package/dist-client/pages/kpi-category/kpi-category-importer.d.ts +0 -23
- package/dist-client/pages/kpi-category/kpi-category-importer.js +0 -92
- package/dist-client/pages/kpi-category/kpi-category-importer.js.map +0 -1
- package/dist-client/pages/kpi-category/kpi-category-list-page.d.ts +0 -74
- package/dist-client/pages/kpi-category/kpi-category-list-page.js +0 -517
- package/dist-client/pages/kpi-category/kpi-category-list-page.js.map +0 -1
- package/dist-client/pages/kpi-category/kpi-category-value-calculator.d.ts +0 -13
- package/dist-client/pages/kpi-category/kpi-category-value-calculator.js +0 -256
- package/dist-client/pages/kpi-category/kpi-category-value-calculator.js.map +0 -1
- package/dist-client/pages/kpi-category-value/kpi-category-value-list-page.d.ts +0 -63
- package/dist-client/pages/kpi-category-value/kpi-category-value-list-page.js +0 -393
- package/dist-client/pages/kpi-category-value/kpi-category-value-list-page.js.map +0 -1
- package/dist-server/service/kpi-category/index.d.ts +0 -6
- package/dist-server/service/kpi-category/index.js +0 -10
- package/dist-server/service/kpi-category/index.js.map +0 -1
- package/dist-server/service/kpi-category/kpi-category-mutation.d.ts +0 -9
- package/dist-server/service/kpi-category/kpi-category-mutation.js +0 -221
- package/dist-server/service/kpi-category/kpi-category-mutation.js.map +0 -1
- package/dist-server/service/kpi-category/kpi-category-query.d.ts +0 -18
- package/dist-server/service/kpi-category/kpi-category-query.js +0 -115
- package/dist-server/service/kpi-category/kpi-category-query.js.map +0 -1
- package/dist-server/service/kpi-category/kpi-category-type.d.ts +0 -24
- package/dist-server/service/kpi-category/kpi-category-type.js +0 -100
- package/dist-server/service/kpi-category/kpi-category-type.js.map +0 -1
- package/dist-server/service/kpi-category/kpi-category.d.ts +0 -22
- package/dist-server/service/kpi-category/kpi-category.js +0 -106
- package/dist-server/service/kpi-category/kpi-category.js.map +0 -1
- package/dist-server/service/kpi-category-value/index.d.ts +0 -6
- package/dist-server/service/kpi-category-value/index.js +0 -10
- package/dist-server/service/kpi-category-value/index.js.map +0 -1
- package/dist-server/service/kpi-category-value/kpi-category-value-mutation.d.ts +0 -8
- package/dist-server/service/kpi-category-value/kpi-category-value-mutation.js +0 -102
- package/dist-server/service/kpi-category-value/kpi-category-value-mutation.js.map +0 -1
- package/dist-server/service/kpi-category-value/kpi-category-value-query.d.ts +0 -13
- package/dist-server/service/kpi-category-value/kpi-category-value-query.js +0 -91
- package/dist-server/service/kpi-category-value/kpi-category-value-query.js.map +0 -1
- package/dist-server/service/kpi-category-value/kpi-category-value-type.d.ts +0 -19
- package/dist-server/service/kpi-category-value/kpi-category-value-type.js +0 -73
- package/dist-server/service/kpi-category-value/kpi-category-value-type.js.map +0 -1
- package/dist-server/service/kpi-category-value/kpi-category-value.d.ts +0 -19
- package/dist-server/service/kpi-category-value/kpi-category-value.js +0 -91
- package/dist-server/service/kpi-category-value/kpi-category-value.js.map +0 -1
- package/helps/kpi/kpi-category.md +0 -160
- package/server/service/kpi-category/index.ts +0 -7
- package/server/service/kpi-category/kpi-category-mutation.ts +0 -217
- package/server/service/kpi-category/kpi-category-query.ts +0 -87
- package/server/service/kpi-category/kpi-category-type.ts +0 -73
- package/server/service/kpi-category/kpi-category.ts +0 -95
- package/server/service/kpi-category-value/index.ts +0 -7
- package/server/service/kpi-category-value/kpi-category-value-mutation.ts +0 -88
- package/server/service/kpi-category-value/kpi-category-value-query.ts +0 -62
- package/server/service/kpi-category-value/kpi-category-value-type.ts +0 -48
- package/server/service/kpi-category-value/kpi-category-value.ts +0 -79
|
@@ -5,6 +5,7 @@ const shell_1 = require("@things-factory/shell");
|
|
|
5
5
|
const kpi_1 = require("./kpi");
|
|
6
6
|
const kpi_metric_1 = require("../kpi-metric/kpi-metric");
|
|
7
7
|
const kpi_value_1 = require("../kpi-value/kpi-value");
|
|
8
|
+
const kpi_org_scope_1 = require("../kpi-org-scope/kpi-org-scope");
|
|
8
9
|
const kpi_formula_service_1 = require("./kpi-formula.service");
|
|
9
10
|
const aggregate_kpi_metric_1 = require("../kpi-metric/aggregate-kpi-metric");
|
|
10
11
|
const kpi_value_score_service_1 = require("../kpi-value/kpi-value-score.service");
|
|
@@ -37,20 +38,20 @@ async function aggregateKpiValue(kpiId, domainId, context) {
|
|
|
37
38
|
throw new Error(`KPI formula metric '${code}' not found`);
|
|
38
39
|
codeValueMap[code] = await (0, aggregate_kpi_metric_1.aggregateKpiMetricValue)(metric.id, domainId, context);
|
|
39
40
|
}
|
|
40
|
-
//
|
|
41
|
-
const
|
|
42
|
-
const
|
|
41
|
+
// org/date/period별로 값 매핑(가장 최근 기준, org key 조합)
|
|
42
|
+
const orgKey = v => [v.date, v.period, v.org].join('|');
|
|
43
|
+
const orgMap = {};
|
|
43
44
|
for (const code of metricCodes) {
|
|
44
45
|
for (const v of codeValueMap[code]) {
|
|
45
|
-
const key =
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
const key = orgKey(v);
|
|
47
|
+
orgMap[key] = orgMap[key] || { ...v, _values: {} };
|
|
48
|
+
orgMap[key]._values[code] = v.value;
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
// formula 계산 (js eval)
|
|
51
52
|
const savedValues = [];
|
|
52
|
-
for (const key in
|
|
53
|
-
const ctx =
|
|
53
|
+
for (const key in orgMap) {
|
|
54
|
+
const ctx = orgMap[key]._values;
|
|
54
55
|
let value = null;
|
|
55
56
|
try {
|
|
56
57
|
value = Function(...Object.keys(ctx), `return (${kpi.formula})`)(...Object.values(ctx));
|
|
@@ -58,15 +59,30 @@ async function aggregateKpiValue(kpiId, domainId, context) {
|
|
|
58
59
|
catch (e) {
|
|
59
60
|
value = null;
|
|
60
61
|
}
|
|
61
|
-
const valueDate =
|
|
62
|
-
const
|
|
62
|
+
const valueDate = orgMap[key].date;
|
|
63
|
+
const org = orgMap[key].org;
|
|
63
64
|
const version = kpi.version || 1;
|
|
64
65
|
if (value == null || isNaN(value))
|
|
65
66
|
continue;
|
|
66
|
-
//
|
|
67
|
+
// KpiOrgScope 처리 (org 문자열로 찾기 또는 생성)
|
|
68
|
+
const kpiOrgScopeRepo = (0, shell_1.getRepository)(kpi_org_scope_1.KpiOrgScope, context.state?.tx);
|
|
69
|
+
let kpiOrgScope = await kpiOrgScopeRepo.findOne({
|
|
70
|
+
where: { org: org, domain: { id: domainId } }
|
|
71
|
+
});
|
|
72
|
+
if (!kpiOrgScope) {
|
|
73
|
+
// 새 KpiOrgScope 생성
|
|
74
|
+
kpiOrgScope = await kpiOrgScopeRepo.save({
|
|
75
|
+
entityType: 'AutoAggregate',
|
|
76
|
+
entityId: `auto-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
77
|
+
entityName: org,
|
|
78
|
+
org: org,
|
|
79
|
+
domain: kpi.domain
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
// upsert(동일 KPI, valueDate, kpiOrgScope, version) 기준으로 저장
|
|
67
83
|
const repo = (0, shell_1.getRepository)(kpi_value_1.KpiValue, context.state?.tx);
|
|
68
84
|
const existing = await repo.findOne({
|
|
69
|
-
where: { kpi: { id: kpi.id }, valueDate,
|
|
85
|
+
where: { kpi: { id: kpi.id }, valueDate, kpiOrgScope: { id: kpiOrgScope.id }, version, domain: { id: domainId } }
|
|
70
86
|
});
|
|
71
87
|
let entity = existing || repo.create();
|
|
72
88
|
entity.kpi = kpi;
|
|
@@ -74,7 +90,8 @@ async function aggregateKpiValue(kpiId, domainId, context) {
|
|
|
74
90
|
entity.version = version;
|
|
75
91
|
entity.valueDate = valueDate;
|
|
76
92
|
entity.value = value;
|
|
77
|
-
entity.
|
|
93
|
+
entity.kpiOrgScope = kpiOrgScope;
|
|
94
|
+
entity.kpiOrgScopeId = kpiOrgScope.id;
|
|
78
95
|
entity.inputType = kpi_value_1.KpiValueInputType.AUTO;
|
|
79
96
|
entity.source = 'AUTO';
|
|
80
97
|
entity.domain = kpi.domain;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aggregate-kpi.js","sourceRoot":"","sources":["../../../server/service/kpi/aggregate-kpi.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"aggregate-kpi.js","sourceRoot":"","sources":["../../../server/service/kpi/aggregate-kpi.ts"],"names":[],"mappings":"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","sourcesContent":["import { getRepository } from '@things-factory/shell'\nimport { Kpi } from './kpi'\nimport { KpiMetric } from '../kpi-metric/kpi-metric'\nimport { KpiValue, KpiValueInputType } from '../kpi-value/kpi-value'\nimport { KpiOrgScope } from '../kpi-org-scope/kpi-org-scope'\nimport { KpiFormulaService } from './kpi-formula.service'\nimport { aggregateKpiMetricValue } from '../kpi-metric/aggregate-kpi-metric'\nimport { KpiValueScoreService } from '../kpi-value/kpi-value-score.service'\n\n/**\n * KPI 단위 집계/산식 자동화 함수\n * @param kpiId KPI ID\n * @param domainId 도메인 ID\n * @param context ResolverContext\n * @returns 저장된 KPI Value 배열\n */\nexport async function aggregateKpiValue(kpiId: string, domainId: string, context: ResolverContext) {\n const tx = context.state?.tx || getRepository(Kpi).manager\n const scoreService = new KpiValueScoreService()\n\n // 1. KPI 정보 조회\n const kpi = await getRepository(Kpi).findOne({ where: { id: kpiId, domain: { id: domainId } } })\n if (!kpi) throw new Error('KPI 정보 없음')\n if (!kpi.active) throw new Error('비활성화된 KPI')\n if (!kpi.formula) throw new Error('KPI formula 없음')\n\n // 2. formula 파싱 및 metric code별 값 집계\n const formulaService = new KpiFormulaService()\n const metricCodes = formulaService.extractMetricCodes(kpi.formula)\n const codeValueMap: Record<string, any[]> = {}\n for (const code of metricCodes) {\n // code로 metric 찾기\n const metric = await getRepository(KpiMetric).findOne({ where: { name: code, domain: { id: domainId } } })\n if (!metric) throw new Error(`KPI formula metric '${code}' not found`)\n codeValueMap[code] = await aggregateKpiMetricValue(metric.id, domainId, context)\n }\n // org/date/period별로 값 매핑(가장 최근 기준, org key 조합)\n const orgKey = v => [v.date, v.period, v.org].join('|')\n const orgMap: Record<string, any> = {}\n for (const code of metricCodes) {\n for (const v of codeValueMap[code]) {\n const key = orgKey(v)\n orgMap[key] = orgMap[key] || { ...v, _values: {} }\n orgMap[key]._values[code] = v.value\n }\n }\n // formula 계산 (js eval)\n const savedValues = []\n for (const key in orgMap) {\n const ctx = orgMap[key]._values\n let value = null\n try {\n value = Function(...Object.keys(ctx), `return (${kpi.formula})`)(...Object.values(ctx))\n } catch (e) {\n value = null\n }\n const valueDate = orgMap[key].date\n const org = orgMap[key].org\n const version = kpi.version || 1\n if (value == null || isNaN(value)) continue\n // KpiOrgScope 처리 (org 문자열로 찾기 또는 생성)\n const kpiOrgScopeRepo = getRepository(KpiOrgScope, context.state?.tx)\n let kpiOrgScope = await kpiOrgScopeRepo.findOne({\n where: { org: org, domain: { id: domainId } }\n })\n if (!kpiOrgScope) {\n // 새 KpiOrgScope 생성\n kpiOrgScope = await kpiOrgScopeRepo.save({\n entityType: 'AutoAggregate',\n entityId: `auto-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,\n entityName: org,\n org: org,\n domain: kpi.domain\n })\n }\n\n // upsert(동일 KPI, valueDate, kpiOrgScope, version) 기준으로 저장\n const repo = getRepository(KpiValue, context.state?.tx)\n const existing = await repo.findOne({\n where: { kpi: { id: kpi.id }, valueDate, kpiOrgScope: { id: kpiOrgScope.id }, version, domain: { id: domainId } }\n })\n let entity = existing || repo.create()\n entity.kpi = kpi\n entity.kpiId = kpi.id\n entity.version = version\n entity.valueDate = valueDate\n entity.value = value\n entity.kpiOrgScope = kpiOrgScope\n entity.kpiOrgScopeId = kpiOrgScope.id\n entity.inputType = KpiValueInputType.AUTO\n entity.source = 'AUTO'\n entity.domain = kpi.domain\n entity.creator = context.state?.user\n entity.updater = context.state?.user\n\n // 성과 점수 자동 계산 및 저장\n await scoreService.calculateAndSaveScore(entity, kpi)\n\n entity = await repo.save(entity)\n savedValues.push(entity)\n }\n return savedValues\n}\n"]}
|
|
@@ -21,4 +21,19 @@ export declare class KpiFormulaService {
|
|
|
21
21
|
valid: boolean;
|
|
22
22
|
errors: string[];
|
|
23
23
|
}>;
|
|
24
|
+
/**
|
|
25
|
+
* 계층 구조 KPI의 값을 자식 KPI들로부터 집계 계산
|
|
26
|
+
* @param kpiId 부모 KPI ID
|
|
27
|
+
* @param valueDate 계산 대상 날짜
|
|
28
|
+
* @param org 조직 단위
|
|
29
|
+
* @returns Promise<number | null> 집계된 값
|
|
30
|
+
*/
|
|
31
|
+
calculateHierarchicalValue(kpiId: string, valueDate: string, org?: string): Promise<number | null>;
|
|
32
|
+
/**
|
|
33
|
+
* KPI가 순환 참조를 생성하는지 확인
|
|
34
|
+
* @param kpiId KPI ID
|
|
35
|
+
* @param parentId 설정하려는 부모 KPI ID
|
|
36
|
+
* @returns Promise<boolean> 순환 참조 여부
|
|
37
|
+
*/
|
|
38
|
+
hasCircularReference(kpiId: string, parentId: string): Promise<boolean>;
|
|
24
39
|
}
|
|
@@ -3,6 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.KpiFormulaService = void 0;
|
|
4
4
|
const shell_1 = require("@things-factory/shell");
|
|
5
5
|
const kpi_metric_1 = require("../kpi-metric/kpi-metric");
|
|
6
|
+
const kpi_1 = require("./kpi");
|
|
7
|
+
const kpi_value_1 = require("../kpi-value/kpi-value");
|
|
8
|
+
const kpi_org_scope_1 = require("../kpi-org-scope/kpi-org-scope");
|
|
6
9
|
/**
|
|
7
10
|
* KPI formula 파싱/검증/매핑 유효성 검사 서비스
|
|
8
11
|
* - formula에서 Metric 코드(변수명) 추출
|
|
@@ -59,6 +62,93 @@ class KpiFormulaService {
|
|
|
59
62
|
// ...
|
|
60
63
|
return { valid: errors.length === 0, errors };
|
|
61
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* 계층 구조 KPI의 값을 자식 KPI들로부터 집계 계산
|
|
67
|
+
* @param kpiId 부모 KPI ID
|
|
68
|
+
* @param valueDate 계산 대상 날짜
|
|
69
|
+
* @param org 조직 단위
|
|
70
|
+
* @returns Promise<number | null> 집계된 값
|
|
71
|
+
*/
|
|
72
|
+
async calculateHierarchicalValue(kpiId, valueDate, org) {
|
|
73
|
+
const kpiRepo = (0, shell_1.getRepository)(kpi_1.Kpi);
|
|
74
|
+
const kpi = await kpiRepo.findOne({
|
|
75
|
+
where: { id: kpiId },
|
|
76
|
+
relations: ['children']
|
|
77
|
+
});
|
|
78
|
+
if (!kpi || !kpi.children || kpi.children.length === 0) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
const childValues = [];
|
|
82
|
+
const childWeights = [];
|
|
83
|
+
for (const child of kpi.children) {
|
|
84
|
+
let childValue = null;
|
|
85
|
+
if (child.isLeaf) {
|
|
86
|
+
// Leaf KPI인 경우 KpiValue에서 실제 값을 가져옴
|
|
87
|
+
const kpiValueRepo = (0, shell_1.getRepository)(kpi_value_1.KpiValue);
|
|
88
|
+
let kpiValue = null;
|
|
89
|
+
if (org) {
|
|
90
|
+
const kpiOrgScope = await (0, shell_1.getRepository)(kpi_org_scope_1.KpiOrgScope).findOne({
|
|
91
|
+
where: { org: org, domain: { id: child.domain?.id } }
|
|
92
|
+
});
|
|
93
|
+
if (kpiOrgScope) {
|
|
94
|
+
kpiValue = await kpiValueRepo.findOne({
|
|
95
|
+
where: {
|
|
96
|
+
kpi: { id: child.id },
|
|
97
|
+
valueDate,
|
|
98
|
+
kpiOrgScope: { id: kpiOrgScope.id }
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
// org가 없는 경우 kpiOrgScope 없이 조회
|
|
105
|
+
kpiValue = await kpiValueRepo.findOne({
|
|
106
|
+
where: {
|
|
107
|
+
kpi: { id: child.id },
|
|
108
|
+
valueDate,
|
|
109
|
+
kpiOrgScope: null
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
childValue = kpiValue?.value || null;
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
// 중간 노드인 경우 재귀적으로 계산
|
|
117
|
+
childValue = await this.calculateHierarchicalValue(child.id, valueDate, org);
|
|
118
|
+
}
|
|
119
|
+
if (childValue !== null) {
|
|
120
|
+
childValues.push(childValue);
|
|
121
|
+
childWeights.push(child.weight || 1);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (childValues.length === 0) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
// 가중 평균 계산
|
|
128
|
+
const totalWeight = childWeights.reduce((sum, weight) => sum + weight, 0);
|
|
129
|
+
const weightedSum = childValues.reduce((sum, value, index) => sum + value * childWeights[index], 0);
|
|
130
|
+
return totalWeight > 0 ? weightedSum / totalWeight : null;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* KPI가 순환 참조를 생성하는지 확인
|
|
134
|
+
* @param kpiId KPI ID
|
|
135
|
+
* @param parentId 설정하려는 부모 KPI ID
|
|
136
|
+
* @returns Promise<boolean> 순환 참조 여부
|
|
137
|
+
*/
|
|
138
|
+
async hasCircularReference(kpiId, parentId) {
|
|
139
|
+
if (kpiId === parentId) {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
const kpiRepo = (0, shell_1.getRepository)(kpi_1.Kpi);
|
|
143
|
+
const parent = await kpiRepo.findOne({
|
|
144
|
+
where: { id: parentId },
|
|
145
|
+
relations: ['parent']
|
|
146
|
+
});
|
|
147
|
+
if (!parent || !parent.parent) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
return await this.hasCircularReference(kpiId, parent.parent.id);
|
|
151
|
+
}
|
|
62
152
|
}
|
|
63
153
|
exports.KpiFormulaService = KpiFormulaService;
|
|
64
154
|
//# sourceMappingURL=kpi-formula.service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kpi-formula.service.js","sourceRoot":"","sources":["../../../server/service/kpi/kpi-formula.service.ts"],"names":[],"mappings":";;;AAAA,iDAAqD;AACrD,yDAAoD;
|
|
1
|
+
{"version":3,"file":"kpi-formula.service.js","sourceRoot":"","sources":["../../../server/service/kpi/kpi-formula.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { getRepository } from '@things-factory/shell'\nimport { KpiMetric } from '../kpi-metric/kpi-metric'\nimport { Kpi } from './kpi'\nimport { KpiValue } from '../kpi-value/kpi-value'\nimport { KpiOrgScope } from '../kpi-org-scope/kpi-org-scope'\n\n/**\n * KPI formula 파싱/검증/매핑 유효성 검사 서비스\n * - formula에서 Metric 코드(변수명) 추출\n * - 각 Metric의 존재/매핑 유효성 검사\n * - 구문 오류, 미정의 Metric, 매핑 오류 등 에러 리포팅\n */\nexport class KpiFormulaService {\n /**\n * formula 문자열에서 Metric 코드(변수명) 추출\n * @param formula KPI formula (예: 'defect_count / total_count * 100')\n * @returns string[] 추출된 Metric 코드 리스트\n */\n extractMetricCodes(formula: string): string[] {\n // 변수명: 알파벳/언더스코어로 시작, 숫자/알파벳/언더스코어 포함\n const regex = /[a-zA-Z_][a-zA-Z0-9_]*/g\n // 숫자/예약어/연산자 제외(후처리 필요)\n const reserved = new Set(['if', 'else', 'return', 'true', 'false'])\n return Array.from(new Set((formula.match(regex) || []).filter(code => isNaN(Number(code)) && !reserved.has(code))))\n }\n\n /**\n * formula 내 Metric 코드의 존재/매핑 유효성 검사 + 순환참조 검출\n * @param formula KPI formula\n * @param visited 순환참조 검출용 Set (재귀 호출 시 사용)\n * @returns { valid: boolean, errors: string[] }\n */\n async validateFormula(\n formula: string,\n visited: Set<string> = new Set()\n ): Promise<{ valid: boolean; errors: string[] }> {\n const errors: string[] = []\n const metricCodes = this.extractMetricCodes(formula)\n const metricRepo = getRepository(KpiMetric)\n for (const code of metricCodes) {\n if (visited.has(code)) {\n errors.push(`순환참조 감지: ${Array.from(visited).join(' → ')} → ${code}`)\n continue\n }\n visited.add(code)\n const metric = await metricRepo.findOne({ where: { name: code } })\n if (!metric) {\n errors.push(`Metric '${code}' is not defined.`)\n visited.delete(code)\n continue\n }\n if (!metric.dataSetId || !metric.fieldName) {\n errors.push(`Metric '${code}' is not mapped to a dataset field.`)\n }\n // metric이 formula를 가지고 있다면 재귀적으로 순환참조 검증\n if ((metric as any).formula) {\n const subResult = await this.validateFormula((metric as any).formula, new Set(visited))\n if (!subResult.valid) errors.push(...subResult.errors)\n }\n visited.delete(code)\n }\n // (선택) formula 구문 오류, 괄호 불일치 등 추가 검사 가능\n // ...\n return { valid: errors.length === 0, errors }\n }\n\n /**\n * 계층 구조 KPI의 값을 자식 KPI들로부터 집계 계산\n * @param kpiId 부모 KPI ID\n * @param valueDate 계산 대상 날짜\n * @param org 조직 단위\n * @returns Promise<number | null> 집계된 값\n */\n async calculateHierarchicalValue(kpiId: string, valueDate: string, org?: string): Promise<number | null> {\n const kpiRepo = getRepository(Kpi)\n const kpi = await kpiRepo.findOne({\n where: { id: kpiId },\n relations: ['children']\n })\n\n if (!kpi || !kpi.children || kpi.children.length === 0) {\n return null\n }\n\n const childValues: number[] = []\n const childWeights: number[] = []\n\n for (const child of kpi.children) {\n let childValue: number | null = null\n \n if (child.isLeaf) {\n // Leaf KPI인 경우 KpiValue에서 실제 값을 가져옴\n const kpiValueRepo = getRepository(KpiValue)\n let kpiValue: KpiValue | null = null\n if (org) {\n const kpiOrgScope = await getRepository(KpiOrgScope).findOne({\n where: { org: org, domain: { id: child.domain?.id } }\n })\n if (kpiOrgScope) {\n kpiValue = await kpiValueRepo.findOne({ \n where: { \n kpi: { id: child.id }, \n valueDate,\n kpiOrgScope: { id: kpiOrgScope.id }\n }\n })\n }\n } else {\n // org가 없는 경우 kpiOrgScope 없이 조회 \n kpiValue = await kpiValueRepo.findOne({ \n where: { \n kpi: { id: child.id }, \n valueDate,\n kpiOrgScope: null\n }\n })\n }\n childValue = kpiValue?.value || null\n } else {\n // 중간 노드인 경우 재귀적으로 계산\n childValue = await this.calculateHierarchicalValue(child.id, valueDate, org)\n }\n\n if (childValue !== null) {\n childValues.push(childValue)\n childWeights.push(child.weight || 1)\n }\n }\n\n if (childValues.length === 0) {\n return null\n }\n\n // 가중 평균 계산\n const totalWeight = childWeights.reduce((sum, weight) => sum + weight, 0)\n const weightedSum = childValues.reduce((sum, value, index) => sum + value * childWeights[index], 0)\n \n return totalWeight > 0 ? weightedSum / totalWeight : null\n }\n\n /**\n * KPI가 순환 참조를 생성하는지 확인\n * @param kpiId KPI ID\n * @param parentId 설정하려는 부모 KPI ID\n * @returns Promise<boolean> 순환 참조 여부\n */\n async hasCircularReference(kpiId: string, parentId: string): Promise<boolean> {\n if (kpiId === parentId) {\n return true\n }\n\n const kpiRepo = getRepository(Kpi)\n const parent = await kpiRepo.findOne({\n where: { id: parentId },\n relations: ['parent']\n })\n\n if (!parent || !parent.parent) {\n return false\n }\n\n return await this.hasCircularReference(kpiId, parent.parent.id)\n }\n}\n"]}
|
|
@@ -2,7 +2,6 @@ import { HistoryActionType, HistoryEntityInterface } from '@operato/typeorm-hist
|
|
|
2
2
|
import { User } from '@things-factory/auth-base';
|
|
3
3
|
import { Domain } from '@things-factory/shell';
|
|
4
4
|
import { Kpi, KpiStatus, KpiPeriodType } from './kpi';
|
|
5
|
-
import { KpiCategory } from '../kpi-category/kpi-category';
|
|
6
5
|
import { KpiScores } from './kpi-grade.types';
|
|
7
6
|
export declare class KpiHistory implements HistoryEntityInterface<Kpi> {
|
|
8
7
|
readonly id: string;
|
|
@@ -11,8 +10,6 @@ export declare class KpiHistory implements HistoryEntityInterface<Kpi> {
|
|
|
11
10
|
domainId?: string;
|
|
12
11
|
name: string;
|
|
13
12
|
description?: string;
|
|
14
|
-
category?: KpiCategory;
|
|
15
|
-
categoryId?: string;
|
|
16
13
|
formula?: string;
|
|
17
14
|
active?: boolean;
|
|
18
15
|
state?: KpiStatus;
|
|
@@ -9,7 +9,6 @@ const auth_base_1 = require("@things-factory/auth-base");
|
|
|
9
9
|
const env_1 = require("@things-factory/env");
|
|
10
10
|
const shell_1 = require("@things-factory/shell");
|
|
11
11
|
const kpi_1 = require("./kpi");
|
|
12
|
-
const kpi_category_1 = require("../kpi-category/kpi-category");
|
|
13
12
|
const ORMCONFIG = env_1.config.get('ormconfig', {});
|
|
14
13
|
const DATABASE_TYPE = ORMCONFIG.type;
|
|
15
14
|
let KpiHistory = class KpiHistory {
|
|
@@ -47,15 +46,6 @@ tslib_1.__decorate([
|
|
|
47
46
|
(0, type_graphql_1.Field)({ nullable: true }),
|
|
48
47
|
tslib_1.__metadata("design:type", String)
|
|
49
48
|
], KpiHistory.prototype, "description", void 0);
|
|
50
|
-
tslib_1.__decorate([
|
|
51
|
-
(0, typeorm_1.ManyToOne)(() => kpi_category_1.KpiCategory, { nullable: true }),
|
|
52
|
-
(0, type_graphql_1.Field)(type => kpi_category_1.KpiCategory, { nullable: true, description: 'Category to which this KPI belongs.' }),
|
|
53
|
-
tslib_1.__metadata("design:type", kpi_category_1.KpiCategory)
|
|
54
|
-
], KpiHistory.prototype, "category", void 0);
|
|
55
|
-
tslib_1.__decorate([
|
|
56
|
-
(0, typeorm_1.RelationId)((kpi) => kpi.category),
|
|
57
|
-
tslib_1.__metadata("design:type", String)
|
|
58
|
-
], KpiHistory.prototype, "categoryId", void 0);
|
|
59
49
|
tslib_1.__decorate([
|
|
60
50
|
(0, typeorm_1.Column)({ nullable: true }),
|
|
61
51
|
(0, type_graphql_1.Field)({ nullable: true, description: 'Calculation formula for the KPI.' }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kpi-history.js","sourceRoot":"","sources":["../../../server/service/kpi/kpi-history.ts"],"names":[],"mappings":";;;;AAAA,+CAAoD;AACpD,qCAA0G;AAE1G,8DAKiC;AACjC,yDAAsD;AACtD,6CAA4C;AAC5C,iDAA4D;AAE5D,+BAAqD;
|
|
1
|
+
{"version":3,"file":"kpi-history.js","sourceRoot":"","sources":["../../../server/service/kpi/kpi-history.ts"],"names":[],"mappings":"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","sourcesContent":["import { Field, ID, ObjectType } from 'type-graphql'\nimport { Column, Entity, Index, ManyToOne, PrimaryGeneratedColumn, RelationId, JoinColumn } from 'typeorm'\n\nimport {\n HistoryActionColumn,\n HistoryActionType,\n HistoryEntityInterface,\n HistoryOriginalIdColumn\n} from '@operato/typeorm-history'\nimport { Role, User } from '@things-factory/auth-base'\nimport { config } from '@things-factory/env'\nimport { Domain, ScalarObject } from '@things-factory/shell'\n\nimport { Kpi, KpiStatus, KpiPeriodType } from './kpi'\nimport { KpiScores } from './kpi-grade.types'\n\nconst ORMCONFIG = config.get('ormconfig', {})\nconst DATABASE_TYPE = ORMCONFIG.type\n\n@Entity()\n@Index('ix_kpi_history_0', (kpiHistory: KpiHistory) => [kpiHistory.originalId, kpiHistory.version], { unique: true })\n@Index('ix_kpi_history_1', (kpiHistory: KpiHistory) => [kpiHistory.domain, kpiHistory.originalId, kpiHistory.version], {\n unique: true\n})\n@ObjectType({ description: 'History Entity of Kpi' })\nexport class KpiHistory implements HistoryEntityInterface<Kpi> {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID)\n readonly id: string\n\n @Column({ nullable: true, default: 1 })\n @Field({ nullable: true })\n version?: number = 1\n\n @ManyToOne(type => Domain)\n @Field({ nullable: true })\n domain?: Domain\n\n @RelationId((kpi: Kpi) => kpi.domain)\n domainId?: string\n\n @Column()\n @Field()\n name: string\n\n @Column({ nullable: true })\n @Field({ nullable: true })\n description?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Calculation formula for the KPI.' })\n formula?: string\n\n @Column({ nullable: false, default: false })\n @Field({ nullable: true, description: 'Whether this KPI is active (usable) or not.' })\n active?: boolean\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Current state of the KPI (DRAFT, RELEASED, ARCHIVED).' })\n state?: KpiStatus\n\n @Field(type => String, { nullable: true, description: 'Thumbnail image or file path for this KPI.' })\n thumbnail?: string\n\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, {\n nullable: true,\n description: 'Grade configuration for this KPI version'\n })\n grades?: KpiScores\n\n @Column({ type: 'float', nullable: true, default: 1 })\n @Field({ nullable: true, description: 'Weight for aggregation in parent category.' })\n weight?: number\n\n @Column({ default: 'DAY' })\n @Field(type => KpiPeriodType, { nullable: true })\n periodType: KpiPeriodType\n\n @Column({ nullable: true })\n @Field({ nullable: true })\n createdAt?: Date\n\n @Column({ nullable: true })\n @Field({ nullable: true })\n updatedAt?: Date\n\n @Column({ nullable: true })\n @Field({ nullable: true })\n deletedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true })\n creator?: User\n\n @RelationId((kpi: Kpi) => kpi.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true })\n updater?: User\n\n @RelationId((kpi: Kpi) => kpi.updater)\n updaterId?: string\n\n @HistoryOriginalIdColumn()\n public originalId!: string\n\n @HistoryActionColumn({\n nullable: false,\n type:\n DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'\n ? 'enum'\n : DATABASE_TYPE == 'oracle'\n ? 'varchar2'\n : DATABASE_TYPE == 'mssql'\n ? 'nvarchar'\n : 'varchar',\n enum:\n DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'\n ? HistoryActionType\n : undefined,\n length: DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb' ? undefined : 32\n })\n public action!: HistoryActionType\n}\n"]}
|
|
@@ -10,5 +10,5 @@ export declare class KpiMutation {
|
|
|
10
10
|
importKpis(kpis: KpiPatch[], context: ResolverContext): Promise<boolean>;
|
|
11
11
|
releaseKpi(id: string, context: ResolverContext): Promise<Kpi>;
|
|
12
12
|
revertKpiVersion(id: string, version: number, context: ResolverContext): Promise<Kpi>;
|
|
13
|
-
calculateKpiValue(kpiId: string, valueDate: string,
|
|
13
|
+
calculateKpiValue(kpiId: string, valueDate: string, org: string, context: ResolverContext): Promise<KpiValue>;
|
|
14
14
|
}
|
|
@@ -8,11 +8,11 @@ const shell_1 = require("@things-factory/shell");
|
|
|
8
8
|
const attachment_base_1 = require("@things-factory/attachment-base");
|
|
9
9
|
const kpi_1 = require("./kpi");
|
|
10
10
|
const kpi_type_1 = require("./kpi-type");
|
|
11
|
-
const kpi_category_1 = require("../kpi-category/kpi-category");
|
|
12
11
|
const kpi_history_1 = require("./kpi-history");
|
|
13
12
|
const kpi_formula_service_1 = require("./kpi-formula.service");
|
|
14
13
|
const scheduler_client_1 = require("@things-factory/scheduler-client");
|
|
15
14
|
const kpi_value_1 = require("../kpi-value/kpi-value");
|
|
15
|
+
const kpi_org_scope_1 = require("../kpi-org-scope/kpi-org-scope");
|
|
16
16
|
const typeorm_2 = require("typeorm");
|
|
17
17
|
const parser_1 = require("../../calculator/parser");
|
|
18
18
|
const evaluator_1 = require("../../calculator/evaluator");
|
|
@@ -21,12 +21,20 @@ const kpi_metric_value_provider_1 = require("../../controllers/kpi-metric-value-
|
|
|
21
21
|
let KpiMutation = class KpiMutation {
|
|
22
22
|
async createKpi(kpi, context) {
|
|
23
23
|
const { domain, user, tx } = context.state;
|
|
24
|
-
let
|
|
25
|
-
? await (0, shell_1.getRepository)(
|
|
24
|
+
let parent = kpi.parent
|
|
25
|
+
? await (0, shell_1.getRepository)(kpi_1.Kpi).findOne({ where: { id: kpi.parent.id, domain: { id: domain.id } } })
|
|
26
26
|
: undefined;
|
|
27
|
+
// 순환 참조 검사
|
|
28
|
+
if (parent) {
|
|
29
|
+
const formulaService = new kpi_formula_service_1.KpiFormulaService();
|
|
30
|
+
const hasCircular = await formulaService.hasCircularReference(parent.id, parent.id);
|
|
31
|
+
if (hasCircular) {
|
|
32
|
+
throw new Error('Circular reference detected in KPI hierarchy');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
27
35
|
const result = await (0, shell_1.getRepository)(kpi_1.Kpi, tx).save({
|
|
28
36
|
...kpi,
|
|
29
|
-
|
|
37
|
+
parent,
|
|
30
38
|
domain,
|
|
31
39
|
creator: user,
|
|
32
40
|
updater: user
|
|
@@ -91,13 +99,21 @@ let KpiMutation = class KpiMutation {
|
|
|
91
99
|
const kpi = await repository.findOne({
|
|
92
100
|
where: { domain: { id: domain.id }, id }
|
|
93
101
|
});
|
|
94
|
-
let
|
|
95
|
-
? await (0, shell_1.getRepository)(
|
|
96
|
-
: kpi.
|
|
102
|
+
let parent = patch.parent
|
|
103
|
+
? await (0, shell_1.getRepository)(kpi_1.Kpi).findOne({ where: { id: patch.parent.id, domain: { id: domain.id } } })
|
|
104
|
+
: patch.parent === null ? null : kpi.parent;
|
|
105
|
+
// 순환 참조 검사 (parent가 변경되는 경우)
|
|
106
|
+
if (parent && parent.id !== kpi.parentId) {
|
|
107
|
+
const formulaService = new kpi_formula_service_1.KpiFormulaService();
|
|
108
|
+
const hasCircular = await formulaService.hasCircularReference(kpi.id, parent.id);
|
|
109
|
+
if (hasCircular) {
|
|
110
|
+
throw new Error('Circular reference detected in KPI hierarchy');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
97
113
|
const result = await repository.save({
|
|
98
114
|
...kpi,
|
|
99
115
|
...patch,
|
|
100
|
-
|
|
116
|
+
parent,
|
|
101
117
|
updater: user
|
|
102
118
|
});
|
|
103
119
|
if (patch.thumbnail) {
|
|
@@ -288,8 +304,6 @@ let KpiMutation = class KpiMutation {
|
|
|
288
304
|
...kpi,
|
|
289
305
|
name: kpiHistory.name,
|
|
290
306
|
description: kpiHistory.description,
|
|
291
|
-
category: kpiHistory.category,
|
|
292
|
-
categoryId: kpiHistory.categoryId,
|
|
293
307
|
formula: kpiHistory.formula,
|
|
294
308
|
active: kpiHistory.active,
|
|
295
309
|
state: 'DRAFT',
|
|
@@ -298,7 +312,7 @@ let KpiMutation = class KpiMutation {
|
|
|
298
312
|
});
|
|
299
313
|
return updated;
|
|
300
314
|
}
|
|
301
|
-
async calculateKpiValue(kpiId, valueDate,
|
|
315
|
+
async calculateKpiValue(kpiId, valueDate, org, context) {
|
|
302
316
|
const { domain, user, tx } = context.state;
|
|
303
317
|
const kpiRepo = (0, shell_1.getRepository)(kpi_1.Kpi, tx);
|
|
304
318
|
const metricRepo = (0, shell_1.getRepository)(require('../kpi-metric/kpi-metric').KpiMetric, tx);
|
|
@@ -334,7 +348,7 @@ let KpiMutation = class KpiMutation {
|
|
|
334
348
|
metric: { id: metric.id },
|
|
335
349
|
valueDate: valueDateToUse,
|
|
336
350
|
periodType,
|
|
337
|
-
|
|
351
|
+
org: org ?? '',
|
|
338
352
|
domain: { id: domain.id }
|
|
339
353
|
}
|
|
340
354
|
});
|
|
@@ -350,7 +364,7 @@ let KpiMutation = class KpiMutation {
|
|
|
350
364
|
metric: { id: metric.id },
|
|
351
365
|
valueDate: (0, typeorm_2.Between)(startDate, endDate),
|
|
352
366
|
periodType: metric.periodType,
|
|
353
|
-
|
|
367
|
+
org: org ?? '',
|
|
354
368
|
domain: { id: domain.id }
|
|
355
369
|
}
|
|
356
370
|
});
|
|
@@ -368,18 +382,37 @@ let KpiMutation = class KpiMutation {
|
|
|
368
382
|
const ast = (0, parser_1.parseFormula)(kpi.formula);
|
|
369
383
|
const provider = new kpi_metric_value_provider_1.KpiMetricValueProvider({
|
|
370
384
|
valueDate: valueDateToUse,
|
|
371
|
-
|
|
385
|
+
org,
|
|
372
386
|
domainId: domain.id,
|
|
373
387
|
tx
|
|
374
388
|
});
|
|
375
389
|
const evalContext = { functions: functions_1.builtinFunctions, provider };
|
|
376
390
|
const kpiValueResult = await (0, evaluator_1.evaluateFormula)(ast, evalContext);
|
|
377
|
-
// 5.
|
|
391
|
+
// 5. KpiOrgScope 처리
|
|
392
|
+
let kpiOrgScope = null;
|
|
393
|
+
if (org) {
|
|
394
|
+
kpiOrgScope = await (0, shell_1.getRepository)(kpi_org_scope_1.KpiOrgScope, tx).findOne({
|
|
395
|
+
where: { org: org, domain: { id: domain.id } }
|
|
396
|
+
});
|
|
397
|
+
if (!kpiOrgScope) {
|
|
398
|
+
// 새 KpiOrgScope 생성
|
|
399
|
+
kpiOrgScope = await (0, shell_1.getRepository)(kpi_org_scope_1.KpiOrgScope, tx).save({
|
|
400
|
+
entityType: 'KpiCalculation',
|
|
401
|
+
entityId: `calc-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
402
|
+
entityName: org,
|
|
403
|
+
org: org,
|
|
404
|
+
domain,
|
|
405
|
+
creator: user,
|
|
406
|
+
updater: user
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
// 6. KPI Value upsert
|
|
378
411
|
let kpiValue = await kpiValueRepo.findOne({
|
|
379
412
|
where: {
|
|
380
413
|
kpi: { id: kpi.id },
|
|
381
414
|
valueDate: valueDateToUse,
|
|
382
|
-
|
|
415
|
+
kpiOrgScope: kpiOrgScope ? { id: kpiOrgScope.id } : null,
|
|
383
416
|
version: kpi.version,
|
|
384
417
|
domain: { id: domain.id }
|
|
385
418
|
}
|
|
@@ -389,17 +422,21 @@ let KpiMutation = class KpiMutation {
|
|
|
389
422
|
kpiValue.updater = user;
|
|
390
423
|
}
|
|
391
424
|
else {
|
|
392
|
-
|
|
425
|
+
const createData = {
|
|
393
426
|
kpi,
|
|
394
427
|
kpiId: kpi.id,
|
|
395
428
|
version: kpi.version,
|
|
396
429
|
valueDate: valueDateToUse,
|
|
397
430
|
value: kpiValueResult,
|
|
398
|
-
group: group ?? '',
|
|
399
431
|
domain,
|
|
400
432
|
creator: user,
|
|
401
433
|
updater: user
|
|
402
|
-
}
|
|
434
|
+
};
|
|
435
|
+
if (kpiOrgScope) {
|
|
436
|
+
createData.kpiOrgScope = kpiOrgScope;
|
|
437
|
+
createData.kpiOrgScopeId = kpiOrgScope.id;
|
|
438
|
+
}
|
|
439
|
+
kpiValue = Object.assign(new kpi_value_1.KpiValue(), createData);
|
|
403
440
|
}
|
|
404
441
|
return await kpiValueRepo.save(kpiValue);
|
|
405
442
|
}
|
|
@@ -493,7 +530,7 @@ tslib_1.__decorate([
|
|
|
493
530
|
(0, type_graphql_1.Mutation)(returns => kpi_value_1.KpiValue, { description: 'KPI 기준으로 formula 계산 및 KPI Value upsert' }),
|
|
494
531
|
tslib_1.__param(0, (0, type_graphql_1.Arg)('kpiId')),
|
|
495
532
|
tslib_1.__param(1, (0, type_graphql_1.Arg)('valueDate', { nullable: true })),
|
|
496
|
-
tslib_1.__param(2, (0, type_graphql_1.Arg)('
|
|
533
|
+
tslib_1.__param(2, (0, type_graphql_1.Arg)('org', { nullable: true })),
|
|
497
534
|
tslib_1.__param(3, (0, type_graphql_1.Ctx)()),
|
|
498
535
|
tslib_1.__metadata("design:type", Function),
|
|
499
536
|
tslib_1.__metadata("design:paramtypes", [String, String, String, Object]),
|