From 6118141f6e979b4d024c1a62d657d96eb6bd212e Mon Sep 17 00:00:00 2001 From: JooWangi Date: Mon, 15 Jun 2026 14:43:53 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=A7=81=EB=AC=B4=EB=B3=84=20=EA=B8=B0?= =?UTF-8?q?=EC=A4=80=20=EC=82=AC=EC=96=91(job=5Fspec=5Fstandards)=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=EB=A5=BC=20=ED=99=9C=EC=9A=A9?= =?UTF-8?q?=ED=95=9C=20=EB=B6=80=EC=A1=B1=EC=82=AC=EC=96=91,=20=EC=98=A4?= =?UTF-8?q?=EB=B2=84=EC=8A=A4=ED=8E=99=20=ED=8C=90=EC=A0=95=20=EB=B0=8F=20?= =?UTF-8?q?=EB=93=B1=EA=B8=89=EB=B3=84=20=EB=B6=80=EC=A1=B1=EB=B6=84(?= =?UTF-8?q?=EA=B5=AC=EB=A7=A4=20=ED=95=84=EC=9A=94)=20=EC=82=B0=EC=B6=9C?= =?UTF-8?q?=20=EA=B3=B5=EC=8B=9D=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/Dashboard/HwDashboard.ts | 25 +++++++++++++++++-------- src/views/List/ListFactory.ts | 29 ++++++++++++++++++++++------- 2 files changed, 39 insertions(+), 15 deletions(-) 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; });