@things-factory/kpi 9.2.5 → 10.0.0-beta.10

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 (139) 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/tsconfig.tsbuildinfo +1 -1
  43. package/package.json +18 -18
  44. package/client/tsconfig.json +0 -11
  45. package/dist-server/tsconfig.json +0 -10
  46. package/server/@types/index.d.ts +0 -11
  47. package/server/calculator/evaluator.ts +0 -45
  48. package/server/calculator/functions.ts +0 -67
  49. package/server/calculator/index.ts +0 -4
  50. package/server/calculator/parser.ts +0 -137
  51. package/server/calculator/provider.ts +0 -10
  52. package/server/controllers/index.ts +0 -2
  53. package/server/controllers/kpi-metric-value-provider.ts +0 -79
  54. package/server/controllers/kpi-value-provider.ts +0 -51
  55. package/server/index.ts +0 -6
  56. package/server/migrations/1752190849680-seed-kpi-metrics.ts +0 -124
  57. package/server/migrations/1752190849681-seed-kpi.ts +0 -356
  58. package/server/migrations/1752192090123-add-grades-to-kpi.ts +0 -67
  59. package/server/migrations/1752192090124-add-kpi-statistics.ts +0 -719
  60. package/server/migrations/1752192090128-seed-kpi-org-scope.ts +0 -132
  61. package/server/migrations/1752192090129-seed-kpi-values.ts +0 -207
  62. package/server/migrations/grade-data/x11-performance-table.json +0 -962
  63. package/server/migrations/grade-data/x12-performance-table.json +0 -611
  64. package/server/migrations/grade-data/x14-performance-table.json +0 -42
  65. package/server/migrations/grade-data/x21-performance-table.json +0 -889
  66. package/server/migrations/grade-data/x22-performance-table.json +0 -1064
  67. package/server/migrations/grade-data/x23-performance-table.json +0 -42
  68. package/server/migrations/grade-data/x31-performance-table.json +0 -644
  69. package/server/migrations/grade-data/x32-performance-table.json +0 -993
  70. package/server/migrations/grade-data/x33-performance-table.json +0 -195
  71. package/server/migrations/grade-data/x34-performance-table.json +0 -12
  72. package/server/migrations/grade-data/x35-performance-table.json +0 -42
  73. package/server/migrations/grade-data/x41-performance-table.json +0 -825
  74. package/server/migrations/grade-data/x42-performance-table.json +0 -786
  75. package/server/migrations/grade-data/x43-performance-table.json +0 -12
  76. package/server/migrations/grade-data/x44-performance-table.json +0 -42
  77. package/server/migrations/grade-data/x51-performance-table.json +0 -924
  78. package/server/migrations/grade-data/x52-performance-table.json +0 -42
  79. package/server/migrations/grade-data/x61-performance-table.json +0 -261
  80. package/server/migrations/grade-data/x62-performance-table.json +0 -42
  81. package/server/migrations/index.ts +0 -9
  82. package/server/migrations/seed-data/kpi-metrics-seed.json +0 -454
  83. package/server/migrations/seed-data/kpi-org-scope-seed.json +0 -1676
  84. package/server/migrations/seed-data/kpi-scopes-seed.json +0 -121
  85. package/server/migrations/seed-data/kpi-values-seed.json +0 -402
  86. package/server/migrations/seed-data/kpis-seed.json +0 -488
  87. package/server/migrations/seed-data/scope-definitions-seed.json +0 -90
  88. package/server/routes.ts +0 -81
  89. package/server/service/index.ts +0 -51
  90. package/server/service/kpi/aggregate-kpi.ts +0 -103
  91. package/server/service/kpi/event-subscriber.ts +0 -29
  92. package/server/service/kpi/index.ts +0 -9
  93. package/server/service/kpi/kpi-formula.service.ts +0 -164
  94. package/server/service/kpi/kpi-grade.types.ts +0 -28
  95. package/server/service/kpi/kpi-history.ts +0 -126
  96. package/server/service/kpi/kpi-mutation.ts +0 -553
  97. package/server/service/kpi/kpi-query.ts +0 -224
  98. package/server/service/kpi/kpi-type.ts +0 -151
  99. package/server/service/kpi/kpi.ts +0 -254
  100. package/server/service/kpi-alert/index.ts +0 -3
  101. package/server/service/kpi-alert/kpi-alert-query.ts +0 -59
  102. package/server/service/kpi-alert/kpi-alert-type.ts +0 -20
  103. package/server/service/kpi-metric/aggregate-kpi-metric.ts +0 -132
  104. package/server/service/kpi-metric/index.ts +0 -7
  105. package/server/service/kpi-metric/kpi-metric-mutation.ts +0 -309
  106. package/server/service/kpi-metric/kpi-metric-query.ts +0 -70
  107. package/server/service/kpi-metric/kpi-metric-type.ts +0 -111
  108. package/server/service/kpi-metric/kpi-metric.ts +0 -134
  109. package/server/service/kpi-metric-value/index.ts +0 -7
  110. package/server/service/kpi-metric-value/kpi-metric-value-mutation.ts +0 -270
  111. package/server/service/kpi-metric-value/kpi-metric-value-query.ts +0 -62
  112. package/server/service/kpi-metric-value/kpi-metric-value-type.ts +0 -82
  113. package/server/service/kpi-metric-value/kpi-metric-value.ts +0 -93
  114. package/server/service/kpi-org-scope/index.ts +0 -6
  115. package/server/service/kpi-org-scope/kpi-org-scope-mutation.ts +0 -173
  116. package/server/service/kpi-org-scope/kpi-org-scope-query.ts +0 -127
  117. package/server/service/kpi-org-scope/kpi-org-scope-type.ts +0 -68
  118. package/server/service/kpi-org-scope/kpi-org-scope.ts +0 -123
  119. package/server/service/kpi-scope/index.ts +0 -11
  120. package/server/service/kpi-scope/kpi-scope-mutation.ts +0 -129
  121. package/server/service/kpi-scope/kpi-scope-query.ts +0 -63
  122. package/server/service/kpi-scope/kpi-scope-type.ts +0 -96
  123. package/server/service/kpi-scope/kpi-scope.ts +0 -143
  124. package/server/service/kpi-statistic/index.ts +0 -7
  125. package/server/service/kpi-statistic/kpi-statistic-batch.service.ts +0 -231
  126. package/server/service/kpi-statistic/kpi-statistic-calculation.service.ts +0 -410
  127. package/server/service/kpi-statistic/kpi-statistic-mutation.ts +0 -291
  128. package/server/service/kpi-statistic/kpi-statistic-query.ts +0 -146
  129. package/server/service/kpi-statistic/kpi-statistic-type.ts +0 -152
  130. package/server/service/kpi-statistic/kpi-statistic.ts +0 -199
  131. package/server/service/kpi-value/index.ts +0 -7
  132. package/server/service/kpi-value/kpi-value-mutation.ts +0 -432
  133. package/server/service/kpi-value/kpi-value-query.ts +0 -61
  134. package/server/service/kpi-value/kpi-value-score.service.ts +0 -106
  135. package/server/service/kpi-value/kpi-value-type.ts +0 -122
  136. package/server/service/kpi-value/kpi-value.ts +0 -160
  137. package/server/service/utils/value-date-util.ts +0 -119
  138. package/server/tsconfig.json +0 -10
  139. 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 = []