부산본부 대시보드
Busan Headquarters Dashboard
다시 만나서 반갑습니다
통합 운영 모니터링에 접근하려면 비밀번호를 입력해주세요.
접근 비밀번호
부산본부 대시보드
Integrated Ops v1.6
데이터 현황
손익현황LIVE
일일매출LIVE
인원현황LIVE
운영 관리
매출 분석
비용분석LIVE
현금흐름
유류비 점검
사업장 정보
정보
개발 이력↗
접속시간
포털 · 메인 메뉴
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장일 때는 .single grid 로 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 → 신규 photoList closure 캡처 + 클릭한 인덱스로 진입. ← / → 키로 8장 사진 순환 가능. 사업장 기본정보 탭 사용성 향상.
  • FEAT라이트박스 키보드/접근성 보강 — ESC 닫기 (이전) + ← 이전 + → 다음. 첫/마지막 사진에서 해당 화살표 visibility:hidden 자동. close 버튼 호버 시 빨강 톤. aria-label 3개 (닫기/이전 사진/다음 사진).
  • 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.js OK. 빌드 산출물: 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_json 3시트 (~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= + sseClientsFacility Set + 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개 시각 노이즈. 신규: validAddons filter 적용 + 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) 으로 "회귀잔차" 라벨이 그대로 노출되던 사각지대. detectVariability variable/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.js OK.
  • OPS변경 파일 4개 — src/server.js (_lsRegression valid 플래그 +8줄 · detectVariability fallback 분기 +10줄 · 응답 필드 4개 추가 +6줄 · computeCostSummary ma12DevPct 추가 +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.js line 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} 가 JS style.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 워밍 자동 대기
  • FIXs_currentYearMonth 데이터 기반 회계마감 월 fallback — 사용자 보고(2026-05-08, 4월 마감 진행 중): 매출 분석 진입 시 KPI ① 당월 매출 0원 / 12M 끝 라벨 '26.04' 빈 막대. 원인: 캘린더 기반 setMonth(d.getMonth() - 1) 가 5월 진입 시 무조건 4월 반환 → 4월 마감 미반영(Sales=0) 데이터로 KPI 망가짐. 픽스: 비용분석 V19 autoLatestMonth 패턴 차용 — _rdCache.db[year].total.{Sales,TotalCOGS} 역순 검색 → 첫 양수 월 자동 선택. 결과: 5월 초(4월 마감 전) → 3월 자동 표시. 4월 마감 후 SSE rowdata-watch 자동 갱신 → _rdCache 재할당 → 자동 4월 전환 (사용자 개입 0).
  • OPSscripts/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`) 다발. /health 200 은 워밍 완료를 보장하지 않음. 픽스: wait_for_warmup 함수 신설 — 헬스체크 통과 후 /api/fuel-info 5초 간격 폴링, 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-json db.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.js OK. staging smoke 21/21 PASS (1차, 이전 deploy 에서는 워밍 미완료로 11/21).
  • OPS변경 파일 2개 — src/js/57-view-sales.js 3 위치 (모듈변수 _rdCache 추가 / loadSalesData 의 _rdCache = rd 갱신 / s_currentYearMonth 데이터 기반 분기, +18줄 / -7줄) + scripts/deploy.py wait_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.js OK.
  • OPS변경 파일 1개 — src/server.js line 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 워닝으로 모달 노출. 원인: detectVariability Info 룰 (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.js OK.
  • OPS변경 파일 1개 — src/server.js line 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 가 prevByClient map 으로 우회 매칭만 처리. 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 의 _byClient map 그룹화 ~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.js OK.
  • OPS변경 파일 1개 — src/server.js 4 위치 (메인 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.js OK.
  • 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_drawStabMini Chart.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/부산본부_대시보드.html line 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.js OK / staging 재배포 후 V19 7 라우트 모두 정상: cost-classifications 90개 계정 자동 분류 (창고일반 기타 → semi-variable r²=0.52 cv=0.32 등) / cost-warnings 29건 워닝 (Critical 0 / Warning 14 / Info 15, notesMissingAged 14건) / cost-summary 3 카테고리 (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_renderEquip cats 배열에 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.js s_clientSeries 직후 신규 12줄.
  • FEATdrop 분기 4 flag — 12M slope + 3M slope 이중 분기 — s_computeAnomalies drop 분기 (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_renderExistingClients drop 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.md V20.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:nowrap 3속성 추가. <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 _classifyPipelineStatus currentStatus 분기 제거) / 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 양쪽). environment PIPELINE_DIR=/sales-pipeline env 오버라이드. server.js +상수 + 헬퍼 + 2 라우트 (GET /api/sales-pipeline + /api/sales-pipeline-watch SSE) + chokidar + /health pipeline: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_computeAnomalies drop 분기에 prev11 mean/std 기반 zScore 산출 + isStatOutlier flag (|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) 위반 → fetch throw '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 + tag v20.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-28
V20.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-28
V20.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-28
V20.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 필터 적용.
  • OPSs_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-28
V20.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-28
V20.1 매출 분석 — Phase 2 데이터 결선 (사업계획 vs 회계마감 + 거래처 TOP·BOTTOM 실데이터)
  • FEATloadSalesData() 빈 함수 → 두 기존 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% 이내 → 미표시.
  • FIXMONTHS_24 하드코드 라벨 → s_months24Labels() 동적 슬라이딩 (current month back 12). enterSales 시점이 5월/6월/...로 변하면 콤보차트 X축 자동 갱신.
  • UIs_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-28
V20.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-28
V19.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-right flex 컨테이너로.
  • 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-btn ID 그대로 보존하여 f_setSite/v16_toggleEditMode/toggleTheme 영향 0. 죽은 셀렉터(v16-tbar/brand/blogo/btt/bsb/link/div/tright) CSS 동시 정리.
  • OPSportal-hdr 글로벌 클래스(30-layout.css:14-22)는 일일매출·인원·유류비·비용분석·현금흐름 등 다른 뷰가 공유하므로 무수정 — 이번 변경은 #view-facility 스코프에 한정. 타뷰 시각 회귀 0.
2026-04-28
V19.2.7 본부 일정 슬라이드쇼 — 파일명 구분자 _ / - / . / 공백 모두 허용
  • FIXhqParseTitle() 정규식 ^(\d{6})_(.+?)… → ^(\d{6})[_\-.\s]+(.+?)… — 운영팀이 260417-MBC 생방송 부라보 방영1.jpg 처럼 하이픈으로 작성한 파일이 date:'' 로 파싱 실패하여 슬라이드쇼 필터(line 2442 if (!it.date) return false)에서 즉시 제외되던 이슈 해결.
  • FIX4/17 MBC 부라보 방영 사진 3장 슬라이드쇼 정상 노출 확인. 향후 운영팀 파일명 자율성(언더스코어/하이픈/점/공백) 확보로 동일 사고 재발 차단.
2026-04-28
V19.3 현금흐름 (Cash Flow) 통합 재무 대시보드 신설 (v1 시안 1:1 이식, 데이터 연동은 v2 별도)
  • FEAT사이드바 운영관리 > 현금흐름 메뉴 신설 (비용분석 다음, 유류비 점검 위) + 표준 진입점 App.view.enterCashflow.
  • FEAT3탭 구조(SUMMARY / DWLG / BNCC) — 시안 박은경 사원 작성 부산본부_통합재무대시보드.html 1: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 하위, id cf- 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-27
V19.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.1
V19.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 핵심 패치) —
    1. vehicle+suffix: 4.5톤(7325)-BNCC, 16톤(7124)-부원글로벌 → name="4.5톤", id="7325" (사업장/소속사 접미사 무시)
    2. driver: 조문성(4.5T)-04나7459 → name="조문성(4.5T)", id="04나7459" (운전자별 차량 unique)
    3. paren: 45톤장비(8711), 30톤(6395), 리치(01-1234)
    4. dash: 리치-04나8120, 30T-0004가6935, 3.5T-004나3796
    5. aggregate skip: 합계/소계/총계/취합/계/total/sum 패턴은 continue 차단
    분기 룰: driverWithVehicle 매칭 시 첫 그룹이 차종 키워드 포함 여부로 vehicle+suffix vs driver 자동 판단. 이전 버그: paren 만 매칭해 DWLG 16명 4.5T 운전자가 모두 id="4.5T" 로 합쳐졌고, BNCC 4.5톤 5대가 id="BNCC" 로 합쳐져 동일일 다중 주유 거짓 양성 8건 발생.
  • 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} + canvas position:absolute;inset:0!important. Chart.js maintainAspectRatio:false 사용 시 부모 컨테이너 고정 높이 필수.
  • FIX클라이언트 isAggregateRow 2차 방어선 — server 차단 후에도 캐시/구버전 데이터 대비 filterRecords 에서 합계/소계/총계/취합 이름 + 미확인 id 의 비정상 주유량 행 제외.
  • OPSsrc/js/55-view-fuel.js 805→1041줄 (Hero KPI / 24M 콤보 / 워닝 모달 record-level 분기 / 패널 토글). 데이터 레이어(loadFuelData/computeAll/detectFuelWarnings)는 B-1 그대로.
  • OPSsrc/css/55-view-fuel.css 210→255줄. 글로벌 토큰 사용 + 반응형 1280/900 브레이크포인트.
  • OPSsrc/server.js 830→849줄 (parseFuelSheet 5단계 패턴 + AGG_HEADER_RE 차단 + isVehicleTypeName 헬퍼 + FUEL_CAPACITY 키워드 추가). --include-server-js 배포 + 컨테이너 재시작 필수.
  • OPSSSOT: 1.기초정보/09_유류비_V2_점검모드.md V3.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('수출')!==-1 AND 매칭. 운영 엑셀 헤더 "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-total 8개 토큰을 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.allSettled 1 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.js suggestedMax = max * 1.10. 5천만 매출이 1억 라운드로 막대 절반만 차지하던 문제 해결.
  • FIX색 hex 인라인 제거 (A-4) — #3d8eff/#dceeff 등 모두 토큰 read (siteColor()). .kpi-lbl 의 color:#dceeff → var(--text2). 라이트 테마에서 안 보이던 KPI 라벨 가독성 회복.
  • FIX미매칭 합계 청구처명 기반 (B-6 부록) — matchedOtherAmts set 의 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 --check 14 모듈 + preflight + 인라인 2 블록 OK. 빌드 산출물 md5 0e3c7915d50e834a431fa55d1d5ae450 (564,368 B, V18.6.1 +6,604 B). 51-view-daily.js 895 → 1009줄, 00-tokens.css +6줄(8 토큰), 20-components.css +30줄(KPI grid · integrity bar), 51-view-daily.css 67 → 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()의 regOsHtml flex 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행 수.
  • OPS08 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] 로그인 깨짐 — 복구
  • FIXsrc/HTML 끝부분 </script></body></html> 누락으로 main inline script 미닫힘 → 브라우저 파싱 비정상 → doLogin is not defined 로그인 불가. 끝부분 복구 + 모듈 추출 안내 코멘트 정리.
  • OPSbuild.log 분석으로 V18.3 만 inline_blocks=1 (V18.2까지 모두 2)인 것 단서로 추적. node --check src inline 2 blocks OK 회복 확인.
2026-04-26 오늘 · 야간 staging
비용분석 — 용어/5대원칙 팝업화 (룰박스 컴팩트)
  • UI룰박스가 화면을 너무 차지하던 문제 해결 — 룰박스 본체를 한 줄(타이틀 + 📖 용어·원칙 보기 + ⚙ 사업장별 기준 편집)로 축소.
  • FEAT용어 해설 8칩 + 5대 원칙 카드 5개를 신규 팝업 모달(rd-rules-modal)로 분리. 📖 버튼 클릭 시 풀화면 팝업, ESC/외곽클릭/✕ 닫기. body overflow:hidden 처리.
  • OPS기존 보드/차트 영역으로 화면 확보. 본부장 의사결정에 필요한 KPI/워닝/차트가 first-fold 에 더 들어옴.
2026-04-26 오늘 · 야간 staging
비용분석 — 용어 해설 + 사업장별 KPI 기준 편집
  • FEAT5대 원칙 룰박스 상단에 용어 해설 영역(8칩: MoM·YoY·MA12·Plan·σ·z-score·waterfall·등급) 추가. 5대 원칙 카드 본문은 본부장이 즉시 이해 가능한 한글 표현으로 전면 재작성.
  • FEAT사업장별 KPI 기준 구조 도입 — KPI_TARGETS_BY_BRANCH (DWLG/Terminal/CFS 별 cogsRatio/cogsCritical/sgaRatio/sgaCritical/opRatio/opCritical 6값). 전체는 사업장별 매출액 가중평균으로 자동 계산.
  • FEAT기준 편집 모달 신규 — 사업장 3 × 임계값 6 매트릭스 인풋, 입력 즉시 가중평균 미리보기, localStorage 저장(busan_dashboard_kpi_targets_v1), Default 복원 버튼. ESC/외곽클릭 닫기. 룰박스 헤더의 ⚙ 버튼으로 진입.
  • FIXrenderAll() 진입부에서 KPI_TARGET = computeKpiTarget(RD.selBranch) 재계산 → 모든 KPI 카드/보드/차트가 사업장 전환 즉시 해당 기준 반영.
  • OPScss 추가 ~125줄(.rd-glossary, .rd-pill, .rd-target-editor-*, .rd-tgt-*). B-2 진입 시 server.js env 로 이관 권장 (08 SSOT §7 갱신).
2026-04-26 오늘 · 야간 staging
비용분석/유류비 — 'CFO' 문구 일괄 제거
  • FIXHTML view-rowdata 헤더 💰 비용분석 (RAW) — CFO 점검 모드 → 💰 비용분석 (RAW), 룰박스 타이틀 ⚙️ CFO 점검 5대 원칙 → ⚙️ 점검 5대 원칙.
  • FIXview-fuel은 본문 텍스트에 'CFO' 노출 없었음. dev-history 팝업의 두 뷰 dev-row 4건에서 CFO 표현 제거.
  • OPSSSOT 파일명 변경: 08_비용분석_V18_CFO점검모드.md → 08_비용분석_V18_점검모드.md, 09_유류비_V2_CFO점검모드.md → 09_유류비_V2_점검모드.md. 모든 참조(CLAUDE.md, 03·05·08·09 SSOT, JS·CSS 코멘트) 동기화.
  • OPSstaging (3002) 재배포 + smoke 검증. prod 승격 대기.
2026-04-26 오늘 · 야간 staging
유류비 점검 V2.0 — 점검 모드 (B-1)
  • FEATsrc/js/55-view-fuel.js 전면 재작성 (248→553줄). 5대 원칙 유류 도메인 적용 + 12섹션 구조. 워닝 룰 7개(단가 z-score·단가 MoM·수량 MoM·비용 MoM·탱크 초과·주유 주기·동일일 중복) + 신뢰도 점수 1~4.
  • FEATsrc/css/55-view-fuel.css 신규 작성 (~210줄). #view-fuel 스코프 + .fuel2- prefix. 워닝 배너·룰 박스·KPI 미니그리드·목표 보드·워닝 카드 3분할·TOP 이상치·사업장 4카드·모달 5섹션.
  • FEATHTML #view-fuel 슬롯 12섹션 확장 (워닝배너·룰박스·KPI·목표보드·워닝카드·인과분해 placeholder·단가 ±2σ band·산점도·TOP·사업장비교·드릴다운·모달).
  • OPS새 SSOT 1.기초정보/09_유류비_V2_점검모드.md 작성 (15섹션, 본부장 결재 항목 5가지 명시). 08번(비용분석 V18) 패턴 미러링.
  • FIX기존 V1 의 트렌드 차트 필터 정합성 문제 해결 (KPI는 필터·트렌드는 전체 → 모두 일관). 사업장 점유율 도넛을 주유량→비용 점유율 로 교체 (의사결정 적합).
  • OPSB-1 frontend-only 구현 (server.js 무변경). B-2(가동시간·거래처 컬럼·trendsBySite)·B-3(시장 ref·Plan 연동·인과분해 waterfall) 인계는 09 SSOT §11 명시.
  • OPSstaging (3002) 배포 + smoke 15/15 통과 (md5 326500493e00cb7ba5dcc0371e3419d3, 518,393 B). prod 승격은 본부장 결재 후 진행.
2026-04-26 오늘 · 야간
V18.0 · 비용분석 (RAW) 점검 모드 — mockup v3 적용 (B-1)
  • FEAT비용분석 뷰 전면 재설계 — 단순 차트 2개·테이블 1개 → 점검 5대 원칙 적용 풀 대시보드. 워닝 배너 + 룰 박스 + KPI 4개(4-baseline 미니그리드) + 목표·임계값 보드 + 워닝 카드 3분할(Critical/Warning/Info) + 인과분석 placeholder + 매출 대비 비율 추이(±2σ band) + 변동/고정비 분리 + TOP10 + 사업장 비교 + 드릴다운 테이블.
  • FEAT워닝 모달 시스템 — 워닝 카드 클릭 시 5섹션 상세 팝업(핵심지표·12개월 추이 ±2σ band·거래처 분해·자연어 컨텍스트·권장 액션). 거래처 분해는 server.js Details[m][typeKey][acc] 활용. ESC/외곽클릭/✕ 닫기 + 차트 자동 destroy.
  • FEAT워닝 검출 (B-1 임시 룰) — MoM 매출비% ±2%p / ±5%p 임계 + 절대금액 ±20% / ±50%. 신규 계정(이전 3개월 0) 자동 Info. 변동/고정비 마스터(운반·외주·연료=변동, 임차·감가=고정) 하드코딩(B-2 단계 회계팀 협의 후 보정). KPI 목표값 환경변수화 준비(KPI_TARGET 객체).
  • FEATsrc/css/54-view-rowdata.css 신규 작성(280줄, mockup v3 톤 #view-rowdata 스코프). 모달은 .rd-modal-* 별도 클래스. 다른 뷰와 충돌 0.
  • FEATsrc/js/54-view-rowdata.js 전면 재작성(260→760줄). 기존 /api/rowdata-json (server.js buildRowdataJson) 응답 그대로 활용 + 추가 API 0개. 차트 6개(band·variable·fixed·waterfall placeholder·cogsTop·sgaTop) + 모달 차트 1개. SSE 자동 갱신 유지.
  • OPSB-2/B-3 단계 안내 명시 — 워닝 카드·드릴다운 테이블·KPI 미니그리드에 "B-2", "B-3" 표시로 다음 단계에서 추가될 기능을 사용자에게 미리 노출. B-2: server.js 4-baseline(YoY/MA12/Plan) + z-score + 변동/고정 분류 + 신뢰도 점수. B-3: 인과분석 waterfall + 사업계획.xlsx 연동 + 거래처 단가 추적 + 자연어 컨텍스트 자동 생성.
2026-04-26 오늘 · 저녁
V17.4.1 · 비용분석 데이터 파일명 ROW → RAW 변경 (404 픽스)
  • FIX비용분석 (ROW) → 비용분석 (RAW) — 사용자 측에서 데이터 파일명을 ROW-비용분석.xlsx → RAW-비용분석.xlsx 로 변경. server.js 가 기존 파일명을 못 찾아 /api/rowdata-info 가 404 반환 → 사용자에게 "로드 실패 · API 오류 404" 표시되던 이슈 해결.
  • FIXserver.js ROWDATA_FILENAME 상수 변경(line 61). HTML 섹션 타이틀 💰 비용분석 (ROW) → 💰 비용분석 (RAW), 로딩 메시지 2개(HTML + JS), 코멘트 6곳 동기화. 내부 식별자(view-rowdata · RD · rd_* · /api/rowdata-*)는 회귀 위험 회피 위해 호환성 그대로 유지.
  • FIXdocker-compose.yml 환경변수 — ROWDATA_FILENAME=ROW-비용분석.xlsx 가 양쪽 컨테이너에 박혀 있어 server.js default 를 덮어씀. RAW-비용분석.xlsx 로 변경 + docker compose up -d 로 재생성(restart 만으로는 env 반영 안됨). docker-compose.yml.bak_<ts> 백업 동시 생성.
  • FIXSERVER_HOST 하드코딩 제거 — 00-app-init.js 의 SERVER_HOST: '1.254.6.240:3001' 평문 → window.location.host 동적 결정(http:// 진입 시) + 1.254.6.240:3001 폴백(file:// 진입 시, 원칙 13 보존). 이전: staging 3002 페이지가 항상 prod 3001 API 호출하여 staging 검증 무의미했음. 이제 같은 origin 자동 매칭.
  • OPS문서 동기화 — 1.기초정보/03_모듈별_기능기획.md 모듈 6 타이틀 + 데이터 출처, 1.기초정보/05_데이터매핑_가이드.md 6장 타이틀 + 파일 경로(원칙 5·10).
  • OPS배포 — staging(3002) 먼저 빌드/배포 → 사용자 검증 → prod(3001) 승격. scripts/smoke.py 15/15 통과 확인. 인라인 <script> 2블록 + 모듈 14개 node --check OK(원칙 19).
2026-04-26 오후
V17.4 Phase 4·5 완료 · 파이프라인 강화 (sentinel/node--check/SFTP/롤백/preflight 분리/smoke)
  • FEATbuild.py V17.4 sentinel을 양쪽 코멘트 포함 형태(/*__BUSAN_INLINE_*__*/)로 변경. 부재/중복/잔존 모두 빌드 중단(원칙 19 자동화). node --check 모듈 14개 + preflight.js + src 인라인 2블록 자동. dev-row 검증 추가. bindfs invalidate 범위 src/HTML→src/HTML+css/*+js/*+preflight 확장.
  • FEATdeploy.py V17.4 SFTP 우선 + base64 폴백 (실패 시 자동 전환), 자동 롤백(헬스체크 실패 시 backup 자동 cp + 재시작 + 재헬스체크), --rollback N(직전 N번째 백업) / --rollback-to TAG(git tag 빌드 재생성) 옵션, SynologyDrive 동시 복사(SYNCDRIVE_LOCAL 자격증명 활용).
  • FEATpreflight.js 분리 file:// 진입용 IIFE 셸을 src/preflight.js(53줄, 3,041 B)로 분리. build.py가 /*__BUSAN_INLINE_PREFLIGHT__*/ sentinel에 주입. 원칙 13(file:// 더블클릭 보존) 그대로.
  • FEATsmoke.py 신설 15개 자동 검증 (8 GET API + 4 SSE 첫바이트<3s + Auth 401 + build/NAS md5 일치 + preflight IIFE 본문 포함). scripts/smoke.py --target=staging 1 명령 + --json 옵션.
  • OPSscripts/new-entry.py 신설 — dev-history 엔트리 CLI(원칙 17 자동화, 이전 row latest 클래스 자동 제거). scripts/new-view.py 신설 — 신규 뷰 IIFE 패턴 스캐폴딩(JS+CSS 양쪽).
  • OPSKPI 실측 — 빌드 583ms(< 2s 충족), 배포 ~5s(< 30s 충족). 빌드 산출물 387,827→388,175 B(+348 = preflight 헤더 코멘트). md5 c2d3a705…→2842ef2a…. Phase 4·5 완료, Build-Inline Hybrid 100% 완수.
2026-04-25 오늘 · 오후
V17.3 Phase 3 · JS 14개 파일 분리 (Build-Inline Hybrid 완성) + I-4 종결
  • FEAT인라인 <script> 메인 블록(약 5,400줄)을 src/js/*.js 14개 파일로 분리. 인프라 7개(00-app-init · 10-common · 20-api · 30-chart · 40-theme · 41-auth · 42-view) + 뷰별 7개(50-view-pl · 51-view-daily · 52-view-personnel · 54-view-rowdata · 55-view-fuel · 60-view-facility · 90-devhistory). Phase 2 의 CSS 분리(14파일)와 함께 Build-Inline Hybrid 완성: 개발은 모듈 파일로, 배포는 단일 HTML 로(원칙 13 SynologyDrive 로컬 더블클릭 보존).
  • FEATscripts/build.py 가 {{INLINE_CSS}} + {{INLINE_JS}} 양쪽 placeholder 처리. JS 도 prefix 정렬 concat(00→10→…→90). 뷰별 모듈은 IIFE 래핑 + window.App.view.enterXxx Phase 3 표준 진입점 + window.* onclick 호환성 글로벌 노출 패턴 적용. 인프라 7개는 평면 전역 + onclick 핸들러 호환성 유지.
  • FEATI-4 종결: 50-view-pl.js 상단 const PLAN_SHEET_NAME = '26년 사업계획 집계'; 상수 분리. 매년 1월 여기 한 곳만 수정하면 됨(이전: HTML 본문 2곳 직접 수정 필요). server.js 는 별도 변경(deploy.py --include-server-js 활용).
  • OPSscripts/deploy.py 에 --include-server-js 옵션 추가(Task #15) — V17.2.1 paramiko 일회성 스크립트 우회 정식화. scripts/_safe_commit.py 신설 — bindfs sandbox .git/index.lock 잔존 우회(plumbing + ref 직접 갱신 + reflog append + .git/index sync). 다음 세션 인계 시점부터는 cp /tmp/git-idx-phase3-* .git/index 강제 sync 가 매 commit 후 권장.
  • OPSHTML 6,949 → 1,490줄 (-78.6%), 372,895 → 384,417 B(빌드 산출물, 모듈 코멘트 포함으로 약간 증가). 메인 인라인 <script> 본문이 14개 src/js/*.js 파일로 분산되어 단일 HTML 편집 시 무관한 기능까지 깨지는 문제(CLAUDE.md §6) 완전 해결. 인라인 <script> 2블록 node --check 양 블록 OK(원칙 19).
  • OPS검증 — staging(3002) 모듈 4개(daily/personnel/fuel/rowdata) 시점 + 7개 모두 추출 후 시점에 사용자 육안 검증, 8개 뷰 + 다크/라이트 토글 시각 회귀 0 확인. Git 태그 v17.3. 이슈 I-1·I-2·I-3·I-4 모두 종결. 외부 UI 동작 V17.2.1 과 완전 동일(JS 모듈 분리·IIFE 래핑만, 동작 변경 0).
2026-04-25 오후
V17.2.1 · I-2 가마감 dead code 제거 (Phase 3 사전 정리)
  • REMOVEHTML 가마감 블록 일괄 삭제 — enterGamagam()·GM 상태 객체·loadGamagamData()·refreshGamagamData()·동적 컬럼 파싱·차트·SSE(App.api.connectSSE) 등 메인 305줄 + 진입점 5줄 + 전역 플래그(gamagamLoaded) 3곳 + showView views 배열의 'view-gamagam' 엔트리. 총 306줄 감소. 메뉴/onclick/링크 등 사용자 진입 경로 0개를 사전 검증 후 제거.
  • REMOVEserver.js 가마감 영역 일괄 삭제 — DATA4_DIR 상수, findGamagamFiles(), /api/gamagam-info·/api/gamagam-file·/api/gamagam-watch 3개 라우트, sseClients4 Set, chokidar 폴더 감시, /health 의 data4 키, 부팅 로그 1줄. 957 → 830줄 (-127줄). node --check OK.
  • OPSsrc/css/53-view-gamagam.css 1줄 코멘트로 비움 — 슬롯 보존하여 향후 재활성화 시 같은 prefix 재사용 가능. build.py CSS concat 영향 0. 개발이력(#dev-history-source) 안 가마감 언급 3곳(line 199·410·412)은 역사 기록으로 의도적 보존.
  • OPSHTML 7,259 → 6,949줄 (-310), 385,410 → 369,915 B (-15.5KB / -4%). md5 86b9ea14… → 86a64d9e…. 인라인 <script> 2블록(preflight 50줄 · main 3,833줄) node --check 통과(원칙 19).
  • OPSscripts/deploy.py 가 HTML 전용 업로드 한계 — server.js 변경분은 paramiko 일회성 스크립트로 staging+prod NAS 직접 업로드(/volume1/docker/busan-dashboard*/server.js). 컨테이너 재시작 시 새 server.js 로드. 다음 세션 deploy.py 에 --include-server-js 옵션 추가 예정.
  • OPS이슈 I-2(가마감 뷰 DOM 부재 dead code) ✅ 종결(2026-04-25). Git 태그 v17.2.1. 외부 UI 동작 V17.2 와 완전 동일(가마감은 원래 사용자 진입 경로 0이라 시각/기능 회귀 없음).
2026-04-25 오늘 · 정오
V17.2 Phase 2 · 인라인 CSS 14개 파일 분리 (Build-Inline Hybrid)
  • FEATHTML 인라인 <style> 블록 3개(메인 1551줄 + 두번째 252줄 + nested v16-facility 151줄, 총 1953줄)를 src/css/*.css 14개 파일로 분리. 00-tokens · 10-base · 20-components · 30-layout · 40-view-login · 41-view-menu · 50~55-view-* · 60-view-facility · 90-devhistory. 단일 HTML 편집 시 무관한 기능까지 깨지는 문제(CLAUDE.md §6) 해결의 핵심 단계.
  • FEATscripts/build.py 가 src/css/*.css 정렬 concat 후 {{INLINE_CSS}} placeholder 치환. ORDER 는 prefix 정렬(00→10→20→30→40→41→50→…→90)로 cascading 우선순위 최대 보존. 빌드 후 단일 HTML 산출(원칙 13 SynologyDrive 로컬 더블클릭 보존).
  • FEATnested <style> 버그 정리 — line 2259 빈 <style> + line 2261 <style id="v16-facility-design"> + line 2415 orphan </style> 의 잘못된 중첩 구조를 단일 <style> 블록으로 통합.
  • OPSscripts/deploy.py upload_via_b64 함수를 16KB 청크 base64 append 패턴으로 정식 반영(인계 §2-A). paramiko exec_command 단일 heredoc 500KB+ EOFError 회피. scripts/build.py 시작부에 mv 2회 rename 으로 bindfs 캐시 invalidate 추가(인계 §2-B, Windows Edit 후 Linux sandbox stale capping 방지).
  • OPS검증 — staging(3002) 먼저 배포 → 사용자 육안 검증(다크/메뉴/슬라이드쇼) prod(3001) V17.1 과 시각 동일 확인. 셀렉터 카운트 일치(.menu-card 15·.login-box 5·v16- 269·:root[data-theme] 5). 인라인 <script> 2블록 node --check OK(원칙 19).
  • OPSHTML 크기 377,607 → 382,586 B (+5KB CSS 영역 코멘트만), 줄 수 7,140 → 7,243 (+103). md5 a69a3b61… → dd485cf0…. Git 태그 v17.2. 외부 UI 동작 V17.1 과 완전 동일(CSS 분리·코멘트 추가만).
2026-04-24 어제 · 오후
V17.1 Phase 1 · App 네임스페이스 + 공통 헬퍼 3종 도입
  • FEATwindow.App.* 네임스페이스 신설 — App.common/api/chart/theme/auth/view/util 7개 스텁 + 기존 평면 전역(SERVER_HOST·SERVER_PW)을 App.common SSOT 와 동기화. 원칙 6(전역 상태 네임스페이스) 충족.
  • FEATApp.api.apiFetch(path, opts) 도입 — URL 자동 prefix, 인증 헤더 자동, 실패 시 err.status/err.response 보존 예외. 기존 fetch 16 사용자 호출 중 15 치환(로그인 1개만 입력 pw 특수성 때문에 raw 유지). 원칙 9 충족.
  • FEATApp.api.connectSSE(path, {onmessage,onopen,onerror}, label) 도입 — 지수 백오프(1→30s) 재연결, 호출자 close() 취소 가능. 5개 SSE(손익·일일·인원·가마감·비용분석) 전부 이관. 이슈 I-3(가마감·비용분석 SSE 재연결 누락) 종결. 원칙 8 충족.
  • FEATApp.chart.chartTxt/chartTick/chartSurf — 기존 chartTxt/chartTick/chartSurf 함수를 App.chart 에 이관(별칭). return chart*( 패턴 22 사이트 App.chart.* 네임스페이스로 일괄 치환. 원칙 2(Canvas var() 미해석) 재확인.
  • OPS배포 전 인라인 <script> 2블록 node --check 전부 OK (원칙 19). scripts/build.py copy-through + 청크 base64 업로드 (SFTP 미가용 NAS 환경 대비). staging(3002) 먼저 배포 → md5 bit-exact 검증 후 운영(3001) 승격. 자동 백업 _backup_auto_20260424_081815.html.
  • OPSHTML 크기 371 → 375KB (+3.7KB), 줄 수 7,024 → 7,125 (+101). md5 f9acbb9d… → 2c362cc9…. Git 태그 v17.1. 외부 UI 동작 V16.1 과 완전 동일(구조 리팩토링만).
2026-04-22 심야
v1.6 · 사업장 기본정보 전면 재설계
  • UI사업장 기본정보 뷰(view-facility)를 전면 재설계. 상단 `v16-tbar`(브랜드 · DWLG/DWLT/BNCC 3버튼 · 데이터 연동 pill) + 좌측 2열 구조(232px `v16-sbar` + `v16-main`) 도입. 좌측 사이드바에 활성 4개(기본정보/하역설비/소방설비/편의시설) + 비활성 6개(보안·주차·IT·에너지·근태·회의실 "준비중")를 명시적으로 노출해 향후 확장 로드맵을 UI 로 가시화. 기존 V15 표 레이아웃 대비 정보 밀도 약 40% 향상.
  • FEAT기본정보 섹션에 KPI 4종(부지 면적·연면적·층수·준공) + 위치 카드 + "일반현황/건축·규모" 2-카드 + 현장사진 4-그리드 + 라이트박스 줌(`v16_openImage`). 하역설비 섹션에 6대 지게차 표(작업/용도/제원/부착물/유류/검사일) + 3개 보조장비(DRM/YRP/FRK) 카드. 소방설비 섹션에 9종 법정 설비 + 자위소방대 조직도(3단계). 편의시설에 탭 6종(탈의·휴게·식당·주차·정자·트럭수리).
  • FEAT디자인 CSS 는 `#view-facility` 스코프 + `v16-*` 클래스 프리픽스로 완전 격리 — 기존 손익/일일/인원/비용 등 7개 뷰의 스타일과 상호 간섭 없음. V15 기존 `enterFacility()`·`loadFacilityData()`·`/api/facility-info`·`/api/facility-assets/:site` 는 그대로 재사용(데이터 플로우 0 변경). 엑셀 파일(`04_사업장_기본정보_입력양식.xlsx`) 갱신 시 페이지도 자동 반영.
  • OPS배포 전 `node --check` 로 인라인 `<script>` 본문 구문 검증(원칙 19 준수). 기존 V15 대비 추가 JS 약 +600 줄, 추가 CSS 약 +19KB. 전체 HTML 크기 ~331KB. 사이드바 버전 표기 `Integrated Ops v1.6`.
