Skip to content

산출표 집계 계약 — BE 참고

관리비 상용화 보고서 확충 트랙(2026-07-11, B-1) — 산출표(신규). 설계 정본: docs/superpowers/specs/2026-07-11-period-tag-minors-reports-xlsx-design.md §B-1. as-built 정본 소스: src/composables/useCalculationTable.js.


1. 개요

산출표는 이번 차수(당기)에 활성 상태인 관리비 항목 각각이 어떤 수량·단가로 얼마나 발생하고 할인·조정을 거쳐 최종 얼마로 부과됐는지를 항목 축 하나로 보여주는 read-only 문서다. 총괄표·부과내역서·수납현황이 세대(유닛) 축 중심이라면, 산출표는 부과 콘솔(설정 > 항목, useCharges)의 계산 결과를 그대로 항목별로 나열한다. 재계산은 일절 하지 않는다useCharges.amountsOf()가 이미 산출한 발생/부과 원금·단가를 그대로 재투영할 뿐이다.

2. 데이터 정본 — useCalculationTable

src/composables/useCalculationTable(){ calculationRows, calculationTotals, formatAmount }.

내부적으로 useCharges(activeCharges·amountsOf·parseAmount·formatAmount) 하나만 소비한다.

2-1. calculationRows() — 활성 항목 1행씩

js
function calculationRows() {
  return activeCharges.value.map((c) => {
    const a = amountsOf(c);
    return {
      chargeCode: c.chargeCode,
      name: c.name,
      chargeBasis: c.chargeBasis,
      수량: parseAmount(c.targetCount),
      단가: a.unitPrice,
      발생금액: a.accruedPrincipal,
      할인금액: parseAmount(c.chargeDiscount),
      부과금액: a.chargePrincipal,
    };
  });
}
  • 수량/단가/발생금액/부과금액 전부 useCharges.amountsOf(charge)(SC-3a 4-addend 모델 — 발생측·부과측 각각 기본+할증+할인+조정 signed addend 합)의 파생값을 그대로 복사한다. 새 산식 없음.
  • 할인금액만 예외적으로 amountsOf의 파생값이 아니라 부과측 입력(chargeDiscount) 원자값parseAmount로 직접 뽑는다 — amountsOf는 4개 addend를 이미 합산해 chargePrincipal만 반환하므로, 할인 하나만 별도 열로 노출하려면 addend를 원자값에서 직접 읽어야 한다(chargePrincipal 자체는 재계산하지 않고 그대로 씀).

2-2. calculationTotals(rows)

js
function calculationTotals(rows = calculationRows()) {
  const sum = (k) => rows.reduce((s, r) => s + r[k], 0);
  return { 발생금액: sum("발생금액"), 할인금액: sum("할인금액"), 부과금액: sum("부과금액") };
}

rows 생략 시 내부에서 calculationRows()를 재호출(총괄표 columnTotals 관용과 동일) — FE 소비 시 rowscomputed로 감싸 명시 전달 권장.

3. 불변식 3종 (vitest, src/composables/__tests__/useCalculationTable.spec.js)

#불변식지키는 회계 정합
각 행 발생금액 === amountsOf(c).accruedPrincipal · 부과금액 === amountsOf(c).chargePrincipal · 단가 === amountsOf(c).unitPrice산출표가 부과 콘솔(useCharges)과 다른 계산 경로를 타지 않는다 — 두 화면 대조 시 항상 일치
Σ부과금액 === useChargeSummaryTable().columnTotals().세전합계 + useAllocations().totalUnallocated()항목축(산출표)과 유닛축(총괄표) 두 서로 다른 투영이 배분 잔차까지 포함해 항등 — 배분 로직이 두 화면 사이에서 값을 잃어버리지 않는다는 교차검증(독립 소스 대조 — 총괄표·useAllocations 둘 다 재사용, 자기순환 아님)
calculationTotals(rows).발생금액/부과금액 === rows.reduce(...)합계 열이 실제 행 합과 일치(열거합 회귀 가드)

as-built 진단(2026-07-11): 3개 불변식 모두 최초 구현에서 통과 — amountsOf를 그대로 복사하는 얇은 재투영 레이어라 새 계산 경로가 없기 때문.

4. 필드 계약

필드정의
chargeCode / name부과항목 식별(useCharges)
chargeBasis배분기준(예: 사용량·전용) — 표시용, 배분 자체는 useAllocations가 별도 수행
수량parseAmount(c.targetCount) — 항목 설정(설정 > 항목)의 대상 수량 입력 원자값
단가amountsOf(c).unitPrice = targetCount ? Math.round(chargePrincipal/targetCount) : 0
발생금액amountsOf(c).accruedPrincipal — 발생측 4-addend 합(기본+할증+할인+조정)
할인금액parseAmount(c.chargeDiscount) — 부과측 할인 addend 원자값(음수 부호 규약, §2-1)
부과금액amountsOf(c).chargePrincipal — 부과측 4-addend 합

5. 스코프 제외

  • 조정명세서·대장: 항목 조정(가감) 이력을 별도 문서로 감사 추적하는 조정명세서·조정대장은 이 트랙 스코프 밖이다. 산출표는 "현재 확정된 값"만 보여주며 조정 이력(누가·언제·왜 바꿨는지)은 다루지 않는다.
  • 기간범위·층/블록 축: 이번 차수 하나·단지 전체 기준만 제공. 여러 차수 비교나 층/블록별 필터는 미구현(FE handoff §확장 포인트 참고).

6. 확장 포인트

  • 조정명세서: 별도 컴포저블 신설 필요 — 항목 조정 입력(chargeAdjustment/accruedAdjustment)의 변경 이력을 감사 로그로 남기는 기능이 선행돼야 한다(현재 useCharges는 최신값만 보유, 이력 없음).
  • 기간범위 조회: 여러 차수(연월)의 산출표를 나란히 비교하려면 useBillingPeriod().periods(차수 이력)를 순회하며 각 차수 시점의 useCharges 스냅샷이 필요 — 현재 useCharges는 차수와 무관한 단일 최신 상태만 갖고 있어(체인 개념 없음), 이 확장은 useCharges 자체의 차수별 스냅샷 구조 도입이 선행돼야 한다(중대한 변경, 별도 트랙 필요).