Skip to content

FE 핸드오프 — 연체료 현황 페이지 + 인식기준 설정

독자: FE 메인테이너/AI. 2026-06-20 신설. 연체료 현황 콘솔 탭 + 인식기준(발생/현금) 설정 UI의 라우트·컴포넌트·데이터 흐름·확장 포인트.

1. 연체료 현황 페이지 (콘솔 탭)

  • 진입: 관리비 앱 → 실제/잠정 콘솔 상단 탭 "연체료" (ConsoleTabBarOrg, active-group late-fee).
  • 라우트 seg: late-fee/overviewbuildLineRoutes.js CORE_VIEWS + SERVICE_CHARGE_CORE 등록. 동적 도달(billingPath('late-fee/overview')), audit-route-integrity [D]=0 통과.
  • 탭 정의: billingLines.js service-charge consoleTabs ({ group:'late-fee', labelKey:'billing.tabs.lateFee', seg:'late-fee/overview' }).
  • 컴포넌트:
    • views/billing/_core/console/late-fee/overview/IndexView.vue (Header + Main)
    • components/billing/_core/console/late-fee/overview/HeaderOrg.vue (page-header + ConsoleTabBarOrg active-group="late-fee")
    • components/billing/_core/console/late-fee/overview/MainOrg.vue (요약 스트립 + 계약별 테이블)
  • 데이터 흐름(읽기 전용):
    • useForwarding.forwardingByContract() → 이월 연체 원금(r.forwarding)·차수(r.overdueCount)
    • useLateFee.lateFeesFor('contract', key, ASOF) → 발생 연체료(interestEngine). ASOF='2025-12-28' = E3 전기일(useBillingJournal POSTING_DATE)과 동일 → GL 발생액과 정합(홍길동 72).
    • lateFeePolicy.recognitionBasis → 인식기준 배지.
  • 차수별 드릴다운(2026-06-21 신설): 행의 계약/세대 이름 클릭(§0-10 IA — <button> + font-medium cursor-pointer hover:underline, 테이블 table-hover) → selected ref 세팅 + overlays/SheetLateFeeDetailArt.vue 오픈(command="show-modal" commandfor="sheet-late-fee-detail").
    • 시트 props: contract-key·name·as-of. forwardingByContract().find(key).periods(미수>0) × lateFeesFor('contract', key, asOf).perId[${key}-${label}].fee차수×구성요소 미수·발생 연체료 분해(읽기전용). 구성요소는 DEFAULT_COMPONENT_ORDER 순 정렬, 라벨 billingNature.componentLabel. 합계는 리스트 행과 동일 소스·asOf → 정합.
  • 테스트: …/late-fee/overview/__tests__/MainOrg.spec.js(발생액 72·인식기준 토글·이름클릭 드릴다운 차수/구성요소 노출).
  • 확장 포인트: 축 토글(계약/세대/멤버 — 현재 계약), 전표 상태 컬럼(E3 전기 여부), 페이지네이션(현재 데모 소량), 드릴다운 차수별 연체료 breakdown(구간 이율) 노출.

