@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.
@@ -10,7 +10,8 @@ function tokenize(formula) {
10
10
  let lastIndex = 0;
11
11
  while ((m = TOKEN_REGEX.exec(formula))) {
12
12
  lastIndex = TOKEN_REGEX.lastIndex;
13
- const [raw] = m;
13
+ // m[0] 공백 포함, m[1]은 capturing group (공백 제외)
14
+ const raw = m[1];
14
15
  if (/^\d/.test(raw)) {
15
16
  tokens.push({ type: 'number', value: raw });
16
17
  }
@@ -64,23 +65,31 @@ function parseFormula(formula) {
64
65
  return { type: 'variable', name: t.value };
65
66
  }
66
67
  if (t.type === 'function') {
67
- // 함수 호출: func(expr, ...)
68
+ // function 타입 토큰을 만났을 때, 다음 토큰이 '('인지 확인
68
69
  const name = t.value;
69
70
  next();
70
- expect('paren', '(');
71
- const args = [];
72
- if ((peek() && peek().type !== 'paren') || (peek() && peek().value !== ')')) {
73
- while (true) {
74
- args.push(parseExpr());
75
- if (peek() && peek().type === 'comma') {
76
- next();
71
+ // 다음 토큰이 '('이면 함수 호출, 아니면 변수로 처리
72
+ if (peek() && peek().type === 'paren' && peek().value === '(') {
73
+ // 함수 호출: func(expr, ...)
74
+ expect('paren', '(');
75
+ const args = [];
76
+ if ((peek() && peek().type !== 'paren') || (peek() && peek().value !== ')')) {
77
+ while (true) {
78
+ args.push(parseExpr());
79
+ if (peek() && peek().type === 'comma') {
80
+ next();
81
+ }
82
+ else
83
+ break;
77
84
  }
78
- else
79
- break;
80
85
  }
86
+ expect('paren', ')');
87
+ return { type: 'function', name, args };
88
+ }
89
+ else {
90
+ // 변수로 처리
91
+ return { type: 'variable', name };
81
92
  }
82
- expect('paren', ')');
83
- return { type: 'function', name, args };
84
93
  }
85
94
  if (t.type === 'operator' && t.value === '-') {
86
95
  next();
@@ -1 +1 @@
1
- {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../server/calculator/parser.ts"],"names":[],"mappings":"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","sourcesContent":["// KPI formula 파서: 수식 문자열을 AST로 변환\n\nexport type FormulaNode =\n | { type: 'number'; value: number }\n | { type: 'variable'; name: string }\n | { type: 'function'; name: string; args: FormulaNode[] }\n | { type: 'binary'; op: string; left: FormulaNode; right: FormulaNode }\n | { type: 'unary'; op: string; arg: FormulaNode }\n\n// 토큰 타입 정의\nconst TOKEN_REGEX = /\\s*(\\d+\\.\\d+|\\d+|\\[.*?\\]|[A-Za-z_][A-Za-z0-9_]*|[+\\-*/(),])/y\n\ninterface Token {\n type: 'number' | 'variable' | 'function' | 'operator' | 'paren' | 'comma'\n value: string\n}\n\nfunction tokenize(formula: string): Token[] {\n const tokens: Token[] = []\n let m: RegExpExecArray | null\n let lastIndex = 0\n while ((m = TOKEN_REGEX.exec(formula))) {\n lastIndex = TOKEN_REGEX.lastIndex\n const [raw] = m\n if (/^\\d/.test(raw)) {\n tokens.push({ type: 'number', value: raw })\n } else if (/^\\[.*\\]$/.test(raw)) {\n tokens.push({ type: 'variable', value: raw.slice(1, -1) })\n } else if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(raw)) {\n tokens.push({ type: 'function', value: raw })\n } else if (/^[+\\-*/]$/.test(raw)) {\n tokens.push({ type: 'operator', value: raw })\n } else if (/^[(),]$/.test(raw)) {\n if (raw === ',') tokens.push({ type: 'comma', value: raw })\n else tokens.push({ type: 'paren', value: raw })\n }\n }\n if (lastIndex < formula.length) {\n throw new Error('Unexpected token at: ' + formula.slice(lastIndex))\n }\n return tokens\n}\n\n// 파서 구현 (재귀 하향, 연산자 우선순위, 함수/변수/숫자/괄호 지원)\nexport function parseFormula(formula: string): FormulaNode {\n const tokens = tokenize(formula)\n let pos = 0\n\n function peek() {\n return tokens[pos]\n }\n function next() {\n return tokens[pos++]\n }\n function expect(type: string, value?: string) {\n const t = next()\n if (!t || t.type !== type || (value && t.value !== value))\n throw new Error('Expected ' + type + (value ? ':' + value : ''))\n return t\n }\n\n function parsePrimary(): FormulaNode {\n const t = peek()\n if (!t) throw new Error('Unexpected end')\n if (t.type === 'number') {\n next()\n return { type: 'number', value: parseFloat(t.value) }\n }\n if (t.type === 'variable') {\n next()\n return { type: 'variable', name: t.value }\n }\n if (t.type === 'function') {\n // 함수 호출: func(expr, ...)\n const name = t.value\n next()\n expect('paren', '(')\n const args: FormulaNode[] = []\n if ((peek() && peek().type !== 'paren') || (peek() && peek().value !== ')')) {\n while (true) {\n args.push(parseExpr())\n if (peek() && peek().type === 'comma') {\n next()\n } else break\n }\n }\n expect('paren', ')')\n return { type: 'function', name, args }\n }\n if (t.type === 'operator' && t.value === '-') {\n next()\n return { type: 'unary', op: '-', arg: parsePrimary() }\n }\n if (t.type === 'paren' && t.value === '(') {\n next()\n const node = parseExpr()\n expect('paren', ')')\n return node\n }\n throw new Error('Unexpected token: ' + t.type + ':' + t.value)\n }\n\n function parseMulDiv(): FormulaNode {\n let node = parsePrimary()\n while (peek() && peek().type === 'operator' && (peek().value === '*' || peek().value === '/')) {\n const op = next().value\n node = { type: 'binary', op, left: node, right: parsePrimary() }\n }\n return node\n }\n\n function parseAddSub(): FormulaNode {\n let node = parseMulDiv()\n while (peek() && peek().type === 'operator' && (peek().value === '+' || peek().value === '-')) {\n const op = next().value\n node = { type: 'binary', op, left: node, right: parseMulDiv() }\n }\n return node\n }\n\n function parseExpr(): FormulaNode {\n return parseAddSub()\n }\n\n const ast = parseExpr()\n if (pos < tokens.length) throw new Error('Unexpected token at end: ' + JSON.stringify(tokens[pos]))\n return ast\n}\n"]}
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../server/calculator/parser.ts"],"names":[],"mappings":"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","sourcesContent":["// KPI formula 파서: 수식 문자열을 AST로 변환\n\nexport type FormulaNode =\n | { type: 'number'; value: number }\n | { type: 'variable'; name: string }\n | { type: 'function'; name: string; args: FormulaNode[] }\n | { type: 'binary'; op: string; left: FormulaNode; right: FormulaNode }\n | { type: 'unary'; op: string; arg: FormulaNode }\n\n// 토큰 타입 정의\nconst TOKEN_REGEX = /\\s*(\\d+\\.\\d+|\\d+|\\[.*?\\]|[A-Za-z_][A-Za-z0-9_]*|[+\\-*/(),])/y\n\ninterface Token {\n type: 'number' | 'variable' | 'function' | 'operator' | 'paren' | 'comma'\n value: string\n}\n\nfunction tokenize(formula: string): Token[] {\n const tokens: Token[] = []\n let m: RegExpExecArray | null\n let lastIndex = 0\n while ((m = TOKEN_REGEX.exec(formula))) {\n lastIndex = TOKEN_REGEX.lastIndex\n // m[0] 공백 포함, m[1]은 capturing group (공백 제외)\n const raw = m[1]\n if (/^\\d/.test(raw)) {\n tokens.push({ type: 'number', value: raw })\n } else if (/^\\[.*\\]$/.test(raw)) {\n tokens.push({ type: 'variable', value: raw.slice(1, -1) })\n } else if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(raw)) {\n tokens.push({ type: 'function', value: raw })\n } else if (/^[+\\-*/]$/.test(raw)) {\n tokens.push({ type: 'operator', value: raw })\n } else if (/^[(),]$/.test(raw)) {\n if (raw === ',') tokens.push({ type: 'comma', value: raw })\n else tokens.push({ type: 'paren', value: raw })\n }\n }\n if (lastIndex < formula.length) {\n throw new Error('Unexpected token at: ' + formula.slice(lastIndex))\n }\n return tokens\n}\n\n// 파서 구현 (재귀 하향, 연산자 우선순위, 함수/변수/숫자/괄호 지원)\nexport function parseFormula(formula: string): FormulaNode {\n const tokens = tokenize(formula)\n let pos = 0\n\n function peek() {\n return tokens[pos]\n }\n function next() {\n return tokens[pos++]\n }\n function expect(type: string, value?: string) {\n const t = next()\n if (!t || t.type !== type || (value && t.value !== value))\n throw new Error('Expected ' + type + (value ? ':' + value : ''))\n return t\n }\n\n function parsePrimary(): FormulaNode {\n const t = peek()\n if (!t) throw new Error('Unexpected end')\n if (t.type === 'number') {\n next()\n return { type: 'number', value: parseFloat(t.value) }\n }\n if (t.type === 'variable') {\n next()\n return { type: 'variable', name: t.value }\n }\n if (t.type === 'function') {\n // function 타입 토큰을 만났을 때, 다음 토큰이 '('인지 확인\n const name = t.value\n next()\n\n // 다음 토큰이 '('이면 함수 호출, 아니면 변수로 처리\n if (peek() && peek().type === 'paren' && peek().value === '(') {\n // 함수 호출: func(expr, ...)\n expect('paren', '(')\n const args: FormulaNode[] = []\n if ((peek() && peek().type !== 'paren') || (peek() && peek().value !== ')')) {\n while (true) {\n args.push(parseExpr())\n if (peek() && peek().type === 'comma') {\n next()\n } else break\n }\n }\n expect('paren', ')')\n return { type: 'function', name, args }\n } else {\n // 변수로 처리\n return { type: 'variable', name }\n }\n }\n if (t.type === 'operator' && t.value === '-') {\n next()\n return { type: 'unary', op: '-', arg: parsePrimary() }\n }\n if (t.type === 'paren' && t.value === '(') {\n next()\n const node = parseExpr()\n expect('paren', ')')\n return node\n }\n throw new Error('Unexpected token: ' + t.type + ':' + t.value)\n }\n\n function parseMulDiv(): FormulaNode {\n let node = parsePrimary()\n while (peek() && peek().type === 'operator' && (peek().value === '*' || peek().value === '/')) {\n const op = next().value\n node = { type: 'binary', op, left: node, right: parsePrimary() }\n }\n return node\n }\n\n function parseAddSub(): FormulaNode {\n let node = parseMulDiv()\n while (peek() && peek().type === 'operator' && (peek().value === '+' || peek().value === '-')) {\n const op = next().value\n node = { type: 'binary', op, left: node, right: parseMulDiv() }\n }\n return node\n }\n\n function parseExpr(): FormulaNode {\n return parseAddSub()\n }\n\n const ast = parseExpr()\n if (pos < tokens.length) throw new Error('Unexpected token at end: ' + JSON.stringify(tokens[pos]))\n return ast\n}\n"]}
@@ -257,7 +257,11 @@ let KpiValueMutation = class KpiValueMutation {
257
257
  });
258
258
  if (!kpiValue)
259
259
  throw new Error('KPI Value not found');
260
- const kpi = kpiValue.kpi || (await kpiRepo.findOne({ where: { id: kpiValue.kpiId, domain: { id: domain.id } } }));
260
+ // 항상 최신 버전의 KPI를 조회하여 사용
261
+ const kpi = await kpiRepo.findOne({
262
+ where: { id: kpiValue.kpiId, domain: { id: domain.id } },
263
+ order: { version: 'DESC' }
264
+ });
261
265
  if (!kpi)
262
266
  throw new Error('KPI 정보 없음');
263
267
  if (!kpi.formula)
@@ -266,7 +270,6 @@ let KpiValueMutation = class KpiValueMutation {
266
270
  const valueDate = kpiValue.valueDate;
267
271
  const kpiOrgScope = kpiValue.kpiOrgScope;
268
272
  const org = kpiOrgScope?.entityName || kpiOrgScope?.org || 'unknown'; // KpiOrgScope에서 org 정보 추출
269
- const version = kpiValue.version;
270
273
  // 2. formula에서 metric code 추출
271
274
  const metricCodes = (kpi.formula.match(/[a-zA-Z_][a-zA-Z0-9_]*/g) || []).filter(code => code !== 'null' && code !== 'undefined');
272
275
  const metricMap = {};
@@ -329,8 +332,9 @@ let KpiValueMutation = class KpiValueMutation {
329
332
  const kpiValueResult = await (0, evaluator_1.evaluateFormula)(ast, evalContext);
330
333
  if (kpiValueResult == null || isNaN(kpiValueResult))
331
334
  throw new Error('KPI formula 결과값 없음');
332
- // 5. KPI Value 업데이트
335
+ // 5. KPI Value 업데이트 (최신 버전으로)
333
336
  kpiValue.value = kpiValueResult;
337
+ kpiValue.version = kpi.version || 1;
334
338
  kpiValue.updater = user;
335
339
  // 6. 성과 점수 자동 계산 및 저장
336
340
  const scoreService = new kpi_value_score_service_1.KpiValueScoreService();
@@ -1 +1 @@
1
- {"version":3,"file":"kpi-value-mutation.js","sourceRoot":"","sources":["../../../server/service/kpi-value/kpi-value-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Resolver, Mutation, Arg, Ctx, Directive } from 'type-graphql'\nimport { In, Between } from 'typeorm'\nimport { getRepository } from '@things-factory/shell'\n\nimport { KpiValue } from './kpi-value'\nimport { NewKpiValue, KpiValuePatch } from './kpi-value-type'\nimport { Kpi } from '../kpi/kpi'\nimport { KpiMetric } from '../kpi-metric/kpi-metric'\nimport { KpiOrgScope } from '../kpi-org-scope/kpi-org-scope'\nimport { KpiMetricValue } from '../kpi-metric-value/kpi-metric-value'\nimport { KpiPeriodType } from '../kpi/kpi'\nimport { getDefaultValueDate } from '../utils/value-date-util'\nimport { KpiValueInputType } from './kpi-value'\nimport { KpiValueScoreService } from './kpi-value-score.service'\nimport { parseFormula } from '../../calculator/parser'\nimport { evaluateFormula } from '../../calculator/evaluator'\nimport { builtinFunctions } from '../../calculator/functions'\nimport { KpiMetricValueProvider } from '../../controllers/kpi-metric-value-provider'\n\n@Resolver(KpiValue)\nexport class KpiValueMutation {\n @Directive('@privilege(category: \"kpi\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => KpiValue, { description: 'Create a new KPI value with the provided details.' })\n async createKpiValue(\n @Arg('kpiValue', { description: 'Input object containing details for the new KPI value.' }) kpiValue: NewKpiValue,\n @Ctx() context: ResolverContext\n ): Promise<KpiValue> {\n const { domain, user, tx } = context.state\n\n let kpi = kpiValue.kpiId ? await getRepository(Kpi).findOne({ where: { id: kpiValue.kpiId } }) : undefined\n\n let inputType: KpiValueInputType | undefined = undefined\n if (kpiValue.inputType) {\n if (typeof kpiValue.inputType === 'string') {\n inputType = KpiValueInputType[kpiValue.inputType as keyof typeof KpiValueInputType]\n } else {\n inputType = kpiValue.inputType\n }\n }\n\n // KpiOrgScope 처리\n let kpiOrgScope: KpiOrgScope | undefined\n if (kpiValue.kpiOrgScopeId) {\n kpiOrgScope = await getRepository(KpiOrgScope, context.state?.tx).findOne({\n where: { id: kpiValue.kpiOrgScopeId, domain: { id: domain.id } }\n })\n if (!kpiOrgScope) {\n throw new Error(`KpiOrgScope not found: ${kpiValue.kpiOrgScopeId}`)\n }\n } else if (kpiValue.org) {\n // Legacy org 처리 - org 문자열로 KpiOrgScope 찾기 또는 생성\n kpiOrgScope = await getRepository(KpiOrgScope, context.state?.tx).findOne({\n where: { org: kpiValue.org, domain: { id: domain.id } }\n })\n if (!kpiOrgScope) {\n // 새 KpiOrgScope 생성\n kpiOrgScope = await getRepository(KpiOrgScope, context.state?.tx).save({\n entityType: 'Manual',\n entityId: `manual-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,\n entityName: kpiValue.org,\n org: kpiValue.org,\n domain,\n creator: user,\n updater: user\n })\n }\n }\n\n const entity: Partial<KpiValue> = {\n kpi,\n kpiId: kpiValue.kpiId,\n version: kpiValue.version,\n valueDate: kpiValue.valueDate,\n value: kpiValue.value,\n source: kpiValue.source,\n domain: domain,\n creator: user,\n updater: user\n }\n \n if (kpiOrgScope) {\n entity.kpiOrgScope = kpiOrgScope\n entity.kpiOrgScopeId = kpiOrgScope.id\n }\n if (inputType) entity.inputType = inputType\n\n return await getRepository(KpiValue, tx).save(entity)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"kpi\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => [KpiValue], { description: 'Create multiple KPI values with the provided details.' })\n async createMultipleKpiValue(\n @Arg('values', type => [NewKpiValue], {\n description: 'Array of input objects containing details for the new KPI values.'\n })\n values: NewKpiValue[],\n @Ctx() context: ResolverContext\n ): Promise<KpiValue[]> {\n const { domain, user, tx } = context.state\n const repository = getRepository(KpiValue, tx)\n const scoreService = new KpiValueScoreService()\n\n const entities: KpiValue[] = []\n\n for (const kpiValue of values) {\n let kpi = kpiValue.kpiId ? await getRepository(Kpi).findOne({ where: { id: kpiValue.kpiId } }) : undefined\n\n let inputType: KpiValueInputType | undefined = undefined\n if (kpiValue.inputType) {\n if (typeof kpiValue.inputType === 'string') {\n inputType = KpiValueInputType[kpiValue.inputType as keyof typeof KpiValueInputType]\n } else {\n inputType = kpiValue.inputType\n }\n }\n\n // KpiOrgScope 처리\n let kpiOrgScope: KpiOrgScope | undefined\n if (kpiValue.kpiOrgScopeId) {\n kpiOrgScope = await getRepository(KpiOrgScope, context.state?.tx).findOne({\n where: { id: kpiValue.kpiOrgScopeId, domain: { id: domain.id } }\n })\n if (!kpiOrgScope) {\n throw new Error(`KpiOrgScope not found: ${kpiValue.kpiOrgScopeId}`)\n }\n } else if (kpiValue.org) {\n // Legacy org 처리\n kpiOrgScope = await getRepository(KpiOrgScope, context.state?.tx).findOne({\n where: { org: kpiValue.org, domain: { id: domain.id } }\n })\n if (!kpiOrgScope) {\n // 새 KpiOrgScope 생성\n kpiOrgScope = await getRepository(KpiOrgScope, context.state?.tx).save({\n entityType: 'Manual',\n entityId: `manual-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,\n entityName: kpiValue.org,\n org: kpiValue.org,\n domain,\n creator: user,\n updater: user\n })\n }\n }\n\n const entity: Partial<KpiValue> = {\n kpi,\n kpiId: kpiValue.kpiId,\n version: kpiValue.version || 1,\n valueDate: kpiValue.valueDate,\n value: kpiValue.value,\n source: kpiValue.source || 'MANUAL',\n domain: domain,\n creator: user,\n updater: user\n }\n\n if (kpiOrgScope) {\n entity.kpiOrgScope = kpiOrgScope\n entity.kpiOrgScopeId = kpiOrgScope.id\n }\n if (inputType) entity.inputType = inputType\n\n const savedEntity = await repository.save(entity)\n\n // 성과 점수 자동 계산 및 저장\n if (kpi) {\n await scoreService.calculateAndSaveScore(savedEntity, kpi)\n }\n\n entities.push(savedEntity)\n }\n\n return entities\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"kpi\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => KpiValue, { description: 'To modify KpiValue information' })\n async updateKpiValue(\n @Arg('id') id: string,\n @Arg('patch') patch: KpiValuePatch,\n @Ctx() context: ResolverContext\n ): Promise<KpiValue> {\n const { domain, user, tx } = context.state\n\n const repository = getRepository(KpiValue, tx)\n const kpiValue = await repository.findOne({\n where: { domain: { id: domain.id }, id }\n })\n\n let kpi = patch.kpiId ? await getRepository(Kpi).findOne({ where: { id: patch.kpiId } }) : kpiValue.kpi\n\n let inputType: KpiValueInputType | undefined = undefined\n if (patch.inputType) {\n if (typeof patch.inputType === 'string') {\n inputType = KpiValueInputType[patch.inputType as keyof typeof KpiValueInputType]\n } else {\n inputType = patch.inputType\n }\n } else {\n inputType = kpiValue.inputType\n }\n\n const entity: any = {\n ...kpiValue,\n ...patch,\n kpi,\n updater: user\n }\n if (inputType) entity.inputType = inputType\n\n return await repository.save(entity)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"kpi\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => [KpiValue], { description: \"To modify multiple KpiValues' information\" })\n async updateMultipleKpiValue(\n @Arg('patches', type => [KpiValuePatch]) patches: KpiValuePatch[],\n @Ctx() context: ResolverContext\n ): Promise<KpiValue[]> {\n const { domain, user, tx } = context.state\n\n let results = []\n const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')\n const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')\n const kpiValueRepo = getRepository(KpiValue, tx)\n\n if (_createRecords.length > 0) {\n for (let i = 0; i < _createRecords.length; i++) {\n const newRecord = _createRecords[i]\n\n const kpi = await getRepository(Kpi, tx).findOne({\n where: { domain: { id: domain.id }, id: newRecord.kpiId }\n })\n\n const result = await kpiValueRepo.save({\n ...newRecord,\n kpi,\n version: newRecord.version || kpi.version,\n domain,\n creator: user,\n updater: user\n } as any)\n\n results.push({ ...result, cuFlag: '+' })\n }\n }\n\n if (_updateRecords.length > 0) {\n for (let i = 0; i < _updateRecords.length; i++) {\n const updateRecord = _updateRecords[i]\n const kpiValue = await kpiValueRepo.findOneBy({ id: updateRecord.id })\n\n const kpi = await getRepository(Kpi, tx).findOne({\n where: { domain: { id: domain.id }, id: updateRecord.kpiId }\n })\n\n const result = await kpiValueRepo.save({\n ...kpiValue,\n ...updateRecord,\n kpi,\n version: updateRecord.version || kpi.version,\n updater: user\n } as any)\n\n results.push({ ...result, cuFlag: 'M' })\n }\n }\n\n return results\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"kpi\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'To delete KpiValue' })\n async deleteKpiValue(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const { domain, tx } = context.state\n\n await getRepository(KpiValue, tx).delete({ domain: { id: domain.id }, id })\n\n return true\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"kpi\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'To delete multiple KpiValues' })\n async deleteKpiValues(\n @Arg('ids', type => [String]) ids: string[],\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, tx } = context.state\n\n await getRepository(KpiValue, tx).delete({\n domain: { id: domain.id },\n id: In(ids)\n })\n\n return true\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"kpi\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'To import multiple KpiValues' })\n async importKpiValues(\n @Arg('kpiValues', type => [KpiValuePatch]) kpiValues: KpiValuePatch[],\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, tx } = context.state\n\n await Promise.all(\n kpiValues.map(async (kpiValue: KpiValuePatch) => {\n const createdKpiValue: KpiValue = await getRepository(KpiValue, tx).save({ domain, ...kpiValue } as any)\n })\n )\n\n return true\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"kpi\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Recalculate scores for all KpiValues of a specific KPI' })\n async recalculateScoresForKpi(@Arg('kpiId') kpiId: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const scoreService = new KpiValueScoreService()\n await scoreService.recalculateScoresForKpi(kpiId, context)\n return true\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"kpi\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => KpiValue, { description: '기존 KPI Value 인스턴스를 현재 formula/metric 값으로 재계산' })\n async recalculateKpiValue(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<KpiValue> {\n const { domain, user, tx } = context.state\n const kpiValueRepo = getRepository(KpiValue, tx)\n const kpiRepo = getRepository(Kpi, tx)\n const metricRepo = getRepository(KpiMetric, tx)\n const metricValueRepo = getRepository(KpiMetricValue, tx)\n\n // 1. 기존 KPI Value 인스턴스 조회\n const kpiValue = await kpiValueRepo.findOne({\n where: { id, domain: { id: domain.id } },\n relations: ['kpi', 'kpiOrgScope']\n })\n if (!kpiValue) throw new Error('KPI Value not found')\n const kpi = kpiValue.kpi || (await kpiRepo.findOne({ where: { id: kpiValue.kpiId, domain: { id: domain.id } } }))\n if (!kpi) throw new Error('KPI 정보 없음')\n if (!kpi.formula) throw new Error('KPI formula 없음')\n const periodType = kpi.periodType || KpiPeriodType.DAY\n const valueDate = kpiValue.valueDate\n const kpiOrgScope = kpiValue.kpiOrgScope\n const org = kpiOrgScope?.entityName || kpiOrgScope?.org || 'unknown' // KpiOrgScope에서 org 정보 추출\n const version = kpiValue.version\n\n // 2. formula에서 metric code 추출\n const metricCodes = (kpi.formula.match(/[a-zA-Z_][a-zA-Z0-9_]*/g) || []).filter(\n code => code !== 'null' && code !== 'undefined'\n )\n const metricMap: Record<string, KpiMetric> = {}\n for (const code of metricCodes) {\n const metric = await metricRepo.findOne({ where: { name: code, domain: { id: domain.id } } })\n if (!metric) throw new Error(`KPI formula metric '${code}' not found`)\n metricMap[code] = metric\n }\n\n // 3. metric 값 집계 (periodType 변환/집계)\n const metricValues: Record<string, number> = {}\n for (const code of metricCodes) {\n const metric = metricMap[code]\n let value = null\n if (metric.periodType === periodType) {\n const mv = await metricValueRepo.findOne({\n where: {\n metric: { id: metric.id },\n valueDate,\n periodType,\n org: org ?? '',\n domain: { id: domain.id }\n }\n })\n value = mv?.value ?? null\n } else {\n let startDate: string, endDate: string\n if (periodType === KpiPeriodType.MONTH && metric.periodType === KpiPeriodType.DAY) {\n startDate = valueDate + '-01'\n endDate = valueDate + '-31'\n const mvs = await metricValueRepo.find({\n where: {\n metric: { id: metric.id },\n valueDate: Between(startDate, endDate),\n periodType: metric.periodType,\n org: org ?? '',\n domain: { id: domain.id }\n }\n })\n value = mvs.reduce((sum, mv) => sum + (mv.value ?? 0), 0)\n } else {\n throw new Error('KPI/Metric periodType 조합 집계 미지원')\n }\n }\n if (value == null) throw new Error(`Metric '${code}' 값 없음`)\n metricValues[code] = value\n }\n\n // 4. formula 계산 (calculator 기반)\n const ast = parseFormula(kpi.formula)\n const provider = new KpiMetricValueProvider({\n valueDate,\n org,\n domainId: domain.id,\n tx\n })\n const evalContext = { functions: builtinFunctions, provider }\n const kpiValueResult = await evaluateFormula(ast, evalContext)\n if (kpiValueResult == null || isNaN(kpiValueResult)) throw new Error('KPI formula 결과값 없음')\n\n // 5. KPI Value 업데이트\n kpiValue.value = kpiValueResult\n kpiValue.updater = user\n\n // 6. 성과 점수 자동 계산 및 저장\n const scoreService = new KpiValueScoreService()\n await scoreService.calculateAndSaveScore(kpiValue, kpi)\n\n return await kpiValueRepo.save(kpiValue)\n }\n}\n"]}
1
+ {"version":3,"file":"kpi-value-mutation.js","sourceRoot":"","sources":["../../../server/service/kpi-value/kpi-value-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Resolver, Mutation, Arg, Ctx, Directive } from 'type-graphql'\nimport { In, Between } from 'typeorm'\nimport { getRepository } from '@things-factory/shell'\n\nimport { KpiValue } from './kpi-value'\nimport { NewKpiValue, KpiValuePatch } from './kpi-value-type'\nimport { Kpi } from '../kpi/kpi'\nimport { KpiMetric } from '../kpi-metric/kpi-metric'\nimport { KpiOrgScope } from '../kpi-org-scope/kpi-org-scope'\nimport { KpiMetricValue } from '../kpi-metric-value/kpi-metric-value'\nimport { KpiPeriodType } from '../kpi/kpi'\nimport { getDefaultValueDate } from '../utils/value-date-util'\nimport { KpiValueInputType } from './kpi-value'\nimport { KpiValueScoreService } from './kpi-value-score.service'\nimport { parseFormula } from '../../calculator/parser'\nimport { evaluateFormula } from '../../calculator/evaluator'\nimport { builtinFunctions } from '../../calculator/functions'\nimport { KpiMetricValueProvider } from '../../controllers/kpi-metric-value-provider'\n\n@Resolver(KpiValue)\nexport class KpiValueMutation {\n @Directive('@privilege(category: \"kpi\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => KpiValue, { description: 'Create a new KPI value with the provided details.' })\n async createKpiValue(\n @Arg('kpiValue', { description: 'Input object containing details for the new KPI value.' }) kpiValue: NewKpiValue,\n @Ctx() context: ResolverContext\n ): Promise<KpiValue> {\n const { domain, user, tx } = context.state\n\n let kpi = kpiValue.kpiId ? await getRepository(Kpi).findOne({ where: { id: kpiValue.kpiId } }) : undefined\n\n let inputType: KpiValueInputType | undefined = undefined\n if (kpiValue.inputType) {\n if (typeof kpiValue.inputType === 'string') {\n inputType = KpiValueInputType[kpiValue.inputType as keyof typeof KpiValueInputType]\n } else {\n inputType = kpiValue.inputType\n }\n }\n\n // KpiOrgScope 처리\n let kpiOrgScope: KpiOrgScope | undefined\n if (kpiValue.kpiOrgScopeId) {\n kpiOrgScope = await getRepository(KpiOrgScope, context.state?.tx).findOne({\n where: { id: kpiValue.kpiOrgScopeId, domain: { id: domain.id } }\n })\n if (!kpiOrgScope) {\n throw new Error(`KpiOrgScope not found: ${kpiValue.kpiOrgScopeId}`)\n }\n } else if (kpiValue.org) {\n // Legacy org 처리 - org 문자열로 KpiOrgScope 찾기 또는 생성\n kpiOrgScope = await getRepository(KpiOrgScope, context.state?.tx).findOne({\n where: { org: kpiValue.org, domain: { id: domain.id } }\n })\n if (!kpiOrgScope) {\n // 새 KpiOrgScope 생성\n kpiOrgScope = await getRepository(KpiOrgScope, context.state?.tx).save({\n entityType: 'Manual',\n entityId: `manual-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,\n entityName: kpiValue.org,\n org: kpiValue.org,\n domain,\n creator: user,\n updater: user\n })\n }\n }\n\n const entity: Partial<KpiValue> = {\n kpi,\n kpiId: kpiValue.kpiId,\n version: kpiValue.version,\n valueDate: kpiValue.valueDate,\n value: kpiValue.value,\n source: kpiValue.source,\n domain: domain,\n creator: user,\n updater: user\n }\n \n if (kpiOrgScope) {\n entity.kpiOrgScope = kpiOrgScope\n entity.kpiOrgScopeId = kpiOrgScope.id\n }\n if (inputType) entity.inputType = inputType\n\n return await getRepository(KpiValue, tx).save(entity)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"kpi\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => [KpiValue], { description: 'Create multiple KPI values with the provided details.' })\n async createMultipleKpiValue(\n @Arg('values', type => [NewKpiValue], {\n description: 'Array of input objects containing details for the new KPI values.'\n })\n values: NewKpiValue[],\n @Ctx() context: ResolverContext\n ): Promise<KpiValue[]> {\n const { domain, user, tx } = context.state\n const repository = getRepository(KpiValue, tx)\n const scoreService = new KpiValueScoreService()\n\n const entities: KpiValue[] = []\n\n for (const kpiValue of values) {\n let kpi = kpiValue.kpiId ? await getRepository(Kpi).findOne({ where: { id: kpiValue.kpiId } }) : undefined\n\n let inputType: KpiValueInputType | undefined = undefined\n if (kpiValue.inputType) {\n if (typeof kpiValue.inputType === 'string') {\n inputType = KpiValueInputType[kpiValue.inputType as keyof typeof KpiValueInputType]\n } else {\n inputType = kpiValue.inputType\n }\n }\n\n // KpiOrgScope 처리\n let kpiOrgScope: KpiOrgScope | undefined\n if (kpiValue.kpiOrgScopeId) {\n kpiOrgScope = await getRepository(KpiOrgScope, context.state?.tx).findOne({\n where: { id: kpiValue.kpiOrgScopeId, domain: { id: domain.id } }\n })\n if (!kpiOrgScope) {\n throw new Error(`KpiOrgScope not found: ${kpiValue.kpiOrgScopeId}`)\n }\n } else if (kpiValue.org) {\n // Legacy org 처리\n kpiOrgScope = await getRepository(KpiOrgScope, context.state?.tx).findOne({\n where: { org: kpiValue.org, domain: { id: domain.id } }\n })\n if (!kpiOrgScope) {\n // 새 KpiOrgScope 생성\n kpiOrgScope = await getRepository(KpiOrgScope, context.state?.tx).save({\n entityType: 'Manual',\n entityId: `manual-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,\n entityName: kpiValue.org,\n org: kpiValue.org,\n domain,\n creator: user,\n updater: user\n })\n }\n }\n\n const entity: Partial<KpiValue> = {\n kpi,\n kpiId: kpiValue.kpiId,\n version: kpiValue.version || 1,\n valueDate: kpiValue.valueDate,\n value: kpiValue.value,\n source: kpiValue.source || 'MANUAL',\n domain: domain,\n creator: user,\n updater: user\n }\n\n if (kpiOrgScope) {\n entity.kpiOrgScope = kpiOrgScope\n entity.kpiOrgScopeId = kpiOrgScope.id\n }\n if (inputType) entity.inputType = inputType\n\n const savedEntity = await repository.save(entity)\n\n // 성과 점수 자동 계산 및 저장\n if (kpi) {\n await scoreService.calculateAndSaveScore(savedEntity, kpi)\n }\n\n entities.push(savedEntity)\n }\n\n return entities\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"kpi\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => KpiValue, { description: 'To modify KpiValue information' })\n async updateKpiValue(\n @Arg('id') id: string,\n @Arg('patch') patch: KpiValuePatch,\n @Ctx() context: ResolverContext\n ): Promise<KpiValue> {\n const { domain, user, tx } = context.state\n\n const repository = getRepository(KpiValue, tx)\n const kpiValue = await repository.findOne({\n where: { domain: { id: domain.id }, id }\n })\n\n let kpi = patch.kpiId ? await getRepository(Kpi).findOne({ where: { id: patch.kpiId } }) : kpiValue.kpi\n\n let inputType: KpiValueInputType | undefined = undefined\n if (patch.inputType) {\n if (typeof patch.inputType === 'string') {\n inputType = KpiValueInputType[patch.inputType as keyof typeof KpiValueInputType]\n } else {\n inputType = patch.inputType\n }\n } else {\n inputType = kpiValue.inputType\n }\n\n const entity: any = {\n ...kpiValue,\n ...patch,\n kpi,\n updater: user\n }\n if (inputType) entity.inputType = inputType\n\n return await repository.save(entity)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"kpi\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => [KpiValue], { description: \"To modify multiple KpiValues' information\" })\n async updateMultipleKpiValue(\n @Arg('patches', type => [KpiValuePatch]) patches: KpiValuePatch[],\n @Ctx() context: ResolverContext\n ): Promise<KpiValue[]> {\n const { domain, user, tx } = context.state\n\n let results = []\n const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')\n const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')\n const kpiValueRepo = getRepository(KpiValue, tx)\n\n if (_createRecords.length > 0) {\n for (let i = 0; i < _createRecords.length; i++) {\n const newRecord = _createRecords[i]\n\n const kpi = await getRepository(Kpi, tx).findOne({\n where: { domain: { id: domain.id }, id: newRecord.kpiId }\n })\n\n const result = await kpiValueRepo.save({\n ...newRecord,\n kpi,\n version: newRecord.version || kpi.version,\n domain,\n creator: user,\n updater: user\n } as any)\n\n results.push({ ...result, cuFlag: '+' })\n }\n }\n\n if (_updateRecords.length > 0) {\n for (let i = 0; i < _updateRecords.length; i++) {\n const updateRecord = _updateRecords[i]\n const kpiValue = await kpiValueRepo.findOneBy({ id: updateRecord.id })\n\n const kpi = await getRepository(Kpi, tx).findOne({\n where: { domain: { id: domain.id }, id: updateRecord.kpiId }\n })\n\n const result = await kpiValueRepo.save({\n ...kpiValue,\n ...updateRecord,\n kpi,\n version: updateRecord.version || kpi.version,\n updater: user\n } as any)\n\n results.push({ ...result, cuFlag: 'M' })\n }\n }\n\n return results\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"kpi\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'To delete KpiValue' })\n async deleteKpiValue(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const { domain, tx } = context.state\n\n await getRepository(KpiValue, tx).delete({ domain: { id: domain.id }, id })\n\n return true\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"kpi\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'To delete multiple KpiValues' })\n async deleteKpiValues(\n @Arg('ids', type => [String]) ids: string[],\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, tx } = context.state\n\n await getRepository(KpiValue, tx).delete({\n domain: { id: domain.id },\n id: In(ids)\n })\n\n return true\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"kpi\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'To import multiple KpiValues' })\n async importKpiValues(\n @Arg('kpiValues', type => [KpiValuePatch]) kpiValues: KpiValuePatch[],\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, tx } = context.state\n\n await Promise.all(\n kpiValues.map(async (kpiValue: KpiValuePatch) => {\n const createdKpiValue: KpiValue = await getRepository(KpiValue, tx).save({ domain, ...kpiValue } as any)\n })\n )\n\n return true\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"kpi\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Recalculate scores for all KpiValues of a specific KPI' })\n async recalculateScoresForKpi(@Arg('kpiId') kpiId: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const scoreService = new KpiValueScoreService()\n await scoreService.recalculateScoresForKpi(kpiId, context)\n return true\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"kpi\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => KpiValue, { description: '기존 KPI Value 인스턴스를 현재 formula/metric 값으로 재계산' })\n async recalculateKpiValue(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<KpiValue> {\n const { domain, user, tx } = context.state\n const kpiValueRepo = getRepository(KpiValue, tx)\n const kpiRepo = getRepository(Kpi, tx)\n const metricRepo = getRepository(KpiMetric, tx)\n const metricValueRepo = getRepository(KpiMetricValue, tx)\n\n // 1. 기존 KPI Value 인스턴스 조회\n const kpiValue = await kpiValueRepo.findOne({\n where: { id, domain: { id: domain.id } },\n relations: ['kpi', 'kpiOrgScope']\n })\n if (!kpiValue) throw new Error('KPI Value not found')\n // 항상 최신 버전의 KPI를 조회하여 사용\n const kpi = await kpiRepo.findOne({\n where: { id: kpiValue.kpiId, domain: { id: domain.id } },\n order: { version: 'DESC' }\n })\n if (!kpi) throw new Error('KPI 정보 없음')\n if (!kpi.formula) throw new Error('KPI formula 없음')\n const periodType = kpi.periodType || KpiPeriodType.DAY\n const valueDate = kpiValue.valueDate\n const kpiOrgScope = kpiValue.kpiOrgScope\n const org = kpiOrgScope?.entityName || kpiOrgScope?.org || 'unknown' // KpiOrgScope에서 org 정보 추출\n\n // 2. formula에서 metric code 추출\n const metricCodes = (kpi.formula.match(/[a-zA-Z_][a-zA-Z0-9_]*/g) || []).filter(\n code => code !== 'null' && code !== 'undefined'\n )\n const metricMap: Record<string, KpiMetric> = {}\n for (const code of metricCodes) {\n const metric = await metricRepo.findOne({ where: { name: code, domain: { id: domain.id } } })\n if (!metric) throw new Error(`KPI formula metric '${code}' not found`)\n metricMap[code] = metric\n }\n\n // 3. metric 값 집계 (periodType 변환/집계)\n const metricValues: Record<string, number> = {}\n for (const code of metricCodes) {\n const metric = metricMap[code]\n let value = null\n if (metric.periodType === periodType) {\n const mv = await metricValueRepo.findOne({\n where: {\n metric: { id: metric.id },\n valueDate,\n periodType,\n org: org ?? '',\n domain: { id: domain.id }\n }\n })\n value = mv?.value ?? null\n } else {\n let startDate: string, endDate: string\n if (periodType === KpiPeriodType.MONTH && metric.periodType === KpiPeriodType.DAY) {\n startDate = valueDate + '-01'\n endDate = valueDate + '-31'\n const mvs = await metricValueRepo.find({\n where: {\n metric: { id: metric.id },\n valueDate: Between(startDate, endDate),\n periodType: metric.periodType,\n org: org ?? '',\n domain: { id: domain.id }\n }\n })\n value = mvs.reduce((sum, mv) => sum + (mv.value ?? 0), 0)\n } else {\n throw new Error('KPI/Metric periodType 조합 집계 미지원')\n }\n }\n if (value == null) throw new Error(`Metric '${code}' 값 없음`)\n metricValues[code] = value\n }\n\n // 4. formula 계산 (calculator 기반)\n const ast = parseFormula(kpi.formula)\n const provider = new KpiMetricValueProvider({\n valueDate,\n org,\n domainId: domain.id,\n tx\n })\n const evalContext = { functions: builtinFunctions, provider }\n const kpiValueResult = await evaluateFormula(ast, evalContext)\n if (kpiValueResult == null || isNaN(kpiValueResult)) throw new Error('KPI formula 결과값 없음')\n\n // 5. KPI Value 업데이트 (최신 버전으로)\n kpiValue.value = kpiValueResult\n kpiValue.version = kpi.version || 1\n kpiValue.updater = user\n\n // 6. 성과 점수 자동 계산 및 저장\n const scoreService = new KpiValueScoreService()\n await scoreService.calculateAndSaveScore(kpiValue, kpi)\n\n return await kpiValueRepo.save(kpiValue)\n }\n}\n"]}
@@ -28,10 +28,8 @@ class KpiValueScoreService {
28
28
  const result = await (0, evaluator_1.evaluateFormula)(ast, evalContext);
29
29
  if (result !== null && result !== undefined && !isNaN(result)) {
30
30
  const performanceScore = Number(result);
31
- // score를 0~1 범위로 제한
32
- const clampedScore = Math.max(0, Math.min(1, performanceScore));
33
31
  return {
34
- score: clampedScore,
32
+ score: performanceScore,
35
33
  calculationMethod: 'formula'
36
34
  };
37
35
  }
@@ -55,10 +53,8 @@ class KpiValueScoreService {
55
53
  if (!grade) {
56
54
  return null;
57
55
  }
58
- // score를 0~1 범위로 제한
59
- const clampedScore = Math.max(0, Math.min(1, grade.score));
60
56
  return {
61
- score: clampedScore,
57
+ score: grade.score,
62
58
  calculationMethod: 'lookup'
63
59
  };
64
60
  }
@@ -1 +1 @@
1
- {"version":3,"file":"kpi-value-score.service.js","sourceRoot":"","sources":["../../../server/service/kpi-value/kpi-value-score.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { getRepository } from '@things-factory/shell'\nimport { Kpi } from '../kpi/kpi'\nimport { KpiValue } from './kpi-value'\nimport { parseFormula } from '../../calculator/parser'\nimport { evaluateFormula } from '../../calculator/evaluator'\nimport { builtinFunctions } from '../../calculator/functions'\n\nexport interface ScoreResult {\n score: number\n calculationMethod?: 'formula' | 'lookup'\n}\n\nexport class KpiValueScoreService {\n /**\n * scoreFormula를 사용한 성과 점수 계산\n */\n async calculateScoreFromFormula(kpi: Kpi, value: number): Promise<ScoreResult | null> {\n if (!kpi.scoreFormula) {\n return null\n }\n\n try {\n const ast = parseFormula(kpi.scoreFormula)\n const provider = {\n get: async (name: string) => {\n if (name === 'value') return value\n return null\n }\n }\n const evalContext = { functions: builtinFunctions, provider }\n const result = await evaluateFormula(ast, evalContext)\n\n if (result !== null && result !== undefined && !isNaN(result)) {\n const performanceScore = Number(result)\n\n // score를 0~1 범위로 제한\n const clampedScore = Math.max(0, Math.min(1, performanceScore))\n\n return {\n score: clampedScore,\n calculationMethod: 'formula'\n }\n }\n } catch (error) {\n console.error(`Score formula evaluation for '${kpi.name}: ${kpi.scoreFormula}' error:`, error)\n }\n\n return null\n }\n\n /**\n * KPI의 grades lookup table을 이용한 성과 점수 변환\n * 복잡한 성과 점수 변환을 수식으로 표현하기 어려운 경우 사용\n * @deprecated 향후 grades 필드 제거 예정. scoreFormula로 대체 권장\n */\n calculateScoreFromLookup(kpi: Kpi, value: number): ScoreResult | null {\n if (!kpi.grades || kpi.grades.length === 0) {\n return null\n }\n\n // grades lookup table에서 해당 값의 범위에 맞는 성과 점수 찾기\n const grade = kpi.grades.find(g => value >= g.minValue && value <= g.maxValue)\n\n if (!grade) {\n return null\n }\n\n // score를 0~1 범위로 제한\n const clampedScore = Math.max(0, Math.min(1, grade.score))\n\n return {\n score: clampedScore,\n calculationMethod: 'lookup'\n }\n }\n\n /**\n * KpiValue 생성/수정 시 성과 점수 자동 계산 및 저장\n */\n async calculateAndSaveScore(kpiValue: KpiValue, kpi: Kpi): Promise<void> {\n // 1. scoreFormula 우선 시도\n let scoreResult = await this.calculateScoreFromFormula(kpi, kpiValue.value)\n\n // 2. scoreFormula가 없거나 실패하면 grades lookup table 사용 (deprecated)\n if (!scoreResult) {\n scoreResult = this.calculateScoreFromLookup(kpi, kpiValue.value)\n }\n\n if (scoreResult) {\n // KpiValue의 score 필드에 성과 점수 저장\n kpiValue.score = scoreResult.score\n }\n }\n\n /**\n * 기존 KpiValue들의 성과 점수 재계산 (배치 처리)\n */\n async recalculateScoresForKpi(kpiId: string, context: ResolverContext): Promise<void> {\n const kpi = await getRepository(Kpi).findOne({ where: { id: kpiId } })\n if (!kpi) return\n\n const kpiValues = await getRepository(KpiValue).find({\n where: { kpiId, version: kpi.version }\n })\n\n for (const kpiValue of kpiValues) {\n await this.calculateAndSaveScore(kpiValue, kpi)\n }\n\n await getRepository(KpiValue).save(kpiValues)\n }\n}\n"]}
1
+ {"version":3,"file":"kpi-value-score.service.js","sourceRoot":"","sources":["../../../server/service/kpi-value/kpi-value-score.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { getRepository } from '@things-factory/shell'\nimport { Kpi } from '../kpi/kpi'\nimport { KpiValue } from './kpi-value'\nimport { parseFormula } from '../../calculator/parser'\nimport { evaluateFormula } from '../../calculator/evaluator'\nimport { builtinFunctions } from '../../calculator/functions'\n\nexport interface ScoreResult {\n score: number\n calculationMethod?: 'formula' | 'lookup'\n}\n\nexport class KpiValueScoreService {\n /**\n * scoreFormula를 사용한 성과 점수 계산\n */\n async calculateScoreFromFormula(kpi: Kpi, value: number): Promise<ScoreResult | null> {\n if (!kpi.scoreFormula) {\n return null\n }\n\n try {\n const ast = parseFormula(kpi.scoreFormula)\n const provider = {\n get: async (name: string) => {\n if (name === 'value') return value\n return null\n }\n }\n const evalContext = { functions: builtinFunctions, provider }\n const result = await evaluateFormula(ast, evalContext)\n\n if (result !== null && result !== undefined && !isNaN(result)) {\n const performanceScore = Number(result)\n\n return {\n score: performanceScore,\n calculationMethod: 'formula'\n }\n }\n } catch (error) {\n console.error(`Score formula evaluation for '${kpi.name}: ${kpi.scoreFormula}' error:`, error)\n }\n\n return null\n }\n\n /**\n * KPI의 grades lookup table을 이용한 성과 점수 변환\n * 복잡한 성과 점수 변환을 수식으로 표현하기 어려운 경우 사용\n * @deprecated 향후 grades 필드 제거 예정. scoreFormula로 대체 권장\n */\n calculateScoreFromLookup(kpi: Kpi, value: number): ScoreResult | null {\n if (!kpi.grades || kpi.grades.length === 0) {\n return null\n }\n\n // grades lookup table에서 해당 값의 범위에 맞는 성과 점수 찾기\n const grade = kpi.grades.find(g => value >= g.minValue && value <= g.maxValue)\n\n if (!grade) {\n return null\n }\n\n return {\n score: grade.score,\n calculationMethod: 'lookup'\n }\n }\n\n /**\n * KpiValue 생성/수정 시 성과 점수 자동 계산 및 저장\n */\n async calculateAndSaveScore(kpiValue: KpiValue, kpi: Kpi): Promise<void> {\n // 1. scoreFormula 우선 시도\n let scoreResult = await this.calculateScoreFromFormula(kpi, kpiValue.value)\n\n // 2. scoreFormula가 없거나 실패하면 grades lookup table 사용 (deprecated)\n if (!scoreResult) {\n scoreResult = this.calculateScoreFromLookup(kpi, kpiValue.value)\n }\n\n if (scoreResult) {\n // KpiValue의 score 필드에 성과 점수 저장\n kpiValue.score = scoreResult.score\n }\n }\n\n /**\n * 기존 KpiValue들의 성과 점수 재계산 (배치 처리)\n */\n async recalculateScoresForKpi(kpiId: string, context: ResolverContext): Promise<void> {\n const kpi = await getRepository(Kpi).findOne({ where: { id: kpiId } })\n if (!kpi) return\n\n const kpiValues = await getRepository(KpiValue).find({\n where: { kpiId, version: kpi.version }\n })\n\n for (const kpiValue of kpiValues) {\n await this.calculateAndSaveScore(kpiValue, kpi)\n }\n\n await getRepository(KpiValue).save(kpiValues)\n }\n}\n"]}
@@ -72,7 +72,7 @@ tslib_1.__decorate([
72
72
  (0, typeorm_1.Column)('float', { nullable: true }),
73
73
  (0, type_graphql_1.Field)(type => type_graphql_1.Float, {
74
74
  nullable: true,
75
- description: 'Performance score calculated from KPI value using scoreFormula or grades lookup table. Range: 0-1.'
75
+ description: 'Performance score calculated from KPI value using scoreFormula or grades lookup table.'
76
76
  }),
77
77
  tslib_1.__metadata("design:type", Number)
78
78
  ], KpiValue.prototype, "score", void 0);
@@ -1 +1 @@
1
- {"version":3,"file":"kpi-value.js","sourceRoot":"","sources":["../../../server/service/kpi-value/kpi-value.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n CreateDateColumn,\n UpdateDateColumn,\n Entity,\n Index,\n Column,\n RelationId,\n ManyToOne,\n PrimaryGeneratedColumn\n} from 'typeorm'\nimport { ObjectType, Field, Int, ID, registerEnumType, Float } from 'type-graphql'\n\nimport { User } from '@things-factory/auth-base'\nimport { Domain, ScalarObject, json5Transformer } from '@things-factory/shell'\nimport { config } from '@things-factory/env'\nimport { Kpi, KpiPeriodType } from '../kpi/kpi'\nimport { KpiOrgScope } from '../kpi-org-scope/kpi-org-scope'\n\nconst ORMCONFIG = config.get('ormconfig', {})\nconst DATABASE_TYPE = ORMCONFIG.type\n\nexport enum KpiValueInputType {\n MANUAL = 'MANUAL',\n AUTO = 'AUTO'\n}\n\nregisterEnumType(KpiValueInputType, {\n name: 'KpiValueInputType',\n description: 'Type of the input (Manual or Auto)'\n})\n\n@Entity()\n@Index('ix_kpi_value_latest', ['domain', 'kpi', 'valueDate', 'kpiOrgScope', 'version'], { unique: true })\n@Index('ix_kpi_value_latest_for_query', ['domain', 'kpi', 'valueDate', 'kpiOrgScope'], { unique: false })\n@Index('ix_kpi_value_group_kpi', ['domain', 'group', 'kpi', 'valueDate'], { unique: false })\n@Index('ix_kpi_value_kpi_group', ['domain', 'kpi', 'group', 'valueDate'], { unique: false })\n@ObjectType({ description: 'Entity for KpiValue' })\nexport class KpiValue {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier for this KPI value record.' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field({ nullable: true, description: 'Domain (tenant) to which this KPI value belongs.' })\n domain?: Domain\n\n @RelationId((kpiValue: KpiValue) => kpiValue.domain)\n @Field({ nullable: true, description: 'ID of the domain (tenant) for this KPI value.' })\n domainId?: string\n\n @ManyToOne(() => Kpi)\n @Field(type => Kpi, {\n nullable: true,\n description: 'Reference to the KPI definition for which this value is calculated.'\n })\n kpi: Kpi\n\n @RelationId((kpiValue: KpiValue) => kpiValue.kpi)\n @Field({ description: 'ID of the referenced KPI.' })\n kpiId: string\n\n @Column('int')\n @Field(type => Int, { description: 'Version of the KPI definition at the time this value was calculated.' })\n version: number\n\n @Column()\n @Field({\n description:\n 'Date or period for which this KPI value is recorded (e.g., day: YYYY-MM-DD, month: YYYY-MM, quarter: YYYY-Qn, range: YYYY-MM-DD~YYYY-MM-DD).'\n })\n valueDate: string\n\n @Column('float')\n @Field(type => Float, { description: 'The calculated numeric value for this KPI and period.' })\n value: number\n\n @Column('float', { nullable: true })\n @Field(type => Float, {\n nullable: true,\n description: 'Performance score calculated from KPI value using scoreFormula or grades lookup table. Range: 0-1.'\n })\n score?: number\n\n @Column({ nullable: true })\n @Field(type => String, {\n nullable: true,\n description: 'Group key for this value (organization, line, user, project, etc.)'\n })\n group?: string\n\n @ManyToOne(() => KpiOrgScope, { nullable: true })\n @Field(type => KpiOrgScope, {\n nullable: true,\n description: 'Reference to the organization scope mapping for this KPI value.'\n })\n kpiOrgScope?: KpiOrgScope\n\n @RelationId((kpiValue: KpiValue) => kpiValue.kpiOrgScope)\n @Field({ nullable: true, description: 'ID of the referenced KPI organization scope.' })\n kpiOrgScopeId?: string\n\n @Column({ nullable: true })\n @Field({\n nullable: true,\n description: 'Indicates whether this value was entered manually or generated automatically.'\n })\n inputType?: KpiValueInputType\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Source of the value (e.g., system, user, external integration).' })\n source?: string\n\n @Column({\n nullable: true,\n type:\n DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'\n ? 'longtext'\n : DATABASE_TYPE == 'oracle'\n ? 'clob'\n : DATABASE_TYPE == 'mssql'\n ? 'nvarchar'\n : 'varchar',\n length: DATABASE_TYPE == 'mssql' ? 'MAX' : undefined,\n transformer: json5Transformer\n })\n @Field(type => ScalarObject, {\n nullable: true,\n description:\n 'Extended or non-numeric information related to this KPI value, stored as JSON5. Can include grade, status, comments, or other metadata.'\n })\n meta?: any\n\n @Column({ default: 'DAY' })\n @Field(type => KpiPeriodType, { description: 'Aggregation period type for this KPI value.' })\n periodType: KpiPeriodType\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Timestamp when this KPI value record was created.' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'Timestamp when this KPI value record was last updated.' })\n updatedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'User who created this KPI value record.' })\n creator?: User\n\n @RelationId((kpiValue: KpiValue) => kpiValue.creator)\n @Field({ nullable: true, description: 'ID of the user who created this KPI value record.' })\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'User who last updated this KPI value record.' })\n updater?: User\n\n @RelationId((kpiValue: KpiValue) => kpiValue.updater)\n @Field({ nullable: true, description: 'ID of the user who last updated this KPI value record.' })\n updaterId?: string\n}\n"]}
1
+ {"version":3,"file":"kpi-value.js","sourceRoot":"","sources":["../../../server/service/kpi-value/kpi-value.ts"],"names":[],"mappings":";;;;AAAA,qCASgB;AAChB,+CAAkF;AAElF,yDAAgD;AAChD,iDAA8E;AAC9E,6CAA4C;AAC5C,oCAA+C;AAC/C,kEAA4D;AAE5D,MAAM,SAAS,GAAG,YAAM,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;AAC7C,MAAM,aAAa,GAAG,SAAS,CAAC,IAAI,CAAA;AAEpC,IAAY,iBAGX;AAHD,WAAY,iBAAiB;IAC3B,sCAAiB,CAAA;IACjB,kCAAa,CAAA;AACf,CAAC,EAHW,iBAAiB,iCAAjB,iBAAiB,QAG5B;AAED,IAAA,+BAAgB,EAAC,iBAAiB,EAAE;IAClC,IAAI,EAAE,mBAAmB;IACzB,WAAW,EAAE,oCAAoC;CAClD,CAAC,CAAA;AAQK,IAAM,QAAQ,GAAd,MAAM,QAAQ;CA0HpB,CAAA;AA1HY,4BAAQ;AAGV;IAFR,IAAA,gCAAsB,EAAC,MAAM,CAAC;IAC9B,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAE,EAAE,EAAE,WAAW,EAAE,8CAA8C,EAAE,CAAC;;oCAChE;AAInB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,CAAC;IACzB,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,kDAAkD,EAAE,CAAC;sCAClF,cAAM;wCAAA;AAIf;IAFC,IAAA,oBAAU,EAAC,CAAC,QAAkB,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;IACnD,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,+CAA+C,EAAE,CAAC;;0CACvE;AAOjB;IALC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,SAAG,CAAC;IACpB,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,SAAG,EAAE;QAClB,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,qEAAqE;KACnF,CAAC;sCACG,SAAG;qCAAA;AAIR;IAFC,IAAA,oBAAU,EAAC,CAAC,QAAkB,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC;IAChD,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC;;uCACvC;AAIb;IAFC,IAAA,gBAAM,EAAC,KAAK,CAAC;IACb,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,WAAW,EAAE,sEAAsE,EAAE,CAAC;;yCAC7F;AAOf;IALC,IAAA,gBAAM,GAAE;IACR,IAAA,oBAAK,EAAC;QACL,WAAW,EACT,8IAA8I;KACjJ,CAAC;;2CACe;AAIjB;IAFC,IAAA,gBAAM,EAAC,OAAO,CAAC;IACf,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAK,EAAE,EAAE,WAAW,EAAE,uDAAuD,EAAE,CAAC;;uCAClF;AAOb;IALC,IAAA,gBAAM,EAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACnC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAK,EAAE;QACpB,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,wFAAwF;KACtG,CAAC;;uCACY;AAOd;IALC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE;QACrB,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,oEAAoE;KAClF,CAAC;;uCACY;AAOd;IALC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,2BAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAChD,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,2BAAW,EAAE;QAC1B,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,iEAAiE;KAC/E,CAAC;sCACY,2BAAW;6CAAA;AAIzB;IAFC,IAAA,oBAAU,EAAC,CAAC,QAAkB,EAAE,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;IACxD,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,8CAA8C,EAAE,CAAC;;+CACjE;AAOtB;IALC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC;QACL,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,+EAA+E;KAC7F,CAAC;;2CAC2B;AAI7B;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,iEAAiE,EAAE,CAAC;;wCAC3F;AAoBf;IAlBC,IAAA,gBAAM,EAAC;QACN,QAAQ,EAAE,IAAI;QACd,IAAI,EACF,aAAa,IAAI,OAAO,IAAI,aAAa,IAAI,SAAS;YACpD,CAAC,CAAC,UAAU;YACZ,CAAC,CAAC,aAAa,IAAI,QAAQ;gBACzB,CAAC,CAAC,MAAM;gBACR,CAAC,CAAC,aAAa,IAAI,OAAO;oBACxB,CAAC,CAAC,UAAU;oBACZ,CAAC,CAAC,SAAS;QACnB,MAAM,EAAE,aAAa,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;QACpD,WAAW,EAAE,wBAAgB;KAC9B,CAAC;IACD,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE;QAC3B,QAAQ,EAAE,IAAI;QACd,WAAW,EACT,yIAAyI;KAC5I,CAAC;;sCACQ;AAIV;IAFC,IAAA,gBAAM,EAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,mBAAa,EAAE,EAAE,WAAW,EAAE,6CAA6C,EAAE,CAAC;;4CACpE;AAIzB;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,mDAAmD,EAAE,CAAC;sCAChF,IAAI;2CAAA;AAIhB;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,wDAAwD,EAAE,CAAC;sCACrF,IAAI;2CAAA;AAIhB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC3C,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,yCAAyC,EAAE,CAAC;sCACtF,gBAAI;yCAAA;AAId;IAFC,IAAA,oBAAU,EAAC,CAAC,QAAkB,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC;IACpD,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,mDAAmD,EAAE,CAAC;;2CAC1E;AAIlB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC3C,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,8CAA8C,EAAE,CAAC;sCAC3F,gBAAI;yCAAA;AAId;IAFC,IAAA,oBAAU,EAAC,CAAC,QAAkB,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC;IACpD,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,wDAAwD,EAAE,CAAC;;2CAC/E;mBAzHP,QAAQ;IANpB,IAAA,gBAAM,GAAE;IACR,IAAA,eAAK,EAAC,qBAAqB,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACxG,IAAA,eAAK,EAAC,+BAA+B,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACxG,IAAA,eAAK,EAAC,wBAAwB,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC3F,IAAA,eAAK,EAAC,wBAAwB,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC3F,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,qBAAqB,EAAE,CAAC;GACtC,QAAQ,CA0HpB","sourcesContent":["import {\n CreateDateColumn,\n UpdateDateColumn,\n Entity,\n Index,\n Column,\n RelationId,\n ManyToOne,\n PrimaryGeneratedColumn\n} from 'typeorm'\nimport { ObjectType, Field, Int, ID, registerEnumType, Float } from 'type-graphql'\n\nimport { User } from '@things-factory/auth-base'\nimport { Domain, ScalarObject, json5Transformer } from '@things-factory/shell'\nimport { config } from '@things-factory/env'\nimport { Kpi, KpiPeriodType } from '../kpi/kpi'\nimport { KpiOrgScope } from '../kpi-org-scope/kpi-org-scope'\n\nconst ORMCONFIG = config.get('ormconfig', {})\nconst DATABASE_TYPE = ORMCONFIG.type\n\nexport enum KpiValueInputType {\n MANUAL = 'MANUAL',\n AUTO = 'AUTO'\n}\n\nregisterEnumType(KpiValueInputType, {\n name: 'KpiValueInputType',\n description: 'Type of the input (Manual or Auto)'\n})\n\n@Entity()\n@Index('ix_kpi_value_latest', ['domain', 'kpi', 'valueDate', 'kpiOrgScope', 'version'], { unique: true })\n@Index('ix_kpi_value_latest_for_query', ['domain', 'kpi', 'valueDate', 'kpiOrgScope'], { unique: false })\n@Index('ix_kpi_value_group_kpi', ['domain', 'group', 'kpi', 'valueDate'], { unique: false })\n@Index('ix_kpi_value_kpi_group', ['domain', 'kpi', 'group', 'valueDate'], { unique: false })\n@ObjectType({ description: 'Entity for KpiValue' })\nexport class KpiValue {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier for this KPI value record.' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field({ nullable: true, description: 'Domain (tenant) to which this KPI value belongs.' })\n domain?: Domain\n\n @RelationId((kpiValue: KpiValue) => kpiValue.domain)\n @Field({ nullable: true, description: 'ID of the domain (tenant) for this KPI value.' })\n domainId?: string\n\n @ManyToOne(() => Kpi)\n @Field(type => Kpi, {\n nullable: true,\n description: 'Reference to the KPI definition for which this value is calculated.'\n })\n kpi: Kpi\n\n @RelationId((kpiValue: KpiValue) => kpiValue.kpi)\n @Field({ description: 'ID of the referenced KPI.' })\n kpiId: string\n\n @Column('int')\n @Field(type => Int, { description: 'Version of the KPI definition at the time this value was calculated.' })\n version: number\n\n @Column()\n @Field({\n description:\n 'Date or period for which this KPI value is recorded (e.g., day: YYYY-MM-DD, month: YYYY-MM, quarter: YYYY-Qn, range: YYYY-MM-DD~YYYY-MM-DD).'\n })\n valueDate: string\n\n @Column('float')\n @Field(type => Float, { description: 'The calculated numeric value for this KPI and period.' })\n value: number\n\n @Column('float', { nullable: true })\n @Field(type => Float, {\n nullable: true,\n description: 'Performance score calculated from KPI value using scoreFormula or grades lookup table.'\n })\n score?: number\n\n @Column({ nullable: true })\n @Field(type => String, {\n nullable: true,\n description: 'Group key for this value (organization, line, user, project, etc.)'\n })\n group?: string\n\n @ManyToOne(() => KpiOrgScope, { nullable: true })\n @Field(type => KpiOrgScope, {\n nullable: true,\n description: 'Reference to the organization scope mapping for this KPI value.'\n })\n kpiOrgScope?: KpiOrgScope\n\n @RelationId((kpiValue: KpiValue) => kpiValue.kpiOrgScope)\n @Field({ nullable: true, description: 'ID of the referenced KPI organization scope.' })\n kpiOrgScopeId?: string\n\n @Column({ nullable: true })\n @Field({\n nullable: true,\n description: 'Indicates whether this value was entered manually or generated automatically.'\n })\n inputType?: KpiValueInputType\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Source of the value (e.g., system, user, external integration).' })\n source?: string\n\n @Column({\n nullable: true,\n type:\n DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'\n ? 'longtext'\n : DATABASE_TYPE == 'oracle'\n ? 'clob'\n : DATABASE_TYPE == 'mssql'\n ? 'nvarchar'\n : 'varchar',\n length: DATABASE_TYPE == 'mssql' ? 'MAX' : undefined,\n transformer: json5Transformer\n })\n @Field(type => ScalarObject, {\n nullable: true,\n description:\n 'Extended or non-numeric information related to this KPI value, stored as JSON5. Can include grade, status, comments, or other metadata.'\n })\n meta?: any\n\n @Column({ default: 'DAY' })\n @Field(type => KpiPeriodType, { description: 'Aggregation period type for this KPI value.' })\n periodType: KpiPeriodType\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Timestamp when this KPI value record was created.' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'Timestamp when this KPI value record was last updated.' })\n updatedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'User who created this KPI value record.' })\n creator?: User\n\n @RelationId((kpiValue: KpiValue) => kpiValue.creator)\n @Field({ nullable: true, description: 'ID of the user who created this KPI value record.' })\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'User who last updated this KPI value record.' })\n updater?: User\n\n @RelationId((kpiValue: KpiValue) => kpiValue.updater)\n @Field({ nullable: true, description: 'ID of the user who last updated this KPI value record.' })\n updaterId?: string\n}\n"]}