diff --git a/frontend/src/views/loans/LoansView.vue b/frontend/src/views/loans/LoansView.vue
index 2bf6d07..219b4dd 100644
--- a/frontend/src/views/loans/LoansView.vue
+++ b/frontend/src/views/loans/LoansView.vue
@@ -84,7 +84,7 @@
{{ loanDetail.termMonths }} months
- Origination Date
+ First Payment Date
{{ formatDate(loanDetail.originationDate) }}
@@ -220,9 +220,9 @@
-
-
+
+
@@ -289,9 +289,9 @@ const payoffForm = ref({
const loanForm = ref({
originalBalance: 0,
interestRate: 0,
- termMonths: 360,
monthlyPayment: 0,
originationDate: '',
+ maturityDate: '',
escrowAmount: null as number | null,
extraPayment: null as number | null,
})
@@ -326,9 +326,9 @@ async function openSetupDialog() {
loanForm.value = {
originalBalance: 0,
interestRate: 0,
- termMonths: 360,
monthlyPayment: 0,
originationDate: new Date().toISOString().split('T')[0],
+ maturityDate: '',
escrowAmount: null,
extraPayment: null,
}
@@ -338,7 +338,6 @@ async function openSetupDialog() {
const { data } = await loansApi.getLoanDefaults(props.id)
if (data.originalBalance > 0) loanForm.value.originalBalance = data.originalBalance
if (data.interestRate > 0) loanForm.value.interestRate = data.interestRate
- if (data.termMonths > 0) loanForm.value.termMonths = data.termMonths
prePopulated.value = data.hasSyncData
} catch {
// Fall back to zero defaults
@@ -354,9 +353,9 @@ function openEditDialog() {
loanForm.value = {
originalBalance: loanDetail.value.originalBalance,
interestRate: loanDetail.value.interestRate,
- termMonths: loanDetail.value.termMonths,
monthlyPayment: loanDetail.value.monthlyPayment,
originationDate: loanDetail.value.originationDate.split('T')[0],
+ maturityDate: loanDetail.value.maturityDate.split('T')[0],
escrowAmount: loanDetail.value.escrowAmount,
extraPayment: loanDetail.value.extraPayment,
}
@@ -367,13 +366,17 @@ async function saveLoanDetail() {
if (!props.id) return
saving.value = true
try {
- const [year, month, day] = loanForm.value.originationDate.split('-').map(Number)
- const maturityDate = new Date(Date.UTC(year, month - 1 + loanForm.value.termMonths, day))
+ const [sY, sM, sD] = loanForm.value.originationDate.split('-').map(Number)
+ const [eY, eM, eD] = loanForm.value.maturityDate.split('-').map(Number)
+ const termMonths = (eY - sY) * 12 + (eM - sM) + 1
const payload = {
- ...loanForm.value,
- originationDate: new Date(Date.UTC(year, month - 1, day)).toISOString(),
- maturityDate: maturityDate.toISOString(),
+ originalBalance: loanForm.value.originalBalance,
+ interestRate: loanForm.value.interestRate,
+ termMonths,
+ monthlyPayment: loanForm.value.monthlyPayment,
+ originationDate: new Date(Date.UTC(sY, sM - 1, sD)).toISOString(),
+ maturityDate: new Date(Date.UTC(eY, eM - 1, eD)).toISOString(),
escrowAmount: loanForm.value.escrowAmount || undefined,
extraPayment: loanForm.value.extraPayment || undefined,
}
diff --git a/src/Purrse.Api/Services/BankSyncService.cs b/src/Purrse.Api/Services/BankSyncService.cs
index a9305ee..a32455f 100644
--- a/src/Purrse.Api/Services/BankSyncService.cs
+++ b/src/Purrse.Api/Services/BankSyncService.cs
@@ -665,20 +665,21 @@ public class BankSyncService : IBankSyncService
var originalBalance = liability.OriginalBalance ?? Math.Abs(linked.LastKnownBalance ?? 0);
var interestRate = liability.InterestRate ?? 0;
var termMonths = liability.TermMonths ?? (liability.LoanType == "Mortgage" ? 360 : 60);
- var originationDate = liability.OriginationDate ?? DateTime.UtcNow;
+ // Plaid gives loan origination date; first payment is typically one month later
+ var firstPaymentDate = liability.OriginationDate?.AddMonths(1) ?? DateTime.UtcNow;
var escrowBalance = liability.EscrowBalance;
// Compute monthly payment via amortization formula if not provided
var monthlyPayment = liability.MonthlyPayment ?? ComputeMonthlyPayment(originalBalance, interestRate, termMonths);
- var maturityDate = liability.MaturityDate ?? originationDate.AddMonths(termMonths);
+ var maturityDate = liability.MaturityDate ?? firstPaymentDate.AddMonths(termMonths - 1);
var request = new CreateLoanDetailRequest(
originalBalance,
interestRate,
termMonths,
monthlyPayment,
- DateTime.SpecifyKind(originationDate, DateTimeKind.Utc),
+ DateTime.SpecifyKind(firstPaymentDate, DateTimeKind.Utc),
DateTime.SpecifyKind(maturityDate, DateTimeKind.Utc),
escrowBalance,
null
diff --git a/src/Purrse.Api/Services/LoanService.cs b/src/Purrse.Api/Services/LoanService.cs
index de6c998..df2bb96 100644
--- a/src/Purrse.Api/Services/LoanService.cs
+++ b/src/Purrse.Api/Services/LoanService.cs
@@ -187,11 +187,11 @@ public class LoanService : ILoanService
var dailyRate = loan.InterestRate / 100m / 365m;
var payment = loan.MonthlyPayment - (loan.EscrowAmount ?? 0);
var extra = loan.ExtraPayment ?? 0;
- var previousDate = loan.OriginationDate;
+ var previousDate = loan.OriginationDate.AddMonths(-1);
for (int i = 1; i <= loan.TermMonths && balance > 0; i++)
{
- var paymentDate = loan.OriginationDate.AddMonths(i);
+ var paymentDate = loan.OriginationDate.AddMonths(i - 1);
var days = (paymentDate - previousDate).Days;
var interest = balance * dailyRate * days;
var principal = Math.Min(payment + extra - interest, balance);