포털 · 메인 메뉴
SERVER HEALTHY
반갑습니다, 부산본부 관리팀
원하는 대시보드를 선택하세요. 실시간 데이터는 자동으로 갱신됩니다.
인증 완료
현재 버전 v1.2
테마 다크
본부 일정
1 / 1
2026-05-14
V19.7.2 사업장 정보 — 편의시설 hero 폐기 + 갤러리 단일화 + 라이트박스 사진 클릭 닫힘
- FIXhero 영역 폐기 + 갤러리 단일 영역 — 사용자 결정 (2026-05-14): "위 하나짜리는 삭제하고 갤러리를 하나로 보여지게 깔끔하게". 진단: V19.7 의
v16-dt-hero가 첫 사진 1장을 크게 띄우고 그 아래v16-amen-gallery에 동일 사진을 다시 thumb 으로 표시 → 사진 1장 중복 + 시각 무게가 위쪽 쏠림. 해결:v16_renderAmen의 hero 블록 제거 →v16-amen-slot슬롯으로 교체,v16_updateAmenityImage가 panel 최상단에 갤러리 1개만 단일 렌더. 1장이어도 표시 (V19.7 의 "2장 이상" 조건 폐기), 1장일 때는.singlegrid 로 16:9 비율 큰 카드. - FIX라이트박스 사진 클릭 시 닫힘 — 사용자 결정: "사진을 눌러서 팝업시 다시 사진을 누르거나 아무데나 눌러도 사진이 꺼지게". 기존:
img.addEventListener('click', e => e.stopPropagation())가 backdrop 닫힘 차단 → 이미지 위 클릭 무시. 신규:img.click핸들러에서cleanup()명시 호출 → 사진/배경 어디 클릭해도 닫힘. prev/next 버튼은stopPropagation유지 (사진 이동 중 닫힘 방지). - FEAT0장 placeholder 톤 정리 —
v16-amen-slot-empty신규 클래스. amenity 아이콘 + "{이름} · 사진 미등록" + NAS 폴더 경로 안내 (영업팀이 사진 추가 시 자동 표시되는 위치). V19.6.ph-act-empty빨강 톤 계승. - TEST검증 —
node --check통과. staging 배포 후 6 amenity 모두 갤러리 1개 영역 (1~4장 사진) + 라이트박스 ←/→ 키 + 사진/배경 클릭 닫힘 동작 확인. 빌드 산출물: 60-view-facility.js 1809줄 / 60-view-facility.css 710줄. - OPS변경 파일 2개 —
src/js/60-view-facility.js(v16_renderAmen hero→slot 변경 +10줄 / v16_updateAmenityImage 갤러리 단일화 ~80줄 재작성 / v16_openImage img click cleanup +1줄) ·src/css/60-view-facility.css(.v16-amen-slot* 신규 +35줄 / .v16-amen-gallery border-top 제거 / .single 추가). server.js 변경 0. 롤백 1명령:py scripts/deploy.py --target=prod --rollback-to v19.7.1.
2026-05-14
V19.7.1 사업장 정보 — 편의시설 사진 매핑 NAS 폴더명 일치 (shw/mtg hotfix)
- FIXFAC_AMENITY_SUBFOLDER 매핑 NAS 실제 폴더명 정확 일치 — 사용자 보고: 편의시설 사진이 안 들어감. 진단: NAS 실제 폴더는
샤워실 탈의실/회의실 교육장인데 코드는샤워실/회의실로 매핑되어 있었음.v16_findAmenityImages의 1순위 substring 매칭이'/' + sub + '/'형태라/샤워실/으로는/샤워실 탈의실/디렉토리 미매칭. 픽스: shw →'샤워실 탈의실', mtg →'회의실 교육장'. 2순위 키워드 fallback (['샤워','탈의'],['회의','교육']) 은 그대로 유지 — 향후 NAS 폴더명 미세 변동 안전망. - TEST매칭 시뮬레이션 검증 — 6 amenity 모두 phase 1 (서브폴더 매칭) hit 확인: caf=2장 · lng=1장 · shw=2장 · gym=1장 · mtg=2장 · smk=1장. node --check 통과.
- OPS변경 파일 1개 —
src/js/60-view-facility.js(FAC_AMENITY_SUBFOLDER 2 키 수정 + 주석 +5줄). server.js 변경 0 →--include-server-js불필요. 롤백 1명령:py scripts/deploy.py --target=prod --rollback-to v19.7. - FEAT참고 — 사용자 screenshot 의 "Photo / Floorplan" placeholder 텍스트는 V17 Phase 2 이전 옛 mockup 텍스트(
부산본부_대시보드.html.prephase2_bak에 잔존). 현재 prod 가 V19.6/V19.7 미배포 상태임을 시사. 본 V19.7.1 hotfix 와 함께 V19.4-V19.7 일괄 배포 필요.
2026-05-14
V19.7 사업장 정보 — 편의시설 사진 갤러리 + 라이트박스 종이동 (←/→ 키 · 카운터 · 캡션)
- FEATv16_openImage 시그니처 확장 — 단일/다중 사진 모두 호환 — 기존
v16_openImage(src)단일 문자열만 받음. 신규:(srcOrList, startIndex). 단일 src 호환 (이전 동작 동일) + 배열[src1, src2, ...]또는[{src, caption}, ...]모두 처리. 다중일 때 ← / → 화살표 버튼, 좌/우 방향키,1 / N카운터 (좌상), 사진 캡션 (하단) 노출. 1장이면 자동 단일 모드(.has-nav 클래스 미부여 → 화살표/카운터 숨김). - FEATamenity 갤러리 그리드 신설 (.v16-amen-gallery) — hero 아래 + v16-dt-body 위에 갤러리 그리드 동적 삽입. 4컬럼 thumb 격자 (모바일 2~3컬럼 반응형), 첫 사진
data-active="1"outline 강조, lazy loading, onerror placeholder. 클릭 시 라이트박스 해당 idx 진입. 사진 2장 이상일 때만 노출 (1장은 hero 만으로 충분 → 시각 노이즈 회피). - FEAT현장사진 그리드도 라이트박스 종이동 (보너스) —
v16_renderPhotos의 각 thumb 이 기존onclick="v16_openImage('src')"단일 src → 신규photoListclosure 캡처 + 클릭한 인덱스로 진입. ← / → 키로 8장 사진 순환 가능. 사업장 기본정보 탭 사용성 향상. - FEAT라이트박스 키보드/접근성 보강 — ESC 닫기 (이전) + ← 이전 + → 다음. 첫/마지막 사진에서 해당 화살표 visibility:hidden 자동. close 버튼 호버 시 빨강 톤.
aria-label3개 (닫기/이전 사진/다음 사진). - TEST검증 —
node --check src/js/60-view-facility.js src/server.js모두 OK. 빌드 산출물: 60-view-facility.js 1,673 → 1,808줄 (+135) / 60-view-facility.css +85줄. v16_openImage 시그니처 변경은 backward-compat — 기존 호출처(현장사진 inline onclick 전환됨, 외부 호출 없음) 모두 정상. 1장만 매칭된 amenity 케이스도 hero 만 노출 (갤러리 그리드 자동 숨김). - OPS변경 파일 2개 —
src/js/60-view-facility.js(v16_openImage 재작성 +90줄 / v16_updateAmenityImage 갤러리 그리드 +50줄 / v16_renderPhotos 종이동 +10줄) ·src/css/60-view-facility.css(#v16-lightbox .nav/.counter/.lb-caption +50줄 / .v16-amen-gallery* 갤러리 그리드 +35줄). server.js 변경 0 →--include-server-js불필요. 롤백 1명령:py scripts/deploy.py --target=prod --rollback-to v19.6.
2026-05-14
V19.6 사업장 정보 — 3차 UX 폴리싱 (라이트 input 토큰 · ↺ 항상 노출 · 사진 검색 중 텍스트 · 빈 사이트 워크플로 안내 · 빈 자유 row prune · parseInt 안전망 · 키워드 충돌)
- FIXU-3 라이트 input 토큰 분리 —
:root[data-theme="light"] #view-facility { --bg-input: #f8fafc }. 기존#ffffff가 흰 카드 위에서 input 영역 인지 불가. 다크 토큰은 변경 없음.60-view-facility.css. - FIXU-4 ↺ 되돌리기 버튼 — 편집 모드 active 시 항상 노출 — 기존 호버 노출만 → 터치/태블릿에서 영영 안 보이던 문제.
#view-facility.v16-edit-mode .btn-revert{display:inline-block}1줄 추가. 비편집 모드는 호버 노출 유지. - FIXU-5 amenity placeholder 텍스트 중립화 — "사진 자동 매칭" → "사진 검색 중" (로드 동안 매칭 약속 없음). 매칭 실패 시
v16_updateAmenityImage가 텍스트를 "사진 미등록" 으로 명시 전환 +.ph-act-empty빨강 톤.ph-act기본 톤도 녹색(약속) → 회색(중립) 으로 변경. - FEATU-10 빈 사이트 배너 시트 복사 워크플로 6단계 명시 — 매핑가이드 §4-4 의 워크플로(시트 우클릭 → 복사본 만들기 → 이름/헤더 변경 → 값 채우기 → 저장) 를 UI 에 노출.
<ol class="v16-empty-steps">+<kbd>키 표시. 영업팀이 매핑가이드 찾지 않아도 추가 가능. - FIXC-7 빈 자유 row 클라이언트 prune — 기존: 빈 라벨/빈 값 row 추가 시 dirty 카운트 +1 → 저장 시 서버 silent skip(line 1419) → 사용자 혼란.
v16_saveOverrides시작에FAC_DIRTY_CUSTOM의_new && !label && !value항목 사전 제거 + 토스트 안내. - FIXD-4 parseInt 안전망 (
_facCount) — 기존:parseInt('200만화소 94대')= 200 → TOTAL 오염. 신규:(\d+)\s*(?:대|개소|면|실|EA|SET|조)단위 prefix 우선 → 94 정확 추출. equip/fire 카드 카운트 양쪽 적용. 매칭 실패 시 마지막 정수 fallback. - FIXC-9 amenity ↔ section 키워드 충돌 정리 —
v16_findSectionImage의 2순위 키워드 fallback 에/편의시설/또는/amenity/prefix 경로 제외 안전망. meeting override section 의 '회의실' 키워드가 amenity 의/편의시설/회의실/foo.jpg까지 매칭하던 의도 모호 케이스 차단. - TEST검증 —
node --check src/js/60-view-facility.js src/server.jsOK. 빌드 산출물: 60-view-facility.js 1384→1673줄 (+289), server.js +85줄, 60-view-facility.css 478→567줄 (+89). 시각 회귀 0 — 모든 변경#view-facility스코프. - OPS변경 파일 2개 —
src/js/60-view-facility.js(_facCount 헬퍼 / U-5 / U-10 / C-7 / D-4 / C-9, ~70줄 net) ·src/css/60-view-facility.css(V19.6 토큰 + .v16-empty-steps + .ph-act 상태별 톤, ~30줄 net). server.js 변경 0 →--include-server-js불필요. 롤백 1명령:py scripts/deploy.py --target=prod --rollback-to v19.5.
2026-05-14
V19.5 사업장 정보 — 2차 데이터 근본 (매칭 우선순위 · dict {value, note} · mtime 캐시 · facility-watch SSE)
- FIXD-1 v16_v 매칭 우선순위 도입 (substring 단일 매칭 폐기) — V19.2.1 '구조'/'응급구조' 사고, V19.2.5 '제연'/'화재 수신기 연동' 사고 같은 substring 충돌의 구조적 픽스. 신규 매칭: ① exact (
dict.hasOwnProperty(k)) → ② startsWith → ③ substring (fallback, 기존 동작). 각 phase 에서 첫 site 값 hit 즉시 반환.v16_v시그니처 무변경 — 호출처 영향 0. 추가로v16_note(dict, site, ...keys)헬퍼 신규 (동일 매칭 우선순위로 비고 컬럼 추출). - FEATD-2 dict 값 구조
{value, note}확장 + 단위/비고 노출 — 기존:dict[label][site] = '94대'문자열 단일. 신규:{value:'94대', note:'200만화소 / 24시간 운영'}객체. 매핑가이드 §4-1 의 세번째 컬럼(단위/비고) 정보 손실 종결.v16_v는 내부 helper_facMatchValue가.value만 반환 (레거시 string 도 처리하는 호환성).v16_renderBasic일반현황 8행에.v16-row-note옅은 표시 추가. - FEATC-1 facility-info mtime 캐시 (
_facilityCache) — 기존: 매 요청마다xlsx.readFile+sheet_to_json3시트 (~30ms disk IO). 신규:fs.statSync.mtimeMs비교, 동일 시 캐시 응답 (~1ms). chokidar 가 파일 변경 감지 시_facilityCache.mtime=0강제 무효화. fuel/rowdata 모듈과 일관 패턴. - FEATC-3 facility-watch SSE 라우트 + 클라이언트 통합 — server.js:
GET /api/facility-watch?pw=+sseClientsFacilitySet +broadcastFacility(eventType)함수. POST 라우트(저장/revert) 양쪽에서 명시 broadcast (즉시 응답성) + chokidar 가FACILITY_PATH(엑셀, 'data-changed') 와OVERRIDES_PATH(JSON, 'overrides-changed') 양쪽 감지. 클라이언트:App.api.connectSSE('/api/facility-watch?pw=', ...)— enterFacility 진입 시 1회 연결, 'overrides-changed' 수신 시v16_loadOverrides+ 현재 섹션 재렌더, 'data-changed' 수신 시loadFacilityData. - FEATC-5 v16_facRowMap 메모이제이션 (
_facRowMapCache) — 기존: f_renderSection 매 호출마다 174행 × 3시트 머지. 신규: FAC_DATA 동일 ref 면 dict 재사용.loadFacilityData/ SSE 갱신 시 FAC_DATA 객체 교체 → 캐시 자동 무효화. - TEST검증 —
node --check src/js/60-view-facility.js src/server.js모두 OK. v16_v 신규 동작 — exact 우선 → startsWith → substring fallback. 기존 호출처 (v16_renderBasic/Equip/Fire/Amen + override 섹션) 호환성 무변경. - OPS변경 파일 2개 —
src/js/60-view-facility.js(매칭 우선순위 재작성 +60줄 / dict 구조 확장 +30줄 / SSE 클라이언트 +35줄 / 일반현황 note 렌더 +20줄) ·src/server.js(mtime 캐시 +15줄 / facility-watch SSE +40줄 / chokidar 감시 +18줄 / POST broadcast 2 지점 +2줄). server.js 변경 →--include-server-js필요. 롤백 1명령:py scripts/deploy.py --target=prod --rollback-to v19.4.
2026-05-14
V19.4 사업장 정보 — 1차 응급 5건 (If-Match 강제 · brigade dict 제외 · addons 빈 카드 · ✎ disabled · 📜 history 모달)
- FIXC-2 facility-overrides POST — If-Match 강제 (lost update 차단) — 기존:
if (ifMatch && ifMatch !== curEtag)조건. ifMatch 누락 시 통과 → 다중 사용자/curl 직접 호출에서 lost update 위험. 신규:if (!ifMatch || ifMatch !== curEtag)→ 누락도 409 반환 +hint: 'If-Match header missing'. 클라이언트(v16_saveOverrides) 는 항상 etag 전송 → 호환성 영향 0. server.js line 1385-1389. - FIXD-3 v16_facRowMap brigade scope 분리 — 기존: DWLG 시트의 디더블유엘글로벌/세중해운 2 brigade 가
소방대장/부대장/...8 동일 라벨 → dict 에서 마지막 brigade 만 남음 (의미 없는 데이터). 신규:'자체소방대 조직도'헤더 만나면inBrigade=true, 8역할(FAC_BRIGADE_ROLES) 라벨은 dict 등록 자체 제외. 조직도 렌더는v16_facBrigades가 행 순서로 별도 처리. - FIXC-6 addons 빈 카드 자동 숨김 (V19.3 cats 패턴 확장) — 기존: 부속장비 6종(드럼/야드램프/포크연장바/코일발/지게차연장발/컨테이너발판) 무조건 모두 노출 → DWLG 외 사이트는 0대인 부속이 다수 → 빈 카드 6개 시각 노이즈. 신규:
validAddonsfilter 적용 + 0건이면 부속 섹션 전체(헤더 포함) 숨김. - FIXU-1 ✎ 편집 버튼 4 엑셀 섹션 dimming + 토스트 안내 — 기존: 기본/장비/소방/편의 진입 후 ✎ 클릭 시 모드 토글되지만 input 없음 + 저장 바도 미노출 → 사용자 혼란. 신규:
v16_toggleEditMode가 비편집 가능 섹션에서 토스트 안내 후 return.v16_syncEditModeUI가.v16-edit-disabled클래스 토글 (opacity .45) + tooltip 분기. - FEATU-2 📜 변경 이력 모달 (server 라우트는 V19.1 부터 존재, 클라이언트 진입점 신설) —
v16_openHistoryModal+v16_closeHistoryModal신규 함수. 헤더 우측에v16-history-btn추가. GET/api/facility-overrides/history?site=§ion=&limit=200호출. 6컬럼 표(시간/사용자/섹션/항목/before→after/액션) + 한글 액션 라벨 매핑 + ESC/backdrop/✕ 닫기 일관..v16-hist-*CSS 신규 (~70줄, 모달 sticky 헤더 + 스크롤 body). - TEST검증 —
node --check통과. POST/api/facility-overrides에 If-Match 누락 → 409 (이전 200). 메모리 동기화 — facility-watch SSE 연결 시 변경된 If-Match 도 정상 동작. - OPS변경 파일 3개 —
src/server.js(If-Match 1줄 강화 + 4줄 hint) ·src/js/60-view-facility.js(brigade dict 제외 +12줄 / addons filter +12줄 / ✎ disabled +6줄 / history 모달 +90줄 / 글로벌 노출 +2줄) ·src/css/60-view-facility.css(.v16-edit-disabled + .v16-hist-* 모달 +70줄) ·src/부산본부_대시보드.html(📜 이력 버튼 +1줄). server.js 변경 →--include-server-js필요. 롤백 1명령:py scripts/deploy.py --target=prod --rollback-to v21.0.7.
2026-05-12
V21.0.7 비용분석 — 회귀 fallback + ma12DevPct 필드 정합 + 분류 override masking 경고 (코드 감사 ③⑤⑨ 묶음)
- FIX③ 회귀 무효 시 MA12 dev fallback 명시화 —
_lsRegression에valid플래그 추가 (표본 N≥6 AND 매출/비용 분산 > 0 AND r² 유한). override 가 occurrences<6 (auto:tentative) 계정에 variable 강제 시 회귀가 무효임에도 silent fallback (slope=0, intercept=yMean) 으로 "회귀잔차" 라벨이 그대로 노출되던 사각지대.detectVariabilityvariable/semi 분기에reg.valid검사 추가, 무효 시 fixed 와 동일한 MA12 dev 룰 (|MA12 dev| > 10%) 로 대체. 응답outlierMethod신규 필드 —'regression' | 'ma12dev' | null(디버그/UI 용). - FIX⑨
momPct→ma12DevPct필드 정합 + UI 라벨 "MoM" → "평균 대비" — 기존momPct가 이름과 달리(last/MA12 - 1) × 100(12M 평균 편차) 였던 mislabeling 정리. 서버 응답에ma12DevPct신규 필드 (동일 값, 의미 명확),momPct와ma12Pct(fixed 전용) 은 한 사이클 backward-compat 유지 (DEPRECATED 주석). 클라이언트 fallback 우선순위:ma12DevPct → ma12Pct → momPct. UI 라벨 7곳 "MoM" → "평균 대비" 일괄 정정 (워닝 그리드 stats, 카테고리 모달 표, 모달 차트, TOP 변동 카드, 안정성 매트릭스 verdict/delta pill).cost-summary의accountList도 동일 패턴. - FEAT⑤ 분류 편집 모달 — override masking 경고 다이얼로그 — 사양서 §4-1 override 적용 우선순위:
<branch>|<account>>통합|<account>> 자동. 사용자가 이 규칙을 모르고 통합/사업장 override 를 동시 보유 상태에서 변경 시 의도와 다른 결과 발생.rd_clsCheckMaskingConflicts신규 함수 — pre-save 단계에 두 시나리오 검증: (A) 통합 변경 시 동일 계정에 사업장 override 존재 → 해당 사업장에서 마스킹됨, (B) 사업장 변경 시 통합 override 존재 → 해당 사업장에서만 통합값 덮어쓰여짐. confirm() 다이얼로그로 명시 동의 요구, 취소 시 저장 중단 (pendingSet 보존). - TEST영향 예측 — ③ 회귀 무효 케이스는 override 강제 시에만 발생 (현재 회계팀 사용 패턴 거의 0) → 기존 워닝 갯수 무변동 예상. ⑨ 라벨 변경은 시각만 (값 동일), 회계팀 멘탈 모델 정렬. ⑤ masking 경고는 confirm 추가로 1 클릭 증가, 의도된 변경은 영향 없음.
node --check src/server.jsOK. - OPS변경 파일 4개 —
src/server.js(_lsRegressionvalid 플래그 +8줄 ·detectVariabilityfallback 분기 +10줄 · 응답 필드 4개 추가 +6줄 ·computeCostSummaryma12DevPct 추가 +1줄) ·src/js/54-view-rowdata.js(UI 라벨 정정 7곳 ~30줄 · masking 경고 함수 +40줄) ·src/부산본부_대시보드.html(dev-row V21.0.7 + V21.0.6 latest 강등) ·1.기초정보/08_비용분석_V18_점검모드.md(§4-2 부분 갱신 — 회귀 fallback 추가). server.js 변경 →--include-server-js필요. 롤백 1명령:py scripts/deploy.py --target=prod --rollback-to v21.0.6.
2026-05-12
V21.0.6 비용분석 — fixed 워닝 룰 상승/하락 비대칭 분기 (한 달 급등 fixed 진짜 위험 신호 회복)
- FIXfixed Critical 게이트 — 상승/하락 분기 — V21.0.5 의 Critical 게이트가
|MA12 dev|>10% AND isLongDown AND isShortDown AND |trueMoM|≥1%4중 AND. 추세 게이트가 12M·3M 둘 다 음수 slope 만 검사하는 구조라 한 달 급등 fixed 항목(임차료 인상·보험료 재계약·일회성 보수비 등) 의 진짜 위험 신호가 Critical 에 영구 미진입하던 사각지대. V21.0.6:ma12Dev부호로 상승/하락 분기. 상승(ma12Dev > 0) 은 추세 조건 없이|dev|만으로 판정 (한 달 급등도 위험). 하락(ma12Dev < 0) 은 기존 추세 게이트 유지 (V21.0.5 step-down 안정화 노이즈 방어 의도 보존).|trueMoM| ≥ 1%공통 가드는 양쪽 유지. - TEST영향 예측 — 추가로 잡힐 항목: 한 달 급등 fixed (예상 0~3건/월). 제외 유지: step-down 후 안정화 케이스(V21.0.5 4 BNCC 케이스). variable/semi-variable 룰 무수정.
node --check src/server.js통과. - OPS변경 파일 1개 —
src/server.jsline 442~474 (fixed 분기 재작성 +12줄 / -2줄). HTML/CSS/JS 무수정. server.js 변경 →--include-server-js필요. 롤백 1명령:py scripts/deploy.py --target=prod --rollback-to v21.0.5.
2026-05-08
V21.0.5 비용분석 — Summary 탭 신설 + 통합 모드 폐지 + 워닝 룰/UX 보강 9건 통합
- FEAT📊 Summary 탭 신설 (디폴트 활성) — 사용자 의도: "각 사업장의 고정성 비용 규모를 한눈에 + 변동성의 변화 흐름 보고 싶다". §1 KPI 4 카드 (DWLG/DWLT/BNCC + 통합) · §2 사업장별 고정비 비교 막대 · §3 사업장별 비용 누적 추이 (16M grouped+stacked 막대 — 월별 3 사업장 그룹, 각 막대 안 고정비(아래)+변동비(위) 누적, 사업장별 색조 진한/옅은 톤) · §4 사업장별 워닝 분포 (Critical/Warning/Info × DWLG/DWLT/BNCC + 상위 3 계정).
- FEAT통합 사업장 모드 폐지 — 헤더 [통합] 버튼 제거, 디폴트 branch = dwlglobal. 통합 정보는 Summary 탭에서만 노출. 변동성/고정비 점검 탭은 단일 사업장 데이터만 처리 → 인지 단순화.
- FIX워닝 모달 차트 신규 + 자동 단위 — 자동 진단 ↔ 거래처 분해 사이에 📈 장기 비용 흐름 차트 (가용 전체 최대 24M, 회계마감 월 색 강조 + 12M 평균 점선). max abs 기반 단위 자동 (원/만/백만/억) → 소액 (266,650원, 15,360원 등) 도 0 떨어지지 않고 정확 표시.
- FIX고정비 점검 탭 본문 빈 화면 픽스 — 사용자 보고: 🔷 고정비 점검 탭 본문 완전히 빈 화면. 원인: HTML
<div class="rd-main dn">의.dn클래스 + CSS.dn{display:none!important}가 JSstyle.display='block'inline 토글 차단. fix:.dn클래스 제거, inline style 만 사용. - FIX부제 텍스트 동적 갱신 — 탭 전환 시 부제가 항상 "V19 변동성 점검" 으로 하드코드 →
rd_updateSubtitle헬퍼 신설, Summary/고정비/변동성 탭별 라벨 자동 변경. - FIX워닝 mismatch — fixed 룰 보강 — 사용자 보고 (BNCC 4 케이스, 거래처 분해 +0% 인데 워닝): step-down 후 새 수준에서 안정화된 fixed 가 매월 false-positive. 원인: 기존 룰이
|MA12 dev|만 검사 → 변동 정지 후에도 평균과의 차이 지속. fix:&& |trueMoM| ≥ 1%AND 추가 → 안정화된 step-down 자동 제외. 추세 정보는 모달 차트 + "평균 대비" 셀에서 노출. - FIX워닝 모달 5칸 → 6칸 + trueMoM 신설 — server.js 의
momPct가 이름과 달리 (last/MA12-1)×100 (12M 평균 편차) — UI 라벨 "전월 대비" mislabeling 의 원인. 신규 필드trueMoM= (last-prev1)/prev1×100 (실제 MoM, 거래처 표 변화율과 일치). 모달 셀 6개: 매출 중 비중 / 전월 대비(trueMoM) / 평균 대비(MA12, 신규) / 평소 대비 / 1년 흐름 / 최근 3개월. CSS 6칸 grid + 1100px 미만 3칸 / 700px 미만 2칸 반응형. - FIX§4 사업장별 고정비 분포 — 통합 분류 강제 (옵션 A) — 사용자 보고: 사업장 필터 변경 시 §4 합계마저 달라짐. 원인:
cost-summary라우트가 사용자 branch 기준 분류 산출 → 같은 계정이 사업장별로 다르게 분류 → set 자체 변동. fix:computeCostSummary시그니처에distClassifications추가, siteDistribution 만 통합(total) 분류 + 통합 계정 set 강제 사용. branch 필터로 §1~§3 만 영향, §4 는 항상 "전사 분류 기준 사업장 분포". - FEATserver.js cost-summary 응답 보강 — Summary 탭 데이터 한 번 fetch 로 처리하기 위해 응답에
siteSeries: {DWLG/DWLT/BNCC: [16M]}+siteSeriesMonths추가. cost-warnings 응답에는byBranch: {사업장: {critical, warning, info, topAccounts}}추가 (3 사업장 워닝 갯수 + 상위 3 계정명, 부하 약 3배). - TESTstaging 검증 — staging 21/21 PASS · 사용자 시각 검증: Summary 탭 §1~§4 정상 노출, §3 누적 막대 차트 정상 (월별 3 사업장 그룹 + 고정비/변동비 누적, 사업장별 색조), 워닝 모달 차트 + 6칸 셀 + 자동 단위 정상, 4 BNCC 안정화 fixed 워닝 자동 제외.
node --check통과. - OPS변경 파일 4개 —
src/server.js(trueMoM + fixed 룰 + siteDistribution 통합 분류 + siteSeries + byBranch, ~80줄) ·src/js/54-view-rowdata.js(Summary 탭 IIFE + 모달 6칸 + 차트 자동 단위 + 누적 막대, ~280줄) ·src/css/54-view-rowdata.css(Summary 스타일 + 6칸 grid 반응형, ~25줄) ·src/부산본부_대시보드.html(Summary 탭 골격 + 탭 변경 + 통합 버튼 제거 + 모달 차트 섹션, ~50줄). server.js 변경 →--include-server-js필요. 롤백 1명령:py scripts/deploy.py --target=prod --rollback-to v20.7.
2026-05-08
V20.7 매출 분석 — 시점 산출 데이터 기반 fallback (4월 마감 미반영 시 3월 자동) + deploy.py 워밍 자동 대기
- FIX
s_currentYearMonth데이터 기반 회계마감 월 fallback — 사용자 보고(2026-05-08, 4월 마감 진행 중): 매출 분석 진입 시 KPI ① 당월 매출 0원 / 12M 끝 라벨 '26.04' 빈 막대. 원인: 캘린더 기반setMonth(d.getMonth() - 1)가 5월 진입 시 무조건 4월 반환 → 4월 마감 미반영(Sales=0) 데이터로 KPI 망가짐. 픽스: 비용분석 V19autoLatestMonth패턴 차용 —_rdCache.db[year].total.{Sales,TotalCOGS}역순 검색 → 첫 양수 월 자동 선택. 결과: 5월 초(4월 마감 전) → 3월 자동 표시. 4월 마감 후 SSE rowdata-watch 자동 갱신 →_rdCache재할당 → 자동 4월 전환 (사용자 개입 0). - OPS
scripts/deploy.py워밍 자동 대기 (wait_for_warmup) — 진단: 컨테이너 재시작 후 Fuel 워커 prewarm 60-80초 (3사업장 × 12개월 = 36 xlsx 순차 파싱) 동안 메인 thread 동기 fallback 으로 fuel-info/facility-info 등 blocking → smoke 1차 시 10/21 timeout(`-1`) 다발./health200 은 워밍 완료를 보장하지 않음. 픽스:wait_for_warmup함수 신설 — 헬스체크 통과 후/api/fuel-info5초 간격 폴링, HTTP 200 + 응답 ≥500B 시 통과 (최대 120s).deploy_normal+rollback_n양쪽 적용 (rollback_to_tag는deploy_normal경유로 자동 상속). 결과: V20.7 staging 재배포 검증 — 41초에 자동 통과 → smoke 1차 21/21 PASS (이전 11/21). - TESTRAW 데이터 검증 —
/api/rowdata-jsondb.2026.total: 2026.04 Sales=0/COGS=0(미마감), 2026.03 Sales=24.47억/COGS=19.19억, 2026.02 Sales=23.61억.node --check src/js/57-view-sales.jsOK. staging smoke 21/21 PASS (1차, 이전 deploy 에서는 워밍 미완료로 11/21). - OPS변경 파일 2개 —
src/js/57-view-sales.js3 위치 (모듈변수_rdCache추가 /loadSalesData의_rdCache = rd갱신 /s_currentYearMonth데이터 기반 분기, +18줄 / -7줄) +scripts/deploy.pywait_for_warmup함수 신설 (+38줄). server.js 변경 0 →--include-server-js불필요. 롤백 1명령:py scripts/deploy.py --target=prod --rollback-to v21.0.4.
2026-05-07
V21.0.4 비용분석 — 평균 변동폭 안의 변동 워닝 일괄 제거 (V21.0.3 안전망 확장)
- FIXInfo 트리거를 isStatOutlier 단독으로 단순화 — 사용자 보고: 복리후생비 의료보험료 (통합) 케이스 — momPct=-10% (변동 있음), 1년 ↓ 하락, 최근 3개월 ↑ 상승, 평소 대비 정상(z-score < 1). V21.0.3 룰 `isLongDown && |MoM|≥1%` 분기로 Info 통과되어 노출. 사용자 결정: "변화가 평균변동폭보다 적거나 아예 없으면 화면에 표시 안하는게 더 좋다". V21.0.4:
isLongDown단독 Info 분기 완전 폐기.isStatOutlier(통계적 이상치) 만 Info 트리거. 추세 정보는 워닝 모달 5셀 + 자동 진단 박스에서 여전히 노출 가능. - FIX안전망 확장 — !isStatOutlier 단독으로 reject — V21.0.3 안전망 (`|MoM|<1 AND !isStatOutlier`) → V21.0.4 (`!isStatOutlier` 단독). 즉 z-score 정상 범위 안의 모든 momPct (점진적 하락 -10% 등) 도 일괄 reject. variable/semi-variable 카테고리에서 평소 변동폭 안의 변동은 워닝 가치 없음. fixed 는 MA12 deviation 룰 별도라 제외.
- TEST영향 — Critical/Warning 룰의
isLongDown && isShortDown분기도 안전망에 의해 isStatOutlier 필수가 됨 (즉 추세 동반 하락만으로는 Warning 안 띄움, 통계 이상치 동반 시에만). 진짜 의미 있는 변동만 워닝 그리드 노출.node --check src/server.jsOK. - OPS변경 파일 1개 —
src/server.jsline 446~462 (level 분기 단순화 + 안전망 확장 ~12줄). HTML/CSS/JS 변경 0. 롤백 1명령:py scripts/deploy.py --target=prod --rollback-to v21.0.3.
2026-05-07
V21.0.3 비용분석 — Info 워닝 룰 강화 (변동 0% 노이즈 제거)
- FIXInfo 트리거 조건 강화 — isLongDown 단독 분류 폐기 — 사용자 보고: 인건비 제수당 연차 같은 계정이 당월=전월=3,907,821원 (변동 0%) 인데도 Info 워닝으로 모달 노출. 원인:
detectVariabilityInfo 룰 (line 446)isStatOutlier || isLongDown→ 1년 시계열 회귀 slope 가 음수면 당월 변동 무관하게 Info 분류. 변경:isStatOutlier단독 Info (통계적 이상치는 의미 있음) +isLongDown && |MoM|≥1%동반 조건. 결과: 1년 하락 추세지만 당월 평탄한 계정은 Info 워닝 안 띄움 (추세는 차트로 확인 가능, 회계팀 사유 입력 불필요). - FIX안전망 가드 추가 — variable/semi-variable 카테고리에서
|MoM|<1% AND !isStatOutlier인 케이스는 level 결정 후 reject (level=null). 어떤 룰로 들어와도 변동 0%+통계 정상 거래처는 워닝 그리드 노출 안됨. fixed 는 MA12 deviation 룰 별도라 제외 안함. - TEST영향 — Info 컬럼 워닝 건수 감소 (이전 노이즈 제거). Critical/Warning 룰은 무수정 → 진짜 변동 거래처는 그대로 노출.
node --check src/server.jsOK. - OPS변경 파일 1개 —
src/server.jsline 443~458 (level 분기 + 안전망 ~10줄). HTML/CSS/JS 변경 0. 롤백 1명령:py scripts/deploy.py --target=prod --rollback-to v21.0.2.
2026-05-07
V21.0.2 비용분석 — detail 키 거래처 단위 단순화 (적요별 분리 폐기, V21.0.1 우회 → 본질적 정리)
- FEATdetail 키 자체를 거래처(Client) 단위로 단순화 — 사용자 결정: "적요별 합산은 안되고 거래처별 합산으로 정리". 이전(V21.0.1):
addDetail의 키가${cli}|${nt}(거래처+적요) 조합이라 같은 거래처여도 적요(Note)가 매월 다르면 별개 entry → V21.0.1 hotfix 가prevByClientmap 으로 우회 매칭만 처리. V21.0.2:key = cli단순화 + Note 필드 제거 → detail 객체 ={Client, Amount, PrevAmount}. 결과: 같은 거래처의 모든 적요가 자연스럽게 합산되어 raw 응답부터 거래처 1행. 워닝 모달 / 카테고리 모달 / 모든 화면 일관성. - FIXPass 1 PrevAmount 룰 단순 키 매칭으로 회복 — V21.0.1 의
prevByClient우회 코드 ~25줄 제거 → 옛 단순 키 매칭 (bd.Details[m-1][tk][ac][k]) 회복. 키가 거래처라 직접 매칭으로 정확. 1월(m=0) → 전년 12월 lookup fallback 보존. 메인 thread (line 2102~) + 워커 인라인 (line 38) 두 곳 모두 동일 단순화. - FIXtopClients 그룹화 코드 단순화 — V21.0.1 의
_byClientmap 그룹화 ~12줄 제거 → 단순 slice(5) + map. detail 자체가 거래처 1행이라 그룹화 불필요. 라인수 감소 + 가독성 회복. - TEST영향 범위 — Note 필드 사용처 grep 결과: V18 IIFE 의
aggregateByClient가 unique Note 수집 (현재 dead code), V19 워닝 모달 / 카테고리 모달 / cost-summary events 어디서도 detail.Note 결정적 참조 없음 → 정보 손실 0. 매출 분석(V20.6) 은buildRowdataJson의 Sales/COGS/SGA 시계열만 사용하고 detail 직접 참조 없음 → 회귀 0.node --check src/server.jsOK. - OPS변경 파일 1개 —
src/server.js4 위치 (메인 addDetail / 메인 Pass 1 / 워커 addD / 워커 Pass 1 + topClients 단순화). HTML/CSS/JS 변경 0. 롤백 1명령:py scripts/deploy.py --target=prod --rollback-to v21.0.1.
2026-05-07
V21.0.1 비용분석 hotfix — 거래처 분해 PrevAmount 산출 버그 픽스 (전월 0원 NEW false positive 다발 해결)
- FIXbuildRowdataJson Pass 1 PrevAmount 룰 변경 — 거래처 단위 전월 합계 — 사용자 보고: 워닝 모달 거래처 분해 표에서 (주)대우로지스틱스 부산터미널 같은 단골 거래처가
당월 37,974,000원 / 전월 0원 / NEW로 잘못 표시되어 워닝 false positive 다발. 원인:addDetail의 detail 키가${cli}|${nt}(거래처+적요) 조합 (server.js:2058) → 적요(Note, X열)가 매월 달라지면 (예: "3월분 보관료" / "2월분 보관료") 같은 거래처여도 별개 키로 분리 → 전월 같은 키 부재 → PrevAmount=0 → NEW. 픽스 — Pass 1 에서 전월 dict 를prevByClient[Client] += Amount로 거래처 단위 합산 사전 빌드 → 당월 각 detail 의 PrevAmount = 같은 거래처 전월 총합 (적요 무관). 결과: 거래처가 매월 거래하면 NEW 가 아닌 정확한 deltaPct 산출. - FIXdetectVariability topClients 거래처 단위 그룹화 — V19 워닝 모달 거래처 분해 표가 거래처별 1행 표시 (스크린샷 참조). 이전: 적요별 row 5개 (같은 거래처 다중 적요면 중복) → 가독성 저하 + 비중 분산. 픽스 —
_byClient[c]map 으로 같은 거래처 다중 적요의 Amount 합산, prev 는 거래처 합산값(Pass 1 보장)이라 max 채택, 합산 후 sort+slice(5). 결과: 거래처별 1행 + 정확한 share/deltaPct. - TEST영향 범위 — buildRowdataJson 변경은
/api/rowdata-json응답의 모든 detail 에 영향 (V18 비용분석 IIFE 와 V19 모두 사용). 단 V18 종합 탭은 폐기 상태 + V19 워닝 모달이 PrevAmount 의 주 사용처라 부작용 거의 없음. 매출 분석 (V20.6) 은buildRowdataJson의 Sales/COGS/SGA 시계열만 사용하고 PrevAmount 직접 참조 없음 → 회귀 0.node --check src/server.jsOK. - OPS변경 파일 1개 —
src/server.js(Pass 1 PrevAmount 로직 ~25줄 + topClients 그룹화 ~12줄). HTML/CSS/JS 변경 0. server.js 변경 →--include-server-js필요. 롤백 1명령:py scripts/deploy.py --target=prod --rollback-to v21.0.
2026-05-07
V19.0.1 비용분석 폴리싱 — 히트맵 호버 텍스트 픽스 + §4 사유 타임라인 폐기 + 이번주 신규 칩 폐기
- FIX히트맵 셀 호버 시 텍스트 흐림 픽스 —
.treemap-cell:hover{stroke:#fff;stroke-width:2;...}가 SVG<g>에 적용되어 자식<text>글리프 외곽이 굵은 흰색 stroke 를 상속받아 글자가 흐릿한 흰 덩어리처럼 보이던 버그. 픽스 —filter:brightness(1.15)만 g 에 적용 +:hover>rect{stroke:...}로 stroke 는 rect 만 타게팅 +.treemap-cell text{stroke:none}안전망. SVG 속성 상속 메커니즘 회피. - FEAT§4 사유 누적 타임라인 섹션 폐기 — 변동성/고정비 양 탭의 timeline 블록 (각 16 lines, 검색바 + 5 필터 + tl-list + tl-summary) 통째 제거. 사유는 §3 워닝 모달 + 📜 변경 이력 모달에서 단독 확인 가능, 별도 타임라인은 회계팀 사용 빈도 낮음. 변동성 탭 §5 매출-변동비 → §4 번호 하향.
rd_renderTimeline함수 본체는 dead code 보존 (Phase 5 일괄 정리).rd_renderAll두 호출 제거. - FEAT"이번주 신규" 칩 폐기 — 추적 칩 바 3 칩 → 2 칩 (사유 입력률 + 미입력 14일+). 비용분석은 월단위 회계 마감 점검 모드라 "7일 이내 신규" 시간 단위가 부적합.
rd_renderTrackChips의 newWeek 산출 로직 (missingDays ≤ 7 카운트) + DOM 갱신 5줄 제거. - TESTstaging smoke 21/21 PASS (워밍 ~5분 완료 후 12:13 KST). cost-classifications/cost-overrides 200 + cost-watch SSE 첫 바이트 0.03s. node --check 양 파일 OK. 빌드 산출물 md5 누적 진화:
aaff3976(V19.0 P3-B+P4-B 완성) →3cf221e9(hover) →81e498ba(timeline) →423f7767(newweek). 최종 1,166,537 B (V19.0 대비 -1,386 B = 3 hotfix 누적 dead 코드 제거 효과). - OPS변경 파일 3개 —
src/css/54-view-rowdata.css+5줄 /src/js/54-view-rowdata.js-8줄 (newWeek + timeline 호출) /src/부산본부_대시보드.html-36줄 (timeline 두 블록 + newweek 칩 + V19 dev-row 신규). server.js 변경 0 →--include-server-js불필요. 롤백 1명령:py scripts/deploy.py --target=prod --rollback-to v20.6.
2026-05-07
V19.0 비용분석 완성 — Phase 3-B 고정비 탭 + Phase 4-B 분류 편집·메모 history 결선 (모듈 100% 완수)
- FEATPhase 3-B 고정비 탭 결선 4 영역 — ①
rd_renderFixKpi()KPI 4 카드 (고정비 합계 / 매출 대비 비율 / 워닝 건수 / 사유 미입력 14일+) + 4 sparkline 결선. 매출 대비 비율 16M 평균 비교, missing14 빨간색 강조, 입력률 % 표시. ②rd_renderStabGrid()안정성 매트릭스 7 small multiples — top 7 by lastAmt, 카드별 stab-card.{ok|warn|crit} 외곽 (워닝 매핑),rd_drawStabMiniChart.js 16M 막대 + MA12 ±5% band 점선 (Chart.js fill:'+1' 으로 band 영역 채움), verdict 칩 4단계 (✓매우 안정/✓안정/⚠ 평년 +N%/⚠ MA12 ±10% 이탈). ③rd_renderDist()사업장×고정비 분포 DWLG/DWLT/BNCC 가로 막대 + share 가중치 max 정규화 + 자동 인사이트 푸터. ④ Tier 4 타임라인 —rd_renderTimeline('fix')기존 함수 scope 인자만 추가로 fixed 카테고리 필터. - FEATPhase 4-B 분류 편집 모달 결선 — V18 stub
rd_openClsModal/rd_clsModSetBranch/rd_saveClsOverrides모두 실구현 교체.rd_clsRenderTable사업장 탭별 cost-classifications fetch (캐시RD19.clsModal.classByBranch[branch]) → 90 계정 × 6 컬럼 표 (계정/현재 분류/자동 r²·CV/오버라이드 select/당월금액/↺ reset).rd_clsOnChange가 select 변경 시pendingSet[key]/pendingUnset[key]누적, 행 dirty 시각 강조 (rgba 245,158,11).rd_clsResetRow가 unset 표시. POST/api/cost-overrides+ If-Match etag 헤더 + X-User-Name encodeURIComponent (V20.3 ISO-8859-1 호환 패턴) 결선. 충돌 409 시 자동 알림. 저장 후 메인 데이터 자동 reload. - FEATPhase 4-B 메모 history 모달 결선 —
GET /api/cost-notes/history?key=&limit=50결선. 워닝 모달 사유 폼 우상단에📜 변경 이력버튼 추가 —rd_openMemoHistory(key)호출 시 해당 워닝 키만 필터, 미입력 시 인자 없으면 전체 history 노출. 5 컬럼 표 (시간/사용자/액션 create·update·clear/키/변경 — before→after diff, memo 40자 ellipsis). 다른 사용자 편집 추적 가능. - FEATserver.js cost-summary 응답 확장 (1줄) —
accounts[].costSeries: hist.costSeries.slice(-16)추가. Phase 3-B 안정성 매트릭스 mini chart 가 16M 시계열을 직접 사용. 50개 계정 × 16개월 = 800개 숫자, 응답 크기 부담 미미. 기존 4 카테고리 응답 모두 동일 필드 노출. - FEATrd_renderAll 양 탭 동시 렌더 + display 토글 — V19 Phase 3-B 정책: 진입/필터 변경 시 변동성 + 고정비 양 탭 모두 렌더 (총 9 영역 + 추적 칩 바),
rd_setTab가display:none토글로 즉시 전환. 시각 비용 대비 사용자 체감 응답성 우수 (탭 전환 ms 단위). RD19.tab 상태 보존. - TESTsmoke.py 18 → 21 항목 확장 —
/api/cost-classifications?branch=total(200/503 워밍 중 정상) //api/cost-overrides(200) / SSE/api/cost-watch(첫 바이트 < 3s) 3 항목 신규.node --check src/js/54-view-rowdata.js src/server.js모두 OK. - DOCSdoLogin 콘솔 에러 — 캐시 문제 확정 — staging 컨테이너
/app/부산본부_대시보드.htmlline 6822-6824 에window.doLogin/doLogout/togglePw = ...정확히 노출됨. 사용자 측Ctrl+Shift+R강제 새로고침으로 해결. 동일 패턴(showView/enterPl/enterDaily 등) 모두 정상. - OPS변경 파일 4개 —
src/js/54-view-rowdata.js+400줄 (Phase 3-B 4 함수 + Phase 4-B 두 모달 결선) /src/server.js+1줄 (accounts costSeries) /scripts/smoke.py+6줄 (3 항목 추가) / HTML dev-row 신규 + V19.3 latest 강등. server.js 변경 →--include-server-js필요. 롤백 1명령:py scripts/deploy.py --target=prod --rollback-to v20.6.
2026-05-06
V19.0 비용분석 — 변동성 점검 + 사유 누적 모드 (Phase 1 백엔드 + Phase 2 HTML/CSS 골격)
- FEATserver.js V19 라우트 7종 신규 (+826줄, 1457→2298) —
GET /api/cost-classifications(자동 분류 5범주: variable/fixed/semi-variable/one-time/tentative) ·GET /api/cost-warnings(회귀잔차 ±2σ + MA12 ±5% + V20.6 12M·3M slope 동반 하락 + 신뢰도 점수 1~4) ·GET /api/cost-summary?cat=fixed|variable|one-time(카테고리 세부 분석) ·GET·POST /api/cost-notes(V20.2 sales-notes 패턴 영속, If-Match etag, X-User-Name) ·GET /api/cost-notes/history·GET·POST /api/cost-overrides(V19.1 facility-overrides 패턴, set/unset) ·GET /api/cost-watch(SSE: notes-changed/overrides-changed/data-changed 3 이벤트).SITE_LABEL = {total:'통합', dwlglobal:'DWLG', terminal:'DWLT', cfs:'BNCC'}매핑 — UI 표시는 BNCC, 데이터 키는 cfs 보존(V18 호환). - FEATHTML view-rowdata V19 골격 교체 — V18 12섹션 종합 탭 폐기, 두 탭 구조(
🔷 고정비 점검/🟠 변동성 점검) + 인라인 필터(사업장 통합/DWLG/DWLT/BNCC + 기간 당월/YTD/전년동기/12M) + 트랙 칩 바(사유 입력률/미입력 14일+/이번주 신규) + 모달 4종(워닝/분류 편집/카테고리/메모 history). D3 v7 CDN 1줄 추가(cdnjs/d3/7.8.5/d3.min.js). portal-hdr 우측에⚙ 분류 편집버튼 신규. - FEATCSS V19 신규 ~440줄 —
mockup_비용분석_v19.html신규 스타일#view-rowdata스코프로 일괄 격리 이식..basics-card(KPI 4 카드, 변동비/고정비/일회성/사유) /.treemap-card(D3 squarified Stock-Heatmap, finviz 패턴) /.warn-grid(Critical/Warning/Info 3분할) /.timeline-card(사유 누적 60일) /.scatter-card(매출-변동비 산점도 + 추세선) /.stab-grid(고정비 안정성 매트릭스 small multiples 7 계정) /.dist-card(사업장×고정비 가로 막대) /.mod-bd·.cls-table·.cat-grid(모달 4종).--cat-variable/fixed/semi/onetime/tentative분류 색 토큰 5종 다크/라이트 분리. - FIX_getRowdataDb 가드 503 (메인 thread blocking 차단) — V18 패턴이 워커 pre-warm 미완료 시 메인 thread 에서
buildRowdataJson()(16M xlsx 파싱) 동기 호출 → node.js single-threaded event loop 점유 → /health 포함 모든 라우트 hang. prod 32시간 가동으로 워밍 끝나 미발현이던 잠재 버그. V19 가드 — 캐시 비어있으면 즉시503 + retryAfter:5 + 한글 메시지throw, cost-classifications/warnings/summary catch 에서err.status우선 반환. 클라이언트 retry 로 안전 우회._extractFullHistory미래 연도 차단 1줄(if (yrInt > endYear) continue;) 추가. - OPSPhase 3·4·5 결선 대기 (JS stub) —
54-view-rowdata.js끝에 V19 IIFE append.enterRowdata진입 시 V19 모드 표시("Phase 3 데이터 결선 대기" placeholder),rd_setTab/rd_setBranch/rd_setPeriod/rd_open*Modal/rd_close*Modal글로벌 노출. ESC 키로 4 모달 일괄 닫기. V18 IIFE 위 영역 (1393줄) 은 종합 탭 폐기와 함께 dead code 보존(Phase 5 정리). - TESTstaging 검증 (PASS) —
node --check src/server.jsOK / staging 재배포 후 V19 7 라우트 모두 정상:cost-classifications90개 계정 자동 분류 (창고일반 기타 → semi-variable r²=0.52 cv=0.32 등) /cost-warnings29건 워닝 (Critical 0 / Warning 14 / Info 15, notesMissingAged 14건) /cost-summary3 카테고리 (fixed: 10 계정 1,260백만 / variable: 2 계정 평균 연동성 76% / one-time: 2 events) /siteDistribution{DWLG:81.4%, DWLT:13.8%, BNCC:4.8%} SITE_LABEL 매핑 정상 / cost-notes·overrides·history 빈 골격 + _etag. 부팅 시/app/data/cost_notes.json·cost_overrides.json자동 생성. 롤백 1명령:py scripts/deploy.py --target=prod --rollback-to v20.6.
2026-05-04
V19.3 사업장 — 16T/25T/3.5T 카드 + 편의시설 사진 슬롯 + CSS 토큰 격리
- FEAT장비 카드 3종 추가 (16T/25T/3.5T) —
v16_renderEquipcats배열에 16톤·25톤·3.5톤 추가. 매핑가이드 §5-2 와 일관 (유류비 모듈에 이미 등록됨). DWLG 엑셀 R49코일발 적용장비="30톤, 16톤, 4.5톤"으로 16톤 존재가 명시되어 있었으나 카드 누락 → 픽스. 카드 노출 순서: 큰 톤 → 작은 톤 (45T → 30T → 25T → 16T → 7T → 4.5T → 3.5T → 2.5T → 입식). 빈 데이터(0/-) 카드 자동 숨김(filter 단계). - FEAT편의시설 amenity 사진 슬롯 —
FAC_AMENITY_SUBFOLDER매핑(caf:'구내식당' / lng:'휴게실 라운지' / smk:'흡연구역' / shw:'샤워실' / gym:'체력단련장' / mtg:'회의실') +FAC_AMENITY_KEYWORDS폴백 +v16_findAmenityImages/v16_updateAmenityImage헬퍼 신규.v16_setAmenTab진입 시 NAS 자산 캐시(/api/facility-assets/{site})에서 첫 매칭 사진을 hero 영역에 자동 노출. 다중 사진 시+N장칩. DWLG 12장(/편의시설/구내식당, 휴게실 라운지, 흡연구역) 기존 미노출 자산 활성화. - FIXCSS :root 토큰 글로벌 오염 픽스 (V18.7.6 사고 패턴 재발 방지) —
:root[data-theme="dark"]/[light]두 블록을:root[data-theme="..."] #view-facility스코프로 격리 +!important일괄 제거. 전역html,body/portal-hdr/menu-card,kpi-card,.../btn,theme-toggle-btn등 6개 글로벌 셀렉터도#view-facility한정으로 변경. 이전: facility의 인디고 토큰(#818cf8)이!important로 다른 뷰까지 덮어씀 → V18.7.6 사고 동일 패턴. 현재: 다른 뷰(손익/일일매출/매출분석/유류비) 토큰·디자인 영향 0, 원칙 11(JS 인라인 제어 속성!important금지) 부합. - DOCS운영팀 안내 문서 2건 신규 —
2.리팩토링_계획/14_DWLT_BNCC_시트_작성_안내.md(영업팀 시트 작성 마감 요청, 워크플로 + P1 항목 우선순위),15_사업장_편집_사용자가이드.md(V19.1 facility-overrides 사용 가이드, 6 섹션 권장 입력값). prod 실측 (2026-05-04): DWLT/BNCC 시트 0행, overrides 사용 이력 0건 — 사용자 인지 보강 필요. - TEST검증 — node --check 60-view-facility.js OK / NFC/NFD 한글 path 정규화 처리 / 변경 파일 5개 (60-view-facility.js +60줄 / 60-view-facility.css 글로벌→스코프 격리 / HTML dev-row 신규 + V20.6 latest 강등 / 가이드 .md 2건). server.js 변경 0 →
--include-server-js불필요. 롤백 1명령:python scripts/deploy.py --target=prod --rollback-to v20.6.
2026-04-30
V20.6 매출 분석 — ⚠ 추세↓ 워닝 룰 신설 (12M+3M slope 이중 분기, 사양서 §10 line 275 종결)
- FEATs_slope(arr, n) 헬퍼 신규 — 시계열 마지막 n 포인트의 least squares 선형 회귀 기울기.
x=0..n-1, 0인 월도 포함 (휴면월도 추세 신호). 분모 0 가드 (n<2또는 모든 x 동일 시 0 반환 → slope 음수 분기 false → 격상 없음, 안전). 단일 헬퍼로 12M·3M 모두 처리 (n 인자만 차이, DRY).57-view-sales.jss_clientSeries직후 신규 12줄. - FEATdrop 분기 4 flag — 12M slope + 3M slope 이중 분기 —
s_computeAnomaliesdrop 분기 (line 941 부근) 에 z-score 직후 추가.slope12 = s_slope(series, 12)와slope3 = s_slope(series, 3)산출 →isLongDown(12M↓) /isShortDown(3M↓) /isBothDown(동반 하락) 3 flag + 반올림 slope 값 2개. drop 객체 구조 확장만 — recover/newCli/stop 영향 0, 기존 워닝 모달 4종 / 거래처 모달 / 변경이력 모달 5종 새 필드 무시 → 시각 회귀 0. - FEATsignals 칩 3분기 (동반 하락 / 장기 only / 단기 only) —
s_renderExistingClientsdrop forEach (line 1278 부근) z-score 칩 다음에 추세 칩 추가.isBothDown→⚠ 12M+3M↓ 동반 하락(neg, 강한 신호) /isLongDown only→⚠ 12M↓ (장기 둔화)(warn) /isShortDown only→⚠ 3M↓ (단기 약세)(warn). z-score📊칩과 시각 일관 (neg/warn 톤). 단일 추세는 칩만, 격상 없음. - FEAT우선순위 격상 — isBothDown 1단계 (z-score 와 OR 결합) —
escalated = x.isStatOutlier || x.isBothDown조합. P3→P2 / P2→P1 / P1→P1 (z-score 와 동일 패턴). z-score AND isBothDown 동시 발생 시 OR 결합으로 격상 1번만 (이중 격상 방지). 단일 추세 (장기 only 또는 단기 only) 는 격상 없음 — 칩만 노출. score 가중치 추가 없음 — 격상 단독으로 정렬 효과 충분. - FEAT권장 액션 4단계 —
isStatOutlier ? '긴급 접촉' : isBothDown ? '추세 점검' : pct < -60 ? '단가 재검토' : '방문 지정'. 순서 = z-score 가 통계적으로 더 강한 신호 (가장 최근 1점 vs 11M 분포) 라 우선, 추세는 3M+12M 모두 음수인 구조적 둔화 → 두 번째. 단일 추세 칩은 액션 변경 없음 (칩만 노출). - OPS변경 파일 4개 — server.js·docker-compose·smoke 변경 0 —
src/js/57-view-sales.js(s_slope +12줄 / drop 분기 +8줄 / signals·격상·액션 +8줄, +28줄 net) / HTML dev-row 신규 + V20.5 latest 강등 / 사양서2.리팩토링_계획/12_매출분석_v1_시안_사양서.md§10 line 275⚠ 추세↓미구현 → ✅ 완료 표기 /CLAUDE.mdV20.6 통합 블록.--include-server-js불필요. 사양서 §10 Phase 1~5 + 추가 보강 룰 모두 ✅ 종결 (단📦 물량 -X%는 박스 데이터 거래처 키 부재로 영구 보류). 롤백 1명령:py scripts/deploy.py --target=prod --rollback-to v20.5.
2026-04-30
V20.5 매출 분석 UX 폴리싱 — 칸반 ellipsis + ≤768px 반응형 + HOT 칩 대비도 + 모달 max-width
- FIX칸반 거래처명 ellipsis — V20.4 신설 신규 잠재고객 파이프라인 칸반의
.lead .ln1에text-overflow:ellipsis미적용 → 긴 거래처명("디더블유엘글로벌 부산터미널" 등)이 카드 폭 초과 시 줄바꿈/넘침.overflow:hidden + text-overflow:ellipsis + white-space:nowrap3속성 추가.<div class="ln1" title="...">title 속성으로 호버 시 전체 거래처명 툴팁 노출. 식별성 보존하면서 카드 폭 안정화. - FIX칸반 ≤768px 1컬럼 반응형 — V20.4 의
@media (max-width:1280px)가 칸반 2컬럼만 처리 → 768px 이하 모바일/태블릿에서 2컬럼 그대로 유지되어 가독성 저하. 신규@media (max-width:768px)블록 —.pipe{grid-template-columns:1fr}+.funnel{flex-direction:column;align-items:stretch}+.funnel-stage::after{display:none}(좁은 폭에서 funnel `›` 화살표 숨김). 칸반 1컬럼 적층 + funnel 세로 stack. - FIXHOT 칩 대비도 강화 — V20.4 의
.tag.hot{background:var(--red-bg);color:var(--red)}가 라이트 테마에서--red-bg(rgba 10%) 옅은 분홍 배경 + 빨간 텍스트 조합으로 다른 회색 칩과 시각 구분 약함.border:1px solid var(--red)빨간 보더 +font-weight:800+letter-spacing:.3px자간 추가. 다크/라이트 양쪽에서 4건의 🔥 HOT/NEW 칩 즉시 식별 가능. - FIXlead 모달 max-width 반응형 — V20.4
#pipelineLeadModal .modal인라인max-width:760px고정 → 좁은 viewport 에서 좌우 여백 명시적 패턴 부재.max-width:min(760px,92vw)로 변경 —.modal글로벌width:min(1180px,96vw)와 일관 패턴. 어떤 viewport 에서도 좌우 4vw 여백 보장. - FEAT파이프라인 분류 룰 단순화 — 결과(X열) 단독 기준 — 사용자 요청 "결과(X열)값을 기준으로 정리, 비어있는 부분은 진행중". V20.4 의
_classifyPipelineStatus가 결과(col 23) 외에 currentStatus(col 22)의 '진행' 포함 여부도 함께 분기 → 결과 채워져 있어도 currentStatus 가 "(진행) 견적 제출" 이면 inprogress 로 가는 케이스 존재. 결과 단독 분류로 단순화 — 결과 빈 값 →inprogress, 결과 채워짐 → 그대로 매핑(불성약→lost,지연→delayed,성약→won). 영업팀이 엑셀에 결과 입력하는 시점이 분류 단일 기준이 됨. - FIX워닝 분류 미세 매출 컷 (drop/recover) — 사용자 staging 검증 중 발견. (주)전산교역이 "회복 신호 거래처 1개사" 로 잡혔으나 12M 합산 0.0억 + 차트 모든 막대 0 (실제 last 가 0.001억 같은 미세값) → "회복인데 그래프에 안 보임" 모순.
s_computeAnomalies의 drop·recover 분기 조건last > 0→last >= 0.01(100만원 floor) 변경. 의미 있는 거래 규모만 워닝으로 잡힘. stop(거래중단)·newCli(신규)는 영향 없음. - OPS변경 파일 4개 (server.js +1줄) —
src/css/57-view-sales.css(line 168 ellipsis 3속성 + line 172 hot 칩 3속성 + @media 768px 블록 신규) /src/js/57-view-sales.js(line 709 modal max-width:min + line 933·948 워닝 floor + line 1507 ln1 title) /src/server.js(line 225-234_classifyPipelineStatuscurrentStatus 분기 제거) / HTML dev-row 신규 + V20.4 latest 강등. server.js 변경 →--include-server-js필요. docker-compose 변경 0. 모든 클라이언트 변경#view-sales스코프 한정 → 8개 기존 뷰 시각 회귀 0. 롤백 1명령:py scripts/deploy.py --target=prod --rollback-to v20.4.
2026-04-30
V20.4 매출 분석 — Phase 5 신규 잠재고객 파이프라인 (Sales Opp Pipeline xlsx 자동 참조)
- FEATTier 4 두 번째 탭 실데이터 결선 — V20.0 정적 mockup (시노트랜스/머스크라인/CMA CGM/ONE Korea 등 사명 + HOT 칩 모두 하드코드, 19개 거래처) 제거. 영업팀이 매주 갱신하는
(요청) Sales Opp Pipeline Mgt__M월 N주차__부산본부_YYMMDD.xlsx의 부산 시트 134행 자동 파싱 → funnel 4 stage + 칸반 4 컬럼 실시간 노출. - FEAT4단계 매핑 — 결과 컬럼 기반 — 시안의 4단계(접촉/제안/협상/계약임박) 가 실제 데이터(현재상황 col 22 = "(진행) 견적 제출"·"(종료) 결과 공지" 단 2 값)와 mismatch → 결과 컬럼(col 23) 기준 4범주(
inprogress/won/delayed/lost) 로 변경. 134건 모두 funnel 노출 (진행중 9 / 성약 45 / 지연 32 / 불성약 48). 사업장 검출 = 비고(col 28) + 제목(col 3) 의DWLG_/DWLT_/BNCC_/터미널/CFS substring 매칭 (DWLG 73 / DWLT 26 / BNCC 35). - FEATHOT 플래그 + 사업장 탭 필터 — 전주비 Status Update (col 29) =
Yes또는New인 행에 🔥 HOT/NEW 칩 표시. funnel·칸반 모두 헤더 사업장 탭 (ALL/DWLG/DWLT/BNCC) 변경 시 자동 재렌더. 칸반은 각 컬럼 상위 5건 + "… N건 더" 합산 footer 형태로 가독성 확보. meta footer 에 sourceFile + 갱신시각 + 표시건수/총건수 노출. - FEATlead 카드 클릭 → 상세 모달 (5번째 모달) — 칸반 lead 카드 클릭 시
#pipelineLeadModal신규 모달 노출. 거래처명·영업담당(Lead/Sub)·거래구분(신규/기존)·거래방식(수의계약/입찰)·서비스구분(자사 인프라/협력)·목표매출·예상매출·현재상황·결과·전주비 Status 10행 grid + 비고 전문 (col 28) + 영업기회 설명 (col 12) 별도 영역 (white-space:pre-wrap, max-height:30vh). server.js parsePipelineXlsx 에 4 컬럼 (col 9·10·11·12) 추가 파싱. ESC/backdrop/✕ 닫힘 일관 패턴 (4 모달 → 5 모달). - FEAT최신 주차 자동 탐색 + chokidar 감시 — server.js
findLatestPipelineFile()헬퍼 —YY년디렉토리 자연수 정렬 → 최신 →M월→M주차가장 최근 → glob(요청) Sales Opp Pipeline Mgt*.xlsx첫 매치. 매주 새 주차 폴더 생성 시 chokidar 30s polling 으로 자동 감지 → SSE/api/sales-pipeline-watch통해 클라이언트 자동 갱신.parsePipelineXlsx+ mtime 캐시 (재파싱 최소화). - OPSdocker-compose 마운트 + server.js 변경 — 신규 마운트
/volume1/부산본부 통합문서관리/영업팀/(회의) 주간 영업회의 보고:/sales-pipeline:ro(prod busan-dashboard-server + staging busan-dashboard-staging 양쪽). environmentPIPELINE_DIR=/sales-pipelineenv 오버라이드. server.js +상수 + 헬퍼 + 2 라우트 (GET /api/sales-pipeline+/api/sales-pipeline-watchSSE) + chokidar + /healthpipeline:true+ 부팅 로그 (~150줄). 변경 파일 4개 (server.js / 57-view-sales.js +200줄 / smoke.py +2 항목 / HTML dev-row + V20.3 latest 강등). compose 변경으로 staging 먼저 down/up + 검증 → prod 승격. 롤백 1명령:python scripts/deploy.py --target=prod --rollback-to v20.3.
2026-04-30
V20.3 매출 분석 — Phase 3 보강 (KPI ④ 모달 결선 + 매출 z-score) + 메모 변경이력 모달
- FEATKPI ④ 모달 4 차트 실데이터 결선 — V20.0 정적 시안의 mockup 데이터 (142개사 / 35·52·68·90% Pareto / 1.61·1.27·0.96억 사업장 평균) 모두 제거.
s_computeModalData(clients, ym, site)헬퍼 신규 (~80줄) — ① 히스토그램 7 buckets (0~0.1/0.1~0.5/0.5~1.0/1.0~2.0/2.0~5.0/5.0~10.0/10.0+ 억) ② Pareto 13 sample 누적 % + 푸터 4 칩 동적 ③ 12M 거래처당 평균 듀얼축 (purple 평균 + accent 활성수) ④ 사업장별 평균 hardcoded bar 동적 교체 (DWLG/DWLT/BNCC/통합 4 row width % + 숫자 + 인사이트 텍스트). KPI 카드 4개 (평균/중앙값/최대/최소) 도 실데이터 산출. - FEAT매출 z-score 워닝 (drop 카테고리) — 사용자 요청 "단가 z-score" 가 raw 데이터에 수량 정보 없어 (Sales Details 의 Note = 텍스트 적요) 구현 불가능 → 매출 자체 z-score 로 대체.
s_computeAnomaliesdrop 분기에prev11 mean/std기반 zScore 산출 +isStatOutlierflag (|z|≥2σ).s_renderExistingClients에서 통계 이상치는 P3→P2 또는 P2→P1 1단계 격상 + score × 1.5 가중 + signals 에📊 |z|=Nσ 통계 이상치칩 추가. 권장 액션도 일반 "방문 지정" → "긴급 접촉" 으로 격상. - FEAT메모 변경이력 모달 — Tier 4 보강 표 행 ✎ 옆에 📜 버튼 추가. 4번째 모달
#memoHistoryModal신규 — 거래처별 메모 set/clear history 시간 역순 (최대 50건) 표시. 시간/사용자/액션/before→after 4컬럼 테이블.GET /api/sales-notes/history?client=&limit=50결선 — V20.2 server 라우트 100% 재활용. 3 모달 → 4 모달, ESC/backdrop/✕ 닫힘 일관 패턴. - FIXX-User-Name 헤더 ISO-8859-1 호환 — 한글 이름 (예: "철운") 이
X-User-Name헤더에 직접 들어가면 HTTP 헤더 스펙(ISO-8859-1) 위반 → fetchthrow 'String contains non ISO-8859-1 code point'. 사용자 staging 검증 중 발견 (메모 저장 실패). 클라이언트 4곳 (sales-notes 1 + facility-overrides 3) 모두encodeURIComponent(userName), server.js_userFromReq가decodeURIComponent안전 처리 (양쪽 라우트 공유 함수, 한 곳 fix). V19.1 부터 잠재 버그였으나 facility 편집 시 영문 이름이거나 미실행이라 미발견. - FIXKPI ④ 모달 인사이트 박스 + 푸터 mockup 잔존 — 사용자 staging 스샷 검증 시 발견. ① 인사이트 박스 셀렉터
.mod-grid:last-of-type .mod-sec:last-child > div:last-of-type가 부모 .modal 의 마지막 div 가 .mod-foot 이라 매치 안 되던 버그 →siteCmp.nextElementSibling으로 단순화. ② 푸터 "▲ 핵심 진단" / "📌 권장 액션" 은 plan 단계 누락으로 V20.0 mockup (14개사 / 43개사 / 52% / 35%) 그대로 잔존 →data.pareto.milestones활용해 동적 갱신 (상위 10% 매출% + 상위 20% 80/20 룰 비교 + 의존도 톤 + 중간층 거래처수). - OPSserver.js 변경 5줄 (FIX 만) — V20.3 본 결선 자체는 server 변경 0 (Phase 3 + 메모 이력은 기존 인프라 재활용). 위 ISO-8859-1 핫픽스로
--include-server-js필요. docker-compose 변경 0. 변경 파일 4개 (57-view-sales.js +200줄 / 60-view-facility.js +3 encode / server.js +5줄 decode / HTML dev-row 신규 + V20.2 latest 강등 + 2 FIX 항목). 사양서 §10 Phase 3 보강 ✅ + Phase 4 메모 이력 UI ✅ + Phase 5 NAS 경로 보강. 롤백 1명령:python scripts/deploy.py --target=prod --rollback-to v20.2.
2026-04-30
V20.2 매출 분석 — 영업 메모 서버 영속 (Phase 4) + git 이력 정리
- FEAT영업 메모 NAS JSON 영속 — 기존
window._salesMemos(메모리 only) →/app/data/sales_notes.json영구 저장. 페이지 새로고침/세션 변경 후에도 거래처별 메모 보존. V20.1.7 까지 메모 입력해도 새로고침 시 사라지던 데이터 유실 문제 해결. - FEATPOST /api/sales-notes — V19.1 facility-overrides 패턴 100% 재사용. 원자적 쓰기 (tmp + renameSync) + 손상 감지 자동 백업 + If-Match etag 충돌 감지 (409) + history 누적 (최대 1,000건). server.js 라우트 3종 신규 (GET / POST / GET history).
- FEATX-User-Name 추적 — facility-overrides 와 동일한
localStorage busan_facility_user_name키 공유. 첫 메모 입력 시 사용자 이름 1회 prompt → 이후 모든 변경에 자동 첨부. history 에서 누가 언제 무엇을 변경했는지 감사 추적 가능. - FEAT진입 시 GET /api/sales-notes 자동 로드 —
loadSalesData()의Promise.all에s_loadSalesNotes()추가. PL/RAW 두 API 와 병렬 fetch → KPI 렌더 직전 SALES_MEMOS 객체 갱신 + SALES_NOTES_ETAG 저장. 메모 로드 실패 시 메모리 only fallback (사용자 알림 안 함, 콘솔 warn 만). - OPSgit 이력 정리 (트랙 A) — V19.1.2 commit 이후 V19.2.x ~ V20.1.7 까지 21개 버전이 commit 없이 prod 까지 배포되어 있던 상태. 단일 누적 commit + tag
v20.1.7부여 →--rollback-to v20.1.7명령 정상 작동. 본 V20.2 배포 후 별도 commit + tagv20.2부여 예정. - OPSserver.js +80줄 / 57-view-sales.js +50줄 / dev-row 신규 / 사양서 §10 Phase 4 ✅. SSE 추가 0 (단일 사용자 가정, facility-overrides 와 동일). docker-compose 변경 0. 롤백 1명령:
python scripts/deploy.py --target=prod --rollback-to v20.1.7.
2026-04-30
V20.1.7 매출 분석 — Canvas reuse 차단 + SSE rowdata-watch 401 픽스 (Tier 5 로딩 영구 잔존 근본 해결)
- FIXCanvas reuse throw 근본 해결 — 사용자 콘솔 분석:
[sales] loadSalesData 실패: Canvas is already in use. Chart with ID '1' must be destroyed before the canvas with ID 'sp1' can be reused. 원인:s_drawSpark가 이전 Chart 인스턴스 destroy 안 하고 재생성 → Chart.js throw → loadSalesData .catch 로 진입 → s_renderAll 미완료 → Tier 5 의 "📊 데이터 로딩 중…" placeholder (V20.1.6) 가 영구 잔존. - FIXs_drawSpark Chart.getChart(c) destroy 추가 — Chart.js v3+ 정적 메서드 활용. 기존 차트 인스턴스 자동 탐지 후 destroy. 다른 차트 (combo/modal/warn/client) 는 모두 인스턴스 reference 유지하며 destroy 했지만 sp1~sp5 sparkline 만 누락. enterSales 1차 더미 → loadSalesData 2차 → MutationObserver 테마 토글 → SSE refresh 등 모든 재렌더 경로 안전.
- FIXSSE /api/rowdata-watch 401 Unauthorized — 사용자 콘솔:
GET /api/rowdata-watch 401두 번. 원인: PL SSE 는?pw=...query string 인증인데 RAW SSE 는 누락. EventSource 가 custom header 못 보내므로 query string 필수.'/api/rowdata-watch'→'/api/rowdata-watch?pw=' + encodeURIComponent(pw)로 PL SSE 와 동일 패턴 통일. - OPS변경 파일 1개 (57-view-sales.js +6줄). server.js 변경 0. 사용자 권장: Ctrl+Shift+R 새로고침 후 콘솔 (F12) 에서 401 + Canvas reuse 에러 모두 사라진 것 확인.
2026-04-28
V20.1.6 매출 분석 — Tier 5 TOP/BOTTOM mockup fallback 차단 (race condition 방어)
- FIXTier 5 mockup 거래처 노출 이슈 — 사용자 보고 "매출거래처 탑10과 감소율 거래처가 적용 안되었어" + 스크린샷에 V20.0 mockup (팬스타라인닷컴/씨엠씨로지스/한진해운로직스 등) 표시. 원인: enterSales 시 1차 더미 렌더 → SALES_DATA = null 상태에서 `var topData = TOP, botData = BOT` (mockup module constant) 사용 → 캐시 또는 race condition 으로 mockup 잔존.
- FIXTOP/BOT mockup 데이터 자체 제거 — `var TOP = [...10개 mockup...]` / `var BOT = [...10개 mockup...]` → `var TOP = []` / `var BOT = []`. 24행 → 4행 (mockup 제거 -20줄). loadSalesData 의 `Array.prototype.push.apply(TOP, s_computeTop10(clients, 'ALL'))` 는 그대로 작동 (빈 배열에 push).
- FEATs_renderBars 3-state 명확화 — `loaded = !!(SALES_DATA && SALES_DATA.clients)` 분기로 ① 미로드 = "📊 데이터 로딩 중…" placeholder ② 로드 + 빈 결과 = "해당 사업장 매출 거래처 없음" / "감소 거래처 없음 — 모든 거래처 안정적" ③ 로드 + 데이터 = 정상 막대 렌더. mockup fallback 경로 자체 차단.
- OPS다른 mockup module constant (PLAN/ACT/WARN_DATA) 는 그대로 — 콤보차트 1차 더미 렌더 + 워닝 모달 정적 데이터 보존 (s_renderWarnCards/s_updateWarnData 가 실데이터로 교체). 향후 동일 이슈 발생 시 동일 패턴으로 제거 가능.
- OPS변경 파일 1개 (57-view-sales.js -20줄 mockup + 5줄 placeholder). server.js 변경 0. 사용자에게 권장: Ctrl+Shift+R 새로고침 (브라우저 캐시 무효화 후 재진입).
2026-04-28
V20.1.5 매출 분석 — Tier 4 보강 표 행 클릭 시 거래처별 연단위 매출 흐름 모달 (3번째 모달)
- FEAT거래처별 연단위 매출 흐름 모달 — 사용자 요청 "기존 거래처 보강의 거래처를 클릭하면 연단위 매출의 흐름". Tier 4 보강 표 어느 행이든 클릭 시 해당 거래처 단일 24개월 매출 분석 모달 (`#clientModal`) 오픈. KPI ④ 거래처 분포 / 워닝 공유 / 거래처 연단위 = 총 3종 모달.
- FEATs_extractClientFull24M(rd, clientName) — `/api/rowdata-json` 의 `db.2025` + `db.2026` 두 해 풀 데이터에서 단일 거래처 24M 시계열 추출 (12 슬라이딩 윈도우와 독립). 반환: `{name, bySite:{DWLG:{y2025:[12], y2026:[12]},...}, total:{y2025, y2026}, dominantSite, siteSums, accNames}`.
- FEAT3 차트 + 6 KPI 모달 구성: ① 연도별 월간 비교 막대 (1~12월, 2025 옅은색 / 2026 진한색) ② 사업장별 24M 분포 도넛 (DWLG/DWLT/BNCC) ③ 24M 시계열 막대 (25.01 ~ 26.12, 마지막 회계마감 월 강조). KPI 6장: 2025 총매출 / 2026 YTD / YoY 변화 / 월평균 / 최대월 / 최소월. 푸터에 트렌드 진단 (성장/감소/유지) + 주력 사업장 비중.
- FEAT모달 헤더 동적 — 거래처명 + 주력 사업장 (색 강조) + 매출 적요 다양도 (예: "운임수익, 보관료수익 외 2종") 표시. 적요별 다양도가 영업 깊이 가시화.
- FEATYoY 동기간 비교 — 2026 1~전월 누계 vs 2025 동기간 누계 % 변화. KPI 3번째 카드에 색상 (양수=초록, 음수=빨강) + 푸터 트렌드 진단 (`+10% 이상 = 성장 / -20% 이하 = 점검 필요 / 그 외 = 모니터링 또는 안정`).
- UI표 행 인터랙션 — `
` + `cursor:pointer` + `title="클릭 — 거래처 연단위 매출 흐름"` 툴팁. 메모 ✎ / 권장 액션 버튼 클릭은 `e.stopPropagation()` 으로 행 클릭 차단 (편집/액션과 모달 오픈 분리). - UI모달 닫기 일관 — 기존 2 모달과 동일 패턴: ESC 키 / backdrop (`.modal-bg`) 클릭 / ✕ 버튼. 닫을 때 차트 destroy + body overflow 복구. 다크/라이트 토글 시 열려있어도 `s_drawClientCharts(window._currentClientData)` 자동 재렌더.
- OPS변경 파일 1개 (57-view-sales.js +220줄). server.js 변경 0. 글로벌 노출: `window.s_openClientModal` / `window.s_closeClientModal`.
2026-04-28V20.1.4 매출 분석 — Tier 3 워닝 4분할 + Tier 4 보강 표 + 워닝 모달 실데이터 결선 (Phase 3 룰 엔진)- FIXTier 3 워닝 4 카드 mockup 데이터 결선 — 사용자 보고 "정합성 안맞는 더미 데이터". V20.0 시안의 하드코드 (한진해운로직스/씨엠씨로지스/케이씨티엘 등) → `s_renderWarnCards(anom)` 동적 렌더. count + 상위 3 거래처 미리보기 (마지막 거래월 / -X% MoM / 첫 거래월 / N개월 휴면) 자동 산출.
- FIXTier 4 보강 표 mockup 데이터 결선 — V20.0 의 7행 하드코드 → `s_renderExistingClients(anom)` TOP 20 동적 렌더. P1/P2/P3 우선순위 점수 산출: 거래중단 = P1 전건 / 매출급감 = P1(12M ≥5억) · P2(≥1억) · P3 / 회복 = P2(12M ≥3억) · P3 / 신규 = P3. 같은 우선순위 내 매출 규모 × 감소율 가중. 자동 시그널 칩 + 영업 메모 + 권장 액션 (긴급 접촉 / 단가 재검토 / 방문 지정 / 감사 인사 / 환영 미팅 / 정기 컨택) 자동 결정.
- FEATs_computeAnomalies 리팩토링 — count → 리스트 반환. `{stop:[], drop:[], newCli:[], recover:[]}` 각 거래처 객체 반환 (n/site/last12/lastSaleIdx/avg3/pct/dormantMonths/series 12M 시계열 포함). 매출 규모 큰 순 정렬. KPI ⑤ 도 `.length` 사용으로 일관.
- FEAT워닝 모달 (4종) 실데이터 결선 — `s_updateWarnData(anom)` 가 `WARN_DATA[stop|drop|new|recover]` 4 엔트리 동적 갱신: 4 KPI (대상/매출 합산/평균 휴면 또는 감소율/P1) + 거래처 표 + 12M 합산 추이 + 사업장 분포 도넛 + 푸터. 카드 클릭 시 모달이 시안과 동일 구조로 실데이터 표시. 행 클릭 시 단독 거래처 chart12 보기 기능 그대로 유지 (V20.0 인터랙션 보존).
- FEAT영업 메모 — 거래처명 기반 (메모리 only). V20.0 의 DOM-based 메모 (재렌더 시 손실) → `window._salesMemos = {clientName: memoText}` 거래처명 기반. site 탭 변경으로 재렌더 시에도 보존. `s_bindMemoHandlers()` 가 ✎ 클릭 시 prompt() → 즉시 시각 갱신 + 메모리 저장. Phase 4 server.js POST /api/sales-notes 영속 결선 예정.
- FEAT날짜 헬퍼 신규 — `s_idxToDate(idx)` (12 슬라이딩 윈도우 인덱스 → 'YY.MM' 표기) + `s_daysSinceMonth(idx)` (해당 월 마지막일 부터 오늘까지 일수). 거래중단 카드 / 모달 / 보강 표에서 "마지막 26.01" / "120D 무거래" 등 자동 산출.
- UIHTML marker 추가 — `data-warn-type="stop|drop|new|recover"` (4 워닝 카드) + `id="existingClientsTbody"` (보강 표) + `id="existingBadge"` (탭 카운트). YTD 매출 컬럼 라벨 → "12M 매출" 정확 명칭. 빈 결과 시 친근 메시지 ("해당 거래처 없음" / "우선순위 영업 대상 없음 — 모든 거래처 정상").
- OPS변경 파일 1개 (57-view-sales.js +260줄). server.js 변경 0. site 탭 변경 시 워닝 4 카드 + 보강 표 + 모달 데이터 모두 자동 갱신 (`s_updateKpiCards` 마지막에 3 render 함수 호출).
2026-04-28V20.1.3 매출 분석 — KPI 5장 정확성 보강 (전월=2월 / 컬러 룰 일관 / 신규·이탈·이상 동적 산출 / 다중 사업장 거래처)- FIXKPI ② 전월 = 2월 (3월 아님) — 사용자 보고 "당월이 3월이면 전월은 2월". `act[site][11]` (3월) → `act[site][10]` (2월) 로 변경. 라벨 "전월 매출 (3월)" → "전월 매출 (2월)". 전월 대비 비교도 (1월 vs 2월) 로 시프트. KPI ① "당월(3월)" 과 의미 명확 분리.
- FIXKPI ① ② 컬러 룰 일관화 — 사용자 보고 "94.2% 둘 다인데 한쪽 초록 한쪽 주황". `s_achvColor(achv)` 공통 헬퍼: ≥100% 초록 / ≥90% 노랑 / <90% 빨강. KPI ① 의 hardcoded `class="val pos"` 도 동적 컬러로 교체.
- FEATKPI ③ 신규 진입 / 이탈 동적 산출 — V20.0 mockup 의 하드코드 +7/-3 → `s_computeChurn(clients, site)` 신규.
신규 = 3월 매출 있음 + 2월 매출 없음/이탈 = 2월 매출 있음 + 3월 매출 없음. 80/20 집중 관리 = 활성 거래처 × 0.2 동적. 게이지 = 활성/전체 비율, 바 pill = net (신규-이탈). - FEATKPI ④ 사업장별 정확 변화 — `s_extractClientSeries` 재구성: 거래처별 `bySite: {DWLG:[12M], DWLT:[12M], BNCC:[12M]}` per-site 시계열 + `totalSeries` 통합 + 주력 사업장 = 12M 합산 최대 사업장. `s_clientSeries(client, site)` 헬퍼로 site 별 시계열 추출. 다중 사업장 동시 거래 거래처 정확 분리.
- FEATKPI ⑤ 이상 거래처 동적 산출 (Phase 3 정식 룰 엔진 전 기초) — V20.0 하드코드 11건 → `s_computeAnomalies(clients, site)` 신규.
중단= 직전 3M 평균 0.5억+ 이지만 가장 최근 0 /급감= 가장 최근 < 직전 3M 평균 × 0.5 /신규= 가장 최근 > 0 + 그 이전 11M 0 /회복= 가장 최근 > 0 + 직전 3M 0 + 그 이전 이력 있음. P1 즉시 조치 = 중단 전건 + 급감 절반 추정. - FEATTOP/BOT site 인자 추가 — `s_computeTop10/Bot10(clients, site)` 가 `s_clientSeries(c, site)` 사용. 다중 사업장 거래처가 site 탭별 정확한 매출 합산으로 표시. 거래처 row의 `site` 속성도 site === 'ALL' 인 경우만 주력 사업장, 외에는 선택된 사업장.
- OPSbackward compat — `c.series` = `c.totalSeries` alias 유지 (워닝 모달 등 기존 코드 영향 0). 변경 파일 1개 (57-view-sales.js +180줄).
2026-04-28V20.1.2 매출 분석 — 헤더 사업장/기간 탭 실동작 결선- FIX헤더 탭 dead 이슈 — V20.0 시안에서 헤더 사업장 탭(
#siteTabs통합/DWLG/DWLT/BNCC)과 기간 탭(#periodTabs당월/YTD/분기/전년동기)이 시각 토글만 하고 데이터 필터는 미연결. 사용자 보고 "버튼 선택시 반영안됨".s_bindTabs()onclick 에 데이터 필터링 로직 추가. - FEAT사업장 탭 (4종) — KPI ① ② ③ ④ + 콤보차트 + sp1·sp2 스파크라인 + Tier 5 TOP·BOTTOM 10 모두 해당 사업장으로 필터. 라벨 우측에
[DWLG]표기. 사업장 게이지 3분할은 cross-site 비교 의도라 그대로(필터 영향 없음). 콤보 모드(#combMode) 와 양방향 sync — 한 쪽 클릭 시 다른 쪽 시각 자동 동기화. - FEAT기간 탭 (4종) —
s_periodWindow(period, ym, labels)신규 헬퍼가 12 라벨 인덱스 윈도우 산출. ① 당월 = 전월 1개월만 (라벨 "당월(3월)") ② YTD = 1월~전월 누계 (기본, 라벨 "3월 누계") ③ 분기 = 가장 최근 완료 분기 (라벨 "Q1 누계") ④ 전년동기 = 당년 1~전월 + 전년 동기간 비교 (KPI ① 두 번째 foot 에 YoY% 표시). - FEAT거래처 site 필터링 — Tier 5 TOP/BOTTOM 이
SALES_DATA.clients에서 currentSite 로 미리 필터링 후s_computeTop10/Bot10재호출. 빈 결과 시 친근한 메시지 ("해당 사업장 거래처 데이터 없음" / "감소 거래처 없음"). KPI ③ 활성 거래처 카운트도 site 필터 적용. - OPS
s_rerenderForFilters()신규 — 사업장/기간 탭 변경 시 KPI 5장 + 콤보 + 스파크 + TOP·BOT 일괄 재렌더. SALES_DATA 미로드 시 더미 데이터로 폴백. 모듈 상태currentSite+currentPeriod추가 (기존 currentMode 와 양방향 sync). - OPS분기 윈도우 산출 —
ym.month % 3 === 0(3/6/9/12) 이면 그 분기 사용, 아니면 직전 완료 분기. 1·2월 효과 월(시스템 2·3월) 시 전년 Q4 자동 시프트.
2026-04-28V20.1.1 매출 분석 — 회계마감 기준 월(전월) 적용- FIX당월 미마감 이슈 — 4월 시점에 4월 매출은 회계마감 전이라 미완성.
s_currentYearMonth()헬퍼가 항상 전월 반환하도록 수정 (`d.setDate(1); d.setMonth(d.getMonth()-1)`). 모든 KPI/게이지/무결성 배너/TOP·BOT delta 가 이 함수 1곳을 통과하므로 한 줄 수정으로 일괄 적용. - UIKPI 라벨 갱신 — "당월 매출 (4월)" → "전월 매출 (3월, 회계마감 기준)". YTD 매출 라벨은 기존 동적 (`(X월 누계)`) 이라 "(3월 누계)" 로 자동 변경. 사업장 게이지 메타도 자동 (`2026-01 ~ 2026-03 누계`).
- FEAT12 슬라이딩 윈도우도 자동 -1 month 적용 — 시안의 `25.05~26.04` → `25.04~26.03` 으로 시프트. 콤보차트 X축, 거래처 시계열, 모든 후속 계산이 회계마감 기준 정합.
- OPS월말 일자 차이 회피 — `setDate(1)` 선행으로 31일에 setMonth(-1) 시 fallback (예: 3/31 → 2/28 자동 보정) 방지. 매월 1일~31일 어느 일자에 진입해도 동일한 전월 결과.
2026-04-28V20.1 매출 분석 — Phase 2 데이터 결선 (사업계획 vs 회계마감 + 거래처 TOP·BOTTOM 실데이터)- FEAT
loadSalesData()빈 함수 → 두 기존 API 병렬 fetch —App.data.pl.ensureLoaded()(50-view-pl 의 RAW 공유) +apiFetch('/api/rowdata-json'). 신규 server.js 라우트 0, 기존 인프라 100% 재활용. - FEATApp.data.pl 공유 노출 — 50-view-pl.js IIFE 마지막에
window.App.data.pl = {RAW, YEARS, TEAMS, ensureLoaded(), reload()}read-only getter 추가 (+12줄). 57-view-sales 가 손익 PL 데이터 직접 read 가능. PL 뷰 단독 동작 영향 0. - FEAT헬퍼 5종 신설 —
s_extractPlan(plRaw)(PL row → {ALL/DWLG/DWLT/BNCC: [12M]}) ·s_extractAct(rd)(rowdata-json db → 동일) ·s_extractClientSeries(rd)(거래처별 12M 시계열 + 사업장 + delta) ·s_computeTop10/Bot10(YTD 매출/감소율 sort). - FEATKPI 5장 + 사업장 게이지 3분할 실데이터 결선 —
data-kpi-id="ytd|monthly|active|avg|anomaly"marker 추가 +s_updateKpiCards/s_updateSiteGauges가 YTD 누계, 당월/MoM, 활성거래처(당월 매출>0), 거래처당 평균, 사업장 달성률(실적/계획) 동적 계산. KPI ⑤ 이상 거래처는 Phase 3 워닝 룰 결선 전 더미 유지. - FEATSSE 자동 갱신 2개 —
App.api.connectSSE('/api/watch?pw=')(PL 파일 변경) +'/api/rowdata-watch'(RAW 변경). 두 SSE 모두 view-sales 활성 시에만 처리 + onerror 시 server-badge "감시 재연결 중" 톤 전환. 원칙 8 헬퍼 경유 (직접 EventSource 금지). - FEAT무결성 배너 — V18.7 일일매출 패턴 차용. 손익 PL 매출 합계(
r.as_누계) vs RAW 비용분석 매출 합계(db.YYYY.total.Sales누계) 차이 ±5% 초과 시 노란 배너(`#s-integrity-banner`) 동적 삽입. ±5% 이내 → 미표시. - FIX
MONTHS_24하드코드 라벨 →s_months24Labels()동적 슬라이딩 (current month back 12). enterSales 시점이 5월/6월/...로 변하면 콤보차트 X축 자동 갱신. - UI
s_refresh()버튼 동작 변경 — 차트 재렌더만 →loadSalesData()(실제 두 API refetch). 첫 진입 시 1차 더미 즉시 렌더 → 2차 실데이터 fetch 후 자동 재렌더 (UX, 기다림 0). server-badge "loading" → "connected" 톤 전환. - OPSserver.js 변경 0 — 사용자 결정(2026-04-28).
deploy.py --include-server-js불필요. 롤백 1 명령:python scripts/deploy.py --target=prod --rollback-to v20.0. - OPSSSOT —
2.리팩토링_계획/12_매출분석_v1_시안_사양서.md§10 Phase 2 체크박스 4/4 완료 · CLAUDE.md V20.1 블록 추가. Phase 3 워닝 룰 엔진 6종 + 모달 거래처 단독 보기 차세대 결선 가이드 유지.
2026-04-28V20.0 매출 분석 (Sales Analysis) 신설 — 5단 Tier 구조 + 모달 2종 (시안 v1 정적 포팅, Phase 2~5 데이터 결선 예정)- FEAT사이드바 운영관리 > 매출 분석 메뉴 신설 (비용분석 위) + 표준 진입점
App.view.enterSales. 매출(top-line) → 비용분석 → 현금흐름 자연스러운 재무 흐름. - FEAT5단 Tier 구조 — Tier 1 KPI Hero × 5(YTD/당월/활성거래처/거래처당평균/이상알림) · Tier 2 사업계획 vs 회계마감 12M 콤보(달성률 점 색상) + 사업장 3분할 게이지 · Tier 3 거래처 이상 4분할 워닝(중단 3/급감 5/신규 7/회복 4) · Tier 4 영업대상 탭(기존 보강 P1~P3 표 + 신규 잠재 칸반 4단계) · Tier 5 거래처 분해 TOP/BOTTOM 10.
- FEAT모달 2종 — 거래처 분포 상세(KPI ④ 클릭, 히스토그램 + Pareto + 12M 추이 + 사업장 비교 + 핵심 진단/권장 액션) · 워닝 공유 모달(Tier 3 4 카드 클릭,
WARN_DATA[type]동적 재구성 — 4 KPI + 거래처 표 + 12M 합산 막대 + 사업장 도넛 + 푸터 진단). ESC + 외부 backdrop 클릭 닫기. - FEAT자동 시그널 + 영업 메모 하이브리드 — 셀 윗줄(자동 시그널 색칩: 📉/🛑/🔄/📊 z-score/📦 물량/⚠ 추세) + 셀 아랫줄(영업 메모 ✎ 클릭 편집). Phase 1 메모리 only(prompt), Phase 4 V19.1 OVERRIDES 패턴 영속 예정.
- UI스코프 격리 — 모든 CSS 셀렉터
#view-sales하위, 함수s_prefix, CSS var--s-blue/--s-purple(+bg) 4종만 로컬 정의. V18.7 A-1 준수::root토큰 추가 0, 글로벌 토큰(--site-*, --pos/neg, --green/yellow/red) 재사용. - UI한국 회계 컨벤션(--pos 빨강 / --neg 파랑) + 사업장 색(DWLG 청록 / DWLT 호박 / BNCC 자홍) 그대로. 1280px 이하 반응형 — Tier 1 5장→3장 / Tier 3 4장→2장 / Tier 2·5 가로→세로 / 칸반 4컬럼→2컬럼. 모달 1100px 이하 grid 1fr.
- UI다크/라이트 자동 추종 —
MutationObserver가data-theme변화 감지 시 콤보·sparkline·TOP/BOTTOM·열려있는 모달 차트 일괄 재렌더 (Canvas 색은getComputedStyle().getPropertyValue('--*')런타임 해석). - OPSv2 진입점 사전 확보 —
loadSalesData()빈 함수 +SALES_DATA상수 자리 코멘트. Phase 2 server.js/api/sales-overview응답으로Object.assign한 줄 교체. - OPS스모크 테스트 16번째 항목 — 빌드 산출물에
id="view-sales"+App.view.enterSales동시 포함 정적 검증(server.js 무수정 단계 — Phase 2 결선 시 API GET 으로 교체 가능). - OPSSSOT —
2.리팩토링_계획/12_매출분석_v1_시안_사양서.md§10 Phase 1 체크리스트 5/5 완료 ·13_매출분석_차세대_지시문.md가 다음 세션 Phase 2~5 진입 가이드. mockup_매출분석_v1.html 폐기 0(시안 SSOT 보존).
2026-04-28V19.2.8 사업장 기본정보 — 헤더 1줄 통합 (2줄 → 1줄)- UI2줄짜리 상단 헤더(
portal-hdr제목줄 +v16-tbar브랜드/사이트탭/편집/뱃지 줄)를 1줄로 통합 — 세로 공간 약 60px 절감. 사용자 보고 "두번째줄 부산본부 대시보드 삭제 + 사업장 클릭 버튼/편집/SERVER HEALTHY 모두 첫째줄로". - UI제거:
v16-tbar컨테이너 ·v16-brand("부" 로고+"부산본부 대시보드"+"integrated ops v1.6") ·v16-link.current("사업장 정보" 칩, 제목과 의미 중복) ·v16-div구분선. 이동:v16-sgrp(DWLG/DWLT/BNCC 탭) +v16-edit-toggle(✎ 편집) +v16-pill(● SERVER HEALTHY) →portal-hdr우측 신규v16-hdr-rightflex 컨테이너로. - UI반응형 —
portal-hdr의 기존flex-wrap:wrap활용으로 좁은 폭에서 우측 그룹 자동 줄바꿈. 추가로@media (max-width:1280px)에서 사이트 버튼·편집·뱃지 폰트 1~2px 축소 + "사업장" 라벨 칩 숨김. - FIX
.v16-2col min-height:calc(100vh - 120px)→calc(100vh - 62px)보정 (2줄 헤더 → 1줄 헤더 높이 변화 반영). - OPSJS 무수정 —
f-tab-DWLG/DWLT/BNCC·v16-edit-toggle·f-theme-btnID 그대로 보존하여f_setSite/v16_toggleEditMode/toggleTheme영향 0. 죽은 셀렉터(v16-tbar/brand/blogo/btt/bsb/link/div/tright) CSS 동시 정리. - OPS
portal-hdr글로벌 클래스(30-layout.css:14-22)는 일일매출·인원·유류비·비용분석·현금흐름 등 다른 뷰가 공유하므로 무수정 — 이번 변경은#view-facility스코프에 한정. 타뷰 시각 회귀 0.
2026-04-28V19.2.7 본부 일정 슬라이드쇼 — 파일명 구분자 _ / - / . / 공백 모두 허용- FIX
hqParseTitle()정규식^(\d{6})_(.+?)…→^(\d{6})[_\-.\s]+(.+?)…— 운영팀이260417-MBC 생방송 부라보 방영1.jpg처럼 하이픈으로 작성한 파일이date:''로 파싱 실패하여 슬라이드쇼 필터(line 2442if (!it.date) return false)에서 즉시 제외되던 이슈 해결. - FIX4/17 MBC 부라보 방영 사진 3장 슬라이드쇼 정상 노출 확인. 향후 운영팀 파일명 자율성(언더스코어/하이픈/점/공백) 확보로 동일 사고 재발 차단.
2026-04-28V19.3 현금흐름 (Cash Flow) 통합 재무 대시보드 신설 (v1 시안 1:1 이식, 데이터 연동은 v2 별도)- FEAT사이드바 운영관리 > 현금흐름 메뉴 신설 (비용분석 다음, 유류비 점검 위) + 표준 진입점
App.view.enterCashflow. - FEAT3탭 구조(SUMMARY / DWLG / BNCC) — 시안 박은경 사원 작성
부산본부_통합재무대시보드.html1:1 이식. SUMMARY 탭 사업장별 KPI 비교 + 통합 현금흐름 차트(spanGaps 정렬) + 예금·대여·차입 합계 카드 3개. - FEAT차트 8개 (Chart.js 기존 로딩분 재사용) — 통합 잔액 라인 + DWLG/BNCC 잔액 라인(빨간 임계선) + DWLG/BNCC 손익(매출·원가 막대 + 영업·순이익 라인 듀얼축) + DWLG/BNCC 안정성 비율(좌 유동/우 부채·차입). 모든 축·텍스트 색은
chartTick/chartTxt헬퍼 적용 (원칙 2, 다크 자동 대응). - FEAT4종 모달(KPI 상세 표 6개월 / Fund 예금·대여·차입 9컬럼 표 + D-day 배지 / PL 월별 손익 / CF 일자별 입출금·잔액·리스크 배지). 배경 클릭 + ESC 키 닫기.
- FEATA4 인쇄 모달 — canvas 3x 재렌더 캡처(저해상 픽셀화 방지) + 편집 가능 부제(
contenteditable) + 펀드 표 3섹션.@media print로 사이드바·topbar 숨김 + body.cf-print-mode 토글. - UI다크 테마 자동 매핑 —
[data-theme="dark"] #view-cashflow셀렉터로 surface/text 토큰만 부드럽게 어두워짐. 글로벌:root미건드림(V18.7 사고 재발 방지). - UI스코프 격리 — 모든 CSS 셀렉터
#view-cashflow하위, idcf-prefix, 함수cf_prefix, CSS var--cf-prefix. 토큰/이름 충돌 0. - UIv2 진입점 사전 확보 —
loadCashflowData()빈 함수 +CF_DATA / PL_DATA / FUND_DATA데이터 상수 자리 주석. 추후 server.js/api/cashflow-info응답으로Object.assign한 줄로 교체.
2026-04-27V19.2 사업장 기본정보 신 엑셀 + 보안 통합 (V19.2 ~ V19.2.6 누적)- FEAT신 엑셀 양식 동기화 —
대시보드 사업장 기초정보_V1.xlsx(시트=사업장 구조, DWLG 174행). FACILITY_PATH env 오버라이드로 1명령 롤백 가능. - FEAT일반현황 8행(R3-R10) + 창고 세부 사항 표(R12-R17 동별 면적·내용) + 자체소방대 트리 조직도(대장→부대장→지휘조직/현장대응조직 8역할).
- FEAT부속장비 3종 추가 (코일발 / 지게차 연장발 / 컨테이너 발판) — 총 부속 카드 6개.
- FEAT엑셀 ⑤보안 섹션 자동 표시 (CCTV 대수·운영시간·보관기간·보안업체·야간순찰·순찰프로그램·비상연락망 7항목).
v16_facSection일반화 헬퍼로 향후 ⑥주차/⑦IT 등 확장 가능. - FEATNAS Assets 서브폴더 자동 매칭 — server.js facility-assets 재귀 스캔(depth ≤ 3).
Assets/{site}/보안/CCTV.png같은 서브폴더 사진을 보안 카드에 자동 노출. 6섹션 매핑(보안/주차/IT/에너지/타임카드/회의실). - UI보안 카드 2컬럼 grid (왼쪽 데이터 + 오른쪽 CCTV/보안 이미지) + 행 라벨 130px 고정/값 왼쪽 정렬로 가독성 개선.
- UI현장사진 그리드는 루트 파일만 표시 (서브폴더 사진은 섹션별 카드 전용으로 분리).
- UI엑셀 매칭 데이터 있는 섹션은 NAS JSON '권장 항목' 카드 자동 숨김 (중복 표기 제거). 자유 항목 카드는 유지.
- UIDWLT/BNCC 시트 추가 전 안내 배너 (4섹션 통합) — override 6섹션은 시트 부재와 무관하게 정상 동작.
- FIX일반현황 '구조' substring 매칭 사고 제거 — '응급구조' 항목 멤버 이름이 잘못 노출되던 버그.
- FIXSMK(제연·방화셔터) 카드 우상단 수량이 '화재 수신기 연동'으로 잘못 표시되던 substring 매칭 버그 → '방화셔터 수량' 정확 매칭(2 개소).
2026-04-27 2026-04-27 V19.1.2소재지 지도 자연 비율 표시- UI소재지 지도 height:180px 고정 → 이미지 자연 비율 (.has-map-img 클래스, BNCC wide 지도 잘림 해결)
2026-04-27 2026-04-27 V19.1.1사업장 자산 사진 API- FEATserver.js /api/facility-assets/:site + /facility-img 정적 서빙 추가 — 3 사업장 (DWLG 7/DWLT 4/BNCC 3 이미지) NAS Assets 폴더 직접 노출
- FEAT소재지 지도 자동 표시 — 00_
지도 파일 매칭 시 v16-map 영역에 img 교체 - FEAT현장사진 자동 캡션 — v16_parseAsset 가 숫자 prefix 제외 후 파일명을 제목으로
2026-04-27 2026-04-27 V19.1V19.1 사업장 편집 오버레이- FEAT6개 예비 섹션(보안·주차·IT·에너지·타임카드·회의실) 활성화 — 권장 스키마 + 자유 row
- FEATserver.js 첫 POST 라우트 도입 — facility-overrides GET/POST/revert/history
- FEAT편집 모드 토글 + 인라인 수정 + 변경이력 + ↺ 되돌리기
- OPS/app/data/facility_overrides.json 영속 (mtime If-Match 동시성)
- OPSsmoke 15/15 staging+prod
2026-04-27 오늘손익현황 onclick 회귀 픽스 (V17 Phase3 노출 누락 3종)- FIXapplyPreset 글로벌 노출 추가 — 상반기/하반기/전체/Q1~Q4 토글 버튼 ReferenceError 해소
- FIXreloadAndRender 글로벌 노출 추가 — 연도 select onchange 정상화
- FIXrefreshData = refreshPlData 별칭 추가 — 숨김 새로고침 버튼 + 에러 재시도 버튼 dead reference 해소
2026-04-26 오늘 · V19.0 유류비 V3.0 — 디자인 + 파서 정정 + 토글 활성화유류비 점검 V3.0 — mockup_v2 디자인 포팅 + parseFuelSheet 5단계 헤더 파서 + 패널 토글 활성화- FEAT3-tier 레이아웃 재정렬 — Tier 1 (핵심 KPI 4 + 24개월 콤보차트) → Tier 2 (워닝 카드 3분할 + 단가 spread + 사업장 도넛) → Tier 3 (사업장 4카드 + TOP 이상치). 기존 12섹션 동일가중 → 위계 명확화.
- FEAT핵심 KPI 4 재구성 — 매출액 대비 유류비 비중(%) · 월 예산 대비 편차(±%) · 단가 스프레드(본부 vs 시장) · YoY YTD 누적 증감액. 1·4번은 server B-2 응답 확장 후 활성, 2·3번은 B-1 데이터로 즉시 표시.
- FEAT점검 5대 원칙 모달화 — 항상 펼친 룰박스 200px 점유 → 1줄 칩 + 클릭 시 모달. 5원칙(4-baseline/단가·수량 분리/z-score/인과분해/신뢰도 점수)을 번호 카드 + 태그로 표현, ESC/외곽클릭/✕ 닫기.
- FEAT필터 바 button group — 기존 select 드롭다운 → 사업장/연도/월 모두 button 그룹(.f3-fb on/off 토글). 일일매출과 일관된 패턴.
- FEAT워닝 배너 동적 톤 — Crit/Warn/Info 0건이면 녹색 톤("정상 범위") + ✓ 아이콘, ≥1건이면 빨간 톤 + ⚠ 아이콘 + 최상위 워닝 자동 노출. "최대 z" 통계 칸 추가.
- FEAT워닝 모달 record-level 분기 — TANK_OVER/CYCLE/DUP_DAY 같은 레코드 단위 워닝은 12개월 합산 시계열 대신 당월 동일 장비 일자별 주유 막대 + 탱크용량 점선 으로 표시. 핵심지표 5셀도 룰별 구성(주유량·탱크·활용률·단가·비용 / 평균주기·최소주기·단축사례 / 일자·동일일횟수·합계). 12개월 합산 룰(PRICE_Z·MoM)은 기존 시계열 유지.
- FEAT패널 토글 활성화 — 단가 스프레드 [사업장별/합산], 도넛 [₩비용/L수량], TOP [탱크활용률/비용/주유량] 토글 핸들러 추가.
FUEL.spreadMode/donutMode/topMode+f3_setSpreadMode/f3_setDonutMode/f3_setTopMode글로벌. 데이터 재계산 없이 차트만 리렌더. - FEAT사업장 4카드 본부 합산 추가 — 본부 합산(보라) + DWLG(시안)/DWLT(핑크)/BNCC(앰버). 평균단가/총비용/주유량/이상건수 4셀 + 점유율%, 단가 임계값 기반 자동 색상.
- FIXparseFuelSheet 5단계 헤더 파서 (server.js 핵심 패치) —
- vehicle+suffix:
4.5톤(7325)-BNCC,16톤(7124)-부원글로벌→ name="4.5톤", id="7325" (사업장/소속사 접미사 무시) - driver:
조문성(4.5T)-04나7459→ name="조문성(4.5T)", id="04나7459" (운전자별 차량 unique) - paren:
45톤장비(8711),30톤(6395),리치(01-1234) - dash:
리치-04나8120,30T-0004가6935,3.5T-004나3796 - aggregate skip:
합계/소계/총계/취합/계/total/sum패턴은continue차단
- vehicle+suffix:
- FIXFUEL_CAPACITY 키워드 보강 — 25톤(300L) · 16톤(200L) · 3.5T·3.5톤(70L) 추가. BNCC 의 25톤장비/16톤, DWLG 의 3.5T 차량 정상 인식. server.js + 55-view-fuel.js 양쪽 동기화.
- FIX전역 토큰 오염 방어 — mockup의
.kpi-card/.warn-card/.panel/.modal등이 20-components.css 글로벌 클래스와 충돌 → 전부.f3-prefix +#view-fuel스코프로 격리. 51-view-daily의:root오염 사고 재발 방지. - FIXKPI 미니 sparkline canvas 늘어짐 차단 —
.f3-kpi-mini-wrap{height:32px;position:relative}+ canvasposition:absolute;inset:0!important. Chart.jsmaintainAspectRatio:false사용 시 부모 컨테이너 고정 높이 필수. - FIX클라이언트 isAggregateRow 2차 방어선 — server 차단 후에도 캐시/구버전 데이터 대비
filterRecords에서 합계/소계/총계/취합 이름 + 미확인 id 의 비정상 주유량 행 제외. - OPS
src/js/55-view-fuel.js805→1041줄 (Hero KPI / 24M 콤보 / 워닝 모달 record-level 분기 / 패널 토글). 데이터 레이어(loadFuelData/computeAll/detectFuelWarnings)는 B-1 그대로. - OPS
src/css/55-view-fuel.css210→255줄. 글로벌 토큰 사용 + 반응형 1280/900 브레이크포인트. - OPS
src/server.js830→849줄 (parseFuelSheet 5단계 패턴 + AGG_HEADER_RE 차단 + isVehicleTypeName 헬퍼 + FUEL_CAPACITY 키워드 추가).--include-server-js배포 + 컨테이너 재시작 필수. - OPSSSOT:
1.기초정보/09_유류비_V2_점검모드.mdV3.0 격상 ·1.기초정보/05_데이터매핑_가이드.md§5 헤더 파서 5단계 추가. 결정사항:2.리팩토링_계획/10_유류비_결정사항.md. 시안:mockup_유류비_v2.html. B-2 인계:09_유류비_B2_사양서.md. - OPS검증: prod (3001) 데이터 222건, unique 장비 22개(DWLG 14 + DWLT 3 + BNCC 5), DUP_DAY 거짓 양성 0건, 사업장 평균단가 1,836~1,840원/L 정상.
2026-04-26 V18.7.6 일자 정확매칭 + 라벨일일매출 V18.7.6 — 4/31 가짜 일자 차단 + 일별 매출 막대 위 백만 단위 라벨- FIX가짜 일자 4/31 표시 제거 — V18.7.x 의
days = Array.from({length:31})가 모든 월에 31일 강제 표시 +endsWith('-' + d)의 우연 매칭으로 4/31에 잘못된 매출 표시되던 이슈.d_monthDays(year, month) = new Date(year, month, 0).getDate()헬퍼로 실제 월 일수만 (4월=30일), 매칭은x.날짜 === d_datePrefix(year, month) + d정확 매칭으로 변경. 통합뷰 stacked + 사업장 단독 + HKNC 모두 적용. - FEATDWLT/BNCC 단독 차트 막대 위 백만 단위 라벨 — DWLG HKNC 차트와 동일한 방식.
datalabels: anchor:'end' align:'top' formatter: round(val/1M)+'M'.layout.padding.top:25로 라벨 잘림 방지. - FEAT미래/초과 일자 콘솔 경고 —
[일자검증] 오늘(N일) 이후 데이터 발견: 사업장 일자 금액 청구처형태로 운영팀 데이터 무결성 모니터링. 월말 초과 일자(예: 4/31)도 같은 경로로 경고. - OPS실측 DWLT 엑셀 검증 — col 1='청구처', col 9='소계', col 10='날짜' 정상 매칭 확인. 데이터 4/01~4/23 까지만 존재. 4/31 표시는 days 배열 + endsWith 매칭 결합 버그였음.
2026-04-26 오늘 · V18.7.5 HKNC 헤더 AND 매칭일일매출 V18.7.5 — HKNC 헤더 "20+수출" / "40+수출" AND 매칭 (사용자 제안)- FEATHKNC 헤더 AND 조건 —
!/^\d{4}/.test(c) && c.indexOf('20')!==-1단순 OR 매칭 →c.indexOf('20')!==-1 && c.indexOf('수출')!==-1AND 매칭. 운영 엑셀 헤더 "20' 수출" 정확 매칭, 4자리 연도(2024)/행 0 "수출작업댓수" 자동 배제, 다른 사업장 미래 양식("20 수출 BOX" 등) 에도 호환. - OPS사용자 검토 단계에서 운영 엑셀 헤더 패턴(
"20' 수출","40' 수출") 직접 확인 → AND 매칭이 가장 명료한 결정. 정규식 보수성과 가독성 동시 확보.
2026-04-26 오늘 · V18.7.4 HKNC 진짜 누적막대일일매출 V18.7.4 — HKNC stack 누적 정상화 + 헤더 정규식 운영 매칭- FIXy.stacked:true — V18.7.3 의
y.stacked:false가 같은 stack 그룹(curr/prev) 의 누적을 막아 4 막대(20ft·40ft × 당월·전월) 가 한 X 자리에 grouped 4 분할로 그려져 시각 구분 불가했던 이슈 해결. 이제 curr stack(진한) + prev stack(옅은) 두 누적 막대가 X 한 자리 옆에 분명히 분리. - FIXHKNC 헤더 정규식 운영 매칭 — V18.7.3 의
/^20(ft)?$/i가 운영 엑셀의 실제 헤더"20' 수출"(작은따옴표+공백) 을 못 잡던 이슈 (fallback 으로 동작 중이었음) →!/^\d{4}/.test(c) && c.indexOf('20')!==-1로 변경. 4자리 연도(2024 등) 는 명시 제외. 콘솔 디버그[HKNC] sheetName headerRow:N date:N pt20:N pt40:N추가. - OPS실측 NAS HKNC 엑셀 헤더 =
('구분', "20' 수출", "40' 수출")형식 확인. 데이터 파싱 자체는 정상이었으나 정규식 강화 영향으로 fallback 의존이 잠복 위험이었음.
2026-04-26 오늘 · V18.7.3 HKNC 가독성 회복일일매출 V18.7.3 — HKNC 도넛/막대 차트 V18.6.1 가독성 회복- FIXHKNC 막대 X축 31일 전부 표시 — V18.7 의
autoSkip:true,maxTicksLimit:16으로 일부 일자(4/16~) 가 가려지던 이슈 → V18.6.1 회복(autoSkip:false,maxRotation:45). 4/01~4/31 모든 일자 라벨 표시. - FIX전월 막대 가시화 — V18.7 의
backgroundColor:'transparent', borderWidth:1로 전월 막대가 사실상 보이지 않던 이슈 → 토큰 색의 rgba .20 채움 + .55 테두리 + 라벨(.70) 으로 V18.6.1 톤 회복. 신규 헬퍼toRgba(hex, alpha)추가. - FIX도넛 라벨 위계 회복 — V18.7 의 "당월/N 전월" 한 줄 → V18.6.1 의 "당월 N (큰 숫자)" + 도넛 아래 "N 전월(작은 회색)" 두 줄 분리 (
.hknc-kpi-row). 20ft/40ft 둘 다 시각 구분 명확. - OPS차트 색은 토큰 기반 유지 (
siteColor('DWLG'/'DWLT')) — 다크/라이트 자동 적응.toRgba가 토큰 hex 를 rgba 로 변환해 다크/라이트 양쪽에서 옅은 색 일관 유지.
2026-04-26 오늘 · V18.7.2 헤더 회복일일매출 V18.7.2 — portal-hdr 글로벌 회복 + "부산본부 관리팀" 칩 위치 시안 매칭- FIXportal-hdr 글로벌 회복 — V18.7 에서
51-view-daily.css의:root정리 시 함께 사라진.portal-hdr/.portal-hdr-l/.portal-title/.portal-sub/.back-btn정의를30-layout.css에 정식 등록. 일일매출 외 인원·유류비·비용분석·사업장 등 다른 뷰의 헤더도 함께 정상화. - FIX"부산본부 관리팀" 칩 위치 — 컨트롤 패널 좌측 → 헤더 우측(서버뱃지 옆) 으로 이관. 새 글로벌 클래스
.badge-team. - FEAT컨트롤 패널 좌측 영업일 경과 — "26년 4월 26일(일요일) · 영업일 N/M일 경과(P%)" 시안과 매칭.
2026-04-26 오늘 · V18.7.1 KPI 톤 회복일일매출 V18.7.1 — KPI 카드 톤 회복 (시안 vs 운영 갭 보정)- FIXKPI 라벨 톤 회복 — 시안의 11px uppercase var(--text2) 가 실제 운영 환경에서 너무 옅어 보이던 이슈 → 14px var(--text) weight 700 + letter-spacing -.2px 로 복원. 기존 V18.6.1 의 "당월 총 매출금액" 톤과 유사하게.
- FIXKPI 숫자 폰트 26px 복원 — 시안의 22px 가 작게 느껴지던 위계 문제 해결. 카드 padding 18px 22px / top stripe 4px / sub padding-top 12px 로 V18.6.1 톤 회복.
- FIXKPI sub 두 토큰(왼/오) 분리 — "전월: X · 증감: Y" 한 줄 → "전월: X" 왼쪽 + "증감: Y" 오른쪽 정렬 (justify-content:space-between). 정보 밀도 ↑, 가독성 ↑.
- FIX5장 grid breakpoint 1280→1480px — 5장 grid 가 좁은 화면(13~15인치 노트북) 에서 카드 폭 부족했던 이슈 → 1480 미만은 3칸, 1100 미만은 2칸으로 자연스럽게 wrap.
- OPS본 패치 범위는 CSS + JS d_kpiCard 시그니처(subLeft, subRight) 확장만. 데이터 흐름·차트·SSE·server.js 모두 V18.7 그대로 유지. 빌드 산출물 md5 갱신.
2026-04-26 오늘 · V18.7 일일매출 리뉴얼일일매출 V18.7 — 12개 결정사항 일괄 적용 (디자인 + 데이터 파이프라인)- FEATCSS 토큰 글로벌화 (A-1) —
51-view-daily.css의:root/body글로벌 오염 제거.--pos/--neg/--surface/--muted/--site-dwlg/--site-dwlt/--site-bncc/--site-total8개 토큰을00-tokens.css다크/라이트 양쪽 정의. 라이트 테마 가독성 회복. - FEATKPI 5장 그리드 (A-3) — 통합뷰: 당월총매출 · 일평균 · 잔여영업일 추정도달 · 청구처합계 · 신규확보. 사업장뷰: 당월매출+점유율 · MoM · YoY · 신규 · 이탈.
businessDaysInMonth/elapsedBusinessDays헬퍼 추가. - FEAT일별 차트 누적막대 (A-2) — 통합뷰 일별 추이를 사업장 stack 으로 변경. 31일 × 1막대 → 라벨 가독성 회복. 차트 5:5 grid 비율로 변경.
- FEAT병렬 fetch (B-2) —
loadDailyData의 직렬 await 7회 →Promise.allSettled1 wave (curr 3 + prev 3 + hknc 동시). 5~7s → 1~2s 단축 예상. - FEAT혼합 파싱 (B-1) — 1차 고정 인덱스(가이드 §2-4) → 키워드 → 숫자 휴리스틱 폴백.
parsedVia메타데이터를d-file-summary에 표기 ("매칭 경로: fixed | keyword | heuristic"). - FEAT두 패널 사전 생성 (B-4) —
d-bottom-overview/d-bottom-site항상 DOM 보유,display토글로 전환.innerHTML통째 교체 + Chart.js destroy/create 깜빡임 제거. - FEAT무결성 배너 (B-6) — 엑셀 합계행 vs 계산 합계 차이 10원 초과 시 노란 배너 + 사업장 칩. 클릭 시 상세(파일명·스킵행) 모달.
- FIX5분 룰 reload (B-3) —
enterDaily가lastFetchAt > 5분이면 자동 reload. SSE 끊김 시refresh-btn.urgent깜빡임 강조. - FIXHKNC 정규식 강화 (B-5) —
'20'단순 검색 →/^20(ft)?$/i.'2024'같은 4자리 연도 텍스트가 pt20Idx 로 잡히던 위험 제거. 헤더 스캔 5행 → 15행. - FIXY축 자동 nice scale (A-5) —
Math.ceil(max * 1.005 / 1억) * 1억강제 라운드 제거 → Chart.jssuggestedMax = max * 1.10. 5천만 매출이 1억 라운드로 막대 절반만 차지하던 문제 해결. - FIX색 hex 인라인 제거 (A-4) —
#3d8eff/#dceeff등 모두 토큰 read (siteColor())..kpi-lbl의color:#dceeff→var(--text2). 라이트 테마에서 안 보이던 KPI 라벨 가독성 회복. - FIX미매칭 합계 청구처명 기반 (B-6 부록) —
matchedOtherAmtsset 의 amount 기반 매칭이 동일금액 두 거래처 수집 누락 → 청구처명 정규화 set 으로 변경. - FIX~$ 임시파일 필터 (server.js) — 엑셀 열려 있을 때 NAS 에 생기는
~$DWLG_*.xlsx가findDailyFiles결과에 포함되어 빈 파싱이 발생하던 위험 제거.!f.startsWith('~')추가. - OPS모바일 모드 활성화 —
isMobileMode가 영구 false 였던 dead code →window.matchMedia('(max-width:768px)')+ change 리스너로 동적 갱신. 모바일에서 KPI/테이블 "만" 단위 표기 작동. - OPS헤더 sub 갱신 + scan-status 조건부 페이드 —
d-hdr-sub가 SSE 후에도 갱신 안되던 문제 →d_setHdrSub()매 fetch 후 호출.d-scan-status정상 1.5s / 경고 5s 페이드. - OPSSSE 인증 변경(B-7)은 보류 —
EventSource헤더 한계로 폴리필 도입이 필요해 별도 보안 패치 PR 로 분리. 현 세션 변경 범위는 디자인 + 데이터 신뢰성으로 한정. - OPS검증 —
node --check14 모듈 + preflight + 인라인 2 블록 OK. 빌드 산출물 md50e3c7915d50e834a431fa55d1d5ae450(564,368 B, V18.6.1 +6,604 B).51-view-daily.js895 → 1009줄,00-tokens.css+6줄(8 토큰),20-components.css+30줄(KPI grid · integrity bar),51-view-daily.css67 → 14줄(빈 슬롯). 결정사항/시안 SSOT:2.리팩토링_계획/05_일일매출_결정사항.md·06_일일매출_디자인시안.html.
2026-04-26 오늘 · V18.6.1 야간 staging인원현황 — 1명 장비 묶기 + DWLT 기사→리치 분류- FEAT장비 카드 — 인원 1명짜리 장비(리치/30t/7t 등) 는 별도 카드로 분리하지 않고 한 카드 안에 세로 한 줄로 묶음(라벨 · 인원수 헤더 + 행마다 "장비명 + 이름"). 2명 이상(4.5t 10명·2.5t 등) 은 기존 별도 카드 유지. 1명짜리 통합 카드를 먼저 배치 → 다인원 카드 순.
- FIXDWLT OS직원 "기사" 직책이 OS직원 풀에 머물던 이슈 — DWLT 는 리치 전용 사업장이므로
getEquipType()에 site 인자 추가, 직책에 "기사" 포함 시 (대홍/지입 키워드 없어도) site === 'DWLT' 면 자동으로 리치 분류 → 리치기사 그룹으로 이동.parsePersonnelExcel호출부도 site 전달. - OPS장비 정렬 순서
equipOrder=['리치','7t','30t','4.5t','2.5t']→['리치','30t','7t','4.5t','2.5t'](큰 톤 → 작은 톤 자연 순서). 통합 카드 헤더 라벨은 " · " 로 구분 (예:리치 · 30t · 7t 3명).
2026-04-26 오늘 · 야간 staging인원현황 조직도 — 정규직/OS직원 세로 스택 배치- FIX인원현황 사업장별 조직도에서 정규직(2/3) + OS직원(1/3) 좌우 분할 시 DWLG 정규직 19명이 가로 스크롤로 잘려 운영팀 일부 인원이 화면에 노출되지 않던 이슈 해결.
renderSite()의regOsHtmlflex row → 단순 concat 으로 변경 → 부모의flex-direction:column / gap:14px가 그대로 적용되어 정규직(위) → OS직원(아래) 세로 스택으로 배치. - OPS각 site 의 정규직 블록이 카드 폭 전체(1/3 page) 사용 → 영업팀·운영팀·관리팀 3카드가 가로 스크롤 없이 표시. OS직원·장비·경비/미화 등 후속 그룹은 기존 흐름 유지(경비+미화는 좌우 그대로).
2026-04-26 오늘 · 야간 staging워닝 모달 — 컨텍스트/권장 액션 섹션 제거- REMOVE비용분석·유류비 워닝 모달의
💡 컨텍스트 (자동 분석)+🎯 권장 액션두 섹션 일괄 삭제. HTML 슬롯(rd-modal-context/rd-modal-actions, fuel2-modal-context/fuel2-modal-actions) 제거 + JS 채우는 코드 + generateContext/generateActions 함수 제거. - OPS모달 5섹션 → 3섹션(헤더·핵심지표·12개월 추이·거래처분해)으로 간소화. 본부장 의사결정에 직접 필요한 데이터만 노출. 자연어 컨텍스트는 B-3 단계에서 정밀하게 재도입 검토.
2026-04-26 오늘 · 야간 staging비용분석 모달 — 거래처 분해를 업체명 단위 합산으로- FIX모달 거래처 분해에서 전월 금액이 모두 0/NEW 로 표시되던 이슈 우회 — 적요(예: '쇼링료/3월') 가 매월 달라 server.js 의
${Client}|${Note}키 매칭이 분리되던 것을 업체명(Client) 단위 합산으로 client side 에서 우회. 같은 거래처의 모든 적요 행을 합산해 당월 vs 전월 비교. - FEAT당월·전월 Details 배열에서 각각 Client 로 group by 한 후 outer join. 1월(m=0)은 자동으로 전년 12월(m=11) Details 참조. 표에
(N/M건)표시 — 당월 적요 N행 + 전월 적요 M행 수. - OPS
08 SSOT 이슈 #1갱신 — V18.5 client-side 우회로 운영 해결. server.js 측 키 정규화 (B-2) 는 선택 사항으로 표기. server.js 무변경.
2026-04-26 오늘 · 야간 staging비용분석 — 차트 24개월화 (전년+올해 동시 표시)- FEAT매출 대비 비율 추이(band)·고정비 추이·변동비 산점도 모두 24개월(전년 12 + 올해 12)로 확장. 연도별 색상 분리(전년=옅음, 올해=강조), Chart.js segment 옵션으로 한 라인 안에 자연스러운 톤 전환.
- FEAT24개월 헬퍼 추가 —
getPrevYear()·months24Labels()·get24mSeries(accessor)·segPrevDim(). 모든 시계열 차트가 같은 패턴으로 통일. - OPSMA·±2σ band·평균은 24개월 valid 기준으로 재산정. 변동비 산점도는 회귀선이 24개 점 합산으로 산출 → 매출-변동비 동조성 가시성 향상. 워닝 모달의 12개월 차트는 이미 24개월화 완료(drawModalChart).
2026-04-26 오늘 · 야간 hotfix[CRITICAL HOTFIX] 로그인 깨짐 —