2026-04-22
오늘 (V15)
FIXV15 슬라이드쇼 자동전환 차단 해제 (prefers-reduced-motion 가드 제거)
  • V15 FIX: startHqAutoplay() 내부 prefers-reduced-motion: reduce 가드가 Windows 전역 "애니메이션 표시" 비활성화 PC 에서 자동전환을 차단하던 버그 해결. V14 배포 후 사용자 PC 에서 재현 확인. 접근성 설정은 추후 수동 토글로 대체 예정
  • 진단 로그 추가: autoplay 시작/스킵 시 console.info("[hq] ...") 출력 — F12 DevTools Console 탭 에서 [hq] autoplay start — n=6, interval=3000ms 확인 가능
  • 방어적 초기화: startHqAutoplay() 진입 시 HQ.paused = false 명시적 리셋 — 이전 세션의 터치/포커스 이벤트가 paused=true 로 남아 있던 회귀 방지
2026-04-22
어제 (V14)
UIFIXFEATV14 슬라이드쇼 5일 필터 + V13 메뉴 그리드 제거 + doLogin 구문 에러 복구
  • CRITICAL 복구: V13 배포본 HTML 이 openDevHistoryWindow 내부 CSS 템플릿 문자열 중간(line 5937)에서 단일따옴표 쌍이 깨지며 파일이 297,263 bytes 로 잘려 있었음 → doLogin is not defined 참조 오류로 로그인 불가. V12 pristine 백업(312,038 bytes)에서 복구 후 재작업
  • V14 5일 필터: loadHqSlides() 내 클라이언트 사이드에서 오늘 포함 최근 5일(오늘·어제·2·3·4일 전) 사진만 표시. 파일명 YYMMDD_내용.jpg 의 날짜 접두사를 Date 객체로 파싱, _cutoff 와 비교해 필터링. 필터 후 0 장이면 컴포넌트 숨김
  • V13 메뉴 그리드 제거: "데이터 현황 / 운영 관리" 6 개 .mcard 블록 삭제. 좌측 사이드바 내비게이션과 중복이었음. 랜딩이 환영 박스 + 본부 일정 슬라이드쇼 2단 구성으로 단순화. .hq-slides-track max-height 380 → 560 px
  • V13 라이트박스: hqOpenOriginal 을 window.open('_blank') 에서 인페이지 오버레이로 전환. 고정 오버레이 위 max-width:80vw/max-height:80vh. 이미지·배경·✕·ESC 중 무엇이든 누르면 닫힘
  • V13 자동전환 버그 수정: mouseenter → HQ.paused = true 가 대면적 슬라이드쇼에서 자동 전환을 영구 정지시키던 회귀. 호버 기반 pause 제거, 포커스(키보드)·터치·visibilitychange·라이트박스 오픈 시에만 pause
  • 교훈: ①대용량 HTML 에 인라인 CSS를 문자열 concat 으로 쓸 땐 따옴표 충돌 위험이 높으므로 template literal + 별도 변수 또는 외부 CSS 로 분리, ②배포 전 반드시 node --check 로 추출한 <script> 본문 검증 (CLAUDE.md 원칙 19 신설), ③대면적 UI 에 호버 pause 금지 (원칙 18)
