diff --git a/src/views/Dashboard/HwDashboard.ts b/src/views/Dashboard/HwDashboard.ts index 58e49e7..6b2c478 100644 --- a/src/views/Dashboard/HwDashboard.ts +++ b/src/views/Dashboard/HwDashboard.ts @@ -265,7 +265,14 @@ function updateDashboardData(pcs: any[], selectedDept: string) { p._pc_score = calculatePcScoreDeductive(p.cpu, p.ram, p.gpu, p.purchase_date); }); - // 3. 전사 직무군별 평균 점수 산출 + // 3. DB 기준 사양 데이터 맵핑 (state.masterData.jobSpecs 이용) + const jobSpecsMap: Record = {}; + if (state.masterData.jobSpecs) { + state.masterData.jobSpecs.forEach((s: any) => { + jobSpecsMap[s.job_name] = s.min_score; + }); + } + const jobScores: Record = {}; pcs.forEach((p: any) => { const score = calculatePcScoreDeductive(p.cpu, p.ram, p.gpu, p.purchase_date); @@ -332,15 +339,15 @@ function updateDashboardData(pcs: any[], selectedDept: string) { // 직무 적정성 계산 (재직 중이고 실 사용자 매핑 자산만 검토 대상) const job = p[ASSET_SCHEMA.USER_POSITION.key] || '미분류'; - const avg = jobScores[job]?.avg || 0; + const standardScore = jobSpecsMap[job] !== undefined ? jobSpecsMap[job] : (jobScores[job]?.avg || 0); let isUnder = false; - if (avg > 0 && job !== '재고PC') { - if (score < avg * 0.6) { + if (standardScore > 0 && job !== '재고PC') { + if (score < standardScore) { isUnder = true; p._spec_status = '사양 부족'; - } else if (score > avg * 1.5 && !win11Incompatible) { + } else if (score > standardScore * 1.2 && !win11Incompatible) { p._spec_status = '오버스펙'; criticalList.push(p); overSpecCount++; @@ -354,6 +361,8 @@ function updateDashboardData(pcs: any[], selectedDept: string) { if (win11Incompatible) { isUnder = true; p._spec_status = '사양 부족'; + } else { + p._spec_status = '적정'; } } @@ -363,11 +372,11 @@ function updateDashboardData(pcs: any[], selectedDept: string) { // 2. 사양 부족 시 교체받아야 할 직무별 권장 목표 등급 판정 let targetGradeKey: keyof typeof matrix; - if (avg >= 85) { + if (standardScore >= 85) { targetGradeKey = 'premium'; - } else if (avg >= 70) { + } else if (standardScore >= 70) { targetGradeKey = 'high'; - } else if (avg >= 40) { + } else if (standardScore >= 40) { targetGradeKey = 'normal'; } else { targetGradeKey = 'entry'; // 교체 대상은 최소 보급형 사양으로 교체 diff --git a/src/views/List/ListFactory.ts b/src/views/List/ListFactory.ts index b5f799d..7cf937a 100644 --- a/src/views/List/ListFactory.ts +++ b/src/views/List/ListFactory.ts @@ -914,33 +914,45 @@ export function createListView(container: HTMLElement, config: ListViewConfig) { jobScores[job].avg = jobScores[job].count > 0 ? jobScores[job].totalScore / jobScores[job].count : 0; }); + // DB 기준 사양 데이터 맵핑 (state.masterData.jobSpecs 이용) + const jobSpecsMap: Record = {}; + if (state.masterData.jobSpecs) { + state.masterData.jobSpecs.forEach((s: any) => { + jobSpecsMap[s.job_name] = s.min_score; + }); + } + // 기준 대비 사양 부족/오버스펙 분류 const criticalPcList: any[] = []; pcs.forEach((pc: any) => { const job = pc[ASSET_SCHEMA.USER_POSITION.key] || '미분류'; const score = pc['_pc_score']; - const avg = jobScores[job].avg; + const standardScore = jobSpecsMap[job] !== undefined ? jobSpecsMap[job] : (jobScores[job]?.avg || 0); const cpu = pc[ASSET_SCHEMA.CPU.key] || ''; const ram = pc[ASSET_SCHEMA.RAM.key] || ''; const win11Incompatible = isWindows11Incompatible(cpu, ram); let isUnder = false; - if (avg > 0) { - if (score < avg * 0.6) { + if (standardScore > 0) { + if (score < standardScore) { isUnder = true; pc['_spec_status'] = '사양 부족'; - } else if (score > avg * 1.5 && !win11Incompatible) { + } else if (score > standardScore * 1.2 && !win11Incompatible) { pc['_spec_status'] = '오버스펙'; criticalPcList.push(pc); } else if (win11Incompatible) { isUnder = true; pc['_spec_status'] = '사양 부족'; + } else { + pc['_spec_status'] = '적정'; } } else { if (win11Incompatible) { isUnder = true; pc['_spec_status'] = '사양 부족'; + } else { + pc['_spec_status'] = '적정'; } } @@ -949,12 +961,15 @@ export function createListView(container: HTMLElement, config: ListViewConfig) { } }); - // 정렬: 직무 평균 대비 사양 부족이 심한 순(비율이 낮은 순)으로 정렬 + // 정렬: 기준 점수 대비 사양 부족이 심한 순(비율이 낮은 순)으로 정렬 criticalPcList.sort((a: any, b: any) => { const jobA = a[ASSET_SCHEMA.USER_POSITION.key] || '미분류'; const jobB = b[ASSET_SCHEMA.USER_POSITION.key] || '미분류'; - const ratioA = jobScores[jobA].avg > 0 ? a['_pc_score'] / jobScores[jobA].avg : 1; - const ratioB = jobScores[jobB].avg > 0 ? b['_pc_score'] / jobScores[jobB].avg : 1; + const stdA = jobSpecsMap[jobA] !== undefined ? jobSpecsMap[jobA] : (jobScores[jobA]?.avg || 0); + const stdB = jobSpecsMap[jobB] !== undefined ? jobSpecsMap[jobB] : (jobScores[jobB]?.avg || 0); + + const ratioA = stdA > 0 ? a['_pc_score'] / stdA : 1; + const ratioB = stdB > 0 ? b['_pc_score'] / stdB : 1; return ratioA - ratioB; });