Private
Public Access
1
0
Commit Graph

10 Commits

Author SHA1 Message Date
Catherine Renelle dd2cdbf815 Use daily interest accrual for HELOC and auto loan amortization
Mortgages and personal loans use monthly compounding (rate/12), but
HELOCs and auto loans accrue interest daily (rate/365 * actual days).
Select the calculation method based on account type and update the
disclaimer to reflect which method is being used.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 18:41:32 -05:00
Catherine Renelle 428e18bb41 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 <noreply@anthropic.com>
2026-02-14 17:26:55 -05:00
Catherine Renelle 0f3ad89c59 Fix loan edit concurrency error with ExecuteDeleteAsync
The change tracker-based approaches (RemoveRange, Clear) both caused
DbUpdateConcurrencyException when deleting amortization entries.
Use ExecuteDeleteAsync to delete directly in the database, bypassing
the change tracker entirely.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 17:12:20 -05:00
Catherine Renelle 6ddecd7a99 Use first payment date and maturity date instead of origination date and term
Replace the term months field with a maturity date picker - users know
when their loan ends, not the month count. Compute termMonths from the
two dates. Rename "Origination Date" to "First Payment Date" and adjust
the amortization schedule so payment #1 falls on the entered date.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 17:06:21 -05:00
Catherine Renelle 7efeb4957b Fix concurrency exception when editing loan details
RemoveRange + collection replacement caused EF Core to attempt a
double-delete on amortization entries. Use Clear() on the tracked
collection instead, letting EF handle orphan deletion in a single pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 17:00:47 -05:00
Catherine Renelle b7ef9e36ce Fix loan interest calculation to use daily accrual instead of rate/12
The amortization schedule and payoff calculator were using rate/12 for
monthly interest, which assumes 30.42 days per period and overestimates
interest. Switch to daily accrual (rate/365 * actual days) to match how
lenders actually compute interest between payment dates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 16:52:50 -05:00
Catherine Renelle 08a0bcda3d Don't pre-populate original balance from current balance in loan defaults
The current account balance is not the origination balance, so defaulting
it into the Original Balance field is misleading. Leave it at 0 so users
enter the actual loan origination amount.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 16:39:23 -05:00
Catherine Renelle 3bb9c688ed Auto-populate loan details from Plaid liabilities and pre-fill setup form
Fetch loan data (mortgage/student) from Plaid's Liabilities API during sync
and auto-create LoanDetail records. For accounts without liabilities data,
pre-populate the setup form with balance, interest rate, and smart term
defaults. Also fixes maturity date computation in the frontend form.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 16:23:49 -05:00
Catherine Renelle 8b2f5aad56 Normalize all DateTime values to UTC across the codebase
Npgsql requires DateTimeKind.Utc for timestamp with time zone
columns. This fixes errors in transaction create/edit, budgets,
reports, loans, scheduled transactions, and file imports.

Changes:
- TransactionService: SpecifyKind on request.Date for create,
  update, and transfer
- BudgetService: UTC kind on all new DateTime(year, month, 1)
- ReportService: UTC kind on endOfMonth; rewrite spending-by-
  category GroupBy to avoid untranslatable navigation properties
- LoanService: UTC kind on payoff scenario date construction
- ScheduledTransactionService: UTC kind on SemiMonthly date
- ImportService: SpecifyKind on parsed.Date when persisting
- OFX/CSV/QIF parsers: AssumeUniversal + AdjustToUniversal on
  all date parsing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 01:07:26 -05:00
Catherine Renelle 6520ebf221 Initial commit: Purrse personal finance app
Self-hosted, plugin-extensible personal finance manager built with
ASP.NET Core 9.0, Vue 3 + Vuetify 3, and PostgreSQL 17.

Backend (8 .NET projects):
- Core: 19 domain models, 6 enums, 14 DTOs, 12 service interfaces
- Data: EF Core DbContext, 16 entity configurations, category seeder
- API: 14 controllers, 15 services, JWT auth, SignalR, middleware
- Plugins: Abstractions + OFX/CSV/QIF file parsers
- Tests: 28 xUnit tests (fingerprinting, duplicate detection, parsers)

Frontend (Vue 3 + Vuetify 3 + TypeScript):
- 13 views, Pinia stores, Axios API services with JWT interceptors
- Dashboard, accounts, transactions, categories, imports, and more

Deployment:
- Docker Compose (PostgreSQL 17 + .NET API + nginx frontend)
- Auto-migration on startup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 08:56:46 -05:00