@things-factory/kpi 9.1.19 → 10.0.0-beta.2

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 (140) hide show
  1. package/client/pages/kpi/kpi-list-page.ts +339 -525
  2. package/client/pages/kpi/kpi-tree-page.ts +135 -207
  3. package/client/pages/kpi-metric/kpi-metric-list-page.ts +146 -226
  4. package/client/pages/kpi-metric-value/kpi-metric-value-editor-page.ts +187 -295
  5. package/client/pages/kpi-metric-value/kpi-metric-value-list-page.ts +123 -194
  6. package/client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.ts +57 -91
  7. package/client/pages/kpi-statistic/kpi-statistic-editor-page.ts +180 -278
  8. package/client/pages/kpi-statistic/kpi-statistic-list-page.ts +186 -286
  9. package/client/pages/kpi-value/kpi-value-editor-page.ts +189 -292
  10. package/client/pages/kpi-value/kpi-value-list-page.ts +170 -264
  11. package/dist-client/pages/kpi/kpi-list-page.d.ts +0 -6
  12. package/dist-client/pages/kpi/kpi-list-page.js +150 -282
  13. package/dist-client/pages/kpi/kpi-list-page.js.map +1 -1
  14. package/dist-client/pages/kpi/kpi-tree-page.d.ts +1 -7
  15. package/dist-client/pages/kpi/kpi-tree-page.js +76 -127
  16. package/dist-client/pages/kpi/kpi-tree-page.js.map +1 -1
  17. package/dist-client/pages/kpi-metric/kpi-metric-list-page.d.ts +0 -6
  18. package/dist-client/pages/kpi-metric/kpi-metric-list-page.js +62 -116
  19. package/dist-client/pages/kpi-metric/kpi-metric-list-page.js.map +1 -1
  20. package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.d.ts +1 -7
  21. package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.js +82 -140
  22. package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.js.map +1 -1
  23. package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.d.ts +0 -6
  24. package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js +54 -98
  25. package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js.map +1 -1
  26. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.d.ts +1 -7
  27. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.js +30 -57
  28. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.js.map +1 -1
  29. package/dist-client/pages/kpi-statistic/kpi-statistic-editor-page.d.ts +1 -7
  30. package/dist-client/pages/kpi-statistic/kpi-statistic-editor-page.js +91 -153
  31. package/dist-client/pages/kpi-statistic/kpi-statistic-editor-page.js.map +1 -1
  32. package/dist-client/pages/kpi-statistic/kpi-statistic-list-page.d.ts +0 -6
  33. package/dist-client/pages/kpi-statistic/kpi-statistic-list-page.js +81 -155
  34. package/dist-client/pages/kpi-statistic/kpi-statistic-list-page.js.map +1 -1
  35. package/dist-client/pages/kpi-value/kpi-value-editor-page.d.ts +1 -7
  36. package/dist-client/pages/kpi-value/kpi-value-editor-page.js +80 -136
  37. package/dist-client/pages/kpi-value/kpi-value-editor-page.js.map +1 -1
  38. package/dist-client/pages/kpi-value/kpi-value-list-page.d.ts +0 -6
  39. package/dist-client/pages/kpi-value/kpi-value-list-page.js +73 -134
  40. package/dist-client/pages/kpi-value/kpi-value-list-page.js.map +1 -1
  41. package/dist-client/tsconfig.tsbuildinfo +1 -1
  42. package/dist-server/service/index.d.ts +1 -1
  43. package/dist-server/tsconfig.tsbuildinfo +1 -1
  44. package/package.json +18 -18
  45. package/client/tsconfig.json +0 -11
  46. package/dist-server/tsconfig.json +0 -10
  47. package/server/@types/index.d.ts +0 -11
  48. package/server/calculator/evaluator.ts +0 -45
  49. package/server/calculator/functions.ts +0 -67
  50. package/server/calculator/index.ts +0 -4
  51. package/server/calculator/parser.ts +0 -137
  52. package/server/calculator/provider.ts +0 -10
  53. package/server/controllers/index.ts +0 -2
  54. package/server/controllers/kpi-metric-value-provider.ts +0 -79
  55. package/server/controllers/kpi-value-provider.ts +0 -51
  56. package/server/index.ts +0 -6
  57. package/server/migrations/1752190849680-seed-kpi-metrics.ts +0 -124
  58. package/server/migrations/1752190849681-seed-kpi.ts +0 -356
  59. package/server/migrations/1752192090123-add-grades-to-kpi.ts +0 -67
  60. package/server/migrations/1752192090124-add-kpi-statistics.ts +0 -719
  61. package/server/migrations/1752192090128-seed-kpi-org-scope.ts +0 -132
  62. package/server/migrations/1752192090129-seed-kpi-values.ts +0 -207
  63. package/server/migrations/grade-data/x11-performance-table.json +0 -962
  64. package/server/migrations/grade-data/x12-performance-table.json +0 -611
  65. package/server/migrations/grade-data/x14-performance-table.json +0 -42
  66. package/server/migrations/grade-data/x21-performance-table.json +0 -889
  67. package/server/migrations/grade-data/x22-performance-table.json +0 -1064
  68. package/server/migrations/grade-data/x23-performance-table.json +0 -42
  69. package/server/migrations/grade-data/x31-performance-table.json +0 -644
  70. package/server/migrations/grade-data/x32-performance-table.json +0 -993
  71. package/server/migrations/grade-data/x33-performance-table.json +0 -195
  72. package/server/migrations/grade-data/x34-performance-table.json +0 -12
  73. package/server/migrations/grade-data/x35-performance-table.json +0 -42
  74. package/server/migrations/grade-data/x41-performance-table.json +0 -825
  75. package/server/migrations/grade-data/x42-performance-table.json +0 -786
  76. package/server/migrations/grade-data/x43-performance-table.json +0 -12
  77. package/server/migrations/grade-data/x44-performance-table.json +0 -42
  78. package/server/migrations/grade-data/x51-performance-table.json +0 -924
  79. package/server/migrations/grade-data/x52-performance-table.json +0 -42
  80. package/server/migrations/grade-data/x61-performance-table.json +0 -261
  81. package/server/migrations/grade-data/x62-performance-table.json +0 -42
  82. package/server/migrations/index.ts +0 -9
  83. package/server/migrations/seed-data/kpi-metrics-seed.json +0 -454
  84. package/server/migrations/seed-data/kpi-org-scope-seed.json +0 -1676
  85. package/server/migrations/seed-data/kpi-scopes-seed.json +0 -121
  86. package/server/migrations/seed-data/kpi-values-seed.json +0 -402
  87. package/server/migrations/seed-data/kpis-seed.json +0 -488
  88. package/server/migrations/seed-data/scope-definitions-seed.json +0 -90
  89. package/server/routes.ts +0 -81
  90. package/server/service/index.ts +0 -51
  91. package/server/service/kpi/aggregate-kpi.ts +0 -103
  92. package/server/service/kpi/event-subscriber.ts +0 -29
  93. package/server/service/kpi/index.ts +0 -9
  94. package/server/service/kpi/kpi-formula.service.ts +0 -164
  95. package/server/service/kpi/kpi-grade.types.ts +0 -28
  96. package/server/service/kpi/kpi-history.ts +0 -126
  97. package/server/service/kpi/kpi-mutation.ts +0 -553
  98. package/server/service/kpi/kpi-query.ts +0 -224
  99. package/server/service/kpi/kpi-type.ts +0 -151
  100. package/server/service/kpi/kpi.ts +0 -254
  101. package/server/service/kpi-alert/index.ts +0 -3
  102. package/server/service/kpi-alert/kpi-alert-query.ts +0 -59
  103. package/server/service/kpi-alert/kpi-alert-type.ts +0 -20
  104. package/server/service/kpi-metric/aggregate-kpi-metric.ts +0 -132
  105. package/server/service/kpi-metric/index.ts +0 -7
  106. package/server/service/kpi-metric/kpi-metric-mutation.ts +0 -309
  107. package/server/service/kpi-metric/kpi-metric-query.ts +0 -70
  108. package/server/service/kpi-metric/kpi-metric-type.ts +0 -111
  109. package/server/service/kpi-metric/kpi-metric.ts +0 -134
  110. package/server/service/kpi-metric-value/index.ts +0 -7
  111. package/server/service/kpi-metric-value/kpi-metric-value-mutation.ts +0 -270
  112. package/server/service/kpi-metric-value/kpi-metric-value-query.ts +0 -62
  113. package/server/service/kpi-metric-value/kpi-metric-value-type.ts +0 -82
  114. package/server/service/kpi-metric-value/kpi-metric-value.ts +0 -93
  115. package/server/service/kpi-org-scope/index.ts +0 -6
  116. package/server/service/kpi-org-scope/kpi-org-scope-mutation.ts +0 -173
  117. package/server/service/kpi-org-scope/kpi-org-scope-query.ts +0 -127
  118. package/server/service/kpi-org-scope/kpi-org-scope-type.ts +0 -68
  119. package/server/service/kpi-org-scope/kpi-org-scope.ts +0 -123
  120. package/server/service/kpi-scope/index.ts +0 -11
  121. package/server/service/kpi-scope/kpi-scope-mutation.ts +0 -129
  122. package/server/service/kpi-scope/kpi-scope-query.ts +0 -63
  123. package/server/service/kpi-scope/kpi-scope-type.ts +0 -96
  124. package/server/service/kpi-scope/kpi-scope.ts +0 -143
  125. package/server/service/kpi-statistic/index.ts +0 -7
  126. package/server/service/kpi-statistic/kpi-statistic-batch.service.ts +0 -231
  127. package/server/service/kpi-statistic/kpi-statistic-calculation.service.ts +0 -410
  128. package/server/service/kpi-statistic/kpi-statistic-mutation.ts +0 -291
  129. package/server/service/kpi-statistic/kpi-statistic-query.ts +0 -146
  130. package/server/service/kpi-statistic/kpi-statistic-type.ts +0 -152
  131. package/server/service/kpi-statistic/kpi-statistic.ts +0 -199
  132. package/server/service/kpi-value/index.ts +0 -7
  133. package/server/service/kpi-value/kpi-value-mutation.ts +0 -432
  134. package/server/service/kpi-value/kpi-value-query.ts +0 -61
  135. package/server/service/kpi-value/kpi-value-score.service.ts +0 -106
  136. package/server/service/kpi-value/kpi-value-type.ts +0 -122
  137. package/server/service/kpi-value/kpi-value.ts +0 -160
  138. package/server/service/utils/value-date-util.ts +0 -119
  139. package/server/tsconfig.json +0 -10
  140. package/server/types/global.d.ts +0 -8
