@dssp/dkpi 1.0.26 → 1.0.29

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 (56) hide show
  1. package/dist-client/pages/kpi-dashboard/cards/kpi-level1-card.d.ts +2 -0
  2. package/dist-client/pages/kpi-dashboard/cards/kpi-level1-card.js +19 -4
  3. package/dist-client/pages/kpi-dashboard/cards/kpi-level1-card.js.map +1 -1
  4. package/dist-client/pages/kpi-dashboard/cards/kpi-level2-comparison.d.ts +2 -0
  5. package/dist-client/pages/kpi-dashboard/cards/kpi-level2-comparison.js +19 -4
  6. package/dist-client/pages/kpi-dashboard/cards/kpi-level2-comparison.js.map +1 -1
  7. package/dist-client/pages/kpi-dashboard/cards/kpi-level3-comparison.d.ts +2 -0
  8. package/dist-client/pages/kpi-dashboard/cards/kpi-level3-comparison.js +19 -4
  9. package/dist-client/pages/kpi-dashboard/cards/kpi-level3-comparison.js.map +1 -1
  10. package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.d.ts +2 -0
  11. package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.js +78 -4
  12. package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.js.map +1 -1
  13. package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.d.ts +2 -0
  14. package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.js +35 -4
  15. package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.js.map +1 -1
  16. package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.d.ts +2 -0
  17. package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js +29 -1
  18. package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js.map +1 -1
  19. package/dist-client/pages/kpi-dashboard/kpi-dashboard.d.ts +11 -0
  20. package/dist-client/pages/kpi-dashboard/kpi-dashboard.js +65 -12
  21. package/dist-client/pages/kpi-dashboard/kpi-dashboard.js.map +1 -1
  22. package/dist-client/pages/project-complete-tabs/pc-tab1-plan.d.ts +18 -0
  23. package/dist-client/pages/project-complete-tabs/pc-tab1-plan.js +138 -64
  24. package/dist-client/pages/project-complete-tabs/pc-tab1-plan.js.map +1 -1
  25. package/dist-client/pages/project-complete-tabs/pc-tab3-upload.js +80 -8
  26. package/dist-client/pages/project-complete-tabs/pc-tab3-upload.js.map +1 -1
  27. package/dist-client/pages/sv-project-detail.d.ts +33 -0
  28. package/dist-client/pages/sv-project-detail.js +130 -8
  29. package/dist-client/pages/sv-project-detail.js.map +1 -1
  30. package/dist-client/pages/sv-project-update.js +98 -31
  31. package/dist-client/pages/sv-project-update.js.map +1 -1
  32. package/dist-client/shared/complete-api.d.ts +7 -0
  33. package/dist-client/shared/complete-api.js +27 -0
  34. package/dist-client/shared/complete-api.js.map +1 -1
  35. package/dist-client/shared/project-axis.d.ts +23 -0
  36. package/dist-client/shared/project-axis.js +42 -0
  37. package/dist-client/shared/project-axis.js.map +1 -0
  38. package/dist-client/shared/sentiment-index.d.ts +47 -0
  39. package/dist-client/shared/sentiment-index.js +119 -0
  40. package/dist-client/shared/sentiment-index.js.map +1 -0
  41. package/dist-client/tsconfig.tsbuildinfo +1 -1
  42. package/dist-server/index.js +14 -0
  43. package/dist-server/index.js.map +1 -1
  44. package/dist-server/scripts/load-grade-data-migration.js +17 -3
  45. package/dist-server/scripts/load-grade-data-migration.js.map +1 -1
  46. package/dist-server/scripts/propagate-parent-kpi-values.js +13 -2
  47. package/dist-server/scripts/propagate-parent-kpi-values.js.map +1 -1
  48. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.d.ts +22 -0
  49. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js +93 -1
  50. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js.map +1 -1
  51. package/dist-server/service/kpi-stat/kpi-stat-query.d.ts +9 -9
  52. package/dist-server/service/kpi-stat/kpi-stat-query.js +71 -84
  53. package/dist-server/service/kpi-stat/kpi-stat-query.js.map +1 -1
  54. package/dist-server/tsconfig.tsbuildinfo +1 -1
  55. package/package.json +3 -3
  56. package/schema.graphql +2011 -67
@@ -1,6 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
+ const auth_base_1 = require("@things-factory/auth-base");
5
+ /*
6
+ * kpi 카테고리가 쓰는 어휘.
7
+ *
8
+ * 전송 용어(query/mutation)가 아니라 이 모듈의 게이트 이름이다 — 입력·평가·확정처럼
9
+ * 실제로 역할이 나뉘는 지점을 그대로 쓴다. 기본 어휘는 @dssp/project 가 선언하고,
10
+ * declareAxes 는 additive 라 두 선언이 합쳐진다.
11
+ *
12
+ * readOnly 에 read 를 넣는 이유: 이 집의 읽기 axis 는 query 가 아니라 read 다.
13
+ * 말해 주지 않으면 역할 화면에서 VIEWER 템플릿이 조용히 빠진다.
14
+ *
15
+ * 최상위에서 부를 것 — bootstrap 훅은 schema() 보다 뒤라서 늦다.
16
+ */
17
+ (0, auth_base_1.declareAxes)(['read', 'input', 'assessment', 'sentiment', 'finalize', 'recalculate', 'auto-collect', 'basic-info'], { readOnly: ['read'] });
4
18
  tslib_1.__exportStar(require("./migrations/index.js"), exports);
5
19
  tslib_1.__exportStar(require("./service/index.js"), exports);
6
20
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../server/index.ts"],"names":[],"mappings":";;;AAAA,gEAAqC;AACrC,6DAAkC","sourcesContent":["export * from './migrations/index.js'\nexport * from './service/index.js'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../server/index.ts"],"names":[],"mappings":";;;AAAA,yDAAuD;AAEvD;;;;;;;;;;;GAWG;AACH,IAAA,uBAAW,EACT,CAAC,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,CAAC,EACrG,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,CACvB,CAAA;AAED,gEAAqC;AACrC,6DAAkC","sourcesContent":["import { declareAxes } from '@things-factory/auth-base'\n\n/*\n * kpi 카테고리가 쓰는 어휘.\n *\n * 전송 용어(query/mutation)가 아니라 이 모듈의 게이트 이름이다 — 입력·평가·확정처럼\n * 실제로 역할이 나뉘는 지점을 그대로 쓴다. 기본 어휘는 @dssp/project 가 선언하고,\n * declareAxes 는 additive 라 두 선언이 합쳐진다.\n *\n * readOnly 에 read 를 넣는 이유: 이 집의 읽기 axis 는 query 가 아니라 read 다.\n * 말해 주지 않으면 역할 화면에서 VIEWER 템플릿이 조용히 빠진다.\n *\n * 최상위에서 부를 것 — bootstrap 훅은 schema() 보다 뒤라서 늦다.\n */\ndeclareAxes(\n ['read', 'input', 'assessment', 'sentiment', 'finalize', 'recalculate', 'auto-collect', 'basic-info'],\n { readOnly: ['read'] }\n)\n\nexport * from './migrations/index.js'\nexport * from './service/index.js'\n"]}
@@ -8,8 +8,22 @@ const tslib_1 = require("tslib");
8
8
  const typeorm_1 = require("typeorm");
9
9
  const fs = tslib_1.__importStar(require("fs"));
10
10
  const path = tslib_1.__importStar(require("path"));
11
- /** X31/X32 비활성화 대상 KPI 이름 */
12
- const DEACTIVATE_KPI_NAMES = ['X31. 품질시험 불합격률', 'X32. 검수자재 불합격률'];
11
+ /**
12
+ * 계산에서 빼는 KPI.
13
+ *
14
+ * 지우지 않고 비활성화한다. 재계산은 active !== false 인 KPI 만 보므로(kpi-metric-value-
15
+ * mutation.ts) 계산과 화면에서는 빠지고, 쌓인 값과 grade table 은 남는다.
16
+ *
17
+ * X34/X43 은 2026-08-07 회의에서 정성 평가(X35/X44)로 흡수·통합하기로 한 항목이다.
18
+ * 이 둘의 grade table 은 지우면 안 된다 — 체감지수 지수값을 5단계로 환산하는 구간 정의가
19
+ * 거기에만 있고, 감리의견서 화면의 범례가 그것을 읽는다.
20
+ */
21
+ const DEACTIVATE_KPI_NAMES = [
22
+ 'X31. 품질시험 불합격률',
23
+ 'X32. 검수자재 불합격률',
24
+ 'X34. 품질 SL-PA 결과값',
25
+ 'X43. 안전 SL-PA 결과값'
26
+ ];
13
27
  function isGrade2DLookup(grades) {
14
28
  return grades && typeof grades === 'object' && !Array.isArray(grades) && (grades.type === 'PROGRESS_DEVIATION_LOOKUP' || grades.type === 'PROGRESS_DEVIATION_LOOKUP');
15
29
  }
