- 기존 대출(loanStart 없음)이 남은 회차=전체(60회)로 나오던 문제 수정: 현재 잔액과 최초 상환액으로 남은 개월수 역산(날짜 정보 불필요) - '이번 달 상환' → '이번 달 상환 예정금액', 금액 앞 '이번 달' 제거 - '남은 N회' → '남은 회차 N회' Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+18
-5
@@ -71,19 +71,32 @@ export function loanSchedule(w, now = currentYm(), cap = 600) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EQUAL_PAYMENT 원리금균등: 매월 상환액 고정
|
// EQUAL_PAYMENT 원리금균등: 매월 상환액 고정
|
||||||
if (!nRem) {
|
// 남은 개월수는 '현재 잔액 + 최초 상환액'으로 역산 → loanStart 없어도 정확(기존 대출 대응)
|
||||||
// 총개월 정보 없음 → 이번 달 이자만 안내(원금 분리 불가)
|
let n = null
|
||||||
|
let payment = null
|
||||||
|
if (w.loanAmount && w.loanMonths && r > 0) {
|
||||||
|
const origPay = (Number(w.loanAmount) * r) / (1 - Math.pow(1 + r, -Number(w.loanMonths)))
|
||||||
|
payment = Math.round(origPay)
|
||||||
|
// bal = origPay·(1-(1+r)^-n)/r → n = -ln(1 - bal·r/origPay) / ln(1+r)
|
||||||
|
const ratio = 1 - (bal * r) / origPay
|
||||||
|
if (ratio > 0 && ratio < 1) {
|
||||||
|
n = Math.min(Number(w.loanMonths), Math.max(1, Math.ceil(-Math.log(ratio) / Math.log(1 + r) - 1e-9)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (n == null) n = nRem // 잔액 역산 불가 시 loanStart 경과 기반
|
||||||
|
if (n == null) {
|
||||||
|
// 개월·원금 정보 부족 → 이번 달 이자만 안내(원금 분리 불가)
|
||||||
const interest = Math.round(bal * r)
|
const interest = Math.round(bal * r)
|
||||||
return {
|
return {
|
||||||
rows: [{ label: label(y, m), principal: null, interest, total: null, balance: bal }],
|
rows: [{ label: label(y, m), principal: null, interest, total: null, balance: bal }],
|
||||||
partial: true,
|
partial: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const payment = r > 0 ? Math.round((bal * r) / (1 - Math.pow(1 + r, -nRem))) : Math.round(bal / nRem)
|
if (payment == null) payment = r > 0 ? Math.round((bal * r) / (1 - Math.pow(1 + r, -n))) : Math.round(bal / n)
|
||||||
for (let i = 0; i < nRem && bal > 0 && rows.length < cap; i++) {
|
for (let i = 0; i < n && bal > 0 && rows.length < cap; i++) {
|
||||||
const interest = Math.round(bal * r)
|
const interest = Math.round(bal * r)
|
||||||
let principal = payment - interest
|
let principal = payment - interest
|
||||||
if (i === nRem - 1 || principal > bal) principal = bal // 마지막 회차 잔액 정산
|
if (i === n - 1 || principal > bal) principal = bal // 마지막 회차 잔액 정산
|
||||||
bal = Math.max(0, bal - principal)
|
bal = Math.max(0, bal - principal)
|
||||||
rows.push({ label: label(y, m), principal, interest, total: principal + interest, balance: bal })
|
rows.push({ label: label(y, m), principal, interest, total: principal + interest, balance: bal })
|
||||||
;({ y, m } = addMonths(y, m, 1))
|
;({ y, m } = addMonths(y, m, 1))
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ function toggle(id) {
|
|||||||
<!-- 합계 요약 -->
|
<!-- 합계 요약 -->
|
||||||
<div class="summary">
|
<div class="summary">
|
||||||
<div class="sum-card accent">
|
<div class="sum-card accent">
|
||||||
<span class="k">이번 달 상환</span>
|
<span class="k">이번 달 상환 예정금액</span>
|
||||||
<span class="v">{{ won(thisMonth.t) }}</span>
|
<span class="v">{{ won(thisMonth.t) }}</span>
|
||||||
<span class="split">원금 {{ won(thisMonth.p) }} · 이자 {{ won(thisMonth.i) }}</span>
|
<span class="split">원금 {{ won(thisMonth.p) }} · 이자 {{ won(thisMonth.i) }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -157,8 +157,8 @@ function toggle(id) {
|
|||||||
<span class="sub">{{ it.sub }}</span>
|
<span class="sub">{{ it.sub }}</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="amt">
|
<span class="amt">
|
||||||
<span class="amt-now">이번 달 {{ won(itemThisMonth(it)) }}</span>
|
<span class="amt-now">{{ won(itemThisMonth(it)) }}</span>
|
||||||
<span class="amt-rem">남은 {{ it.rows.length }}회 · {{ won(itemRemain(it)) }}</span>
|
<span class="amt-rem">남은 회차 {{ it.rows.length }}회 · {{ won(itemRemain(it)) }}</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="chev">{{ expanded.has(it.id) ? '▾' : '▸' }}</span>
|
<span class="chev">{{ expanded.has(it.id) ? '▾' : '▸' }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user