다크모드
수납현황 — FE 메인테이너 참고
관리비 상용화 필수 문서 트랙(펀치리스트 점검 ④)의 3호. 설계 정본:
docs/superpowers/specs/2026-07-10-charge-statement-collection-status-design.md. 데이터 계약은docs/handoff/backend/report-collection-status.md참고. ①총괄표 FE handoff(report-summary-table.md) 패턴 복제.
1. 라우트 / feature 게이트
1-1. 콘솔 탭
신규 탭 없음 — 부과내역서와 동일하게 기존 보고서 탭(feature:'reports')의 내부 세그먼트로 편입(§3 ReportKindTabsAto).
1-2. 페이지 라우트 (buildLineRoutes.js)
editions.actual.own에 report/collection-status 키:
js
'report/collection-status': () => import('../views/service-charge/actual/console/report/collection-status/IndexView.vue')provisional에는 없음 — 라우트 부재로 게이트(테스트: buildLineRoutes.spec.js).
1-3. 인쇄 문서 라우트
/document/report/collection-status-view → views/document/report/CollectionStatusView.vuefeature 게이트 없음(document 앱 공통 패턴).
1-4. i18n
신규 키 없음(§ 부과내역서 handoff 1-4와 동일 근거).
2. 데이터 컴포저블 — useCollectionStatus
위치: src/composables/useCollectionStatus.js.
API 시그니처:
statusRows()→useReceivableAging().agingByAxis('unit')그대로 반환(가공 없음). 각 행은key·name·전기이월·당기발생·회수·조정·차기이월·연체차수·anomalous·periods.statusTotals(rows = statusRows())→ 5개 열(전기이월·당기발생·회수·조정·차기이월)의 합산 객체.formatAmount→ 재-export.
2-1. 호출 관용 — rows를 한 번 계산해 재사용
총괄표 columnTotals/부과내역서와 동일 관용: 컴포넌트에서 rows를 computed로 한 번 감싸고 statusTotals(rows.value)처럼 명시 전달한다. 인자 없이 호출하면 내부에서 statusRows()(=agingByAxis('unit'))를 또 호출해 중복 스캔이 발생한다. MainOrg.vue가 이 관용을 그대로 따른다(const totals = computed(() => statusTotals(rows.value))).
3. 보고서 종 세그먼트
부과내역서 handoff §3과 동일 — ReportKindTabsAto.vue를 그대로 재사용한다. 이 문서에서 반복하지 않음.
4. 컴포넌트 구조
src/views/service-charge/actual/console/report/collection-status/IndexView.vue— 콘솔 페이지 shell(공용report/_shared/HeaderOrg[기간 헤더+콘솔 탭 레일] + MainOrg — 2026-07-10 후속: 헤더 누락 정정).src/components/service-charge/actual/console/report/collection-status/MainOrg.vue— 웹조회:ReportKindTabsAto+ roll-forward 표(table table-sm table-divide-y sticky-thead) + [인쇄] 버튼 1개(총괄표·부과내역서와 달리 뷰 토글·복수 인쇄 버튼 없음 — 단일 서식).src/views/document/report/CollectionStatusView.vue— 인쇄 문서 뷰.
4-1. anomalous 배지 렌더
html
<td class="font-medium">
{{ r.name }}
<span v-if="r.anomalous" class="badge badge-sm badge-red-subtle">확인필요</span>
</td>웹조회 MainOrg에만 배지가 있다(CollectionStatusView.vue 인쇄 뷰는 배지 미포함 — 인쇄물은 흑백 프린터 대응 위해 텍스트만, 컬러 배지 강조는 화면 전용). 인쇄 뷰에 배지가 필요해지면 흑백 대비 표시(예: [확인필요] 텍스트 접두)로 별도 검토 필요.
5. 인쇄 뷰 패턴
CollectionStatusView.vue는 총괄표·부과내역서와 동일한 print-a4-portrait-flow-scoped(폭 190mm, 높이 auto)를 재사용한다. 열이 7개(세대·전기이월·당기발생·회수·조정·차기이월·연체차수)로 세로 용지에 여유가 있어 landscape 전환이 필요 없다 — 총괄표의 named @page(landscape) 패턴이 이 문서에는 적용되지 않는다.
단지 1장(세대 수만큼 세로로 길어짐) 문서라 대량 인쇄 파이프(njk) 대상이 아니다 — 부과내역서·고지서 묶음과 달리 세대별 개별 블록/페이지가 아닌 단일 표이기 때문(문서류 매트릭스 §6 참고).
6. [시트] — xlsxExport 유틸 계약 (2026-07-11 후속, B-3)
js
import { periodOf, periodLabelOf } from "@/composables/useBillingPeriod";
import { exportXlsx } from "@/lib/report/xlsxExport";
const XLSX_COLUMNS = [
{ key: "name", label: "세대" },
{ key: "전기이월", label: "전기이월" },
{ key: "당기발생", label: "당기발생" },
{ key: "회수", label: "회수" },
{ key: "조정", label: "조정" },
{ key: "차기이월", label: "차기이월" },
{ key: "연체차수", label: "연체차수" },
];
const downloadXlsx = () =>
exportXlsx({
fileName: `수납현황-${periodLabelOf("service-charge", "actual")}.xlsx`,
sheetName: "수납현황",
columns: XLSX_COLUMNS,
rows: rows.value,
});exportXlsx({ fileName, sheetName, columns, rows })(src/lib/report/xlsxExport.js, SheetJS write-only) —rows.value(=statusRows(), prior-only 세대 포함 전체)를 그대로 export한다. 화면의[확인필요]배지(anomalous)는 시트에 별도 열로 내보내지 않는다 —연체차수숫자로 동일 정보를 유추할 수 있다(§4-2 배지 기준overdueCount >= 2).- 값 규율: 숫자는 raw number로 기록 —
rows.value를 그대로 넘기므로 자동으로 지켜진다. - 배선 스모크:
src/components/service-charge/actual/console/report/__tests__/XlsxWiring.spec.js— 5보고서 공통.
7. 알려진 미해결 사항
- document 앱 셸 no-print 갭 — 총괄표 §6와 동일 근거로 스코프 밖.
- 수납 채널별 분해 없음(§ backend handoff §4-3) — 대사 3채널 트랙(파킹 중)과 연계될 후속 사항.
8. 테스트 위치
src/composables/__tests__/useCollectionStatus.spec.js— 불변식 4종(backend handoff §3 대응). 특히 불변식④가 시드 202호(prior-only)의 존재를 가드 — 이 테스트가 깨지면useReceivableAging/useForwarding쪽의 행집합 변경이 원인일 가능성이 높다.src/router/__tests__/buildLineRoutes.spec.js— actual 전용 게이트.src/components/service-charge/actual/console/report/__tests__/XlsxWiring.spec.js—[시트]배선 스모크(수납현황 케이스 포함).- Playwright 라이브 실측: 수납현황에 202호(prior-only·당기발생 0) 행 존재 확인,
[시트]다운로드, 인쇄 뷰 개봉 — SDD plan §검증 절 참고.
9. 확장 절차
docs/handoff/frontend/report-summary-table.md §8의 일반 절차를 따름. 채널별 회수 분해가 실제로 추가될 때는 이 문서(§7)와 backend handoff(§4-3·§5)를 함께 갱신할 것.
2026-07-10 후속 2 (SSOT 정합): 웹조회 MainOrg는 leysys-design 정본
pattern-app/transaction/table/static-table패턴을 따른다 —container루트 > 보고서 종 세그먼트(page-header-below p-1 bg-neutral-minimal rounded-full필 스트립) >card card-md(card-header bg-neutral-minimal inset-edge-b툴바 +card-body bg-neutral-minimal표). 테이블은 정본 static 계열table table-hover table-sm table-static table-divide-y(장표는 +sticky-thead). 미수금 연령분석 축탭도 동일 필 스트립·h-fit래퍼(flex shrink 압축 방지).