@@ -1,146 +0,0 @@
1
- import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx, Directive } from 'type-graphql'
2
- import { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'
3
- import { User } from '@things-factory/auth-base'
4
- import type ResolverContext from '@things-factory/auth-base'
5
- import { KpiStatistic } from './kpi-statistic.js'
6
- import { KpiStatisticList } from './kpi-statistic-type.js'
7
- import { Kpi, KpiPeriodType } from '../kpi/kpi.js'
8
- import { KpiOrgScope } from '../kpi-org-scope/kpi-org-scope.js'
9
-
10
- @Resolver(KpiStatistic)
11
- export class KpiStatisticQuery {
12
- @Directive('@privilege(category: "kpi", privilege: "query", domainOwnerGranted: true, superUserGranted: true)')
13
- @Query(returns => KpiStatistic!, { nullable: true, description: 'To fetch a KpiStatistic' })
14
- async kpiStatistic(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<KpiStatistic> {
15
- const { domain } = context.state
16
-
17
- return await getRepository(KpiStatistic).findOne({
18
- where: { domain: { id: domain.id }, id }
19
- })
20
- }
21
-
22
- @Query(returns => KpiStatisticList, { description: 'To fetch multiple KpiStatistics' })
23
- @Directive('@privilege(category: "kpi", privilege: "query", domainOwnerGranted: true, superUserGranted: true)')
24
- async kpiStatistics(
25
- @Args(type => ListParam) params: ListParam,
26
- @Ctx() context: ResolverContext
27
- ): Promise<KpiStatisticList> {
28
- const { domain } = context.state
29
-
30
- const queryBuilder = getQueryBuilderFromListParams({
31
- domain,
32
- params,
33
- repository: await getRepository(KpiStatistic),
34
- searchables: ['kpi', 'valueDate'],
35
- filtersMap: {
36
- kpi: { columnName: 'id', relationColumn: 'kpi' },
37
- kpiOrgScope: { columnName: 'id', relationColumn: 'kpiOrgScope' },
38
- periodType: { columnName: 'periodType' },
39
- valueDate: { columnName: 'valueDate' },
40
- scope02: {
41
- columnName: 'scope02',
42
- relationColumn: 'kpiOrgScope'
43
- }
44
- }
45
- })
46
-
47
- const [items, total] = await queryBuilder.getManyAndCount()
48
-
49
- return { items, total }
50
- }
51
-
52
- @FieldResolver(type => Kpi)
53
- async kpi(@Root() kpiStatistic: KpiStatistic): Promise<Kpi> {
54
- return kpiStatistic.kpiId && (await getRepository(Kpi).findOneBy({ id: kpiStatistic.kpiId }))
55
- }
56
-
57
- @FieldResolver(type => Domain)
58
- async domain(@Root() kpiStatistic: KpiStatistic): Promise<Domain> {
59
- return kpiStatistic.domainId && (await getRepository(Domain).findOneBy({ id: kpiStatistic.domainId }))
60
- }
61
-
62
- @FieldResolver(type => User)
63
- async updater(@Root() kpiStatistic: KpiStatistic): Promise<User> {
64
- return kpiStatistic.updaterId && (await getRepository(User).findOneBy({ id: kpiStatistic.updaterId }))
65
- }
66
-
67
- @FieldResolver(type => User)
68
- async creator(@Root() kpiStatistic: KpiStatistic): Promise<User> {
69
- return kpiStatistic.creatorId && (await getRepository(User).findOneBy({ id: kpiStatistic.creatorId }))
70
- }
71
-
72
- @FieldResolver(type => KpiOrgScope)
73
- async kpiOrgScope(@Root() kpiStatistic: KpiStatistic): Promise<KpiOrgScope> {
74
- return kpiStatistic.kpiOrgScopeId && (await getRepository(KpiOrgScope).findOneBy({ id: kpiStatistic.kpiOrgScopeId }))
75
- }
76
-
77
- @Directive('@privilege(category: "kpi", privilege: "query", domainOwnerGranted: true, superUserGranted: true)')
78
- @Query(returns => [KpiStatistic], {
79
- description: 'Get regional statistics for dashboard map visualization'
80
- })
81
- async regionalKpiStatistics(
82
- @Arg('valueDate') valueDate: string,
83
- @Arg('periodType', type => KpiPeriodType, { defaultValue: KpiPeriodType.MONTH }) periodType: KpiPeriodType,
84
- @Arg('regions', type => [String], { nullable: true }) regions: string[] | undefined,
85
- @Ctx() context: ResolverContext
86
- ): Promise<KpiStatistic[]> {
87
- const { domain } = context.state
88
-
89
- const queryBuilder = getRepository(KpiStatistic)
90
- .createQueryBuilder('stat')
91
- .leftJoinAndSelect('stat.kpi', 'kpi')
92
- .leftJoinAndSelect('stat.kpiOrgScope', 'orgScope')
93
- .where('stat.domain = :domainId', { domainId: domain.id })
94
- .andWhere('stat.periodType = :periodType', { periodType })
95
- .andWhere('stat.valueDate = :valueDate', { valueDate })
96
- .andWhere('orgScope.scope02 IS NOT NULL') // 지역 정보가 있는 것만
97
-
98
- if (regions && regions.length > 0) {
99
- queryBuilder.andWhere('orgScope.scope02 IN (:...regions)', { regions })
100
- }
101
-
102
- queryBuilder.orderBy('orgScope.scope02', 'ASC')
103
- .addOrderBy('kpi.name', 'ASC')
104
-
105
- return await queryBuilder.getMany()
106
- }
107
-
108
- @Directive('@privilege(category: "kpi", privilege: "query", domainOwnerGranted: true, superUserGranted: true)')
109
- @Query(returns => [KpiStatistic], {
110
- description: 'Get aggregated statistics by scope02 (regional level) for dashboard'
111
- })
112
- async dashboardRegionalStatistics(
113
- @Arg('valueDate') valueDate: string,
114
- @Arg('periodType', type => KpiPeriodType, { defaultValue: KpiPeriodType.MONTH }) periodType: KpiPeriodType,
115
- @Ctx() context: ResolverContext
116
- ): Promise<KpiStatistic[]> {
117
- const { domain } = context.state
118
-
119
- // 지역별로 평균을 내서 하나의 통계로 합침
120
- const query = `
121
- SELECT
122
- 'regional-aggregate-' || orgScope.scope02 as id,
123
- kpi.id as kpiId,
124
- kpi.name as kpiName,
125
- orgScope.scope02 as region,
126
- AVG(stat.mean) as avgMean,
127
- AVG(stat.median) as avgMedian,
128
- MIN(stat.minimum) as overallMin,
129
- MAX(stat.maximum) as overallMax,
130
- AVG(stat.standardDeviation) as avgStdDev,
131
- SUM(stat.count) as totalCount,
132
- COUNT(*) as orgCount
133
- FROM kpi_statistic stat
134
- LEFT JOIN kpi ON stat.kpiId = kpi.id
135
- LEFT JOIN kpi_org_scope orgScope ON stat.kpiOrgScopeId = orgScope.id
136
- WHERE stat.domainId = ?
137
- AND stat.periodType = ?
138
- AND stat.valueDate = ?
139
- AND orgScope.scope02 IS NOT NULL
140
- GROUP BY kpi.id, orgScope.scope02
141
- ORDER BY orgScope.scope02, kpi.name
142
- `
143
-
144
- return await getRepository(KpiStatistic).query(query, [domain.id, periodType, valueDate])
145
- }
146
- }
@@ -1,152 +0,0 @@
1
- import { ObjectType, Field, InputType, Int, ID } from 'type-graphql'
2
-
3
- import { ObjectRef, ScalarObject } from '@things-factory/shell'
4
- import { KpiPeriodType } from '../kpi/kpi'
5
-
6
- import { KpiStatistic } from './kpi-statistic.js'
7
-
8
- @InputType()
9
- export class NewKpiStatistic {
10
- @Field({ nullable: true })
11
- kpi?: ObjectRef
12
-
13
- @Field({
14
- description:
15
- 'Date or period for which this statistic is calculated (e.g., day: YYYY-MM-DD, month: YYYY-MM, quarter: YYYY-Qn, range: YYYY-MM-DD~YYYY-MM-DD).'
16
- })
17
- valueDate: string
18
-
19
- @Field(type => KpiPeriodType)
20
- periodType: KpiPeriodType
21
-
22
- // 핵심 통계 필드들
23
- @Field({ nullable: true })
24
- count?: number
25
-
26
- @Field({ nullable: true })
27
- sum?: number
28
-
29
- @Field({ nullable: true })
30
- range?: number
31
-
32
- @Field({ nullable: true })
33
- mean?: number
34
-
35
- @Field({ nullable: true })
36
- median?: number
37
-
38
- @Field({ nullable: true })
39
- minimum?: number
40
-
41
- @Field({ nullable: true })
42
- maximum?: number
43
-
44
- @Field({ nullable: true })
45
- standardDeviation?: number
46
-
47
- @Field({ nullable: true })
48
- variance?: number
49
-
50
- @Field({ nullable: true })
51
- percentile25?: number
52
-
53
- @Field({ nullable: true })
54
- percentile75?: number
55
-
56
- @Field({ nullable: true })
57
- iqr?: number
58
-
59
- @Field({ nullable: true })
60
- lowerFence?: number
61
-
62
- @Field({ nullable: true })
63
- upperFence?: number
64
-
65
- // 확장 필드들
66
- @Field(type => ScalarObject, { nullable: true })
67
- additionalStatistics?: { [metricName: string]: number }
68
-
69
- @Field(type => ScalarObject, { nullable: true })
70
- metadata?: { [key: string]: any }
71
- }
72
-
73
- @InputType()
74
- export class KpiStatisticPatch {
75
- @Field(type => ID, { nullable: true })
76
- id?: string
77
-
78
- @Field({ nullable: true })
79
- kpi?: ObjectRef
80
-
81
- @Field({
82
- nullable: true,
83
- description:
84
- 'Date or period for which this statistic is calculated (e.g., day: YYYY-MM-DD, month: YYYY-MM, quarter: YYYY-Qn, range: YYYY-MM-DD~YYYY-MM-DD).'
85
- })
86
- valueDate?: string
87
-
88
- @Field(type => KpiPeriodType, { nullable: true })
89
- periodType?: KpiPeriodType
90
-
91
- // 핵심 통계 필드들
92
- @Field({ nullable: true })
93
- count?: number
94
-
95
- @Field({ nullable: true })
96
- sum?: number
97
-
98
- @Field({ nullable: true })
99
- range?: number
100
-
101
- @Field({ nullable: true })
102
- mean?: number
103
-
104
- @Field({ nullable: true })
105
- median?: number
106
-
107
- @Field({ nullable: true })
108
- minimum?: number
109
-
110
- @Field({ nullable: true })
111
- maximum?: number
112
-
113
- @Field({ nullable: true })
114
- standardDeviation?: number
115
-
116
- @Field({ nullable: true })
117
- variance?: number
118
-
119
- @Field({ nullable: true })
120
- percentile25?: number
121
-
122
- @Field({ nullable: true })
123
- percentile75?: number
124
-
125
- @Field({ nullable: true })
126
- iqr?: number
127
-
128
- @Field({ nullable: true })
129
- lowerFence?: number
130
-
131
- @Field({ nullable: true })
132
- upperFence?: number
133
-
134
- // 확장 필드들
135
- @Field(type => ScalarObject, { nullable: true })
136
- additionalStatistics?: { [metricName: string]: number }
137
-
138
- @Field(type => ScalarObject, { nullable: true })
139
- metadata?: { [key: string]: any }
140
-
141
- @Field({ nullable: true })
142
- cuFlag?: string
143
- }
144
-
145
- @ObjectType()
146
- export class KpiStatisticList {
147
- @Field(type => [KpiStatistic])
148
- items: KpiStatistic[]
149
-
150
- @Field(type => Int)
151
- total: number
152
- }
@@ -1,199 +0,0 @@
1
- import {
2
- CreateDateColumn,
3
- UpdateDateColumn,
4
- Entity,
5
- Index,
6
- Column,
7
- RelationId,
8
- ManyToOne,
9
- PrimaryGeneratedColumn
10
- } from 'typeorm'
11
- import { ObjectType, Field, Int, ID } from 'type-graphql'
12
-
13
- import { Domain, ScalarObject } from '@things-factory/shell'
14
- import { User } from '@things-factory/auth-base'
15
- import { Kpi, KpiPeriodType } from '../kpi/kpi'
16
- import { KpiOrgScope } from '../kpi-org-scope/kpi-org-scope'
17
-
18
- @Entity()
19
- @Index('ix_kpi_statistic_target', (kpiStatistic: KpiStatistic) => [kpiStatistic.domain, kpiStatistic.kpi])
20
- @Index('ix_kpi_statistic_period', (kpiStatistic: KpiStatistic) => [
21
- kpiStatistic.domain,
22
- kpiStatistic.valueDate,
23
- kpiStatistic.periodType
24
- ])
25
- @Index('ix_kpi_statistic_scope', (kpiStatistic: KpiStatistic) => [
26
- kpiStatistic.domain,
27
- kpiStatistic.kpi,
28
- kpiStatistic.kpiOrgScope,
29
- kpiStatistic.valueDate
30
- ])
31
- @Index('ix_kpi_statistic_legacy_scope', (kpiStatistic: KpiStatistic) => [
32
- kpiStatistic.domain,
33
- kpiStatistic.kpi,
34
- kpiStatistic.scope,
35
- kpiStatistic.valueDate
36
- ])
37
- @ObjectType({
38
- description:
39
- 'KPI Statistics Entity - Stores comprehensive statistical information for KPIs and Categories including central tendency measures (mean, median), dispersion metrics (standard deviation, variance), range indicators (min, max), and percentile distributions (25th, 75th percentiles, IQR). Supports both KPI and Category targets with flexible period-based aggregation (daily, weekly, monthly, yearly). Includes extensible JSON fields for additional metrics and metadata for calculation tracking.'
40
- })
41
- export class KpiStatistic {
42
- @PrimaryGeneratedColumn('uuid')
43
- @Field(type => ID)
44
- readonly id: string
45
-
46
- // === 대상 정보 ===
47
-
48
- @ManyToOne(() => Kpi)
49
- @Field(type => Kpi, {
50
- nullable: true,
51
- description: 'Reference to the KPI definition for which this value is calculated.'
52
- })
53
- kpi: Kpi
54
-
55
- @RelationId((kpiStatistic: KpiStatistic) => kpiStatistic.kpi)
56
- kpiId: string
57
-
58
- // === 통계 기간 ===
59
- @Column()
60
- @Field({
61
- description:
62
- 'Date or period for which this statistic is calculated (e.g., day: YYYY-MM-DD, month: YYYY-MM, quarter: YYYY-Qn, range: YYYY-MM-DD~YYYY-MM-DD).'
63
- })
64
- valueDate: string
65
-
66
- @Column({ default: 'DAY' })
67
- @Field(type => KpiPeriodType, { description: 'Aggregation period type for this statistic.' })
68
- periodType: KpiPeriodType
69
-
70
- // === 스코프 정보 ===
71
-
72
- @ManyToOne(() => KpiOrgScope, { nullable: true })
73
- @Field(type => KpiOrgScope, {
74
- nullable: true,
75
- description: 'Organization scope for scoped statistics. Null for overall statistics.'
76
- })
77
- kpiOrgScope?: KpiOrgScope
78
-
79
- @RelationId((kpiStatistic: KpiStatistic) => kpiStatistic.kpiOrgScope)
80
- kpiOrgScopeId?: string
81
-
82
- @Column({ nullable: true })
83
- @Field({
84
- nullable: true,
85
- description: 'Legacy scope field - use kpiOrgScope instead. Statistical scope - null for overall statistics, category value for scoped statistics (e.g., "서울", "부장", "대규모")'
86
- })
87
- scope?: string
88
-
89
- // === 핵심 통계 필드 (14개) ===
90
-
91
- // 1. 기본 정보 (3개)
92
- @Column({ nullable: true })
93
- @Field({ nullable: true, description: 'Number of data points used in calculation' })
94
- count?: number // 데이터 개수
95
-
96
- @Column({ type: 'float', nullable: true })
97
- @Field({ nullable: true, description: 'Sum of all values in the dataset' })
98
- sum?: number // 합계
99
-
100
- @Column({ type: 'float', nullable: true })
101
- @Field({ nullable: true, description: 'Range of values (maximum - minimum)' })
102
- range?: number // 범위
103
-
104
- // 2. 중심 경향 (2개)
105
- @Column({ type: 'float', nullable: true })
106
- @Field({ nullable: true, description: 'Arithmetic mean of all values' })
107
- mean?: number // 평균
108
-
109
- @Column({ type: 'float', nullable: true })
110
- @Field({ nullable: true, description: 'Middle value when data is sorted (50th percentile)' })
111
- median?: number // 중앙값
112
-
113
- // 3. 범위 (2개)
114
- @Column({ type: 'float', nullable: true })
115
- @Field({ nullable: true, description: 'Minimum value in the dataset' })
116
- minimum?: number // 최소값
117
-
118
- @Column({ type: 'float', nullable: true })
119
- @Field({ nullable: true, description: 'Maximum value in the dataset' })
120
- maximum?: number // 최대값
121
-
122
- // 4. 분산 (2개)
123
- @Column({ type: 'float', nullable: true })
124
- @Field({ nullable: true, description: 'Standard deviation - measure of data dispersion' })
125
- standardDeviation?: number // 표준편차
126
-
127
- @Column({ type: 'float', nullable: true })
128
- @Field({ nullable: true, description: 'Variance - square of standard deviation' })
129
- variance?: number // 분산
130
-
131
- // 5. 분위수 (5개)
132
- @Column({ type: 'float', nullable: true })
133
- @Field({ nullable: true, description: '25th percentile - 25% of data is below this value' })
134
- percentile25?: number // 25분위수
135
-
136
- @Column({ type: 'float', nullable: true })
137
- @Field({ nullable: true, description: '75th percentile - 75% of data is below this value' })
138
- percentile75?: number // 75분위수
139
-
140
- @Column({ type: 'float', nullable: true })
141
- @Field({ nullable: true, description: 'Interquartile range (75th percentile - 25th percentile)' })
142
- iqr?: number // 사분위수 범위
143
-
144
- @Column({ type: 'float', nullable: true })
145
- @Field({ nullable: true, description: 'Lower fence for outlier detection (Q1 - 1.5 * IQR)' })
146
- lowerFence?: number // 하위 울타리
147
-
148
- @Column({ type: 'float', nullable: true })
149
- @Field({ nullable: true, description: 'Upper fence for outlier detection (Q3 + 1.5 * IQR)' })
150
- upperFence?: number // 상위 울타리
151
-
152
- // === 확장 가능한 필드 (JSON) ===
153
- @Column('simple-json', { nullable: true })
154
- @Field(type => ScalarObject, {
155
- nullable: true,
156
- description: 'Additional statistical metrics stored as key-value pairs'
157
- })
158
- additionalStatistics: {
159
- [metricName: string]: number
160
- }
161
-
162
- // === 메타데이터 (JSON) ===
163
- @Column('simple-json', { nullable: true })
164
- @Field(type => ScalarObject, {
165
- nullable: true,
166
- description: 'Calculation metadata including method, timestamp, and data quality information'
167
- })
168
- metadata: { [key: string]: any }
169
-
170
- // === 표준 필드들 ===
171
- @ManyToOne(type => Domain)
172
- @Field({ nullable: true, description: 'Domain this statistic belongs to' })
173
- domain?: Domain
174
-
175
- @RelationId((kpiStatistic: KpiStatistic) => kpiStatistic.domain)
176
- domainId?: string
177
-
178
- @CreateDateColumn()
179
- @Field({ nullable: true, description: 'Timestamp when this statistic was created' })
180
- createdAt?: Date
181
-
182
- @UpdateDateColumn()
183
- @Field({ nullable: true, description: 'Timestamp when this statistic was last updated' })
184
- updatedAt?: Date
185
-
186
- @ManyToOne(type => User, { nullable: true })
187
- @Field(type => User, { nullable: true, description: 'User who created this statistic' })
188
- creator?: User
189
-
190
- @RelationId((kpiStatistic: KpiStatistic) => kpiStatistic.creator)
191
- creatorId?: string
192
-
193
- @ManyToOne(type => User, { nullable: true })
194
- @Field(type => User, { nullable: true, description: 'User who last updated this statistic' })
195
- updater?: User
196
-
197
- @RelationId((kpiStatistic: KpiStatistic) => kpiStatistic.updater)
198
- updaterId?: string
199
- }
@@ -1,7 +0,0 @@
1
- import { KpiValue } from './kpi-value'
2
- import { KpiValueQuery } from './kpi-value-query'
3
- import { KpiValueMutation } from './kpi-value-mutation'
4
-
5
- export const entities = [KpiValue]
6
- export const resolvers = [KpiValueQuery, KpiValueMutation]
7
- export const subscribers = []