From 428e18bb41d556f6046a1d7855f1d1fb2d746931 Mon Sep 17 00:00:00 2001 From: Catherine Renelle <32781029+catrenelle@users.noreply.github.com> Date: Sat, 14 Feb 2026 17:26:55 -0500 Subject: [PATCH] Fix date display timezone shift and revert to standard monthly interest formatDate was parsing UTC timestamps in local time, shifting dates back a day in western timezones. Strip the time portion before parsing so dates display correctly. Revert interest calculation from daily accrual back to standard monthly compounding (rate/12) with per-payment rounding. This matches how mortgage servicers calculate interest and produces correct amortization schedules. Co-Authored-By: Claude Opus 4.6 --- frontend/src/utils/formatters.ts | 2 +- src/Purrse.Api/Services/LoanService.cs | 14 ++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/frontend/src/utils/formatters.ts b/frontend/src/utils/formatters.ts index 995e23b..a22e9d2 100644 --- a/frontend/src/utils/formatters.ts +++ b/frontend/src/utils/formatters.ts @@ -5,7 +5,7 @@ export function formatCurrency(amount: number): string { } export function formatDate(date: string): string { - return format(parseISO(date), 'MM/dd/yyyy') + return format(parseISO(date.split('T')[0]), 'MM/dd/yyyy') } export function formatDateTime(date: string): string { diff --git a/src/Purrse.Api/Services/LoanService.cs b/src/Purrse.Api/Services/LoanService.cs index 149713b..071326e 100644 --- a/src/Purrse.Api/Services/LoanService.cs +++ b/src/Purrse.Api/Services/LoanService.cs @@ -118,12 +118,11 @@ public class LoanService : ILoanService // Build new schedule with extra payments var balance = Math.Abs(account.Balance); - var dailyRate = l.InterestRate / 100m / 365m; + var monthlyRate = l.InterestRate / 100m / 12m; var extraMonthly = request.ExtraMonthlyPayment ?? 0; var basePayment = l.MonthlyPayment - (l.EscrowAmount ?? 0); var now = DateTime.UtcNow; var startDate = new DateTime(now.Year, now.Month, l.OriginationDate.Day, 0, 0, 0, DateTimeKind.Utc); - var previousDate = startDate; var newEntries = new List(); int paymentNum = 0; @@ -139,15 +138,13 @@ public class LoanService : ILoanService { paymentNum++; var paymentDate = startDate.AddMonths(paymentNum); - var days = (paymentDate - previousDate).Days; - var interest = balance * dailyRate * days; + var interest = Math.Round(balance * monthlyRate, 2); var principal = Math.Min(basePayment + extraMonthly - interest, balance); if (principal < 0) principal = 0; balance -= principal; if (balance < 0.01m) balance = 0; - previousDate = paymentDate; newEntries.Add(new AmortizationEntryResponse( paymentNum, paymentDate, principal + interest + (l.EscrowAmount ?? 0), @@ -188,20 +185,17 @@ public class LoanService : ILoanService { var entries = new List(); var balance = loan.OriginalBalance; - var dailyRate = loan.InterestRate / 100m / 365m; + var monthlyRate = loan.InterestRate / 100m / 12m; var payment = loan.MonthlyPayment - (loan.EscrowAmount ?? 0); var extra = loan.ExtraPayment ?? 0; - var previousDate = loan.OriginationDate.AddMonths(-1); for (int i = 1; i <= loan.TermMonths && balance > 0; i++) { var paymentDate = loan.OriginationDate.AddMonths(i - 1); - var days = (paymentDate - previousDate).Days; - var interest = balance * dailyRate * days; + var interest = Math.Round(balance * monthlyRate, 2); var principal = Math.Min(payment + extra - interest, balance); balance -= principal; if (balance < 0.01m) balance = 0; - previousDate = paymentDate; entries.Add(new AmortizationEntry {