@things-factory/kpi 9.1.8 → 9.1.13
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/client/pages/kpi/kpi-list-page.ts +11 -1
- package/dist-client/pages/kpi/kpi-list-page.js +11 -1
- package/dist-client/pages/kpi/kpi-list-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/calculator/parser.js +22 -13
- package/dist-server/calculator/parser.js.map +1 -1
- package/dist-server/service/kpi-value/kpi-value-mutation.js +7 -3
- package/dist-server/service/kpi-value/kpi-value-mutation.js.map +1 -1
- package/dist-server/service/kpi-value/kpi-value-score.service.js +2 -6
- package/dist-server/service/kpi-value/kpi-value-score.service.js.map +1 -1
- package/dist-server/service/kpi-value/kpi-value.js +1 -1
- package/dist-server/service/kpi-value/kpi-value.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/server/calculator/parser.ts +21 -12
- package/server/service/kpi-value/kpi-value-mutation.ts +7 -3
- package/server/service/kpi-value/kpi-value-score.service.ts +2 -8
- package/server/service/kpi-value/kpi-value.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/kpi",
|
|
3
|
-
"version": "9.1.
|
|
3
|
+
"version": "9.1.13",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "dist-client/index.js",
|
|
6
6
|
"things-factory": true,
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"@operato/shell": "^9.0.0",
|
|
42
42
|
"@operato/styles": "^9.0.0",
|
|
43
43
|
"@operato/utils": "^9.0.0",
|
|
44
|
-
"@things-factory/auth-base": "^9.1.
|
|
45
|
-
"@things-factory/dataset": "^9.1.
|
|
46
|
-
"@things-factory/shell": "^9.1.
|
|
44
|
+
"@things-factory/auth-base": "^9.1.13",
|
|
45
|
+
"@things-factory/dataset": "^9.1.13",
|
|
46
|
+
"@things-factory/shell": "^9.1.13"
|
|
47
47
|
},
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "a65dd907befaf3a422aa0250d6096b86d151d46e"
|
|
49
49
|
}
|
|
@@ -21,7 +21,8 @@ function tokenize(formula: string): Token[] {
|
|
|
21
21
|
let lastIndex = 0
|
|
22
22
|
while ((m = TOKEN_REGEX.exec(formula))) {
|
|
23
23
|
lastIndex = TOKEN_REGEX.lastIndex
|
|
24
|
-
|
|
24
|
+
// m[0]은 공백 포함, m[1]은 capturing group (공백 제외)
|
|
25
|
+
const raw = m[1]
|
|
25
26
|
if (/^\d/.test(raw)) {
|
|
26
27
|
tokens.push({ type: 'number', value: raw })
|
|
27
28
|
} else if (/^\[.*\]$/.test(raw)) {
|
|
@@ -71,21 +72,29 @@ export function parseFormula(formula: string): FormulaNode {
|
|
|
71
72
|
return { type: 'variable', name: t.value }
|
|
72
73
|
}
|
|
73
74
|
if (t.type === 'function') {
|
|
74
|
-
//
|
|
75
|
+
// function 타입 토큰을 만났을 때, 다음 토큰이 '('인지 확인
|
|
75
76
|
const name = t.value
|
|
76
77
|
next()
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
78
|
+
|
|
79
|
+
// 다음 토큰이 '('이면 함수 호출, 아니면 변수로 처리
|
|
80
|
+
if (peek() && peek().type === 'paren' && peek().value === '(') {
|
|
81
|
+
// 함수 호출: func(expr, ...)
|
|
82
|
+
expect('paren', '(')
|
|
83
|
+
const args: FormulaNode[] = []
|
|
84
|
+
if ((peek() && peek().type !== 'paren') || (peek() && peek().value !== ')')) {
|
|
85
|
+
while (true) {
|
|
86
|
+
args.push(parseExpr())
|
|
87
|
+
if (peek() && peek().type === 'comma') {
|
|
88
|
+
next()
|
|
89
|
+
} else break
|
|
90
|
+
}
|
|
85
91
|
}
|
|
92
|
+
expect('paren', ')')
|
|
93
|
+
return { type: 'function', name, args }
|
|
94
|
+
} else {
|
|
95
|
+
// 변수로 처리
|
|
96
|
+
return { type: 'variable', name }
|
|
86
97
|
}
|
|
87
|
-
expect('paren', ')')
|
|
88
|
-
return { type: 'function', name, args }
|
|
89
98
|
}
|
|
90
99
|
if (t.type === 'operator' && t.value === '-') {
|
|
91
100
|
next()
|
|
@@ -344,14 +344,17 @@ export class KpiValueMutation {
|
|
|
344
344
|
relations: ['kpi', 'kpiOrgScope']
|
|
345
345
|
})
|
|
346
346
|
if (!kpiValue) throw new Error('KPI Value not found')
|
|
347
|
-
|
|
347
|
+
// 항상 최신 버전의 KPI를 조회하여 사용
|
|
348
|
+
const kpi = await kpiRepo.findOne({
|
|
349
|
+
where: { id: kpiValue.kpiId, domain: { id: domain.id } },
|
|
350
|
+
order: { version: 'DESC' }
|
|
351
|
+
})
|
|
348
352
|
if (!kpi) throw new Error('KPI 정보 없음')
|
|
349
353
|
if (!kpi.formula) throw new Error('KPI formula 없음')
|
|
350
354
|
const periodType = kpi.periodType || KpiPeriodType.DAY
|
|
351
355
|
const valueDate = kpiValue.valueDate
|
|
352
356
|
const kpiOrgScope = kpiValue.kpiOrgScope
|
|
353
357
|
const org = kpiOrgScope?.entityName || kpiOrgScope?.org || 'unknown' // KpiOrgScope에서 org 정보 추출
|
|
354
|
-
const version = kpiValue.version
|
|
355
358
|
|
|
356
359
|
// 2. formula에서 metric code 추출
|
|
357
360
|
const metricCodes = (kpi.formula.match(/[a-zA-Z_][a-zA-Z0-9_]*/g) || []).filter(
|
|
@@ -415,8 +418,9 @@ export class KpiValueMutation {
|
|
|
415
418
|
const kpiValueResult = await evaluateFormula(ast, evalContext)
|
|
416
419
|
if (kpiValueResult == null || isNaN(kpiValueResult)) throw new Error('KPI formula 결과값 없음')
|
|
417
420
|
|
|
418
|
-
// 5. KPI Value 업데이트
|
|
421
|
+
// 5. KPI Value 업데이트 (최신 버전으로)
|
|
419
422
|
kpiValue.value = kpiValueResult
|
|
423
|
+
kpiValue.version = kpi.version || 1
|
|
420
424
|
kpiValue.updater = user
|
|
421
425
|
|
|
422
426
|
// 6. 성과 점수 자동 계산 및 저장
|
|
@@ -33,11 +33,8 @@ export class KpiValueScoreService {
|
|
|
33
33
|
if (result !== null && result !== undefined && !isNaN(result)) {
|
|
34
34
|
const performanceScore = Number(result)
|
|
35
35
|
|
|
36
|
-
// score를 0~1 범위로 제한
|
|
37
|
-
const clampedScore = Math.max(0, Math.min(1, performanceScore))
|
|
38
|
-
|
|
39
36
|
return {
|
|
40
|
-
score:
|
|
37
|
+
score: performanceScore,
|
|
41
38
|
calculationMethod: 'formula'
|
|
42
39
|
}
|
|
43
40
|
}
|
|
@@ -65,11 +62,8 @@ export class KpiValueScoreService {
|
|
|
65
62
|
return null
|
|
66
63
|
}
|
|
67
64
|
|
|
68
|
-
// score를 0~1 범위로 제한
|
|
69
|
-
const clampedScore = Math.max(0, Math.min(1, grade.score))
|
|
70
|
-
|
|
71
65
|
return {
|
|
72
|
-
score:
|
|
66
|
+
score: grade.score,
|
|
73
67
|
calculationMethod: 'lookup'
|
|
74
68
|
}
|
|
75
69
|
}
|
|
@@ -77,7 +77,7 @@ export class KpiValue {
|
|
|
77
77
|
@Column('float', { nullable: true })
|
|
78
78
|
@Field(type => Float, {
|
|
79
79
|
nullable: true,
|
|
80
|
-
description: 'Performance score calculated from KPI value using scoreFormula or grades lookup table.
|
|
80
|
+
description: 'Performance score calculated from KPI value using scoreFormula or grades lookup table.'
|
|
81
81
|
})
|
|
82
82
|
score?: number
|
|
83
83
|
|