Skip to content

수납 집합 완납 + 계약별 수납 — FE 메인테이너

독자: FE 메인테이너/AI. 집합(유닛/멤버) 완납 fan-out 및 펼침 계약 행 수납 흐름·파일 위치·undo·확장 포인트. 정본 spec: docs/superpowers/specs/2026-06-24-collecting-aggregate-fullpay-policy-design.md. 관련: [[tenancy-axes-billing-tables.md]] · [[collecting-detail-sheet.md]].

흐름

  • 집합 행 [완납] → openFullPayment({ ...fullPaymentBreakdown(axis, key, filterScope), label })selectedFullPayment 적재 → command="show-modal" commandfor="dialog-collecting-fullpayment"DialogCollectingFullPaymentArt.
    • [완납] 버튼 비활성 조건: :disabled="totalOutstanding <= 0". 완납 커밋 후 totalOutstanding이 0으로 갱신되면 버튼이 자동으로 비활성화됨. 미수가 다시 발생하면 활성 복귀.
  • 다이얼로그 [완납 확인] → commitFullPaymentconfirmed emit → 테이블 onFullPaid(토스트 + undoSnapshot {type:'receipts', receiptIds}).
  • 펼침 계약 행 [수납] — 제목 클릭 vs 액션 버튼 분리:
    • 계약명(제목) 클릭openContractDetail(contractCode)sheet-collecting-detail-art(충당순서·백데이트·감면 세밀 조정).
    • [수납] 버튼 클릭useContractQuickCollect(공유 컴포저블) 인라인 quick-collect 모드 진입. 미수금 prefill → 금액 직접 입력(부분·초과 가능) → Enter 확정 / Esc 취소 / ✓버튼 확정. 확정 시 recordReceipt(contractCode) 호출(계약 단일소스 — 집합 집계 자동 반영). 초과분은 선수금 처리.
    • [수납] 버튼 비활성 조건: :disabled="contract.outstanding <= 0".
  • 일괄 모드(canon) = 행 체크 → [선택 완납] → commitBatch → 선택 행마다 commitFullPayment.

파일

  • 컴포저블: src/composables/useCollectingFullPayment.js (fullPaymentBreakdown / commitFullPayment).
  • 컴포저블: src/composables/useContractQuickCollect.js — 계약 행 인라인 quick-collect 공유 컴포저블. 유닛·멤버·계약 탭 펼침 계약 행에서 공유 사용. recordReceipt(contractCode) 호출.
  • 공유 상태: src/components/billing/_core/console/collecting/selectedFullPayment.js (selectedFullPayment ref + openFullPayment).
  • 다이얼로그: src/components/billing/_core/console/collecting/DialogCollectingFullPaymentArt.vue (id dialog-collecting-fullpayment).
  • 탭: src/components/billing/_core/console/collecting/unit/blocks/DynamicTableOrg.vue (유닛 집합 [완납]·펼침 계약 행 [수납] 인라인·제목 클릭 시트·일괄 완납-선택·다이얼로그 마운트).
  • 탭: src/components/billing/_core/console/collecting/member/blocks/DynamicTableOrg.vue (멤버 집합 동일 패턴).
  • 탭: src/components/billing/_core/console/collecting/contract/blocks/DynamicTableOrg.vue (계약 탭 atom 행 [수납] 인라인·제목 클릭 시트).
  • 테스트: src/composables/__tests__/useCollectingFullPayment.spec.js.

undo

undoLastCollect가 두 형태 처리: {type:'receipts', receiptIds} (완납·canon) → cancelReceipt 루프 / Array (non-canon mock) → row 객체 복원.

수납일 (읽기전용)

DialogCollectingFullPaymentArt의 수납일은 표시 전용(편집 불가) — paymentDate(new CalendarDate(2025,12,15) 데모 고정·실서비스는 today)를 displayDate로 읽기전용 표시(<input disabled readonly>). 편집 DatePicker 제거 이유: 날짜 변경이 "타임머신(완납액 재산정)"으로 오해되나 실제로는 receivedAt stamp만 바뀜. 소급/연체료 정산은 계약 상세 시트(수납일 replay) 소관. 목록 as-of 타임머신은 별도 슬라이스(미구현).

확장

  • non-canon(mock) 경로는 기존 인라인 수납 유지(canon만 완납 정책).
  • filterScope(current|forwarded|all)는 부모 toolbar에서 주입(prop) — fullPaymentBreakdown scope 인자로 그대로 전달.
  • 멤버 탭은 fullPaymentBreakdown('member', row.key, filterScope) + label: row.memberDisplayName으로 호출. 나머지 흐름 유닛과 동일.