1-B. 충당 순서 설정 페이지 (G4, 2026-06-21)

  • 위치: 관리비설정 → "충당 순서"(/service-charge/setting/collecting). 기존 mock 페이지를 실제 lateFeePolicy.collectionPolicy에 배선.
  • 컴포넌트: components/service-charge/setting/collecting/MainOrg.vue — 카드1(축1 연체료우선/원금우선·법정/규약 배지) · 카드2(차수순서 periodOrder) · 카드3(적용 순서 미리보기 + 워크드 예시, 읽기전용). 편집 시트 overlays/SheetUpdateCollectingPriority.vue(Select+미리보기→setCollectionPolicy({componentOrder})SheetUpdateOutstandingPriority.vue(→setCollectionPolicy({periodOrder})).
  • 소비 컴포저블: useLateFeePolicy()(policy·setCollectionPolicy), allocationOrder(compileOrder·COMPONENT_ORDER_OPTIONS·PERIOD_ORDER_OPTIONS·periodOrderLabel·componentOrderOption·previewLines·PREVIEW_SAMPLE/PREVIEW_AMOUNT), billingNature.componentLabel.
  • 반영 경로: setCollectionPolicypolicy.value.collectionPolicy 교체 → CollectingActionOrg가 시트 오픈 시 reactive 정책으로 periodOrder/componentOrder prefill(건별 override 유지). ⚠ 인식기준과 동일 패턴(과거 상수 읽기 무반영 → reactive 정정).
  • 삭제/정정: SheetUpdateBillingAmountPriority.vue(부과액 reorder, 거짓 어포던스) 제거. 구 MainOrg의 v-for 안 <DialogDeleteArt>/<SheetCreateUploadUnitArt> 오삽입 버그 제거.
  • 테스트: composables/__tests__/{lateFeePolicy,allocationOrder}.spec.js.

1-B-2. 단계화 + 원금 내부 순서 드래그 (2026-06-22)

오너 요청: 설정을 단계별(stepped) 로 쪼개고 순서를 드래그로. 구 "고정" 부과액 내부 순서를 정책 재량으로 전환(거짓 어포던스 → 실효 컨트롤).

  • 단계 구성(MainOrg): 단계1 기본 수납 순서(축1) · 단계2 차수 순서 · 단계3 원금 내부 충당 순서(드래그·규약) · 단계4 적용순서 미리보기+워크드 예시. 각 disclosure 제목에 단계 N 배지.
  • 드래그 컴포넌트: components/common/SortableList.vue(v-model=[{id,label}], 네이티브 HTML5 DnD). SSOT 카피 — leysys-design pattern-app/sortable-list(ADR PATTERN-SORTABLE-LIST-REORDER-2026-06-22, kanban DnD의 "컬럼 내 정밀 재정렬" 확장). 신규 token·class 0.
  • 단계3 구성: 법정 고정 구간(연체료→부과액) 잠금 안내(자물쇠) + SortableList(버킷 draft) + 푸터([기본값으로]/[저장], 저장은 dirty일 때만). 저장 → setCollectionPolicy({principalOrder: draftIds}). draft는 정책 외부 변경 시 watch로 재동기화.
  • 소비 컴포저블: useLateFeePolicy(policy·setCollectionPolicy({principalOrder})), billingNature(PRINCIPAL_BUCKETS·bucketLabel·componentLabel), allocationOrder(compileOrder(preset, principalBuckets)·previewLines(..., principalBuckets)).
  • 실효 경로: 저장 → policy.collectionPolicy.principalOrder → ① 단계4 미리보기·워크드 예시(즉시) ② useForwardingderiveByComponent 세구분 귀속(수납 상세) ③ CollectingActionOrg 실제 현금 충당. 검증: 비매출·부채를 맨 위로 드래그→저장 시 단계4가 연체료 → 장기수선충당금 → 과세원금 …로 갱신(probe-settings.mjs).
  • 단계1 편집 시트(SheetUpdateCollectingPriority) 미리보기도 principalOrder 반영(일관성).
  • 확장 포인트: 키보드 재정렬(접근성)·터치(MDS Pointer Events)는 ADR 후속. 단지별 정책 분기.

1-B-3. 설정 스코프 토글 — 프리셋/글로벌/로컬 (2026-06-22)

ADR decisions/SETTINGS-SCOPE-GLOBAL-LOCAL-PRESET-2026-06-22. 충당순서에 시범 적용(frozen 클래스).

  • MainOrg 상단 세그먼트 토글 [이 콘솔] [글로벌 기본값](scope ref). active = scope==='global' ? globalCollectionPolicy.value : policy.collectionPolicy. 단계1~4 모든 computed가 active를 읽음.
  • provenance 배지: active를 부모(로컬→글로벌 / 글로벌→프리셋)와 비교 → {부모}과 같음 / 변경됨.
  • 스코프 배너: 글로벌="신규 콘솔에 적용 · 기존 콘솔(이 콘솔 포함) 불변" / 로컬="이 콘솔에만 적용". + 전체 되돌리기 버튼(resetCollectionPolicy(scope), sameAsParent면 disabled).
  • 시트 스코프 인지: SheetUpdateCollectingPriority/SheetUpdateOutstandingPriorityscope prop — activeCP(로컬/글로벌) 기준 draft·미리보기, 저장 setCollectionPolicy(partial, scope). 페이지가 :scope="scope" 전달.
  • 단계3 되돌리기: [부모로](draft만 부모 principalOrder로) + [저장](dirty 게이트, setCollectionPolicy({principalOrder}, scope)).
  • 소비 컴포저블: useLateFeePolicy(policy·globalCollectionPolicy·setCollectionPolicy(p,scope)·resetCollectionPolicy(scope)) + PRESET_COLLECTION_POLICY.
  • 엔진 무영향: 빌링은 로컬만 읽음. 글로벌은 신규 콘솔 시드 표면. 검증 probe(글로벌 탭→배너·provenance).
  • 테스트: lateFeePolicy.spec(규칙3·되돌리기·프리셋 동결). 기존 MainOrg.spec 텍스트 단언 유지.

1-C. 연체요율 설정 — 엔진 배선(목업 제거, 2026-06-22)

기존 연체료 할증 페이지(setting/surcharge)의 연체요율 표는 하드코딩 목업(13개월 12/24/36/48%) + 저장 무동작이었음. 엔진(interestEngine)은 tier 기반 rateSchedule(0/3/6개월 = 3/4/5%)이라 표시·편집이 엔진과 불일치. → 표시·편집을 policy.rateSchedule에 직접 배선.

  • 표시(MainOrg): rateScheduleRows(policy.rateSchedule) → 구간(03개월/36개월/6개월 이상)·연%·월% tier 표. 13개월 목업 표 제거. 또 "연체료 구분(일할 단리 ÷dayCount.base)"·"계산 방식(한편/양편넣기 — dayCount.inclusion)"도 정책에서 파생(과거 "월할/양편넣기" 거짓 표기 정정).
  • 편집(SheetUpdateSurchargeRate): 목업 13행 → rateSchedule tier 편집기(구간 개월·연이율% 입력, 구간 추가/삭제, 첫 구간 0개월 고정). 저장 setRateSchedule(rows→{fromMonths, annualRate:%/100}) → 엔진 즉시 반영. close/취소 wiring 추가(과거 no-op close).
  • 컴포저블: useLateFeePolicy(setRateSchedule) + rateScheduleRows(pure, 표시·편집 공유).
  • 스코프: 현재 단일 정책값(로컬). rateSchedule은 effective-dated 클래스 후보(법정 요율·거래일 기준) — ADR SETTINGS-SCOPE §후속에서 시점 버전화.
  • 테스트: lateFeePolicy.spec(rateScheduleRows·setRateSchedule 검증·엔진 lateFeeOf 즉시 반영·0개월 필수·정렬중복). 검증 probe(편집→저장→메인표 반영).

2. 인식기준(발생/현금) 설정 토글

  • 위치: 관리비설정 → 연체료 정책(/service-charge/setting/surcharge) → 연체료 기본 카드 행 + 편집 시트.
  • 컴포넌트: components/service-charge/setting/surcharge/MainOrg.vue(인식기준 행 표시) + overlays/SheetUpdateAccountInfoArt.vue(Select + 확인 시 커밋).
  • 상태: lateFeePolicy.js 싱글톤 policy ref + setRecognitionBasis(basis)(clone 교체 — 기본 객체 불변). useLateFeePolicy()로 소비.
  • 반영 경로: 토글 변경 → policy.value 교체 → (a) CollectingActionOrgrecognitionBasis = computed(() => policy.value.recognitionBasis)JournalPreviewMol 분기, (b) useBillingJournal(E3 방출 여부·E4 split) 재계산, (c) 연체료 현황 배지·문서.
    • ⚠️ 과거 CollectingActionOrgDEFAULT_LATE_FEE_POLICY.recognitionBasis(상수)를 읽어 토글이 무반영이었음 → reactive로 정정(2026-06-20).
  • 정본 분개 규칙: BE handoff collecting-detail.md §4.

3. 메뉴 위생 (동반 수정)

  • 연체료 할증 메뉴 라벨 billing.setting.discount("할인", 의미 오류) → billing.setting.surcharge("연체료 할증")로 정정.
  • 충당 순서(/service-charge/setting/collecting) — 라우트만 있고 메뉴 진입점 부재였음 → 관리비설정 그룹에 billing.setting.collecting("충당 순서") 노출.