whisper-money/app/Http/Controllers
Víctor Falcón 8f42496a5f
fix(dashboard): avoid month overflow in real estate projection (#340)
## Problem

`DashboardAnalyticsTest > real estate balance evolution appends
projected mortgage balance from linked loan` fails on certain calendar
dates (e.g. when run on 2026-04-30) with:

```
Failed asserting that 17324874 is less than 17324874.
```

## Root cause

Carbon's `addMonths()` defaults to overflow mode, so adding months to a
day that doesn't exist in the target month rolls forward into the next
month:

- `2026-04-30 + 10 months` → `2027-02-30` → overflow → `2027-03-02`
- `2026-04-30 + 11 months` → `2027-03-30`

Both end up in the same `Y-m` (`2027-03`). The dashboard
balance-evolution endpoint and
`LoanAmortizationService::projectFromBalance` use `addMonths` to build
month-keyed projections and to label projected chart points. When two
iterations collapse onto the same `Y-m`:

1. `generateProjection` overwrites the earlier balance with the later
one.
2. The controller emits two consecutive projected points labeled with
that month and assigns the same `mortgage_balance` to both, breaking the
strictly-decreasing assertion.

## Fix

Switch every `addMonths()` call in the projection paths to
`addMonthsNoOverflow()` so each iteration lands on a distinct month.

- `app/Services/LoanAmortizationService.php` — `projectFromBalance`,
`projectFromOriginal`
- `app/Http/Controllers/Api/DashboardAnalyticsController.php` — real
estate projected loop

## Verification

```
php artisan test --compact tests/Feature/DashboardAnalyticsTest.php
Tests: 34 passed (220 assertions)
```

Previously failing on 2026-04-30, now green.
2026-04-30 13:53:01 +00:00
..
Api fix(dashboard): avoid month overflow in real estate projection (#340) 2026-04-30 13:53:01 +00:00
OpenBanking feat(open-banking): remove feature flag gating (#297) 2026-04-17 10:20:05 +02:00
Settings feat(loans): backfill historical balances on loan creation (#322) 2026-04-24 13:09:34 +01:00
Sync refactor: Simplify transaction endpoints architecture (#76) 2026-01-25 16:15:17 +01:00
AccountBalanceController.php feat: investment benefits — show gains/losses on investment accounts (#140) 2026-02-23 13:59:10 +01:00
AccountController.php feat(accounts): merge real estate accounts with linked mortgages in UI (#248) 2026-03-26 20:54:12 +01:00
BudgetController.php chore: upgrade Laravel 12 to 13 (#242) 2026-03-25 12:56:33 +00:00
CashflowController.php fix(cashflow): read period from server props instead of window (#302) 2026-04-17 10:27:49 +01:00
Controller.php Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
DashboardController.php feat(dashboard): merge real estate accounts with linked mortgages on dashboard 2026-03-26 21:04:13 +01:00
EncryptionController.php Remove unused controllers and routes (#11) 2025-12-04 08:48:17 +01:00
LoanDetailController.php feat(loans): backfill historical balances on loan creation (#322) 2026-04-24 13:09:34 +01:00
OnboardingController.php feat: (Onboarding) add categorization intro screen with benefit cards (#201) 2026-03-05 11:47:12 +01:00
ReEvaluateTransactionRulesController.php feat(transactions): re-add select all matching filters to bulk actions bar (#169) 2026-03-01 10:27:43 +00:00
RealEstateDetailController.php feat(accounts): add real estate asset tracking (#241) 2026-03-24 10:21:32 +00:00
RobotsController.php User Onboarding Flow (#23) 2025-12-12 13:06:08 +01:00
SitemapController.php SEO landing page 2025-11-25 11:33:11 +01:00
SubscriptionController.php feat(subscriptions): add configurable trial period to paid plans (#324) 2026-04-24 14:07:46 +02:00
TransactionController.php fix(categorizer): fetch uncategorized transactions from backend instead of IndexedDB (#165) 2026-02-28 16:30:54 +00:00
UserLeadController.php feat: verify waitlist leads (#285) 2026-04-14 11:26:01 +01:00