@@ -157,7 +171,7 @@ async function deactivateDeletedKpis() {
157
171
  const ormconfig = require('@things-factory/shell/dist-server/initializers/ormconfig.js');
158
172
  const connectionConfig = config.get('ormconfig');
159
173
  let connection;
160
- console.log('🚫 Deactivating deleted KPIs (X31, X32)...');
174
+ console.log(`🚫 Deactivating KPIs: ${DEACTIVATE_KPI_NAMES.join(', ')}`);
161
175
  try {
162
176
  console.log('🔌 Connecting to database...');
163
177
  connection = await (0, typeorm_1.createConnection)(Object.assign(Object.assign(Object.assign({}, ormconfig), connectionConfig), { logging: false }));
@@ -1 +1 @@
1
- {"version":3,"file":"load-grade-data-migration.js","sourceRoot":"","sources":["../../server/scripts/load-grade-data-migration.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env ts-node\n\nimport { createConnection } from 'typeorm'\nimport * as fs from 'fs'\nimport * as path from 'path'\n\ninterface GradeEntry {\n name: string\n minValue: number\n maxValue: number\n score?: number\n color?: string\n description?: string\n}\n\ninterface Grade2DLookup {\n type: 'PROGRESS_DEVIATION_LOOKUP' | 'PROGRESS_DEVIATION_LOOKUP'\n description?: string\n rows: Array<{\n progressRate: number\n boundary5to4: number\n boundary4to3: number\n boundary3to2: number\n boundary2to1: number\n }>\n}\n\ninterface GradeData {\n kpiName: string\n version: number\n description: string\n grades: GradeEntry[] | Grade2DLookup\n}\n\n/** X31/X32 비활성화 대상 KPI 이름 */\nconst DEACTIVATE_KPI_NAMES = ['X31. 품질시험 불합격률', 'X32. 검수자재 불합격률']\n\nfunction isGrade2DLookup(grades: any): grades is Grade2DLookup {\n return grades && typeof grades === 'object' && !Array.isArray(grades) && (grades.type === 'PROGRESS_DEVIATION_LOOKUP' || grades.type === 'PROGRESS_DEVIATION_LOOKUP')\n}\n\nfunction normalize2DGrades(grades: Grade2DLookup): Grade2DLookup {\n return { ...grades, type: 'PROGRESS_DEVIATION_LOOKUP' }\n}\n\nfunction getGradeCount(grades: GradeEntry[] | Grade2DLookup): number {\n if (isGrade2DLookup(grades)) {\n return grades.rows.length\n }\n return Array.isArray(grades) ? grades.length : 0\n}\n\n/**\n * Load KPI grade data from JSON files - Migration Style\n * This can be called directly from migrations or other server-side scripts\n */\nexport async function loadKpiGradeData(specificFile?: string): Promise<void> {\n const gradeDataPath = path.join(__dirname, 'grade-data')\n \n // Set NODE_ENV if not set\n if (!process.env.NODE_ENV) {\n process.env.NODE_ENV = 'development'\n }\n\n // Initialize Things-Factory environment\n const { config } = require('@things-factory/env')\n const ormconfig = require('@things-factory/shell/dist-server/initializers/ormconfig.js')\n const connectionConfig = config.get('ormconfig')\n\n let connection\n\n console.log('🚀 Loading KPI Grade Data...')\n console.log(`📁 Source directory: ${gradeDataPath}`)\n\n try {\n // Create database connection using Things-Factory pattern\n console.log('🔌 Connecting to database...')\n connection = await createConnection({\n ...ormconfig,\n ...connectionConfig,\n logging: false\n })\n\n // Register the connection with Things-Factory shell\n const { addDataSource } = require('@things-factory/shell')\n addDataSource('default', connection)\n\n console.log('✅ Database connected')\n\n // Check if grade-data directory exists\n if (!fs.existsSync(gradeDataPath)) {\n console.error(`❌ Grade data directory not found: ${gradeDataPath}`)\n throw new Error('Grade data directory not found')\n }\n\n // Get files to process\n let files: string[]\n if (specificFile) {\n if (!fs.existsSync(path.join(gradeDataPath, specificFile))) {\n throw new Error(`File not found: ${specificFile}`)\n }\n files = [specificFile]\n console.log(`📄 Processing single file: ${specificFile}`)\n } else {\n files = fs.readdirSync(gradeDataPath).filter(file => file.endsWith('.json'))\n console.log(`📁 Found ${files.length} grade data files`)\n }\n\n if (files.length === 0) {\n console.log('⚠️ No JSON files found to process')\n return\n }\n\n let successCount = 0\n let errorCount = 0\n\n // Now we can use getRepository with the registered connection\n const { getRepository } = require('@things-factory/shell')\n const { Kpi } = require('@things-factory/kpi')\n const kpiRepository = getRepository(Kpi)\n\n for (const file of files) {\n try {\n console.log(`\\n📄 Processing: ${file}`)\n \n const filePath = path.join(gradeDataPath, file)\n const fileContent = fs.readFileSync(filePath, 'utf8')\n const gradeData: GradeData = JSON.parse(fileContent)\n\n // Validate grade data structure (1D array or 2D lookup object)\n if (!gradeData.kpiName || !gradeData.grades) {\n console.log(` ❌ Invalid structure - missing kpiName or grades`)\n errorCount++\n continue\n }\n\n const is2D = isGrade2DLookup(gradeData.grades)\n if (!is2D && !Array.isArray(gradeData.grades)) {\n console.log(` ❌ Invalid grades format - expected array or 2d-lookup object`)\n errorCount++\n continue\n }\n\n const gradeCount = getGradeCount(gradeData.grades)\n console.log(` 🔍 KPI Name: ${gradeData.kpiName}`)\n console.log(` 📊 Grades: ${gradeCount} entries${is2D ? ' (2D lookup)' : ''}`)\n\n // Find KPI by name in SYSTEM domain\n const kpi = await kpiRepository.findOne({\n where: { name: gradeData.kpiName, domain: { name: 'SYSTEM' } },\n relations: ['domain']\n })\n\n if (kpi) {\n // Update grades data (normalize 2D type string to 'PROGRESS_DEVIATION_LOOKUP')\n const originalGradesCount = kpi.grades ? getGradeCount(kpi.grades) : 0\n if (is2D) {\n kpi.grades = normalize2DGrades(gradeData.grades as Grade2DLookup) as any\n kpi.scoreType = 'CUSTOM'\n } else {\n kpi.grades = gradeData.grades as any\n kpi.scoreType = 'LOOKUP'\n }\n await kpiRepository.save(kpi)\n\n console.log(` ✅ Updated successfully (scoreType: ${kpi.scoreType})`)\n console.log(` 📈 Grades: ${originalGradesCount} → ${gradeCount}`)\n successCount++\n } else {\n console.log(` ⚠️ KPI not found in SYSTEM domain: ${gradeData.kpiName}`)\n errorCount++\n }\n \n } catch (fileError) {\n console.log(` ❌ File processing error: ${fileError.message}`)\n errorCount++\n }\n }\n\n console.log(`\\n🎉 KPI Grade Data Loading Complete!`)\n console.log(` 📊 Total files: ${files.length}`)\n console.log(` ✅ Successful: ${successCount}`)\n console.log(` ❌ Errors: ${errorCount}`)\n\n if (errorCount > 0) {\n console.log(`\\n⚠️ Some files had errors. Check the logs above for details.`)\n }\n\n } catch (error) {\n console.error(`❌ Fatal error during grade data loading:`, error)\n throw error\n } finally {\n if (connection) {\n await connection.close()\n console.log('🔌 Database connection closed')\n }\n }\n}\n\n/**\n * X31/X32 KPI를 비활성화 (active = false, grades = null)\n */\nexport async function deactivateDeletedKpis(): Promise<void> {\n if (!process.env.NODE_ENV) {\n process.env.NODE_ENV = 'development'\n }\n\n const { config } = require('@things-factory/env')\n const ormconfig = require('@things-factory/shell/dist-server/initializers/ormconfig.js')\n const connectionConfig = config.get('ormconfig')\n\n let connection\n\n console.log('🚫 Deactivating deleted KPIs (X31, X32)...')\n\n try {\n console.log('🔌 Connecting to database...')\n connection = await createConnection({\n ...ormconfig,\n ...connectionConfig,\n logging: false\n })\n\n const { addDataSource } = require('@things-factory/shell')\n addDataSource('default', connection)\n\n const { getRepository } = require('@things-factory/shell')\n const { Kpi } = require('@things-factory/kpi')\n const kpiRepository = getRepository(Kpi)\n\n for (const kpiName of DEACTIVATE_KPI_NAMES) {\n const kpi = await kpiRepository.findOne({\n where: { name: kpiName, domain: { name: 'SYSTEM' } },\n relations: ['domain']\n })\n\n if (kpi) {\n kpi.active = false\n kpi.grades = null\n await kpiRepository.save(kpi)\n console.log(` ✅ Deactivated: ${kpiName}`)\n } else {\n console.log(` ⚠️ KPI not found: ${kpiName}`)\n }\n }\n\n console.log('\\n🎉 Deactivation complete!')\n } catch (error) {\n console.error('❌ Error deactivating KPIs:', error)\n throw error\n } finally {\n if (connection) {\n await connection.close()\n console.log('🔌 Database connection closed')\n }\n }\n}\n\n/**\n * List available grade data files\n */\nexport function listGradeDataFiles(): string[] {\n const gradeDataPath = path.join(__dirname, 'grade-data')\n \n try {\n if (!fs.existsSync(gradeDataPath)) {\n console.log('📁 Grade data directory not found')\n return []\n }\n \n const files = fs.readdirSync(gradeDataPath).filter(file => file.endsWith('.json'))\n \n console.log(`📁 Available grade data files in ${gradeDataPath}:\\n`)\n files.forEach((file, index) => {\n console.log(` ${(index + 1).toString().padStart(2)}: ${file}`)\n })\n console.log(`\\n📈 Total: ${files.length} files`)\n \n return files\n } catch (error) {\n console.error('❌ Error reading grade data directory:', error)\n return []\n }\n}\n\n/**\n * CLI execution when called directly\n */\nasync function main() {\n const args = process.argv.slice(2)\n\n try {\n if (args.includes('--help') || args.includes('-h')) {\n console.log(`\n🎯 KPI Grade Data Loader (Migration Style)\n\nUsage:\n ts-node server/scripts/load-grade-data-migration.ts [options] [fileName]\n\nOptions:\n --list, -l List available grade data files\n --deactivate Deactivate X31/X32 KPIs (set active=false, grades=null)\n --help, -h Show this help\n\nExamples:\n ts-node server/scripts/load-grade-data-migration.ts # Load all files\n ts-node server/scripts/load-grade-data-migration.ts x11-performance-table.json # Load specific file\n ts-node server/scripts/load-grade-data-migration.ts --list # List files\n ts-node server/scripts/load-grade-data-migration.ts --deactivate # Deactivate X31/X32\n\nNote: This script connects to the database using the current Things-Factory configuration.\n Make sure the application is properly configured before running.\n Supports both 1D array grades and 2D lookup grades (X13).\n `)\n return\n }\n\n if (args.includes('--list') || args.includes('-l')) {\n listGradeDataFiles()\n return\n }\n\n if (args.includes('--deactivate')) {\n await deactivateDeletedKpis()\n console.log('\\n✨ Done!')\n return\n }\n\n const specificFile = args.find(arg => !arg.startsWith('--'))\n \n if (specificFile) {\n console.log(`🎯 Loading specific file: ${specificFile}`)\n await loadKpiGradeData(specificFile)\n } else {\n console.log(`🎯 Loading all grade data files`)\n await loadKpiGradeData()\n }\n\n console.log('\\n✨ Done!')\n \n } catch (error) {\n console.error('\\n❌ Script failed:', error.message)\n process.exit(1)\n }\n}\n\n// Run if called directly\nif (require.main === module) {\n main()\n}"]}
1
+ {"version":3,"file":"load-grade-data-migration.js","sourceRoot":"","sources":["../../server/scripts/load-grade-data-migration.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env ts-node\n\nimport { createConnection } from 'typeorm'\nimport * as fs from 'fs'\nimport * as path from 'path'\n\ninterface GradeEntry {\n name: string\n minValue: number\n maxValue: number\n score?: number\n color?: string\n description?: string\n}\n\ninterface Grade2DLookup {\n type: 'PROGRESS_DEVIATION_LOOKUP' | 'PROGRESS_DEVIATION_LOOKUP'\n description?: string\n rows: Array<{\n progressRate: number\n boundary5to4: number\n boundary4to3: number\n boundary3to2: number\n boundary2to1: number\n }>\n}\n\ninterface GradeData {\n kpiName: string\n version: number\n description: string\n grades: GradeEntry[] | Grade2DLookup\n}\n\n/**\n * 계산에서 빼는 KPI.\n *\n * 지우지 않고 비활성화한다. 재계산은 active !== false 인 KPI 만 보므로(kpi-metric-value-\n * mutation.ts) 계산과 화면에서는 빠지고, 쌓인 값과 grade table 은 남는다.\n *\n * X34/X43 은 2026-08-07 회의에서 정성 평가(X35/X44)로 흡수·통합하기로 한 항목이다.\n * 이 둘의 grade table 은 지우면 안 된다 — 체감지수 지수값을 5단계로 환산하는 구간 정의가\n * 거기에만 있고, 감리의견서 화면의 범례가 그것을 읽는다.\n */\nconst DEACTIVATE_KPI_NAMES = [\n 'X31. 품질시험 불합격률',\n 'X32. 검수자재 불합격률',\n 'X34. 품질 SL-PA 결과값',\n 'X43. 안전 SL-PA 결과값'\n]\n\nfunction isGrade2DLookup(grades: any): grades is Grade2DLookup {\n return grades && typeof grades === 'object' && !Array.isArray(grades) && (grades.type === 'PROGRESS_DEVIATION_LOOKUP' || grades.type === 'PROGRESS_DEVIATION_LOOKUP')\n}\n\nfunction normalize2DGrades(grades: Grade2DLookup): Grade2DLookup {\n return { ...grades, type: 'PROGRESS_DEVIATION_LOOKUP' }\n}\n\nfunction getGradeCount(grades: GradeEntry[] | Grade2DLookup): number {\n if (isGrade2DLookup(grades)) {\n return grades.rows.length\n }\n return Array.isArray(grades) ? grades.length : 0\n}\n\n/**\n * Load KPI grade data from JSON files - Migration Style\n * This can be called directly from migrations or other server-side scripts\n */\nexport async function loadKpiGradeData(specificFile?: string): Promise<void> {\n const gradeDataPath = path.join(__dirname, 'grade-data')\n \n // Set NODE_ENV if not set\n if (!process.env.NODE_ENV) {\n process.env.NODE_ENV = 'development'\n }\n\n // Initialize Things-Factory environment\n const { config } = require('@things-factory/env')\n const ormconfig = require('@things-factory/shell/dist-server/initializers/ormconfig.js')\n const connectionConfig = config.get('ormconfig')\n\n let connection\n\n console.log('🚀 Loading KPI Grade Data...')\n console.log(`📁 Source directory: ${gradeDataPath}`)\n\n try {\n // Create database connection using Things-Factory pattern\n console.log('🔌 Connecting to database...')\n connection = await createConnection({\n ...ormconfig,\n ...connectionConfig,\n logging: false\n })\n\n // Register the connection with Things-Factory shell\n const { addDataSource } = require('@things-factory/shell')\n addDataSource('default', connection)\n\n console.log('✅ Database connected')\n\n // Check if grade-data directory exists\n if (!fs.existsSync(gradeDataPath)) {\n console.error(`❌ Grade data directory not found: ${gradeDataPath}`)\n throw new Error('Grade data directory not found')\n }\n\n // Get files to process\n let files: string[]\n if (specificFile) {\n if (!fs.existsSync(path.join(gradeDataPath, specificFile))) {\n throw new Error(`File not found: ${specificFile}`)\n }\n files = [specificFile]\n console.log(`📄 Processing single file: ${specificFile}`)\n } else {\n files = fs.readdirSync(gradeDataPath).filter(file => file.endsWith('.json'))\n console.log(`📁 Found ${files.length} grade data files`)\n }\n\n if (files.length === 0) {\n console.log('⚠️ No JSON files found to process')\n return\n }\n\n let successCount = 0\n let errorCount = 0\n\n // Now we can use getRepository with the registered connection\n const { getRepository } = require('@things-factory/shell')\n const { Kpi } = require('@things-factory/kpi')\n const kpiRepository = getRepository(Kpi)\n\n for (const file of files) {\n try {\n console.log(`\\n📄 Processing: ${file}`)\n \n const filePath = path.join(gradeDataPath, file)\n const fileContent = fs.readFileSync(filePath, 'utf8')\n const gradeData: GradeData = JSON.parse(fileContent)\n\n // Validate grade data structure (1D array or 2D lookup object)\n if (!gradeData.kpiName || !gradeData.grades) {\n console.log(` ❌ Invalid structure - missing kpiName or grades`)\n errorCount++\n continue\n }\n\n const is2D = isGrade2DLookup(gradeData.grades)\n if (!is2D && !Array.isArray(gradeData.grades)) {\n console.log(` ❌ Invalid grades format - expected array or 2d-lookup object`)\n errorCount++\n continue\n }\n\n const gradeCount = getGradeCount(gradeData.grades)\n console.log(` 🔍 KPI Name: ${gradeData.kpiName}`)\n console.log(` 📊 Grades: ${gradeCount} entries${is2D ? ' (2D lookup)' : ''}`)\n\n // Find KPI by name in SYSTEM domain\n const kpi = await kpiRepository.findOne({\n where: { name: gradeData.kpiName, domain: { name: 'SYSTEM' } },\n relations: ['domain']\n })\n\n if (kpi) {\n // Update grades data (normalize 2D type string to 'PROGRESS_DEVIATION_LOOKUP')\n const originalGradesCount = kpi.grades ? getGradeCount(kpi.grades) : 0\n if (is2D) {\n kpi.grades = normalize2DGrades(gradeData.grades as Grade2DLookup) as any\n kpi.scoreType = 'CUSTOM'\n } else {\n kpi.grades = gradeData.grades as any\n kpi.scoreType = 'LOOKUP'\n }\n await kpiRepository.save(kpi)\n\n console.log(` ✅ Updated successfully (scoreType: ${kpi.scoreType})`)\n console.log(` 📈 Grades: ${originalGradesCount} → ${gradeCount}`)\n successCount++\n } else {\n console.log(` ⚠️ KPI not found in SYSTEM domain: ${gradeData.kpiName}`)\n errorCount++\n }\n \n } catch (fileError) {\n console.log(` ❌ File processing error: ${fileError.message}`)\n errorCount++\n }\n }\n\n console.log(`\\n🎉 KPI Grade Data Loading Complete!`)\n console.log(` 📊 Total files: ${files.length}`)\n console.log(` ✅ Successful: ${successCount}`)\n console.log(` ❌ Errors: ${errorCount}`)\n\n if (errorCount > 0) {\n console.log(`\\n⚠️ Some files had errors. Check the logs above for details.`)\n }\n\n } catch (error) {\n console.error(`❌ Fatal error during grade data loading:`, error)\n throw error\n } finally {\n if (connection) {\n await connection.close()\n console.log('🔌 Database connection closed')\n }\n }\n}\n\n/**\n * X31/X32 KPI를 비활성화 (active = false, grades = null)\n */\nexport async function deactivateDeletedKpis(): Promise<void> {\n if (!process.env.NODE_ENV) {\n process.env.NODE_ENV = 'development'\n }\n\n const { config } = require('@things-factory/env')\n const ormconfig = require('@things-factory/shell/dist-server/initializers/ormconfig.js')\n const connectionConfig = config.get('ormconfig')\n\n let connection\n\n console.log(`🚫 Deactivating KPIs: ${DEACTIVATE_KPI_NAMES.join(', ')}`)\n\n try {\n console.log('🔌 Connecting to database...')\n connection = await createConnection({\n ...ormconfig,\n ...connectionConfig,\n logging: false\n })\n\n const { addDataSource } = require('@things-factory/shell')\n addDataSource('default', connection)\n\n const { getRepository } = require('@things-factory/shell')\n const { Kpi } = require('@things-factory/kpi')\n const kpiRepository = getRepository(Kpi)\n\n for (const kpiName of DEACTIVATE_KPI_NAMES) {\n const kpi = await kpiRepository.findOne({\n where: { name: kpiName, domain: { name: 'SYSTEM' } },\n relations: ['domain']\n })\n\n if (kpi) {\n kpi.active = false\n kpi.grades = null\n await kpiRepository.save(kpi)\n console.log(` ✅ Deactivated: ${kpiName}`)\n } else {\n console.log(` ⚠️ KPI not found: ${kpiName}`)\n }\n }\n\n console.log('\\n🎉 Deactivation complete!')\n } catch (error) {\n console.error('❌ Error deactivating KPIs:', error)\n throw error\n } finally {\n if (connection) {\n await connection.close()\n console.log('🔌 Database connection closed')\n }\n }\n}\n\n/**\n * List available grade data files\n */\nexport function listGradeDataFiles(): string[] {\n const gradeDataPath = path.join(__dirname, 'grade-data')\n \n try {\n if (!fs.existsSync(gradeDataPath)) {\n console.log('📁 Grade data directory not found')\n return []\n }\n \n const files = fs.readdirSync(gradeDataPath).filter(file => file.endsWith('.json'))\n \n console.log(`📁 Available grade data files in ${gradeDataPath}:\\n`)\n files.forEach((file, index) => {\n console.log(` ${(index + 1).toString().padStart(2)}: ${file}`)\n })\n console.log(`\\n📈 Total: ${files.length} files`)\n \n return files\n } catch (error) {\n console.error('❌ Error reading grade data directory:', error)\n return []\n }\n}\n\n/**\n * CLI execution when called directly\n */\nasync function main() {\n const args = process.argv.slice(2)\n\n try {\n if (args.includes('--help') || args.includes('-h')) {\n console.log(`\n🎯 KPI Grade Data Loader (Migration Style)\n\nUsage:\n ts-node server/scripts/load-grade-data-migration.ts [options] [fileName]\n\nOptions:\n --list, -l List available grade data files\n --deactivate Deactivate X31/X32 KPIs (set active=false, grades=null)\n --help, -h Show this help\n\nExamples:\n ts-node server/scripts/load-grade-data-migration.ts # Load all files\n ts-node server/scripts/load-grade-data-migration.ts x11-performance-table.json # Load specific file\n ts-node server/scripts/load-grade-data-migration.ts --list # List files\n ts-node server/scripts/load-grade-data-migration.ts --deactivate # Deactivate X31/X32\n\nNote: This script connects to the database using the current Things-Factory configuration.\n Make sure the application is properly configured before running.\n Supports both 1D array grades and 2D lookup grades (X13).\n `)\n return\n }\n\n if (args.includes('--list') || args.includes('-l')) {\n listGradeDataFiles()\n return\n }\n\n if (args.includes('--deactivate')) {\n await deactivateDeletedKpis()\n console.log('\\n✨ Done!')\n return\n }\n\n const specificFile = args.find(arg => !arg.startsWith('--'))\n \n if (specificFile) {\n console.log(`🎯 Loading specific file: ${specificFile}`)\n await loadKpiGradeData(specificFile)\n } else {\n console.log(`🎯 Loading all grade data files`)\n await loadKpiGradeData()\n }\n\n console.log('\\n✨ Done!')\n \n } catch (error) {\n console.error('\\n❌ Script failed:', error.message)\n process.exit(1)\n }\n}\n\n// Run if called directly\nif (require.main === module) {\n main()\n}"]}
@@ -91,7 +91,17 @@ async function processSingleOrg(connection, orgScope, specificKpiName, forceReca
91
91
  if (specificKpiName) {
92
92
  kpisQuery = kpisQuery.andWhere('kpi.name = :name', { name: specificKpiName });
93
93
  }
94
- const allKpis = await kpisQuery.getMany();
94
+ /*
95
+ * 비활성 KPI 는 재계산 대상이 아니다.
96
+ *
97
+ * 흡수·통합되어 내려간 지표(X34/X43)까지 leaf 재계산에 넣으면, 그 value 를 제 grade
98
+ * table 로 다시 채점한다. 증강 데이터의 X34 value 는 지수값이 아니라 이미 1~5 점수라서
99
+ * 체감지수 구간표(0.6/1.0/1.15/1.25)에 넣으면 3.0 이 최상위 구간에 떨어져 5 점이 된다.
100
+ * 계산에 쓰이지 않는 값이라 화면은 멀쩡하지만, DB 에는 틀린 점수가 남는다.
101
+ *
102
+ * kpi-metric-value-mutation.ts 의 재계산도 같은 기준으로 거른다.
103
+ */
104
+ const allKpis = (await kpisQuery.getMany()).filter((kpi) => kpi.active !== false);
95
105
  const parentKpis = allKpis.filter((kpi) => !kpi.isLeaf);
96
106
  const leafKpis = allKpis.filter((kpi) => kpi.isLeaf);
97
107
  console.log(` 📊 KPIs: ${allKpis.length} total (${leafKpis.length} leaf, ${parentKpis.length} parent)`);
@@ -237,7 +247,8 @@ async function propagateParentKpiValues(specificKpiName, forceRecalculate = fals
237
247
  else {
238
248
  console.log('🎯 Processing all KPIs in hierarchy');
239
249
  }
240
- const allKpis = await kpisQuery.getMany();
250
+ /* 비활성 KPI 제외 — 이유는 propagateParentKpiValuesForOrg 쪽 주석 참고. */
251
+ const allKpis = (await kpisQuery.getMany()).filter((kpi) => kpi.active !== false);
241
252
  if (allKpis.length === 0) {
242
253
  console.log('⚠️ No KPIs found');
243
254
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"propagate-parent-kpi-values.js","sourceRoot":"","sources":["../../server/scripts/propagate-parent-kpi-values.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env ts-node\n\nimport { createConnection } from 'typeorm'\nimport * as fs from 'fs'\nimport * as path from 'path'\n\ninterface KpiRecord {\n id: string\n name: string\n isLeaf: boolean\n weight: number\n version?: number\n formula?: string\n scoreFormula?: string\n grades?: any[]\n parent?: {\n id: string\n name: string\n }\n children?: KpiRecord[]\n __level?: number // Added for hierarchy level tracking\n}\n\ninterface KpiValueRecord {\n id: string\n value: number\n score: number\n kpi: {\n id: string\n name: string\n }\n valueDate?: Date\n org?: any\n}\n\n/**\n * Batch process multiple organizations with single initialization (optimized for performance)\n */\nexport async function propagateParentKpiValuesBatch(\n orgScopes: string[],\n specificKpiName?: string,\n forceRecalculate = false,\n targetDate?: string,\n version?: number\n): Promise<void> {\n // Set NODE_ENV if not set\n if (!process.env.NODE_ENV) {\n process.env.NODE_ENV = 'development'\n }\n\n // Initialize Things-Factory environment (ONCE)\n const { config } = require('@things-factory/env')\n const ormconfig = require('@things-factory/shell/dist-server/initializers/ormconfig.js')\n const connectionConfig = config.get('ormconfig')\n\n let connection\n\n console.log('🚀 Starting Batch Parent KPI Value Propagation...')\n console.log(`📦 Processing ${orgScopes.length} organizations`)\n\n try {\n // Create database connection using Things-Factory pattern (ONCE)\n console.log('🔌 Connecting to database...')\n connection = await createConnection({\n ...ormconfig,\n ...connectionConfig,\n logging: false\n })\n\n // Register the connection with Things-Factory shell\n const { addDataSource } = require('@things-factory/shell')\n addDataSource('default', connection)\n\n console.log('✅ Database connected')\n\n let totalProcessed = 0\n let totalCreated = 0\n let totalErrors = 0\n const startTime = Date.now()\n\n // Process each organization\n for (let i = 0; i < orgScopes.length; i++) {\n const orgScope = orgScopes[i].trim()\n console.log(`\\n[${i + 1}/${orgScopes.length}] 🏢 Processing org: ${orgScope}`)\n\n try {\n // Call the core processing logic for single org\n const result = await processSingleOrg(\n connection,\n orgScope,\n specificKpiName,\n forceRecalculate,\n targetDate,\n version\n )\n\n totalProcessed += result.processed\n totalCreated += result.created\n console.log(` ✅ Success: ${result.created} parent KPIs created`)\n } catch (error) {\n totalErrors++\n console.log(` ❌ Failed: ${error.message}`)\n }\n }\n\n const endTime = Date.now()\n const duration = ((endTime - startTime) / 1000).toFixed(2)\n\n console.log(`\\n🎉 Batch Propagation Complete!`)\n console.log(` 📊 Organizations processed: ${orgScopes.length}`)\n console.log(` ✨ Parent KPIs created: ${totalCreated}`)\n console.log(` ❌ Errors: ${totalErrors}`)\n console.log(` ⏱️ Duration: ${duration}s (${(parseFloat(duration) / orgScopes.length).toFixed(2)}s per org)`)\n } catch (error) {\n console.error(`❌ Fatal error during batch propagation:`, error)\n throw error\n } finally {\n if (connection) {\n await connection.close()\n console.log('🔌 Database connection closed')\n }\n }\n}\n\n/**\n * Process single organization (used by batch processor)\n */\nasync function processSingleOrg(\n connection: any,\n orgScope: string,\n specificKpiName?: string,\n forceRecalculate = false,\n targetDate?: string,\n version?: number\n): Promise<{ processed: number; created: number }> {\n const { getRepository } = require('@things-factory/shell')\n const { Kpi, KpiValue } = require('@things-factory/kpi')\n const { Domain } = require('@things-factory/shell')\n\n const kpiRepository = getRepository(Kpi)\n const kpiValueRepository = getRepository(KpiValue)\n const domainRepository = getRepository(Domain)\n\n const systemDomain = await domainRepository.findOne({ where: { name: 'SYSTEM' } })\n if (!systemDomain) {\n throw new Error('SYSTEM domain not found')\n }\n\n // Get all KPIs with their hierarchy\n let kpisQuery = kpiRepository\n .createQueryBuilder('kpi')\n .leftJoinAndSelect('kpi.domain', 'domain')\n .leftJoinAndSelect('kpi.parent', 'parent')\n .leftJoinAndSelect('kpi.children', 'children')\n .where('kpi.domain_id = :domainId', { domainId: systemDomain.id })\n\n if (specificKpiName) {\n kpisQuery = kpisQuery.andWhere('kpi.name = :name', { name: specificKpiName })\n }\n\n const allKpis = await kpisQuery.getMany()\n const parentKpis = allKpis.filter((kpi: any) => !kpi.isLeaf)\n const leafKpis = allKpis.filter((kpi: any) => kpi.isLeaf)\n\n console.log(` 📊 KPIs: ${allKpis.length} total (${leafKpis.length} leaf, ${parentKpis.length} parent)`)\n\n // 1. Recalculate leaf KPI scores\n await recalculateLeafKpiScores(kpiRepository, kpiValueRepository, leafKpis, orgScope, targetDate)\n\n // 2. Delete existing parent KPI values\n if (parentKpis.length > 0) {\n const parentKpiIds = parentKpis.map((kpi: any) => kpi.id)\n let deleteQuery = kpiValueRepository\n .createQueryBuilder('kpiValue')\n .delete()\n .where('kpi_id IN (:...kpiIds)', { kpiIds: parentKpiIds })\n .andWhere('domain_id = (SELECT id FROM domains WHERE name = :domainName)', { domainName: 'SYSTEM' })\n .andWhere('\"group\" = :orgScope', { orgScope })\n\n if (targetDate) {\n deleteQuery = deleteQuery.andWhere('value_date = :targetDate', { targetDate })\n }\n\n await deleteQuery.execute()\n }\n\n // 3. Sort parent KPIs and get combinations\n const sortedParentKpis = await sortKpisByLevel(parentKpis, allKpis)\n\n let groupDateCombinations: { group: string; valueDate: string }[] = []\n if (targetDate) {\n groupDateCombinations = [{ group: orgScope, valueDate: targetDate }]\n } else {\n const dates = await kpiValueRepository.query(\n `SELECT DISTINCT \"value_date\" FROM kpi_values WHERE \"group\" = $1 AND \"group\" IS NOT NULL ORDER BY \"value_date\"`,\n [orgScope]\n )\n groupDateCombinations = dates.map((row: any) => ({ group: orgScope, valueDate: row.value_date }))\n }\n\n console.log(` 📅 Date combinations: ${groupDateCombinations.length}`)\n\n let totalCreated = 0\n\n // 4. Process each parent KPI\n for (const { group: currentGroup, valueDate } of groupDateCombinations) {\n console.log(` 📆 Processing date: ${valueDate}`)\n for (const parentKpi of sortedParentKpis) {\n const childKpis = allKpis.filter((kpi: any) => kpi.parent?.id === parentKpi.id)\n if (childKpis.length === 0) continue\n\n const childValues = await getChildKpiValues(kpiValueRepository, childKpis, valueDate, version, currentGroup)\n if (childValues.length === 0) continue\n\n let calculatedValue: number\n let calculatedScore: number\n\n if (parentKpi.formula) {\n try {\n const result = await calculateParentKpiWithFormula(parentKpi, childValues, childKpis)\n calculatedValue = result.value\n calculatedScore = result.score\n } catch (formulaError) {\n const { weightedValue, weightedScore } = calculateWeightedAverage(childValues, childKpis)\n calculatedValue = weightedValue\n calculatedScore = weightedScore\n }\n } else {\n const { weightedValue, weightedScore } = calculateWeightedAverage(childValues, childKpis)\n calculatedValue = weightedValue\n calculatedScore = weightedScore\n }\n\n const newKpiValue: any = {\n kpi: parentKpi,\n value: calculatedValue,\n score: calculatedScore,\n valueDate: valueDate,\n version: parentKpi.version || 1,\n group: currentGroup,\n kpiScope: currentGroup,\n domain: systemDomain,\n inputType: 'AUTO',\n createdAt: new Date(),\n updatedAt: new Date()\n }\n\n await kpiValueRepository.save(newKpiValue)\n totalCreated++\n }\n }\n\n return { processed: sortedParentKpis.length, created: totalCreated }\n}\n\n/**\n * Propagate parent KPI values based on child KPI scores and weights\n * Processes hierarchy from leaf to root, calculating weighted averages\n */\nexport async function propagateParentKpiValues(\n specificKpiName?: string,\n forceRecalculate = false,\n targetDate?: string,\n orgScope?: string,\n version?: number\n): Promise<void> {\n // Set NODE_ENV if not set\n if (!process.env.NODE_ENV) {\n process.env.NODE_ENV = 'development'\n }\n\n // Initialize Things-Factory environment\n const { config } = require('@things-factory/env')\n const ormconfig = require('@things-factory/shell/dist-server/initializers/ormconfig.js')\n const connectionConfig = config.get('ormconfig')\n\n let connection\n\n console.log('🚀 Starting Parent KPI Value Propagation...')\n\n try {\n // Create database connection using Things-Factory pattern\n console.log('🔌 Connecting to database...')\n connection = await createConnection({\n ...ormconfig,\n ...connectionConfig,\n logging: false\n })\n\n // Register the connection with Things-Factory shell\n const { addDataSource } = require('@things-factory/shell')\n addDataSource('default', connection)\n\n console.log('✅ Database connected')\n\n // Now we can use getRepository with the registered connection\n const { getRepository } = require('@things-factory/shell')\n const { Kpi } = require('@things-factory/kpi')\n const kpiRepository = getRepository(Kpi)\n\n // Get KPI-Value repository\n let kpiValueRepository\n try {\n const { KpiValue } = require('@things-factory/kpi')\n kpiValueRepository = getRepository(KpiValue)\n } catch (error) {\n console.error('❌ KpiValue entity not found. Please ensure it exists in @things-factory/kpi')\n return\n }\n\n // Get Domain repository and find SYSTEM domain\n let systemDomain\n try {\n const { Domain } = require('@things-factory/shell')\n const domainRepository = getRepository(Domain)\n systemDomain = await domainRepository.findOne({ where: { name: 'SYSTEM' } })\n if (!systemDomain) {\n console.error('❌ SYSTEM domain not found')\n return\n }\n } catch (error) {\n console.error('❌ Domain entity not found:', error.message)\n return\n }\n\n // Get all KPIs with their hierarchy\n let kpisQuery = kpiRepository\n .createQueryBuilder('kpi')\n .leftJoinAndSelect('kpi.domain', 'domain')\n .leftJoinAndSelect('kpi.parent', 'parent')\n .leftJoinAndSelect('kpi.children', 'children')\n .where('domain.name = :domainName', { domainName: 'SYSTEM' })\n\n if (specificKpiName) {\n kpisQuery = kpisQuery.andWhere('kpi.name = :name', { name: specificKpiName })\n console.log(`🎯 Processing specific KPI: ${specificKpiName}`)\n } else {\n console.log('🎯 Processing all KPIs in hierarchy')\n }\n\n const allKpis = await kpisQuery.getMany()\n\n if (allKpis.length === 0) {\n console.log('⚠️ No KPIs found')\n return\n }\n\n console.log(`📊 Found ${allKpis.length} KPIs total`)\n\n // Get parent KPIs (non-leaf KPIs) ordered by level (deepest first)\n const parentKpis = allKpis.filter(kpi => !kpi.isLeaf)\n\n if (parentKpis.length === 0) {\n console.log('⚠️ No parent KPIs found')\n return\n }\n\n // Sort parent KPIs by hierarchy level (deepest first for bottom-up processing)\n const sortedParentKpis = await sortKpisByLevel(parentKpis, allKpis)\n\n console.log(`🔄 Processing ${sortedParentKpis.length} parent KPIs`)\n\n // 1. First, recalculate leaf KPI scores using latest KPI versions and grades\n const leafKpis = allKpis.filter(kpi => kpi.isLeaf)\n console.log(`\\n📊 Step 1: Recalculating ${leafKpis.length} leaf KPI scores with latest KPI grades...`)\n await recalculateLeafKpiScores(kpiRepository, kpiValueRepository, leafKpis, orgScope, targetDate)\n\n // 2. Delete existing parent KPI values (not leaf values - they are base data)\n console.log('\\n🗑️ Step 2: Deleting existing parent KPI values...')\n const parentKpiIds = parentKpis.map((kpi: any) => kpi.id)\n let deleteQuery = kpiValueRepository\n .createQueryBuilder('kpiValue')\n .delete()\n .where('kpi_id IN (:...kpiIds)', { kpiIds: parentKpiIds })\n .andWhere('domain_id = (SELECT id FROM domains WHERE name = :domainName)', { domainName: 'SYSTEM' })\n\n if (orgScope) {\n deleteQuery = deleteQuery.andWhere('\"group\" = :orgScope', { orgScope })\n }\n\n if (targetDate) {\n deleteQuery = deleteQuery.andWhere('value_date = :targetDate', { targetDate })\n }\n\n const deleteResult = await deleteQuery.execute()\n console.log(`✅ Deleted ${deleteResult.affected || 0} existing parent KPI values`)\n\n let totalProcessed = 0\n let totalCreated = 0\n let errorCount = 0\n\n // 3. Get all distinct (group, valueDate) combinations from existing KPI values\n console.log('\\n📍 Step 3: Creating parent KPI values from recalculated leaf scores...')\n let groupDateCombinations: { group: string; valueDate: string }[] = []\n if (orgScope && targetDate) {\n groupDateCombinations = [{ group: orgScope, valueDate: targetDate }]\n } else if (orgScope) {\n // Get all dates for specific group\n const dates = await kpiValueRepository.query(\n `\n SELECT DISTINCT \"value_date\"\n FROM kpi_values\n WHERE \"group\" = $1 AND \"group\" IS NOT NULL\n ORDER BY \"value_date\"\n `,\n [orgScope]\n )\n groupDateCombinations = dates.map((row: any) => ({ group: orgScope, valueDate: row.value_date }))\n } else {\n // Get all distinct (group, valueDate) combinations\n const combinations = await kpiValueRepository.query(`\n SELECT DISTINCT \"group\", \"value_date\"\n FROM kpi_values\n WHERE \"group\" IS NOT NULL AND \"group\" != ''\n ORDER BY \"group\", \"value_date\"\n `)\n groupDateCombinations = combinations.map((row: any) => ({ group: row.group, valueDate: row.value_date }))\n }\n\n console.log(` Found ${groupDateCombinations.length} distinct (group, date) combinations`)\n\n // Process each (group, date) combination\n for (const { group: currentGroup, valueDate } of groupDateCombinations) {\n console.log(`\\\\n🏢 Processing Group: ${currentGroup}, Date: ${valueDate}`)\n\n // Process each parent KPI from deepest to shallowest for this group and date\n for (const parentKpi of sortedParentKpis) {\n try {\n console.log(\n `\\\\n📄 Processing Parent KPI: ${parentKpi.name} (Level ${parentKpi.__level || '?'}) - Group: ${currentGroup}, Date: ${valueDate}`\n )\n\n // Get child KPIs\n const childKpis = allKpis.filter(kpi => kpi.parent?.id === parentKpi.id)\n\n if (childKpis.length === 0) {\n console.log(` ⚠️ No child KPIs found, skipping`)\n continue\n }\n\n console.log(` 👶 Found ${childKpis.length} child KPIs`)\n\n // Get child KPI values/scores for the specific group and date\n const childValues = await getChildKpiValues(kpiValueRepository, childKpis, valueDate, version, currentGroup)\n\n if (childValues.length === 0) {\n console.log(` ⚠️ No child KPI values found for date ${valueDate} and group ${currentGroup}, skipping`)\n continue\n }\n\n console.log(` 📊 Found values for ${childValues.length}/${childKpis.length} child KPIs`)\n\n // Calculate parent KPI value and score\n let calculatedValue: number\n let calculatedScore: number\n\n // 1. If parent KPI has formula, use it to calculate\n if (parentKpi.formula) {\n try {\n console.log(` 📐 Using formula: ${parentKpi.formula}`)\n const result = await calculateParentKpiWithFormula(parentKpi, childValues, childKpis)\n calculatedValue = result.value\n calculatedScore = result.score\n console.log(` 🧮 Formula result: value=${calculatedValue.toFixed(4)}, score=${calculatedScore.toFixed(4)}`)\n } catch (formulaError) {\n console.log(` ⚠️ Formula evaluation failed: ${formulaError.message}, falling back to weighted average`)\n const { weightedValue, weightedScore } = calculateWeightedAverage(childValues, childKpis)\n calculatedValue = weightedValue\n calculatedScore = weightedScore\n }\n } else {\n // 2. If no formula, use weighted average\n console.log(` ⚖️ Using weighted average`)\n const { weightedValue, weightedScore } = calculateWeightedAverage(childValues, childKpis)\n calculatedValue = weightedValue\n calculatedScore = weightedScore\n console.log(` 🧮 Weighted average: value=${calculatedValue.toFixed(4)}, score=${calculatedScore.toFixed(4)}`)\n }\n\n // Create new parent KPI value (old values already deleted)\n // Use latest KPI version (parentKpi.version) not the old value's version\n const newKpiValue: any = {\n kpi: parentKpi,\n value: calculatedValue,\n score: calculatedScore,\n valueDate: valueDate,\n version: parentKpi.version || 1, // Use latest KPI version\n group: currentGroup,\n kpiScope: currentGroup, // Set kpiScope same as group\n domain: systemDomain, // Set domain entity\n inputType: 'AUTO', // Set inputType to AUTO\n createdAt: new Date(),\n updatedAt: new Date()\n }\n\n try {\n const savedValue = await kpiValueRepository.save(newKpiValue)\n totalCreated++\n console.log(\n ` ✨ Created: value=${calculatedValue.toFixed(4)}, score=${calculatedScore.toFixed(4)}, version=${\n parentKpi.version || 1\n }, id=${savedValue.id}`\n )\n } catch (saveError) {\n console.log(` ❌ Save failed: ${saveError.message}`)\n errorCount++\n }\n\n totalProcessed++\n } catch (kpiError) {\n console.log(` ❌ Error processing KPI ${parentKpi.name}: ${kpiError.message}`)\n errorCount++\n }\n }\n }\n\n console.log(`\\\\n🎉 Parent KPI Value Propagation Complete!`)\n console.log(` 📊 Parent KPIs processed: ${totalProcessed}`)\n console.log(` ✨ Values created: ${totalCreated}`)\n console.log(` ❌ Errors: ${errorCount}`)\n\n if (errorCount > 0) {\n console.log(`\\\\n⚠️ Some parent KPIs had errors. Check the logs above for details.`)\n }\n } catch (error) {\n console.error(`❌ Fatal error during parent KPI value propagation:`, error)\n throw error\n } finally {\n if (connection) {\n await connection.close()\n console.log('🔌 Database connection closed')\n }\n }\n}\n\n/**\n * Sort KPIs by hierarchy level (deepest first for bottom-up processing)\n */\nasync function sortKpisByLevel(parentKpis: KpiRecord[], allKpis: KpiRecord[]): Promise<KpiRecord[]> {\n // Calculate hierarchy level for each KPI\n const kpiLevels = new Map<string, number>()\n\n function calculateLevel(kpi: KpiRecord): number {\n if (kpiLevels.has(kpi.id)) {\n return kpiLevels.get(kpi.id)!\n }\n\n if (!kpi.parent) {\n kpiLevels.set(kpi.id, 0)\n return 0\n }\n\n const parentKpi = allKpis.find(k => k.id === kpi.parent?.id)\n if (!parentKpi) {\n kpiLevels.set(kpi.id, 1)\n return 1\n }\n\n const level = calculateLevel(parentKpi) + 1\n kpiLevels.set(kpi.id, level)\n return level\n }\n\n // Calculate levels for all parent KPIs\n parentKpis.forEach(kpi => {\n const level = calculateLevel(kpi)\n ;(kpi as any).__level = level\n })\n\n // Sort by level (deepest first)\n return parentKpis.sort((a, b) => ((b as any).__level || 0) - ((a as any).__level || 0))\n}\n\n/**\n * Get child KPI values for a specific date\n * Note: Version filter is NOT applied - uses latest available child KPI values regardless of version\n * This matches the recalculateProjectKpiValues logic in kpi-metric-value-mutation.ts\n */\nasync function getChildKpiValues(\n kpiValueRepository: any,\n childKpis: KpiRecord[],\n valueDate: string,\n version?: number,\n orgScope?: string\n): Promise<KpiValueRecord[]> {\n const childKpiIds = childKpis.map((kpi: any) => kpi.id)\n\n let valuesQuery = kpiValueRepository\n .createQueryBuilder('kpiValue')\n .leftJoinAndSelect('kpiValue.kpi', 'kpi')\n .where('kpi.id IN (:...kpiIds)', { kpiIds: childKpiIds })\n .andWhere('kpiValue.valueDate = :valueDate', { valueDate })\n .andWhere('kpiValue.score IS NOT NULL')\n\n // Version filter is intentionally removed to use latest available child KPI values\n // This ensures we calculate parent KPIs based on the most recent child data\n\n // Filter by group scope\n if (orgScope) {\n valuesQuery = valuesQuery.andWhere('kpiValue.group = :groupScope', { groupScope: orgScope })\n }\n\n const values = await valuesQuery.getMany()\n\n return values\n}\n\n/**\n * Recalculate leaf KPI scores using latest KPI grades lookup table\n */\nasync function recalculateLeafKpiScores(\n kpiRepository: any,\n kpiValueRepository: any,\n leafKpis: KpiRecord[],\n orgScope?: string,\n targetDate?: string\n): Promise<void> {\n let totalRecalculated = 0\n let errorCount = 0\n\n for (const leafKpi of leafKpis) {\n try {\n // Get latest version of this KPI with grades\n const latestKpi = await kpiRepository.findOne({\n where: { id: leafKpi.id },\n order: { version: 'DESC' }\n })\n\n if (!latestKpi) {\n console.log(` ⚠️ Latest KPI not found for ${leafKpi.name}`)\n continue\n }\n\n // Get all leaf KPI values that need score recalculation\n let valuesQuery = kpiValueRepository\n .createQueryBuilder('kpiValue')\n .where('kpiValue.kpi_id = :kpiId', { kpiId: leafKpi.id })\n .andWhere('kpiValue.value IS NOT NULL')\n\n if (orgScope) {\n valuesQuery = valuesQuery.andWhere('kpiValue.group = :orgScope', { orgScope })\n }\n\n if (targetDate) {\n valuesQuery = valuesQuery.andWhere('kpiValue.value_date = :targetDate', { targetDate })\n }\n\n const kpiValues = await valuesQuery.getMany()\n\n if (kpiValues.length === 0) {\n continue\n }\n\n // 2D lookup 여부 확인\n const is2D = latestKpi.grades && !Array.isArray(latestKpi.grades) && latestKpi.grades.type === 'PROGRESS_DEVIATION_LOOKUP'\n const progressRateCache = new Map<string, number>()\n let projectRepo: any = null\n if (is2D) {\n try {\n const { Project } = require('@dssp/project')\n const { getRepository: getRepo } = require('@things-factory/shell')\n projectRepo = getRepo(Project)\n } catch {\n console.log(` ⚠️ @dssp/project not found — using default progressRate for ${leafKpi.name}`)\n }\n }\n\n // Recalculate score for each value using latest KPI grades\n for (const kpiValue of kpiValues) {\n const oldScore = kpiValue.score\n\n let progressRate: number | undefined\n if (is2D && kpiValue.group) {\n if (progressRateCache.has(kpiValue.group)) {\n progressRate = progressRateCache.get(kpiValue.group)\n } else if (projectRepo) {\n const project = await projectRepo.findOne({ where: { id: kpiValue.group } })\n progressRate = project?.totalProgress ?? 50\n progressRateCache.set(kpiValue.group, progressRate)\n }\n }\n\n const newScore = calculateScoreFromGrades(latestKpi, kpiValue.value, progressRate)\n\n if (newScore !== null && newScore !== oldScore) {\n kpiValue.score = newScore\n kpiValue.version = latestKpi.version || 1\n await kpiValueRepository.save(kpiValue)\n totalRecalculated++\n console.log(\n ` ✅ ${leafKpi.name}: score ${oldScore?.toFixed(4) || 'null'} → ${newScore.toFixed(4)} (version ${\n latestKpi.version || 1\n })`\n )\n }\n }\n } catch (error) {\n console.log(` ❌ Error recalculating scores for ${leafKpi.name}: ${error.message}`)\n errorCount++\n }\n }\n\n console.log(`\\n 📊 Leaf scores recalculated: ${totalRecalculated}, Errors: ${errorCount}`)\n}\n\n/**\n * Calculate score from KPI grades lookup table\n * 1D (기존 배열) 및 2D (X13 공정률×편차) lookup 모두 지원\n */\nfunction calculateScoreFromGrades(kpi: any, value: number, progressRate?: number): number | null {\n if (!kpi.grades) {\n return null\n }\n\n // 2D lookup table 처리 (X13: 공정률 × 편차 → 점수)\n if (!Array.isArray(kpi.grades) && kpi.grades.type === 'PROGRESS_DEVIATION_LOOKUP') {\n return calculate2DScore(value, kpi.grades, progressRate ?? 50)\n }\n\n // 1D lookup (기존)\n if (!Array.isArray(kpi.grades) || kpi.grades.length === 0) {\n return null\n }\n\n const grade = kpi.grades.find((g: any) => value >= g.minValue && value <= g.maxValue)\n if (!grade) {\n return null\n }\n\n return grade.score\n}\n\n/**\n * 2D lookup table에서 점수 계산 (X13: 공정률 × 편차 → 점수 1~5)\n */\nfunction calculate2DScore(deviationValue: number, grades: any, progressRate: number): number | null {\n if (!grades.rows || !Array.isArray(grades.rows)) return null\n\n const progressIndex = Math.min(99, Math.max(0, Math.floor(progressRate)))\n const row = grades.rows.find((r: any) => r.progressRate === progressIndex)\n if (!row) return null\n\n if (deviationValue < row.boundary5to4) return 5\n if (deviationValue < row.boundary4to3) return 4\n if (deviationValue < row.boundary3to2) return 3\n if (deviationValue < row.boundary2to1) return 2\n return 1\n}\n\n/**\n * Calculate parent KPI value using formula\n * This matches the logic in kpi-metric-value-mutation.ts recalculateParentKpiValue\n */\nasync function calculateParentKpiWithFormula(\n parentKpi: KpiRecord,\n childValues: KpiValueRecord[],\n childKpis: KpiRecord[]\n): Promise<{ value: number; score: number }> {\n // Import formula evaluation functions\n const { parseFormula, evaluateFormula, builtinFunctions } = require('@things-factory/kpi')\n\n // Create child KPI name -> score mapping\n const childKpiScoreMap: Record<string, number> = {}\n childValues.forEach(kpiValue => {\n const childKpi = childKpis.find((k: any) => k.id === kpiValue.kpi.id)\n if (childKpi) {\n childKpiScoreMap[childKpi.name] = kpiValue.score ?? 0\n }\n })\n\n // Create provider for formula evaluation\n const provider = {\n get: async (name: string) => {\n const value = childKpiScoreMap[name]\n if (value === undefined) {\n throw new Error(`Child KPI '${name}' not found in parent KPI formula`)\n }\n return value\n }\n }\n\n // Parse and evaluate formula\n const ast = parseFormula(parentKpi.formula)\n const evalContext = { functions: builtinFunctions, provider }\n const result = await evaluateFormula(ast, evalContext)\n\n return {\n value: result,\n score: result\n }\n}\n\n/**\n * Calculate weighted average from child KPI values\n */\nfunction calculateWeightedAverage(\n childValues: KpiValueRecord[],\n childKpis: KpiRecord[]\n): { weightedValue: number; weightedScore: number } {\n let totalWeightedValue = 0\n let totalWeightedScore = 0\n let totalWeight = 0\n\n for (const value of childValues) {\n const childKpi = childKpis.find(kpi => kpi.id === value.kpi.id)\n const weight = childKpi?.weight || 1\n\n totalWeightedValue += value.score * weight\n totalWeightedScore += value.score * weight\n totalWeight += weight\n }\n\n if (totalWeight === 0) {\n return { weightedValue: 0, weightedScore: 0 }\n }\n\n return {\n weightedValue: totalWeightedValue / totalWeight,\n weightedScore: totalWeightedScore / totalWeight\n }\n}\n\n/**\n * List parent KPIs and their hierarchy\n */\nexport async function listParentKpiHierarchy(): Promise<void> {\n // Set NODE_ENV if not set\n if (!process.env.NODE_ENV) {\n process.env.NODE_ENV = 'development'\n }\n\n // Initialize Things-Factory environment\n const { config } = require('@things-factory/env')\n const ormconfig = require('@things-factory/shell/dist-server/initializers/ormconfig.js')\n const connectionConfig = config.get('ormconfig')\n\n let connection\n\n try {\n console.log('🔌 Connecting to database...')\n connection = await createConnection({\n ...ormconfig,\n ...connectionConfig,\n logging: false\n })\n\n const { addDataSource } = require('@things-factory/shell')\n addDataSource('default', connection)\n\n const { getRepository } = require('@things-factory/shell')\n const { Kpi } = require('@things-factory/kpi')\n const kpiRepository = getRepository(Kpi)\n\n // Get all KPIs with hierarchy\n const kpis = await kpiRepository\n .createQueryBuilder('kpi')\n .leftJoinAndSelect('kpi.domain', 'domain')\n .leftJoinAndSelect('kpi.parent', 'parent')\n .leftJoinAndSelect('kpi.children', 'children')\n .where('domain.name = :domainName', { domainName: 'SYSTEM' })\n .getMany()\n\n const parentKpis = kpis.filter(kpi => !kpi.isLeaf)\n const sortedParentKpis = await sortKpisByLevel(parentKpis, kpis)\n\n console.log(`📁 Parent KPI Hierarchy (${sortedParentKpis.length} parents):\\\\n`)\n\n if (sortedParentKpis.length === 0) {\n console.log(' No parent KPIs found.')\n return\n }\n\n sortedParentKpis.forEach((kpi, index) => {\n const level = (kpi as any).__level || 0\n const indent = ' '.repeat(level)\n const childCount = kpis.filter(k => k.parent?.id === kpi.id).length\n const weight = kpi.weight || 1\n\n console.log(\n ` ${(index + 1).toString().padStart(2)}: ${indent}${kpi.name} (L${level}, ${childCount} children, weight: ${weight})`\n )\n })\n\n console.log(`\\\\n📈 Total: ${sortedParentKpis.length} parent KPIs`)\n } catch (error) {\n console.error('❌ Error listing parent KPIs:', error)\n } finally {\n if (connection) {\n await connection.close()\n }\n }\n}\n\n/**\n * CLI execution when called directly\n */\nasync function main() {\n const args = process.argv.slice(2)\n\n try {\n if (args.includes('--help') || args.includes('-h')) {\n console.log(`\n🎯 Parent KPI Value Propagator\n\nUsage:\n ts-node server/scripts/propagate-parent-kpi-values.ts [options] [kpiName]\n\nOptions:\n --list, -l List parent KPIs and their hierarchy\n --force, -f Force recalculate all values (not just missing ones)\n --date YYYY-MM-DD Target date for value calculation (default: today)\n --org orgScope Organization scope filter (default: all orgs)\n --orgs org1,org2 Multiple organization scopes (comma-separated)\n --version N KPI version filter (default: latest version)\n --help, -h Show this help\n\nExamples:\n ts-node server/scripts/propagate-parent-kpi-values.ts # Process all parent KPIs for today\n ts-node server/scripts/propagate-parent-kpi-values.ts --force # Recalculate ALL parent values\n ts-node server/scripts/propagate-parent-kpi-values.ts --date 2024-01-15 # Process for specific date\n ts-node server/scripts/propagate-parent-kpi-values.ts --org \"PROJECT-123\" # Process for specific org\n ts-node server/scripts/propagate-parent-kpi-values.ts --orgs \"ID1,ID2,ID3\" # Process multiple orgs\n ts-node server/scripts/propagate-parent-kpi-values.ts --version 2 # Process for specific version\n ts-node server/scripts/propagate-parent-kpi-values.ts \"상위 KPI명\" # Process specific parent KPI\n ts-node server/scripts/propagate-parent-kpi-values.ts --list # List parent KPI hierarchy\n\nNote: Processes parent KPIs from deepest level to root, calculating weighted averages.\n Child KPI scores and weights are used to calculate parent values.\n --orgs option processes multiple orgs with single initialization (faster).\n `)\n return\n }\n\n if (args.includes('--list') || args.includes('-l')) {\n await listParentKpiHierarchy()\n return\n }\n\n const forceRecalculate = args.includes('--force') || args.includes('-f')\n const dateIndex = args.indexOf('--date')\n const targetDate = dateIndex !== -1 && dateIndex + 1 < args.length ? args[dateIndex + 1] : undefined\n const orgIndex = args.indexOf('--org')\n const orgScope = orgIndex !== -1 && orgIndex + 1 < args.length ? args[orgIndex + 1] : undefined\n const orgsIndex = args.indexOf('--orgs')\n const orgScopesString = orgsIndex !== -1 && orgsIndex + 1 < args.length ? args[orgsIndex + 1] : undefined\n const orgScopes = orgScopesString ? orgScopesString.split(',') : undefined\n const versionIndex = args.indexOf('--version')\n const version = versionIndex !== -1 && versionIndex + 1 < args.length ? parseInt(args[versionIndex + 1]) : undefined\n const specificKpiName = args.find(\n arg =>\n !arg.startsWith('--') &&\n arg !== targetDate &&\n arg !== orgScope &&\n arg !== orgScopesString &&\n (version === undefined || arg !== version.toString())\n )\n\n // Use batch processing if multiple orgs specified\n if (orgScopes && orgScopes.length > 0) {\n console.log(`🎯 Propagating values for all parent KPIs (Batch mode)`)\n console.log(` Mode: ${forceRecalculate ? 'Force recalculate ALL' : 'Only missing values'}`)\n console.log(` Date: ${targetDate || 'today'}`)\n console.log(` Orgs: ${orgScopes.length} organizations`)\n console.log(` Version: ${version || 'latest'}`)\n await propagateParentKpiValuesBatch(orgScopes, specificKpiName, forceRecalculate, targetDate, version)\n } else if (specificKpiName) {\n console.log(`🎯 Propagating values for specific KPI: ${specificKpiName}`)\n console.log(` Mode: ${forceRecalculate ? 'Force recalculate ALL' : 'Only missing values'}`)\n console.log(` Date: ${targetDate || 'today'}`)\n console.log(` Org: ${orgScope || 'all'}`)\n console.log(` Version: ${version || 'latest'}`)\n await propagateParentKpiValues(specificKpiName, forceRecalculate, targetDate, orgScope, version)\n } else {\n console.log(`🎯 Propagating values for all parent KPIs`)\n console.log(` Mode: ${forceRecalculate ? 'Force recalculate ALL' : 'Only missing values'}`)\n console.log(` Date: ${targetDate || 'today'}`)\n console.log(` Org: ${orgScope || 'all'}`)\n console.log(` Version: ${version || 'latest'}`)\n await propagateParentKpiValues(undefined, forceRecalculate, targetDate, orgScope, version)\n }\n\n console.log('\\\\n✨ Done!')\n } catch (error) {\n console.error('\\\\n❌ Script failed:', error.message)\n process.exit(1)\n }\n}\n\n// Handle uncaught errors\nprocess.on('unhandledRejection', (error: any) => {\n console.error('❌ Unhandled error:', error.message || error)\n process.exit(1)\n})\n\n// Run if called directly\nif (require.main === module) {\n main()\n}\n"]}
1
+ {"version":3,"file":"propagate-parent-kpi-values.js","sourceRoot":"","sources":["../../server/scripts/propagate-parent-kpi-values.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env ts-node\n\nimport { createConnection } from 'typeorm'\nimport * as fs from 'fs'\nimport * as path from 'path'\n\ninterface KpiRecord {\n id: string\n name: string\n isLeaf: boolean\n weight: number\n version?: number\n formula?: string\n scoreFormula?: string\n grades?: any[]\n parent?: {\n id: string\n name: string\n }\n children?: KpiRecord[]\n __level?: number // Added for hierarchy level tracking\n}\n\ninterface KpiValueRecord {\n id: string\n value: number\n score: number\n kpi: {\n id: string\n name: string\n }\n valueDate?: Date\n org?: any\n}\n\n/**\n * Batch process multiple organizations with single initialization (optimized for performance)\n */\nexport async function propagateParentKpiValuesBatch(\n orgScopes: string[],\n specificKpiName?: string,\n forceRecalculate = false,\n targetDate?: string,\n version?: number\n): Promise<void> {\n // Set NODE_ENV if not set\n if (!process.env.NODE_ENV) {\n process.env.NODE_ENV = 'development'\n }\n\n // Initialize Things-Factory environment (ONCE)\n const { config } = require('@things-factory/env')\n const ormconfig = require('@things-factory/shell/dist-server/initializers/ormconfig.js')\n const connectionConfig = config.get('ormconfig')\n\n let connection\n\n console.log('🚀 Starting Batch Parent KPI Value Propagation...')\n console.log(`📦 Processing ${orgScopes.length} organizations`)\n\n try {\n // Create database connection using Things-Factory pattern (ONCE)\n console.log('🔌 Connecting to database...')\n connection = await createConnection({\n ...ormconfig,\n ...connectionConfig,\n logging: false\n })\n\n // Register the connection with Things-Factory shell\n const { addDataSource } = require('@things-factory/shell')\n addDataSource('default', connection)\n\n console.log('✅ Database connected')\n\n let totalProcessed = 0\n let totalCreated = 0\n let totalErrors = 0\n const startTime = Date.now()\n\n // Process each organization\n for (let i = 0; i < orgScopes.length; i++) {\n const orgScope = orgScopes[i].trim()\n console.log(`\\n[${i + 1}/${orgScopes.length}] 🏢 Processing org: ${orgScope}`)\n\n try {\n // Call the core processing logic for single org\n const result = await processSingleOrg(\n connection,\n orgScope,\n specificKpiName,\n forceRecalculate,\n targetDate,\n version\n )\n\n totalProcessed += result.processed\n totalCreated += result.created\n console.log(` ✅ Success: ${result.created} parent KPIs created`)\n } catch (error) {\n totalErrors++\n console.log(` ❌ Failed: ${error.message}`)\n }\n }\n\n const endTime = Date.now()\n const duration = ((endTime - startTime) / 1000).toFixed(2)\n\n console.log(`\\n🎉 Batch Propagation Complete!`)\n console.log(` 📊 Organizations processed: ${orgScopes.length}`)\n console.log(` ✨ Parent KPIs created: ${totalCreated}`)\n console.log(` ❌ Errors: ${totalErrors}`)\n console.log(` ⏱️ Duration: ${duration}s (${(parseFloat(duration) / orgScopes.length).toFixed(2)}s per org)`)\n } catch (error) {\n console.error(`❌ Fatal error during batch propagation:`, error)\n throw error\n } finally {\n if (connection) {\n await connection.close()\n console.log('🔌 Database connection closed')\n }\n }\n}\n\n/**\n * Process single organization (used by batch processor)\n */\nasync function processSingleOrg(\n connection: any,\n orgScope: string,\n specificKpiName?: string,\n forceRecalculate = false,\n targetDate?: string,\n version?: number\n): Promise<{ processed: number; created: number }> {\n const { getRepository } = require('@things-factory/shell')\n const { Kpi, KpiValue } = require('@things-factory/kpi')\n const { Domain } = require('@things-factory/shell')\n\n const kpiRepository = getRepository(Kpi)\n const kpiValueRepository = getRepository(KpiValue)\n const domainRepository = getRepository(Domain)\n\n const systemDomain = await domainRepository.findOne({ where: { name: 'SYSTEM' } })\n if (!systemDomain) {\n throw new Error('SYSTEM domain not found')\n }\n\n // Get all KPIs with their hierarchy\n let kpisQuery = kpiRepository\n .createQueryBuilder('kpi')\n .leftJoinAndSelect('kpi.domain', 'domain')\n .leftJoinAndSelect('kpi.parent', 'parent')\n .leftJoinAndSelect('kpi.children', 'children')\n .where('kpi.domain_id = :domainId', { domainId: systemDomain.id })\n\n if (specificKpiName) {\n kpisQuery = kpisQuery.andWhere('kpi.name = :name', { name: specificKpiName })\n }\n\n /*\n * 비활성 KPI 는 재계산 대상이 아니다.\n *\n * 흡수·통합되어 내려간 지표(X34/X43)까지 leaf 재계산에 넣으면, 그 value 를 제 grade\n * table 로 다시 채점한다. 증강 데이터의 X34 value 는 지수값이 아니라 이미 1~5 점수라서\n * 체감지수 구간표(0.6/1.0/1.15/1.25)에 넣으면 3.0 이 최상위 구간에 떨어져 5 점이 된다.\n * 계산에 쓰이지 않는 값이라 화면은 멀쩡하지만, DB 에는 틀린 점수가 남는다.\n *\n * kpi-metric-value-mutation.ts 의 재계산도 같은 기준으로 거른다.\n */\n const allKpis = (await kpisQuery.getMany()).filter((kpi: any) => kpi.active !== false)\n const parentKpis = allKpis.filter((kpi: any) => !kpi.isLeaf)\n const leafKpis = allKpis.filter((kpi: any) => kpi.isLeaf)\n\n console.log(` 📊 KPIs: ${allKpis.length} total (${leafKpis.length} leaf, ${parentKpis.length} parent)`)\n\n // 1. Recalculate leaf KPI scores\n await recalculateLeafKpiScores(kpiRepository, kpiValueRepository, leafKpis, orgScope, targetDate)\n\n // 2. Delete existing parent KPI values\n if (parentKpis.length > 0) {\n const parentKpiIds = parentKpis.map((kpi: any) => kpi.id)\n let deleteQuery = kpiValueRepository\n .createQueryBuilder('kpiValue')\n .delete()\n .where('kpi_id IN (:...kpiIds)', { kpiIds: parentKpiIds })\n .andWhere('domain_id = (SELECT id FROM domains WHERE name = :domainName)', { domainName: 'SYSTEM' })\n .andWhere('\"group\" = :orgScope', { orgScope })\n\n if (targetDate) {\n deleteQuery = deleteQuery.andWhere('value_date = :targetDate', { targetDate })\n }\n\n await deleteQuery.execute()\n }\n\n // 3. Sort parent KPIs and get combinations\n const sortedParentKpis = await sortKpisByLevel(parentKpis, allKpis)\n\n let groupDateCombinations: { group: string; valueDate: string }[] = []\n if (targetDate) {\n groupDateCombinations = [{ group: orgScope, valueDate: targetDate }]\n } else {\n const dates = await kpiValueRepository.query(\n `SELECT DISTINCT \"value_date\" FROM kpi_values WHERE \"group\" = $1 AND \"group\" IS NOT NULL ORDER BY \"value_date\"`,\n [orgScope]\n )\n groupDateCombinations = dates.map((row: any) => ({ group: orgScope, valueDate: row.value_date }))\n }\n\n console.log(` 📅 Date combinations: ${groupDateCombinations.length}`)\n\n let totalCreated = 0\n\n // 4. Process each parent KPI\n for (const { group: currentGroup, valueDate } of groupDateCombinations) {\n console.log(` 📆 Processing date: ${valueDate}`)\n for (const parentKpi of sortedParentKpis) {\n const childKpis = allKpis.filter((kpi: any) => kpi.parent?.id === parentKpi.id)\n if (childKpis.length === 0) continue\n\n const childValues = await getChildKpiValues(kpiValueRepository, childKpis, valueDate, version, currentGroup)\n if (childValues.length === 0) continue\n\n let calculatedValue: number\n let calculatedScore: number\n\n if (parentKpi.formula) {\n try {\n const result = await calculateParentKpiWithFormula(parentKpi, childValues, childKpis)\n calculatedValue = result.value\n calculatedScore = result.score\n } catch (formulaError) {\n const { weightedValue, weightedScore } = calculateWeightedAverage(childValues, childKpis)\n calculatedValue = weightedValue\n calculatedScore = weightedScore\n }\n } else {\n const { weightedValue, weightedScore } = calculateWeightedAverage(childValues, childKpis)\n calculatedValue = weightedValue\n calculatedScore = weightedScore\n }\n\n const newKpiValue: any = {\n kpi: parentKpi,\n value: calculatedValue,\n score: calculatedScore,\n valueDate: valueDate,\n version: parentKpi.version || 1,\n group: currentGroup,\n kpiScope: currentGroup,\n domain: systemDomain,\n inputType: 'AUTO',\n createdAt: new Date(),\n updatedAt: new Date()\n }\n\n await kpiValueRepository.save(newKpiValue)\n totalCreated++\n }\n }\n\n return { processed: sortedParentKpis.length, created: totalCreated }\n}\n\n/**\n * Propagate parent KPI values based on child KPI scores and weights\n * Processes hierarchy from leaf to root, calculating weighted averages\n */\nexport async function propagateParentKpiValues(\n specificKpiName?: string,\n forceRecalculate = false,\n targetDate?: string,\n orgScope?: string,\n version?: number\n): Promise<void> {\n // Set NODE_ENV if not set\n if (!process.env.NODE_ENV) {\n process.env.NODE_ENV = 'development'\n }\n\n // Initialize Things-Factory environment\n const { config } = require('@things-factory/env')\n const ormconfig = require('@things-factory/shell/dist-server/initializers/ormconfig.js')\n const connectionConfig = config.get('ormconfig')\n\n let connection\n\n console.log('🚀 Starting Parent KPI Value Propagation...')\n\n try {\n // Create database connection using Things-Factory pattern\n console.log('🔌 Connecting to database...')\n connection = await createConnection({\n ...ormconfig,\n ...connectionConfig,\n logging: false\n })\n\n // Register the connection with Things-Factory shell\n const { addDataSource } = require('@things-factory/shell')\n addDataSource('default', connection)\n\n console.log('✅ Database connected')\n\n // Now we can use getRepository with the registered connection\n const { getRepository } = require('@things-factory/shell')\n const { Kpi } = require('@things-factory/kpi')\n const kpiRepository = getRepository(Kpi)\n\n // Get KPI-Value repository\n let kpiValueRepository\n try {\n const { KpiValue } = require('@things-factory/kpi')\n kpiValueRepository = getRepository(KpiValue)\n } catch (error) {\n console.error('❌ KpiValue entity not found. Please ensure it exists in @things-factory/kpi')\n return\n }\n\n // Get Domain repository and find SYSTEM domain\n let systemDomain\n try {\n const { Domain } = require('@things-factory/shell')\n const domainRepository = getRepository(Domain)\n systemDomain = await domainRepository.findOne({ where: { name: 'SYSTEM' } })\n if (!systemDomain) {\n console.error('❌ SYSTEM domain not found')\n return\n }\n } catch (error) {\n console.error('❌ Domain entity not found:', error.message)\n return\n }\n\n // Get all KPIs with their hierarchy\n let kpisQuery = kpiRepository\n .createQueryBuilder('kpi')\n .leftJoinAndSelect('kpi.domain', 'domain')\n .leftJoinAndSelect('kpi.parent', 'parent')\n .leftJoinAndSelect('kpi.children', 'children')\n .where('domain.name = :domainName', { domainName: 'SYSTEM' })\n\n if (specificKpiName) {\n kpisQuery = kpisQuery.andWhere('kpi.name = :name', { name: specificKpiName })\n console.log(`🎯 Processing specific KPI: ${specificKpiName}`)\n } else {\n console.log('🎯 Processing all KPIs in hierarchy')\n }\n /* 비활성 KPI 제외 — 이유는 propagateParentKpiValuesForOrg 쪽 주석 참고. */\n const allKpis = (await kpisQuery.getMany()).filter((kpi: any) => kpi.active !== false)\n\n if (allKpis.length === 0) {\n console.log('⚠️ No KPIs found')\n return\n }\n\n console.log(`📊 Found ${allKpis.length} KPIs total`)\n\n // Get parent KPIs (non-leaf KPIs) ordered by level (deepest first)\n const parentKpis = allKpis.filter(kpi => !kpi.isLeaf)\n\n if (parentKpis.length === 0) {\n console.log('⚠️ No parent KPIs found')\n return\n }\n\n // Sort parent KPIs by hierarchy level (deepest first for bottom-up processing)\n const sortedParentKpis = await sortKpisByLevel(parentKpis, allKpis)\n\n console.log(`🔄 Processing ${sortedParentKpis.length} parent KPIs`)\n\n // 1. First, recalculate leaf KPI scores using latest KPI versions and grades\n const leafKpis = allKpis.filter(kpi => kpi.isLeaf)\n console.log(`\\n📊 Step 1: Recalculating ${leafKpis.length} leaf KPI scores with latest KPI grades...`)\n await recalculateLeafKpiScores(kpiRepository, kpiValueRepository, leafKpis, orgScope, targetDate)\n\n // 2. Delete existing parent KPI values (not leaf values - they are base data)\n console.log('\\n🗑️ Step 2: Deleting existing parent KPI values...')\n const parentKpiIds = parentKpis.map((kpi: any) => kpi.id)\n let deleteQuery = kpiValueRepository\n .createQueryBuilder('kpiValue')\n .delete()\n .where('kpi_id IN (:...kpiIds)', { kpiIds: parentKpiIds })\n .andWhere('domain_id = (SELECT id FROM domains WHERE name = :domainName)', { domainName: 'SYSTEM' })\n\n if (orgScope) {\n deleteQuery = deleteQuery.andWhere('\"group\" = :orgScope', { orgScope })\n }\n\n if (targetDate) {\n deleteQuery = deleteQuery.andWhere('value_date = :targetDate', { targetDate })\n }\n\n const deleteResult = await deleteQuery.execute()\n console.log(`✅ Deleted ${deleteResult.affected || 0} existing parent KPI values`)\n\n let totalProcessed = 0\n let totalCreated = 0\n let errorCount = 0\n\n // 3. Get all distinct (group, valueDate) combinations from existing KPI values\n console.log('\\n📍 Step 3: Creating parent KPI values from recalculated leaf scores...')\n let groupDateCombinations: { group: string; valueDate: string }[] = []\n if (orgScope && targetDate) {\n groupDateCombinations = [{ group: orgScope, valueDate: targetDate }]\n } else if (orgScope) {\n // Get all dates for specific group\n const dates = await kpiValueRepository.query(\n `\n SELECT DISTINCT \"value_date\"\n FROM kpi_values\n WHERE \"group\" = $1 AND \"group\" IS NOT NULL\n ORDER BY \"value_date\"\n `,\n [orgScope]\n )\n groupDateCombinations = dates.map((row: any) => ({ group: orgScope, valueDate: row.value_date }))\n } else {\n // Get all distinct (group, valueDate) combinations\n const combinations = await kpiValueRepository.query(`\n SELECT DISTINCT \"group\", \"value_date\"\n FROM kpi_values\n WHERE \"group\" IS NOT NULL AND \"group\" != ''\n ORDER BY \"group\", \"value_date\"\n `)\n groupDateCombinations = combinations.map((row: any) => ({ group: row.group, valueDate: row.value_date }))\n }\n\n console.log(` Found ${groupDateCombinations.length} distinct (group, date) combinations`)\n\n // Process each (group, date) combination\n for (const { group: currentGroup, valueDate } of groupDateCombinations) {\n console.log(`\\\\n🏢 Processing Group: ${currentGroup}, Date: ${valueDate}`)\n\n // Process each parent KPI from deepest to shallowest for this group and date\n for (const parentKpi of sortedParentKpis) {\n try {\n console.log(\n `\\\\n📄 Processing Parent KPI: ${parentKpi.name} (Level ${parentKpi.__level || '?'}) - Group: ${currentGroup}, Date: ${valueDate}`\n )\n\n // Get child KPIs\n const childKpis = allKpis.filter(kpi => kpi.parent?.id === parentKpi.id)\n\n if (childKpis.length === 0) {\n console.log(` ⚠️ No child KPIs found, skipping`)\n continue\n }\n\n console.log(` 👶 Found ${childKpis.length} child KPIs`)\n\n // Get child KPI values/scores for the specific group and date\n const childValues = await getChildKpiValues(kpiValueRepository, childKpis, valueDate, version, currentGroup)\n\n if (childValues.length === 0) {\n console.log(` ⚠️ No child KPI values found for date ${valueDate} and group ${currentGroup}, skipping`)\n continue\n }\n\n console.log(` 📊 Found values for ${childValues.length}/${childKpis.length} child KPIs`)\n\n // Calculate parent KPI value and score\n let calculatedValue: number\n let calculatedScore: number\n\n // 1. If parent KPI has formula, use it to calculate\n if (parentKpi.formula) {\n try {\n console.log(` 📐 Using formula: ${parentKpi.formula}`)\n const result = await calculateParentKpiWithFormula(parentKpi, childValues, childKpis)\n calculatedValue = result.value\n calculatedScore = result.score\n console.log(` 🧮 Formula result: value=${calculatedValue.toFixed(4)}, score=${calculatedScore.toFixed(4)}`)\n } catch (formulaError) {\n console.log(` ⚠️ Formula evaluation failed: ${formulaError.message}, falling back to weighted average`)\n const { weightedValue, weightedScore } = calculateWeightedAverage(childValues, childKpis)\n calculatedValue = weightedValue\n calculatedScore = weightedScore\n }\n } else {\n // 2. If no formula, use weighted average\n console.log(` ⚖️ Using weighted average`)\n const { weightedValue, weightedScore } = calculateWeightedAverage(childValues, childKpis)\n calculatedValue = weightedValue\n calculatedScore = weightedScore\n console.log(` 🧮 Weighted average: value=${calculatedValue.toFixed(4)}, score=${calculatedScore.toFixed(4)}`)\n }\n\n // Create new parent KPI value (old values already deleted)\n // Use latest KPI version (parentKpi.version) not the old value's version\n const newKpiValue: any = {\n kpi: parentKpi,\n value: calculatedValue,\n score: calculatedScore,\n valueDate: valueDate,\n version: parentKpi.version || 1, // Use latest KPI version\n group: currentGroup,\n kpiScope: currentGroup, // Set kpiScope same as group\n domain: systemDomain, // Set domain entity\n inputType: 'AUTO', // Set inputType to AUTO\n createdAt: new Date(),\n updatedAt: new Date()\n }\n\n try {\n const savedValue = await kpiValueRepository.save(newKpiValue)\n totalCreated++\n console.log(\n ` ✨ Created: value=${calculatedValue.toFixed(4)}, score=${calculatedScore.toFixed(4)}, version=${\n parentKpi.version || 1\n }, id=${savedValue.id}`\n )\n } catch (saveError) {\n console.log(` ❌ Save failed: ${saveError.message}`)\n errorCount++\n }\n\n totalProcessed++\n } catch (kpiError) {\n console.log(` ❌ Error processing KPI ${parentKpi.name}: ${kpiError.message}`)\n errorCount++\n }\n }\n }\n\n console.log(`\\\\n🎉 Parent KPI Value Propagation Complete!`)\n console.log(` 📊 Parent KPIs processed: ${totalProcessed}`)\n console.log(` ✨ Values created: ${totalCreated}`)\n console.log(` ❌ Errors: ${errorCount}`)\n\n if (errorCount > 0) {\n console.log(`\\\\n⚠️ Some parent KPIs had errors. Check the logs above for details.`)\n }\n } catch (error) {\n console.error(`❌ Fatal error during parent KPI value propagation:`, error)\n throw error\n } finally {\n if (connection) {\n await connection.close()\n console.log('🔌 Database connection closed')\n }\n }\n}\n\n/**\n * Sort KPIs by hierarchy level (deepest first for bottom-up processing)\n */\nasync function sortKpisByLevel(parentKpis: KpiRecord[], allKpis: KpiRecord[]): Promise<KpiRecord[]> {\n // Calculate hierarchy level for each KPI\n const kpiLevels = new Map<string, number>()\n\n function calculateLevel(kpi: KpiRecord): number {\n if (kpiLevels.has(kpi.id)) {\n return kpiLevels.get(kpi.id)!\n }\n\n if (!kpi.parent) {\n kpiLevels.set(kpi.id, 0)\n return 0\n }\n\n const parentKpi = allKpis.find(k => k.id === kpi.parent?.id)\n if (!parentKpi) {\n kpiLevels.set(kpi.id, 1)\n return 1\n }\n\n const level = calculateLevel(parentKpi) + 1\n kpiLevels.set(kpi.id, level)\n return level\n }\n\n // Calculate levels for all parent KPIs\n parentKpis.forEach(kpi => {\n const level = calculateLevel(kpi)\n ;(kpi as any).__level = level\n })\n\n // Sort by level (deepest first)\n return parentKpis.sort((a, b) => ((b as any).__level || 0) - ((a as any).__level || 0))\n}\n\n/**\n * Get child KPI values for a specific date\n * Note: Version filter is NOT applied - uses latest available child KPI values regardless of version\n * This matches the recalculateProjectKpiValues logic in kpi-metric-value-mutation.ts\n */\nasync function getChildKpiValues(\n kpiValueRepository: any,\n childKpis: KpiRecord[],\n valueDate: string,\n version?: number,\n orgScope?: string\n): Promise<KpiValueRecord[]> {\n const childKpiIds = childKpis.map((kpi: any) => kpi.id)\n\n let valuesQuery = kpiValueRepository\n .createQueryBuilder('kpiValue')\n .leftJoinAndSelect('kpiValue.kpi', 'kpi')\n .where('kpi.id IN (:...kpiIds)', { kpiIds: childKpiIds })\n .andWhere('kpiValue.valueDate = :valueDate', { valueDate })\n .andWhere('kpiValue.score IS NOT NULL')\n\n // Version filter is intentionally removed to use latest available child KPI values\n // This ensures we calculate parent KPIs based on the most recent child data\n\n // Filter by group scope\n if (orgScope) {\n valuesQuery = valuesQuery.andWhere('kpiValue.group = :groupScope', { groupScope: orgScope })\n }\n\n const values = await valuesQuery.getMany()\n\n return values\n}\n\n/**\n * Recalculate leaf KPI scores using latest KPI grades lookup table\n */\nasync function recalculateLeafKpiScores(\n kpiRepository: any,\n kpiValueRepository: any,\n leafKpis: KpiRecord[],\n orgScope?: string,\n targetDate?: string\n): Promise<void> {\n let totalRecalculated = 0\n let errorCount = 0\n\n for (const leafKpi of leafKpis) {\n try {\n // Get latest version of this KPI with grades\n const latestKpi = await kpiRepository.findOne({\n where: { id: leafKpi.id },\n order: { version: 'DESC' }\n })\n\n if (!latestKpi) {\n console.log(` ⚠️ Latest KPI not found for ${leafKpi.name}`)\n continue\n }\n\n // Get all leaf KPI values that need score recalculation\n let valuesQuery = kpiValueRepository\n .createQueryBuilder('kpiValue')\n .where('kpiValue.kpi_id = :kpiId', { kpiId: leafKpi.id })\n .andWhere('kpiValue.value IS NOT NULL')\n\n if (orgScope) {\n valuesQuery = valuesQuery.andWhere('kpiValue.group = :orgScope', { orgScope })\n }\n\n if (targetDate) {\n valuesQuery = valuesQuery.andWhere('kpiValue.value_date = :targetDate', { targetDate })\n }\n\n const kpiValues = await valuesQuery.getMany()\n\n if (kpiValues.length === 0) {\n continue\n }\n\n // 2D lookup 여부 확인\n const is2D = latestKpi.grades && !Array.isArray(latestKpi.grades) && latestKpi.grades.type === 'PROGRESS_DEVIATION_LOOKUP'\n const progressRateCache = new Map<string, number>()\n let projectRepo: any = null\n if (is2D) {\n try {\n const { Project } = require('@dssp/project')\n const { getRepository: getRepo } = require('@things-factory/shell')\n projectRepo = getRepo(Project)\n } catch {\n console.log(` ⚠️ @dssp/project not found — using default progressRate for ${leafKpi.name}`)\n }\n }\n\n // Recalculate score for each value using latest KPI grades\n for (const kpiValue of kpiValues) {\n const oldScore = kpiValue.score\n\n let progressRate: number | undefined\n if (is2D && kpiValue.group) {\n if (progressRateCache.has(kpiValue.group)) {\n progressRate = progressRateCache.get(kpiValue.group)\n } else if (projectRepo) {\n const project = await projectRepo.findOne({ where: { id: kpiValue.group } })\n progressRate = project?.totalProgress ?? 50\n progressRateCache.set(kpiValue.group, progressRate)\n }\n }\n\n const newScore = calculateScoreFromGrades(latestKpi, kpiValue.value, progressRate)\n\n if (newScore !== null && newScore !== oldScore) {\n kpiValue.score = newScore\n kpiValue.version = latestKpi.version || 1\n await kpiValueRepository.save(kpiValue)\n totalRecalculated++\n console.log(\n ` ✅ ${leafKpi.name}: score ${oldScore?.toFixed(4) || 'null'} → ${newScore.toFixed(4)} (version ${\n latestKpi.version || 1\n })`\n )\n }\n }\n } catch (error) {\n console.log(` ❌ Error recalculating scores for ${leafKpi.name}: ${error.message}`)\n errorCount++\n }\n }\n\n console.log(`\\n 📊 Leaf scores recalculated: ${totalRecalculated}, Errors: ${errorCount}`)\n}\n\n/**\n * Calculate score from KPI grades lookup table\n * 1D (기존 배열) 및 2D (X13 공정률×편차) lookup 모두 지원\n */\nfunction calculateScoreFromGrades(kpi: any, value: number, progressRate?: number): number | null {\n if (!kpi.grades) {\n return null\n }\n\n // 2D lookup table 처리 (X13: 공정률 × 편차 → 점수)\n if (!Array.isArray(kpi.grades) && kpi.grades.type === 'PROGRESS_DEVIATION_LOOKUP') {\n return calculate2DScore(value, kpi.grades, progressRate ?? 50)\n }\n\n // 1D lookup (기존)\n if (!Array.isArray(kpi.grades) || kpi.grades.length === 0) {\n return null\n }\n\n const grade = kpi.grades.find((g: any) => value >= g.minValue && value <= g.maxValue)\n if (!grade) {\n return null\n }\n\n return grade.score\n}\n\n/**\n * 2D lookup table에서 점수 계산 (X13: 공정률 × 편차 → 점수 1~5)\n */\nfunction calculate2DScore(deviationValue: number, grades: any, progressRate: number): number | null {\n if (!grades.rows || !Array.isArray(grades.rows)) return null\n\n const progressIndex = Math.min(99, Math.max(0, Math.floor(progressRate)))\n const row = grades.rows.find((r: any) => r.progressRate === progressIndex)\n if (!row) return null\n\n if (deviationValue < row.boundary5to4) return 5\n if (deviationValue < row.boundary4to3) return 4\n if (deviationValue < row.boundary3to2) return 3\n if (deviationValue < row.boundary2to1) return 2\n return 1\n}\n\n/**\n * Calculate parent KPI value using formula\n * This matches the logic in kpi-metric-value-mutation.ts recalculateParentKpiValue\n */\nasync function calculateParentKpiWithFormula(\n parentKpi: KpiRecord,\n childValues: KpiValueRecord[],\n childKpis: KpiRecord[]\n): Promise<{ value: number; score: number }> {\n // Import formula evaluation functions\n const { parseFormula, evaluateFormula, builtinFunctions } = require('@things-factory/kpi')\n\n // Create child KPI name -> score mapping\n const childKpiScoreMap: Record<string, number> = {}\n childValues.forEach(kpiValue => {\n const childKpi = childKpis.find((k: any) => k.id === kpiValue.kpi.id)\n if (childKpi) {\n childKpiScoreMap[childKpi.name] = kpiValue.score ?? 0\n }\n })\n\n // Create provider for formula evaluation\n const provider = {\n get: async (name: string) => {\n const value = childKpiScoreMap[name]\n if (value === undefined) {\n throw new Error(`Child KPI '${name}' not found in parent KPI formula`)\n }\n return value\n }\n }\n\n // Parse and evaluate formula\n const ast = parseFormula(parentKpi.formula)\n const evalContext = { functions: builtinFunctions, provider }\n const result = await evaluateFormula(ast, evalContext)\n\n return {\n value: result,\n score: result\n }\n}\n\n/**\n * Calculate weighted average from child KPI values\n */\nfunction calculateWeightedAverage(\n childValues: KpiValueRecord[],\n childKpis: KpiRecord[]\n): { weightedValue: number; weightedScore: number } {\n let totalWeightedValue = 0\n let totalWeightedScore = 0\n let totalWeight = 0\n\n for (const value of childValues) {\n const childKpi = childKpis.find(kpi => kpi.id === value.kpi.id)\n const weight = childKpi?.weight || 1\n\n totalWeightedValue += value.score * weight\n totalWeightedScore += value.score * weight\n totalWeight += weight\n }\n\n if (totalWeight === 0) {\n return { weightedValue: 0, weightedScore: 0 }\n }\n\n return {\n weightedValue: totalWeightedValue / totalWeight,\n weightedScore: totalWeightedScore / totalWeight\n }\n}\n\n/**\n * List parent KPIs and their hierarchy\n */\nexport async function listParentKpiHierarchy(): Promise<void> {\n // Set NODE_ENV if not set\n if (!process.env.NODE_ENV) {\n process.env.NODE_ENV = 'development'\n }\n\n // Initialize Things-Factory environment\n const { config } = require('@things-factory/env')\n const ormconfig = require('@things-factory/shell/dist-server/initializers/ormconfig.js')\n const connectionConfig = config.get('ormconfig')\n\n let connection\n\n try {\n console.log('🔌 Connecting to database...')\n connection = await createConnection({\n ...ormconfig,\n ...connectionConfig,\n logging: false\n })\n\n const { addDataSource } = require('@things-factory/shell')\n addDataSource('default', connection)\n\n const { getRepository } = require('@things-factory/shell')\n const { Kpi } = require('@things-factory/kpi')\n const kpiRepository = getRepository(Kpi)\n\n // Get all KPIs with hierarchy\n const kpis = await kpiRepository\n .createQueryBuilder('kpi')\n .leftJoinAndSelect('kpi.domain', 'domain')\n .leftJoinAndSelect('kpi.parent', 'parent')\n .leftJoinAndSelect('kpi.children', 'children')\n .where('domain.name = :domainName', { domainName: 'SYSTEM' })\n .getMany()\n\n const parentKpis = kpis.filter(kpi => !kpi.isLeaf)\n const sortedParentKpis = await sortKpisByLevel(parentKpis, kpis)\n\n console.log(`📁 Parent KPI Hierarchy (${sortedParentKpis.length} parents):\\\\n`)\n\n if (sortedParentKpis.length === 0) {\n console.log(' No parent KPIs found.')\n return\n }\n\n sortedParentKpis.forEach((kpi, index) => {\n const level = (kpi as any).__level || 0\n const indent = ' '.repeat(level)\n const childCount = kpis.filter(k => k.parent?.id === kpi.id).length\n const weight = kpi.weight || 1\n\n console.log(\n ` ${(index + 1).toString().padStart(2)}: ${indent}${kpi.name} (L${level}, ${childCount} children, weight: ${weight})`\n )\n })\n\n console.log(`\\\\n📈 Total: ${sortedParentKpis.length} parent KPIs`)\n } catch (error) {\n console.error('❌ Error listing parent KPIs:', error)\n } finally {\n if (connection) {\n await connection.close()\n }\n }\n}\n\n/**\n * CLI execution when called directly\n */\nasync function main() {\n const args = process.argv.slice(2)\n\n try {\n if (args.includes('--help') || args.includes('-h')) {\n console.log(`\n🎯 Parent KPI Value Propagator\n\nUsage:\n ts-node server/scripts/propagate-parent-kpi-values.ts [options] [kpiName]\n\nOptions:\n --list, -l List parent KPIs and their hierarchy\n --force, -f Force recalculate all values (not just missing ones)\n --date YYYY-MM-DD Target date for value calculation (default: today)\n --org orgScope Organization scope filter (default: all orgs)\n --orgs org1,org2 Multiple organization scopes (comma-separated)\n --version N KPI version filter (default: latest version)\n --help, -h Show this help\n\nExamples:\n ts-node server/scripts/propagate-parent-kpi-values.ts # Process all parent KPIs for today\n ts-node server/scripts/propagate-parent-kpi-values.ts --force # Recalculate ALL parent values\n ts-node server/scripts/propagate-parent-kpi-values.ts --date 2024-01-15 # Process for specific date\n ts-node server/scripts/propagate-parent-kpi-values.ts --org \"PROJECT-123\" # Process for specific org\n ts-node server/scripts/propagate-parent-kpi-values.ts --orgs \"ID1,ID2,ID3\" # Process multiple orgs\n ts-node server/scripts/propagate-parent-kpi-values.ts --version 2 # Process for specific version\n ts-node server/scripts/propagate-parent-kpi-values.ts \"상위 KPI명\" # Process specific parent KPI\n ts-node server/scripts/propagate-parent-kpi-values.ts --list # List parent KPI hierarchy\n\nNote: Processes parent KPIs from deepest level to root, calculating weighted averages.\n Child KPI scores and weights are used to calculate parent values.\n --orgs option processes multiple orgs with single initialization (faster).\n `)\n return\n }\n\n if (args.includes('--list') || args.includes('-l')) {\n await listParentKpiHierarchy()\n return\n }\n\n const forceRecalculate = args.includes('--force') || args.includes('-f')\n const dateIndex = args.indexOf('--date')\n const targetDate = dateIndex !== -1 && dateIndex + 1 < args.length ? args[dateIndex + 1] : undefined\n const orgIndex = args.indexOf('--org')\n const orgScope = orgIndex !== -1 && orgIndex + 1 < args.length ? args[orgIndex + 1] : undefined\n const orgsIndex = args.indexOf('--orgs')\n const orgScopesString = orgsIndex !== -1 && orgsIndex + 1 < args.length ? args[orgsIndex + 1] : undefined\n const orgScopes = orgScopesString ? orgScopesString.split(',') : undefined\n const versionIndex = args.indexOf('--version')\n const version = versionIndex !== -1 && versionIndex + 1 < args.length ? parseInt(args[versionIndex + 1]) : undefined\n const specificKpiName = args.find(\n arg =>\n !arg.startsWith('--') &&\n arg !== targetDate &&\n arg !== orgScope &&\n arg !== orgScopesString &&\n (version === undefined || arg !== version.toString())\n )\n\n // Use batch processing if multiple orgs specified\n if (orgScopes && orgScopes.length > 0) {\n console.log(`🎯 Propagating values for all parent KPIs (Batch mode)`)\n console.log(` Mode: ${forceRecalculate ? 'Force recalculate ALL' : 'Only missing values'}`)\n console.log(` Date: ${targetDate || 'today'}`)\n console.log(` Orgs: ${orgScopes.length} organizations`)\n console.log(` Version: ${version || 'latest'}`)\n await propagateParentKpiValuesBatch(orgScopes, specificKpiName, forceRecalculate, targetDate, version)\n } else if (specificKpiName) {\n console.log(`🎯 Propagating values for specific KPI: ${specificKpiName}`)\n console.log(` Mode: ${forceRecalculate ? 'Force recalculate ALL' : 'Only missing values'}`)\n console.log(` Date: ${targetDate || 'today'}`)\n console.log(` Org: ${orgScope || 'all'}`)\n console.log(` Version: ${version || 'latest'}`)\n await propagateParentKpiValues(specificKpiName, forceRecalculate, targetDate, orgScope, version)\n } else {\n console.log(`🎯 Propagating values for all parent KPIs`)\n console.log(` Mode: ${forceRecalculate ? 'Force recalculate ALL' : 'Only missing values'}`)\n console.log(` Date: ${targetDate || 'today'}`)\n console.log(` Org: ${orgScope || 'all'}`)\n console.log(` Version: ${version || 'latest'}`)\n await propagateParentKpiValues(undefined, forceRecalculate, targetDate, orgScope, version)\n }\n\n console.log('\\\\n✨ Done!')\n } catch (error) {\n console.error('\\\\n❌ Script failed:', error.message)\n process.exit(1)\n }\n}\n\n// Handle uncaught errors\nprocess.on('unhandledRejection', (error: any) => {\n console.error('❌ Unhandled error:', error.message || error)\n process.exit(1)\n})\n\n// Run if called directly\nif (require.main === module) {\n main()\n}\n"]}
@@ -66,6 +66,28 @@ export declare class KpiMetricValueMutation {
66
66
  * 데이터 서비스키만으로 동작 가능. UI 는 시스템별로 명확한 오류 메시지 노출.
67
67
  */
68
68
  collectProjectExternalData(projectId: string, context: ResolverContext): Promise<ExternalDataCollectionResult[]>;
69
+ /**
70
+ * UI "시공감리 플랫폼 자동 수집" 버튼 전용.
71
+ *
72
+ * 2026-08-07 회의: KPI 기본정보를 사람이 다시 입력하지 않고 시공감리 플랫폼(DCSP)에서
73
+ * 가져온다. 외부 연동이 아니다 — DCSP 와 DKPI 는 **같은 DB 를 본다** (projects 쿼리가
74
+ * DKPI 로 뜰 때만 필터를 걸지 않는다, project-query.ts). 그래서 네트워크 호출 없이
75
+ * 같은 프로젝트 행과 그 단지·검측 기록을 그대로 읽는다.
76
+ *
77
+ * ── 단위가 양쪽에서 다르다 ───────────────────────────────────────────────
78
+ * 시공감리는 사람이 입력하기 자연스러운 단위로 받고, KPI 는 계산에 쓰는 단위로 쓴다.
79
+ * 그 간극을 여기서 메운다 — 화면이나 입력자에게 떠넘기지 않는다.
80
+ *
81
+ * 공사기간 착공일·준공일(date) → 개월 (소수 첫째자리)
82
+ * 재해율 % (재해자수/상시근로자수×100) → 비율 (÷100)
83
+ * 그 밖 단위 동일
84
+ *
85
+ * 값이 없는 항목은 결과에서 뺀다. 0 으로 채우면 "재해가 없었다"는 사실과
86
+ * "아직 입력하지 않았다"가 구별되지 않는다.
87
+ */
88
+ collectProjectSupervisionData(projectId: string, context: ResolverContext): Promise<ExternalDataCollectionResult>;
89
+ /** 두 날짜 사이의 개월 수 (소수 첫째자리). 둘 중 하나라도 없으면 null. */
90
+ private monthsBetween;
69
91
  /**
70
92
  * 프로젝트 정보 수정 화면의 "정보 연동" 버튼 전용 — 세움터 수집.
71
93
  * BuildingComplex 기본 속성 (area / floorAreaRatio / siteType / structureType /