2026-04-22
오늘 (이전)
UIFEATV12 본부 일정 사진 슬라이드쇼 — 랜딩 페이지 카드형 스와이프
  • V12 "반갑습니다, 부산본부 관리팀" 환영 박스 바로 아래 에 카드형 사진 슬라이드쇼(#hq-slides) 신설 — 3 초 자동 재생 + 좌/우 슬라이드 전환(translateX) + 사진 클릭 시 원본 새 탭
  • 사진 소스: /facility/본부 일정 사진/ (NAS File Station 직접 업로드, :ro 볼륨) — 파일명 규칙 YYMMDD_내용.jpg 에서 날짜 접두사·확장자 자동 제거 후 캡션 표시, 내용만 출력
  • 서버 측: server.js 에 /hq-photos(static 서빙, maxAge:5m) + /api/hq-photos(인증 필수, @eaDir·시스템 파일 필터, 파일명 역순 = 날짜 내림차순) 2 개 엔드포인트 추가
  • 접근성: W3C ARIA APG carousel 패턴(role="region", aria-roledescription="carousel", aria-live="polite") + 키보드 내비게이션(←/→/Home/End) + 포커스 시 자동재생 일시정지 + prefers-reduced-motion 준수 + 좌/우 화살표·점(dots) 네비게이터
  • 인터랙션: 터치 스와이프(threshold 40 px) + 호버/포커스 시 자동재생 일시정지, 휠·키보드 시 재시작 — 0 장 시 컴포넌트 숨김, 1 장 시 화살표·점 숨김 등 적응형 렌더
  • 교훈: 이미지 서빙은 기존 /images 라우트 재사용 금지 (FACILITY_DIR/Assets 고정) → 별도 /hq-photos 라우트로 분리, 회귀 없이 병행 운용
2026-04-22
이전
UIFIXV7 file:// 배너 오버레이 + V8 개발 이력 팝업 창 재구성
  • V7 file:// 자동 리다이렉트(V5 방식)가 최신 Chrome/Edge "file:// → http:// unsafe load" 정책에 차단되어 빈 화면이 되는 회귀 발생 → IIFE + DOMContentLoaded 기반 상단 주황 배너 오버레이(#local-preview-banner) + "NAS 에서 열기" 앵커로 사용자 클릭 기반 이동 으로 전환. 로컬 파일에서도 본 UI 정상 렌더
  • V8 V6 에서 메뉴 뷰 최하단에 인라인 렌더링되던 <details> 개발 이력 섹션을 사이드바 "정보 > 개발 이력 ↗" 버튼 + 새 팝업 창(980×860) 으로 승격. window.open() + document.write 로 독립 CSS 렌더링, 본 창의 다크/라이트 테마 동기화, 인쇄/닫기 버튼, @media print 인쇄 친화 CSS 포함
  • 데이터 소스는 <div id="dev-history-source" hidden> 로 본 문서에 보존 — 팝업은 이 DOM 을 outerHTML 로 복제해 렌더
  • 교훈: 새 창의 document.write 는 "이미 파싱된 현재 문서 덮어쓰기" 와 달리 about:blank 상태라 정책 제한 없음. 단, 사용자 제스처 핸들러 안에서만 호출해야 팝업 차단 회피
2026-04-21
어제
UI모던 미니멀 디자인 이식 & 당일 안정화 (V1–V6)
  • V1 모던 미니멀 CSS 오버레이 이식 — 사이드바 + 카드 그리드, Pretendard Variable 폰트, 이모지 → SVG mask-image 전환
  • V2 반응형 4구간(데스크톱·태블릿·모바일·초소형) + inline-style override 패턴 적용
  • V3 backdrop-filter 제거 + 인터랙션 레이어 명시 — 메뉴 카드 클릭 미반응 치명 버그 해결
  • V4 display:flex !important 제거 — 로그인 화면과 메뉴 화면이 동시 표시되던 이중 노출 버그 해결
  • V5 file:// 진입 시 안내 화면 + 5중 폴백(카운트다운·meta refresh·수동 버튼·setInterval·throw) — 로컬 사본 더블클릭 UX 개선
  • V6 개발 이력 타임라인 섹션 신설 (현재 섹션)
2026-04-20
성능·테마
PERF로딩 성능 최적화 & 테마 일관성 정비
  • CDN defer 인시던트 & 긴급 롤백 — Chart·XLSX 전역 TDZ 장애 → DOMContentLoaded 안전 호출 규칙 수립
  • pre-warm 상시화 — /api/fuel-info 응답 ~0.015 s 상시 달성, 재시작 후 25 s 자동 워밍
  • 라이트 모드 차트 라벨 가독성 — Chart.js Canvas 에 CSS var() 금지 원칙 수립, chartTxt()/chartTick() 헬퍼 도입
  • 뷰 겹침·테마 토글 일관성 — showView() views 배열 정비, WCAG AA 텍스트 대비 달성
  • 청구처 순위 정렬 기준 토글 신규 기능 — 영업/대표 관점 UX 반영
2026-04-17
운영
FEAT유류비 점검 뷰 추가
  • 장비별 주유량·주기 분석 · 사업장별 비교 리포트
  • 36개 월별 파일 pre-warm 루틴 추가 (서버 기동 시 순차 로딩)
2026-04-16
정비
FIX사업장 기본정보 뷰 보완
  • 시설 현황·인프라·보관능력·전경사진 섹션 정비
  • facility 볼륨 마운트 경로 점검 (I-1 이슈 지속 추적)
2026-04-10
기획
FEAT사업장 기본정보 뷰 기획 & 초기 구현
  • DWLG·DWLT·BNCC 3개 사업장 시설 데이터 구조 정의
  • facility 폴더 마운트 및 이미지·JSON 서빙 엔드포인트 설계
2026-04-09
데이터
OPS정부지원사업 메일링 · rowdata 점검
  • gov-mailer 컨테이너 운영 루틴 정비 — 정부지원사업 알림 자동화
  • rowdata JSON 캐시 워커(Worker Thread) 정합성 점검
2026-04-08
기능
FEAT일일매출현황 수정 · 정부지원사업 챗봇 POC
  • 일일매출 청구처별 분석 로직 · SSE 실시간 갱신 (15 s 재연결)
  • 정부지원사업 챗봇 응답 포맷 초안 검토
2026-04-07
수정
FIX가마감 작업 · 로그인 비밀번호 오류 수정
  • 가마감 뷰 SSE 연동 초기 설계 (현재는 dead code — 재활성화 대기)
  • 로그인 x-dashboard-password 헤더 전달 오류 수정
2026-04-06
배포
OPSNAS 배포 자동화 (paramiko 기반)
  • nas_oneui_deploy.py 스크립트 도입 — base64 청크 업로드(60 KB) + md5 검증 + docker restart + health check 일원화
  • SSH 키 인증(id_ed25519_nas) 전환 — 비밀번호 입력 제거
2026-04-04
구현
FEAT대시보드 구현 초안 & 데이터 구체화
  • 손익현황·일일매출·인원현황 3대 핵심 뷰 HTML 구조 작성
  • 엑셀 시트 → JSON 매핑 규칙 정의 (연도 경로 패턴 포함)
2026-04-03
시작
OPS프로젝트 착수 — NAS 인프라 설계
  • Synology DS720+ 단일 Docker 컨테이너(Node.js) 아키텍처 확정
  • /volume1 데이터 마운트 (data1·data2·data3·data4·data5 + facility) 구조 정의
  • 포트 3001 게시 · 내부망 단독 서비스 결정
📊 부산본부 손익현황
NAS 서버 연결 대기중
연결 중...
데이터 불러오는 중...
NAS 서버에 연결하고 있습니다
⚠️
연결 실패
서버에 접근할 수 없습니다.
연도: |
기간
선택: — Ctrl+클릭으로 복수선택
부산본부 전체 요약
사업장별 P&L 현황
전년 동기 대비 (YoY)
100% 이상 달성
90~99% 근접
90% 미만 미달
단위: 억원 (소수 1자리)
—
—
🔄 파일이 변경되었습니다. 데이터를 다시 불러옵니다...
—
—
전년(억원) = 전년도 실적
당기(억원) = 당기 실적
달성율 = 당기실적 ÷ 당기계획
전년比 = (당기 − 전년) ÷ |전년| × 100  |  ▲ 이익증가 / 비용감소  ▼ 이익감소 / 비용증가
👥 부산본부 인원현황
NAS 서버 연결 중...
연결 중
인원 데이터 불러오는 중...
비상연락망 파일을 가져오고 있습니다
⚠️
로드 실패
📊 인원 현황 요약
🎂 이달의 생일자
🏢 사업장별 인원 편성
📅 부산본부 일일매출현황
NAS 서버 연결 중...
🏢 부산본부 관리팀
연결 중
데이터 불러오는 중...
NAS에서 엑셀 파일을 가져오고 있습니다
⚠️
로드 실패
🔄 파일이 변경되어 데이터를 다시 불러옵니다...
⏳ 데이터 분석 중...
당월 데이터 대기 중...
전월 데이터 대기 중...
HKNC 작업현황 대기 중...
⚠️ 합계 불일치 감지 엑셀 합계행 vs 계산 합계의 차이가 임계값 초과:
사업장별 매출 달성율
전월(목표)
당월(달성)
부산본부 일일 매출 추이 (사업장 누적)
DWLG
DWLT
BNCC
📊 청구처 순위 정렬 기준:
선택한 월의 매출액이 큰 순으로 정렬
일일 매출 추이
HKNC 작업 비율 (당월 누적)
20ft 수출
0
당월
0
전월
40ft 수출
0
당월
0
전월
HKNC 일일 작업현황
전월 20ft
당월 20ft
전월 40ft
당월 40ft
청구처별 매출 순위 (Top 15)
🏢 부산본부 사업장 기본정보
각 사업장별 주요 시설·장비·소방·편의시설 통합 현황
사업장
SERVER HEALTHY
DWLG
현재 선택 사업장
섹션
i기본 정보
⚙장비 운영 현황
🔥소방시설
◈편의시설
사용자 편집 (V19.1)
🛡보안
P주차
⚡IT 인프라
💡에너지
⏱타임카드
◧회의실
⌛
사업장 정보를 불러오는 중...
미저장 변경: 0개
📊 비용분석 (RAW)
V19 — 운영 변동성 점검 + 사유 누적 추적 모드
연결 중
📊 Summary
🔷 고정비 점검
🟠 변동성 점검●
사업장
기간
사유 입력률
당월 워닝 중
—%
로딩 중
미입력 14일+ ⚠
자동 카드 승격
—
건
마지막 회계마감: —
비용분석 파일 로드 중...
RAW-비용분석.xlsx 파일을 불러옵니다
⚠️
로드 실패
§1. 사업장별 고정비 규모 DWLG/DWLT/BNCC + 통합 — 한눈에 비교
DWLG 고정비 (당월)
—백만
로딩 중…
DWLT 고정비 (당월)
—백만
로딩 중…
BNCC 고정비 (당월)
—백만
로딩 중…
전체 합계 (당월)
—백만
로딩 중…
§2. 사업장별 고정비 비교 3 사업장 막대 + 비중%
§3. 사업장별 비용 누적 추이 16M 누적 막대 — 고정비(아래) + 변동비(위), 월별 3 사업장 그룹
§4. 사업장별 워닝 분포 Critical/Warning/Info × 3 사업장
§1. 변동비 운영 기본기 4 카드 · 모두 전월 대비 증감액·증감율 표시
변동비 합계 (당월)
—백만
로딩 중…
매출 대비 비율
—%
로딩 중…
일회성 비용 (당년 누적) 🔍 클릭
—건
로딩 중…
TOP 변동 계정 🔍 클릭
—
로딩 중…
§2. 비용 히트맵 D3 squarified · 면적=금액 · 색=MoM% 강도 · 좌상단 칩=분류
로딩 중…
MoM% -30%↓
+30%↑
V 변동비 F 고정비 S 준변동 O 일회성 ? 잠정
셀 클릭 → 해당 워닝/계정 모달
§3. 변동성 워닝 신뢰도 점수 4/4 → 1/4
🔴 Critical (4/4)
—
🟡 Warning (2~3/4)
—
🔵 Info (일회성·신규)
—
§4. 매출-변동비 연동 분석 16개월 점 그래프 + 추세선 · 평소 변동폭 표시 · 당월 빨강 강조
로딩 중…
§1. 고정비 운영 기본기 4 카드 · 모두 전월 대비 증감액·증감율 표시
고정비 합계 (당월)
—백만
로딩 중…
매출 대비 비율
—%
로딩 중…
고정비 워닝 ⚠
—건
로딩 중…
사유 미입력 워닝
—건
로딩 중…
§2. 고정비 안정성 매트릭스 계정별 16M 시계열 + MA12 ±5% band · 색=마지막 월 정상도
§3. 고정비 워닝 MA12 ±5%/±10% + 12M·3M slope 동반 하락
🔴 Critical (4/4)
—
🟡 Warning (2~3/4)
—
🔵 Info (분류 재검토)
—
§4. 사업장별 고정비 분포 DWLG/DWLT/BNCC + 본사(통합)
⚠ 워닝 상세
📊 핵심 지표
💡 자동 진단
진단 로딩 중…
📈 장기 비용 흐름 (단위: 백만원)
🏷 거래처 분해 (당월 vs 전월)
📝 사유 입력
⚙ 비용 분류 편집 (사업장×계정 단위)
자동 분류 1차, 회계팀 ✎ 보정 2차. 변경은 If-Match etag 충돌 감지.
사업장
계정현재 분류자동 (r²/CV)오버라이드당월금액
변경 0건
카테고리 세부 분석
📜 사유 변경이력
유류비 점검
주유 데이터 분석 중...
부산본부 관리팀
연결됨
사업장
연도
월
윈도우: 12개월 (B-2 후 24개월) 📅 갱신: —
📖 점검 5대 원칙4-baseline · 단가/수량 분리 · z-score 임계값 · 인과분해 · 신뢰도 점수 상세 보기 →
⚠
데이터 로딩 중…
4-baseline (MoM·YoY·MA12·Plan) 신뢰도 점수 + z-score 통계 임계값 기반 자동 검출. B-2 활성 후 거래처/가동시간 룰 추가.
0
Critical
0
Warning
0
Info
—
최대 z
Tier 1 — 핵심 KPI 4 1초 판단
12개월 추이 — 비용(막대) · 단가(라인 ±2σ band)
비용 (₩) 단가 (원/L) ±2σ band * 시장 경유가 라인은 B-3 활성
Tier 2 — 워닝 분류 + 단가 스프레드 추이 + 사업장 비용 분포 DRILL DOWN
단가 스프레드 (본부 vs 시장)
사업장 비용 점유율
Tier 3 — 사업장×장비 드릴다운
사업장×장비 TOP 이상치
📖 점검 5대 원칙
1
4-baseline 동시 비교
단일 MoM(전월) 비교는 외부 시장 충격을 본부 운영 부실로 오해할 위험. MoM(급변) · YoY(계절성 제거) · MA12(장기추세) · Plan(예산약속) 4축을 동시에 보고, 3개 이상 동일 방향 이탈 = 🔴 Critical, 2개 이탈 = 🟡 Warning, 1개 = 관찰.
베이스라인 4축
2
단가(원/L) vs 수량(L) 분리
"왜 비용이 늘었나" 를 단가 충격(외부 시장 + 협상 효율) 인지 수량 증가(운영 활동량) 인지 구분. 유류비 = 단가 × 수량 분해는 항상 가능하므로, 두 축을 별도 KPI 와 별도 차트로 표현.
변동요인 분리
3
통계적 임계값 (z-score)
단가는 24개월 시리즈에서 z-score 산정 — |z|>2 = Warning, |z|>3 = Critical. 수량/비용은 사업장별 MoM ±30% Warning, ±60% Critical. 탱크 용량 초과는 always Critical, 동일일 다중 주유는 Info(입력 오류 가능성).
통계 룰박스
4
인과분해 (Variance Decomposition)
워닝 발생 시 자동 분해. 예: "3월 유류비 +12% = 단가 +8% (시장 +6% × 본부 spread +2%) + 수량 +4%". waterfall 차트로 표시 — "어디서 늘어났나" 를 그래프로 한눈에.
waterfall 분해
5
신뢰도 점수 + 자연어 컨텍스트
워닝마다 4/4 즉시 검토 · 3/4 Critical · 2/4 Warning · 1/4 관찰 신뢰도 점수. 자연어 컨텍스트 자동 생성 — 예: "본부 단가 +18% 인데 시장 +6% → 협상 효율 악화 또는 입고 시점 불리". False positive 를 신뢰도로 1차 필터링.
False positive 필터
⚠️
제목
📊 핵심 지표 (당월·전월·MoM·12개월 평균·z-score)
📈 12개월 추이 (±2σ band)
🏷 거래처/주유소 분해
ESC 또는 외곽 클릭으로 닫기 · B-1 단계는 단가 z + MoM 임시 룰. B-2/B-3 진행 시 4-baseline + 거래처 분해 + 인과분해 활성
현금흐름
DWLG · BNCC 통합 재무 안정성 + 자금흐름 + 예금·대여·차입
부산본부 관리팀

부산본부 재무현황 대시보드

KPI 기준: 2025-10 ~ 2026-03 (직전 6개월)
현금흐름: 2026-03-31 ~ 2026-09-30  |  기준일: 2026-03-31
사업장별 재무 안정성 KPI (2026-03 기준)
DWLG
유동비율
16.9%
▲ +0.6%p (10월比)
부채비율
158.2%
▼ −8.9%p (10월比)
차입의존비율
42.2%
▼ −15.4%p (10월比)
BNCC
유동비율
323.7%
▼ −500.8%p (10월比)
부채비율
87.7%
▲ +72.9%p (10월比)
차입의존비율
0.0%
6개월 연속
현금흐름 현황 2026-03-31 ~ 2026-09-30 · Y축: 억원
부산본부 현금흐름
DWLG 최저 0.25억 (05-22) · 리스크 6건  |  BNCC 최저 1.91억 (07-10) · 리스크 1건
DWLG 잔액 BNCC 잔액 DWLG 최소유지기준 (5억) BNCC 최소유지기준 (2억)
DWLG
현재잔액 (03-31)
14.58억
최저잔액 (05-22)
0.25억
유동성 리스크 / 기준 5억
6건
BNCC
현재잔액 (04-27)
4.77억
최저잔액 (07-10)
1.91억
유동성 리스크 / 기준 2억
1건
예금 · 대여 · 차입 통합 요약
예금 합계  📋 클릭
—
DWLG 0건 / BNCC 0건
대여 합계  📋 클릭
72억원
DWLG 50억(2건) + BNCC 22억(2건)
차입 합계  📋 클릭
237.2억원
DWLG 40건 / BNCC 0건
출처: DWLG·BNCC 재무제표/손익계산서/자금조달운영/cashflow 파일  |  기준일: 2026-04-26
현금흐름 현황 2026-03-31 ~ 2026-09-30
현재잔액 · 2026-03-31
14.58억
1,458,344,513원
예측 기산일 기준 잔액
최저잔액
0.25억
25,257,893원 · 2026-05-22
기준선(5억) 대비 −4.75억
유동성 리스크 발생
6건
기준선(5억) 미달 구간 존재
5/20·5/22·6/20·7/20·8/20·9/20
DWLG 현금흐름
Y축: 억원 · 빨간 실선: 최소유지기준 5억  |  📋 클릭하면 상세 내역 확인
현금잔액 최소유지기준(5억)
재무 안정성 KPI (직전 6개월: 2025-10 ~ 2026-03)
유동비율 · 2026-03
16.9%
▲ +0.6%p (10월 대비)
유동성장기부채(건설자금 연간상환분 ~2,239억) 기인
부채비율 · 2026-03
158.2%
▼ −8.9%p (10월 대비)
10~11월 167%대 → 12월 이후 158%대 안정화
차입의존비율 · 2026-03
42.2%
▼ −15.4%p (10월 대비)
금융기관 차입금 ÷ 총자산 기준
월별 손익 추이  📋 클릭 → 데이터 보기
막대=매출·원가, 선=영업이익·순이익(우축) · 단위: 백만원
매출 매출원가 영업이익 당기순이익
* 2025-12 당기순이익 17.4M: 법인세비용 환급(280M) 반영
안정성 지표 추이
좌축=유동비율, 우축=부채비율·차입의존비율
유동(좌) 부채(우) 차입의존(우)
예금 · 대여 · 차입 현황
예금  📋 클릭
—
해당 없음 (0건)
대여  📋 클릭
50억원
2건 · (주)대우로지스틱스 · 4.6%
차입  📋 클릭
237.2억원
40건 · 신한은행 · 4.57~5.78%
출처: DWLG_재무제표.xlsx · DWLG_손익계산서.xlsx · DWLG_자금조달운영.xlsx · cashflow_single_template_DWLG.xlsx  |  현금흐름 최소유지기준: 5억원
현금흐름 현황 2026-03-31 ~ 2026-09-30
현재잔액 · 2026-04-27
4.77억
476,690,918원
예측 기산일 기준 잔액
최저잔액
1.91억
191,410,918원 · 2026-07-10
기준선(2억) 대비 −0.09억
유동성 리스크 발생
1건
기준선(2억) 미달 구간 존재
7/10 (1.91억) · 기준선 대비 −0.09억
BNCC 현금흐름
Y축: 억원 · 빨간 실선: 최소유지기준 2억  |  📋 클릭하면 상세 내역 확인
현금잔액 최소유지기준(2억)
재무 안정성 KPI (직전 6개월: 2025-10 ~ 2026-03)
유동비율 · 2026-03
323.7%
▼ −500.8%p (10월 대비)
권장 기준 200% 이상 (12월~이후 IFRS16 반영 기준)
부채비율 · 2026-03
87.7%
▲ +72.9%p (10월 대비)
권장 기준 200% 이하 · 추세적 개선 중
차입의존비율 · 2026-03
0.0%
6개월 연속 0%
금융기관 차입금 없음
월별 손익 추이  📋 클릭 → 데이터 보기
막대=매출·원가, 선=영업이익·순이익(우축) · 단위: 백만원
매출 매출원가 영업이익 당기순이익
* 2025-12 순손실 155M: 리스이자비용 일시 반영(122M) 포함
안정성 지표 추이
좌축=유동비율, 우축=부채비율
유동비율(좌) 부채비율(우)
예금 · 대여 · 차입 현황
예금  📋 클릭
—
해당 없음 (0건)
대여  📋 클릭
22억원
2건 · (주)대우로지스틱스 · 4.6%
차입  📋 클릭
—
해당 없음 (0건)
출처: BNCC_재무제표.xlsx · BNCC_손익계산서.xlsx · BNCC_자금조달운영.xlsx · BNCC_자금흐름.xlsx  |  현금흐름 최소유지기준: 2억원
A4 미리보기 · 소제목을 클릭하여 직접 수정하세요
기준일자 :
1. 현금흐름 상세
2. 현금흐름 차트
3. 예금·대여·차입 현황
부산본부 재무현황 대시보드
화면 바깥 클릭 또는 닫기 버튼으로 닫힙니다