배분방식
배분방식(AllocationRule)은 관리비 항목의 총액 또는 단가를 각 호실에 나누어 얼마를 부과할지를 결정하는 규칙입니다.
이 규칙은 **누구에게 부과할지(부과 대상)**와 **어떻게 나눌지(배분 기준)**의 조합으로 구성됩니다.
TypeScript로 보여주는 배분방식 정의입니다.
// 계산 기준export type CalculationRule = | "PRIVATE_AREA" // 전용면적 | "CONTRACT_AREA" // 계약면적 | "SUPPLY_AREA" // 공급면적 | "UNIT_COUNT" // 균등 배분 (호실 수) | "VEHICLE_COUNT"; // 차량 대수
// 부과 대상 범위export type TargetScope = | "ALL_UNITS" // 전체 호실 | "ONLY_CONTRACT_UNITS" // 계약된 호실 | "ONLY_VACANT_UNITS"; // 공실
// 1. 범위 기반 배분export type ScopeBaseAllocationData = { type: "SCOPE_BASE"; is_unit_cost: boolean; target_scope: TargetScope; calculation_rule: CalculationRule;};
// 2. 특정 호실 지정 배분export type SpecificUnitsAllocationData = { type: "SPECIFIC_UNITS"; is_unit_cost: boolean; units: number[]; calculation_rule: CalculationRule;};
// 3. 호실 지분 배분export type UnitStakeAllocationData = { type: "UNIT_STAKE"; ratios: { [unitId: string]: string };};
// 전체 배분 규칙 타입export type AllocationRule = | ScopeBaseAllocationData | SpecificUnitsAllocationData | UnitStakeAllocationData;Kotlin으로 보여주는 배분방식 정의입니다.
// 계산 기준enum class CalculationRule { PRIVATE_AREA, // 전용면적 CONTRACT_AREA, // 계약면적 SUPPLY_AREA, // 공급면적 UNIT_COUNT, // 균등 배분 (호실 수) VEHICLE_COUNT // 차량 대수}
// 부과 대상 범위enum class TargetScope { ALL_UNITS, // 전체 호실 ONLY_CONTRACT_UNITS, // 계약된 호실 ONLY_VACANT_UNITS // 공실}
// 배분 규칙 (Sealed Class로 정의)sealed class AllocationRule { // 1. 범위 기반 배분 data class ScopeBase( val isUnitCost: Boolean, val targetScope: TargetScope, val calculationRule: CalculationRule ) : AllocationRule()
// 2. 특정 호실 지정 배분 data class SpecificUnits( val isUnitCost: Boolean, val units: List<Long>, val calculationRule: CalculationRule ) : AllocationRule()
// 3. 호실 지분 배분 data class UnitStake( // 호실 ID와 지분율 매핑 val ratios: Map<String, String> ) : AllocationRule()}기본적으로 다음으로 변환할 수 있습니다.
type Unit = { id: string; area: number; };// 부과 대상을 선택하는 함수 타입type SelectFunction = (unit: Unit) => boolean;// 호실의 부과 기준을 계산하는 함수 타입type ImpositionBasisFunction = (unit: Unit) => number;function fromAllocationMethod(allocationMethod: AllocationMethod): { selectFn: SelectFunction; getImpositionBasis: ImpositionBasisFunction;} { // 배분방식에 따라 부과 대상 선택 함수와 분배 기준 함수를 반환합니다. // 예시 구현은 생략합니다. return { selectFn: (unit) => true, // 모든 호실을 선택하는 예시 getImpositionBasis: (unit) => unit.area // 전유면적을 기준으로 하는 예시 };}data class Unit(val id: String, val area: Double) // 부과 대상을 선택하는 함수 타입 typealias SelectFunction = (Unit) -> Boolean // 호실의 부과 기준을 계산하는 함수 타입 typealias ImpositionBasisFunction = (Unit) -> Double data class AllocationFunctions( val selectFn: SelectFunction, val getImpositionBasis: ImpositionBasisFunction )
fun fromAllocationMethod(allocationMethod: AllocationMethod): AllocationFunctions { // 배분방식에 따라 부과 대상 선택 함수와 분배 기준 함수를 반환합니다. // 예시 구현은 생략합니다. return AllocationFunctions( selectFn = { true }, // 모든 호실을 선택하는 예시 getImpositionBasis = { it.area } // 전유면적을 기준으로 하는 예시 ) }배분방식은 크게 3가지로 나눌 수 있습니다.
- 일반 (SCOPE_BASE): 가장 일반적인 배분 방식으로, 지정된 범위(
target_scope)와 계산 기준(calculation_rule)에 따라 비용을 배분합니다.
부과 대상: 전체 호실, 계약 호실, 공실 등
부과 기준: 전유면적, 사용량, 균등 등 기준 - 호실지정 (SPECIFIC_UNITS): 특정 호실 목록(
units)을 명시적으로 지정하여 비용을 배분합니다. 부과 대상: 지정된 호실
부과 기준: 전유면적, 사용량, 균등 등 기준\예: 101호, 102호, 201호에만 엘리베이터 수리비를 부과하는 경우에 사용합니다.
- 호실지분그룹 (UNIT_STAKE): 호실별 지분(
ratios)에 따라 비용을 배분합니다. 부과 대상: 호실 지분 그룹에 속한 호실
부과 기준: 호실 지분 그룹에 속한 호실의 지분 비율\이 방식은 관리비 항목의 총액을 각 호실의 지분 비율에 따라 나누는 정산 방식으로만 동작합니다.
부과 대상 (target_scope)
Section titled “부과 대상 (target_scope)”부과 대상은 실제로 부과할 호실을 정의합니다.
target에 지정된 부과 대상은 다음과 같은 기준으로 선택할 수 있습니다.
ALL_UNITS(전체 호실): 건물의 모든 호실에 비용을 배분합니다.ONLY_CONTRACT_UNITS(계약 호실): 현재 임대 계약이 체결된 호실에만 비용을 배분합니다.ONLY_VACANT_UNITS(공실): 현재 비어있는 호실에만 비용을 배분합니다.
각 호실에 대해 선택할 수 있는 함수가 정의될 수 있다면, 해당 함수의 결과값을 부과 대상으로 사용할 수 있습니다.
TypeScript로 보여주는 부과 대상 선택 함수입니다.
// 부과 대상 호실을 정의합니다. 임시 예시입니다.function selectUnits(units: Unit[], selectFn: SelectFunction): Unit[] { return units.filter(selectFn);}Kotlin으로 보여주는 부과 대상 선택 함수입니다.
// 부과 대상 호실을 정의합니다. 임시 예시입니다.fun selectUnits(units: List<Unit>, selectFn: SelectFunction): List<Unit> { return units.filter(selectFn)}계산 기준 (calculation_rule)
Section titled “계산 기준 (calculation_rule)”배분 기준은 주어진 부과 대상에게 요금을 어떻게 나눌지를 정의합니다.
배분 기준은 크게 정산제와 정액제로 나뉩니다. 이는 is_unit_cost 속성으로 제어됩니다.
-
정산제 (
is_unit_cost: false) 매월 발생하는 **총비용(amount)**을 정해진 기준에 따라 각 세대에 배분하여 정산하는 방식입니다.
입주자가 서비스를 받은 만큼 관리비를 내는 구조로, 주로 수도, 전기, 가스 요금처럼 총사용량이 있고 이를 나눠야 할 때 사용됩니다.호실별 부과액 = 총액(amount) * (개별 호실의 계산 기준 값 / 전체 대상 호실의 계산 기준 값 합계) -
정액제 (
is_unit_cost: true) 매월 일정한 **단가(amount)**를 기준으로 관리비를 부과하는 방식입니다.
예를 들어, 면적(㎡)당 단가나 세대당 고정 금액을 정해두고 부과합니다.
일반관리비, 청소비, 케이블TV 요금 등이 여기에 해당될 수 있습니다.호실별 부과액 = 단가(amount) * 개별 호실의 계산 기준 값
참고:
UNIT_STAKE방식은 항상 총액을 지분율로 나누는 정산 방식이므로is_unit_cost속성이 없습니다.
SCOPE_BASE와 SPECIFIC_UNITS 방식에서 calculation_rule 속성은 비용을 나누는 기준을 정의합니다.
PRIVATE_AREA(전용면적): 각 호실의 전용 면적을 기준으로 사용합니다.CONTRACT_AREA(계약면적): 계약서에 명시된 계약 면적을 기준으로 사용합니다.SUPPLY_AREA(공급면적): 전용면적과 공용면적을 합한 공급면적을 기준으로 사용합니다.UNIT_COUNT(균등분배): 모든 대상 호실에 동일하게 1의 값을 적용하여 균등하게 배분합니다.VEHICLE_COUNT(차량 대수): 각 호실이 등록한 차량 대수를 기준으로 사용합니다.
각 호실에 대해 0보다 큰 실수 값을 반환하는 함수가 정의될 수 있다면, 해당 함수의 결과값을 분배 기준으로 사용할 수 있습니다.
TypeScript로 보여주는 배분 기준 계산 함수입니다.
function imposeCost( units: Unit[], getImpositionBasis: ImpositionBasisFunction, value: CostValue): [Unit, number][] { let unitCost: number; if (value.type === '정액') { unitCost = value.unitCost; } else { const totalBasis = units.reduce((sum, unit) => sum + getImpositionBasis(unit), 0); unitCost = totalBasis / value.totalCost; } return units.map(unit => [unit, getImpositionBasis(unit) * unitCost]);}Kotlin으로 보여주는 배분 기준 계산 함수입니다.
fun imposeCost( units: List<Unit>, getImpositionBasis: (Unit) -> Double, value: CostValue): Map<Unit, Double> { val unitCost = when (value) { is CostValue.Fixed -> value.unitCost is CostValue.Variable -> { val totalBasis = units.sumOf { getImpositionBasis(it) } totalBasis / value.totalCost } } return units.associateWith { getImpositionBasis(it) * unitCost }}계산은 위와 같이 각 호실에 대해 단가를 계산하여 기준을 곱하여 부과합니다.