fix: mortgage and housing categories auto-detected as debt in snowball

This commit is contained in:
null 2026-06-03 22:19:58 -05:00
parent b7c855e570
commit 4188a2059d
3 changed files with 5 additions and 1 deletions

View File

@ -30,6 +30,8 @@
### 🐛 Fixed
- **Mortgage and housing categories now auto-detected as debt**`DEBT_LIKE_CLAUSES` in `routes/snowball.js` matched `%credit%`, `%loan%`, and `%debt%` category names but not `%mortgage%` or `%housing%`. A real user who created a bill under a "Mortgage" or "Housing" category would never see it on the Snowball page unless they manually toggled `snowball_include`. Demo data hid the bug because the seed bill has `snowball_include` pre-set. The frontend's `mortgageIncluded` warning in `SnowballPage.jsx` already checked for mortgage/housing in category and bill name — it just never fired because those bills were filtered out before reaching the page. Added both patterns to `DEBT_LIKE_CLAUSES`; the warning now works as intended, correctly flagging when a mortgage is present so users see the Ramsey Baby Step 2 note about excluding the house.
- **Imported payments now update debt balance** — Every payment creation path except spreadsheet import correctly computed `balance_delta` and updated `bills.current_balance`. Imported payments were permanently orphaned from debt tracking: the snowball page balance stayed wrong after an Excel import, delete/restore was broken (the restore path checks `balance_delta IS NULL` and silently skips the reversal), and any debt-related reporting was incorrect. Three paths were fixed. In `spreadsheetImportService.js` `createPaymentFromImport()`: added `computeBalanceDelta` import, fetches the bill fresh on every call (critical for sequential month imports so each payment sees the post-previous-payment balance), includes `balance_delta` in the INSERT, updates `bills.current_balance`, and sets `payment_source = 'import'` (was null). The `create_payment` action path in the same file had the identical gap and received the same treatment. `routes/matches.js` manual transaction confirm also had no `balance_delta` or `current_balance` update — fixed with the same `computeBalanceDelta` call inside the existing transaction block.
- **Daily worker cycle range bugs for quarterly and annual bills**`dailyWorker.js` had two bugs affecting non-monthly billing cycles. First, `getCycleRange(year, month)` was called without a bill argument, always producing the calendar-month range for payment lookups. A quarterly bill paid in January would be invisible to the autopay check in February and March because the worker only searched that calendar month — a payment that existed was treated as missing. Fixed by calling `getCycleRange(year, month, bill)` per-bill so quarterly bills look at their full 3-month window and annual bills look at the full year. Second, `buildTrackerRow()` returns `null` for bills whose cycle does not apply in the current month (quarterly/annual bills in non-due months), and the code immediately accessed `row.due_date` with no null check. JavaScript's `&&` short-circuit masked the crash for non-autopay bills, but any autopay-enabled quarterly or annual bill in a non-applicable month would throw `TypeError: Cannot read properties of null`. Fixed with an early `continue` when `getCycleRange` returns null and a defensive guard after `buildTrackerRow()`. The issue description incorrectly stated that `resolveDueDate()` and `getCycleRange()` ignore cycle types — both functions already handle quarterly, annual, biweekly, and weekly correctly; the tracker already filters non-applicable bills via `.filter(Boolean)`; no new scheduler was needed.

View File

@ -46,7 +46,7 @@ const PAYMENT_METHODS = [
];
const DEBT_KEYWORDS = ['credit', 'loan', 'mortgage', 'housing', 'debt'];
const SNOWBALL_KEYWORDS = ['credit', 'loan', 'debt'];
const SNOWBALL_KEYWORDS = ['credit', 'loan', 'debt', 'mortgage', 'housing'];
const SUBSCRIPTION_TYPES = [
['streaming', 'Streaming'],
['software', 'Software'],

View File

@ -13,6 +13,8 @@ const DEBT_LIKE_CLAUSES = `(
LOWER(c.name) LIKE '%credit%'
OR LOWER(c.name) LIKE '%loan%'
OR LOWER(c.name) LIKE '%debt%'
OR LOWER(c.name) LIKE '%mortgage%'
OR LOWER(c.name) LIKE '%housing%'
)
)
)`;