Skip to content

BE 참고 — 유닛 점유(소유자/사용자) + 공실 워터폴

독자: BE 개발자/AI. 2026-06-22 신설. 유닛(전유부분)의 소유자/사용자 식별과 관리비 부담자(계약자) 결정 규칙. as-built(프로토 데모) + 확정 규칙 구분. 도메인 정본: docs/REFERENCE-OCCUPANT-TERMINOLOGY-AND-VACANCY-WATERFALL.md. FE: docs/handoff/frontend/unit-occupancy-sheet.md.

1. 데이터 모델 (확정 규칙)

  • 유닛(전유부분) = 소유자(상시·연속, 항상 1명) + 사용자[](기간별 0~N). 각 계약 = { 주체, 시작일(from), 종료일(to) }. to=null = 진행 중.
  • 소유자는 항상 존재 — 미분양 유닛도 시행사/건축주가 소유자. → 부담자 연속(공백 없음).
  • 용어는 법령별 분기(코어는 중립어 소유자/사용자로 저장, 표시만 분기):
코어(중립)공동주택관리법집합건물법주택임대차보호법
소유자입주자(소유자+대리 배우자·직계존비속)구분소유자임대인
사용자사용자(임차 사용, 임대주택 임차인 제외)점유자임차인
통합입주자등(구분소유자·점유자)

2. 공실 워터폴 — 관리비 부담자 결정 (불변식)

임의 시점 t의 관리비 부담자 = (그 시점 유효한 사용자 계약이 있으면 사용자) else 소유자.

  • 유효 판정(경계 포함): from <= t && (to == null || t <= to). 종료일 당일은 아직 점유(to 포함), 종료 익일부터 공실.
  • 공실(유효 사용자 없음) → 소유자 자동 폴백. role = 소유자, vacant = true.
  • 소유자 계약이 끊기지 않으므로 부담자는 항상 1명으로 결정(알려진 유닛이면 payer non-null).
  • 미상 유닛(데이터 없음) → unknown=true, payer=null (방어 — 시트에서 행 누락 없이 표시).
소유자: ├──────────────────────────────────┤ (상시)
사용자A:      ├────────┤      ├──────┤
부담자:  소유 |  A     | 소유 |  A   | 소유 …

3. unitCount 시맨틱 (정정 — 2026-06-22)

  • 계약의 유닛 개수 = distinct unitCode(호수 수), 배분 라인 수가 아니다.
  • 배분 라인은 charge × unit(예: 3차수 × 2호 = 6라인) → 라인 수를 유닛 수로 쓰면 차수배로 부풀려진다(과거 버그).
  • as-built: useAllocations.unitCodesByContract(contractCode) = 라인의 distinct unitCode. invoicingByContract().unitCount = new Set(units.map(u => u.unit.unitCode)).size.
  • BE 계약(API): 계약별 유닛 목록은 distinct 유닛 엔티티 집합으로 반환. 금액 분해(차수·charge별)는 별도 축.

4. 부과/수납 함의

  • 부과 계약자 resolution: 부과 대상 기간 × 워터폴 → 시점별 부담자 산출. 한 부과월 안에서도 임차 종료/공실 전환 시 일할 분할 가능(후속 — 현재 ASOF 단일 시점).
  • 부담자 전환은 청구서 수신자·세금계산서 공급받는자·연체료 귀속 주체에 영향. 귀속 재배정(퇴거)·이관은 별도 슬라이스(범위 밖).

5. as-built (프로토 데모 — 확정 아님)

  • src/composables/useUnitOccupancy.js: 데모 점유 상수 OCCUPANCY + payerAt/unitsOf, ASOF='2025-12-15'.
    • 101: 소유 홍길동, 임차 김철수(2024-06-01~2025-11-30) → 12월 공실 → 홍길동 부담.
    • 102: 소유 홍길동, 자가(2023-03-01~현재) → 사용자=소유자.
  • 실서비스: 유닛 마스터 ↔ 소유자/사용자 계약(기간) 연결 + 부과월 기준일 resolution으로 교체. useUnitOccupancy는 표시·resolution 레이어로 빌링 캐논(useAllocations)과 분리(캐논 무편집).

6. 엣지케이스 체크리스트

  • 종료일 경계(to 당일 점유 / 익일 공실) — 일할 정산 시 명확화.
  • 사용자 계약 중첩/공백 — 데이터 정합(중첩 금지, 공백=공실).
  • 미분양·명의 미정 — 소유자=시행사/건축주 폴백.
  • 미상 유닛 — payer null, UI 누락 없이 표시.