다크모드
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)
- 계약의
유닛 개수= distinctunitCode수(호수 수), 배분 라인 수가 아니다. - 배분 라인은
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 누락 없이 표시.