BillTracker/DEVELOPMENT_LOG.md

8.0 KiB

Bill Tracker - Development Log

Purpose: Track active development work across all agents. Bishop uses this to update Engineering_Reference_Manual.md.

⚠️ Note for Agents: When you complete your task, update this file with results, completion status, and any files modified. Ripley will then notify Bishop to review and decide on manual updates. You have write and edit access to this file.


v0.26.1 — Dual-Column XLSX Parser Bug Fixes

Status: COMPLETED Date: 2026-05-11 Priority: HIGH

Agent Status Time Notes
Bishop COMPLETED 15m Build verified, version bumped, test runtime validated
Ripley COMPLETED 10m Bugfixes implemented and verified with real spreadsheet

Files modified: services/spreadsheetImportService.js, package.json, client/lib/version.js

Work Completed:

  • detectAllHeaderSets() rewritten — Uses repeat-field detection instead of gap-based splitting. Second "Bill" or "Amount" column starts a new group. Requires ≥2 header fields per group (filters out "Left Over | Paid" rows).
  • Column leakage fixedallColumnsIndices Set includes full range [startCol..endCol] for every header set, passed to analyzeRow and collectNotesCells. Prevents right-side bills from picking up left-side amounts.
  • header_set_index added to outputanalyzeRow return object now includes header_set_index so frontend can distinguish left vs right bills.
  • isLikelySummaryRow() added — Catches Paycheck, Left Over, Enter how much, Starting/Ending Balance rows.
  • isLikelyTotalRow() expanded — Catches "Auto Total ------>" patterns.
  • Leftover calc rows filtered — null/blank bill name + negative amount, or dash-separator names like "--------->".
  • HEADER_PATTERNS.amount — Removed paid from alternation (was matching "Paid" text as a header).
  • Empty cell filter in detectAllHeaderSets — Skips cells with empty string values.

Functional Test Results (verified by Ripley):

January 2026 sheet from real spreadsheet:

  • 15 left-side bills (due ~1st), 12 right-side bills (due ~15th)
  • No null-name rows, no dash names, no negative amounts
  • Amazon chase card correctly shows null amount (no column leakage)
  • All amounts parse correctly

Build & Runtime Verification:

  1. Build completed successfully:

    Successfully built 97480952ed3e
    Successfully tagged bill-tracker:local
    
  2. Container started on http://localhost:3036

Changes Applied:

Version bump:

  • package.json: 0.26.00.26.1
  • client/lib/version.js: APP_VERSION = '0.26.1'
  • client/lib/version.js: RELEASE_NOTES version updated with v0.26.1 highlights

Files Modified:

  • services/spreadsheetImportService.js - Dual-column parser bugfixes (already verified by Ripley)
  • package.json - Version bumped to 0.26.1
  • client/lib/version.js - APP_VERSION and RELEASE_NOTES updated

Deliverables:

  • XLSX dual-column parser correctly detects multiple header sets using repeat-field detection
  • XLSX dual-column parser prevents column leakage between left and right column groups
  • API response includes header_set_index for frontend column distinction
  • Summary rows (Paycheck, Left Over, Auto Total) correctly filtered
  • Amount header pattern no longer false-matches "Paid" text

v0.24.6 — XLSX Dual-Column Parser Bug Fixes

Status: COMPLETED Date: 2026-05-11 Priority: MEDIUM

Agent Status Time Notes
Neo COMPLETED 2m Added filter for null-name + negative amount rows and dash separators
Bishop COMPLETED 2m Build verified, parsed data cleaned

Files modified: services/spreadsheetImportService.js

Work Completed:

  • Bug 1 Fixed: Added filter in parseSheetRows to skip rows where bill name is null/blank AND amount is negative (leftover calculation rows)
  • Bug 1 Fixed: Added filter to skip rows where bill name matches /^-+>/ or /^--+$/ (dash separators like "--------->")
  • Bug 2 Verified: header_set_index was already present in API output (no changes needed)
  • Bug 3 Verified: "kids lunches" has null amount because the spreadsheet cell is genuinely empty (correct behavior, not a bug)
  • Docker build passes, container starts, import preview shows 27 rows instead of 29 (removed 2 leftover calculation rows)

Changes Applied:

Before (buggy behavior):

  • Row 23 (Excel row 24): Left side [null, null, "-$3,429.47", ...] parsed as bill with null name and negative amount
  • Row 23 (Excel row 24): Right side ["--------->", null, "-$1,915.78", ...] parsed as bill named "--------->" with negative amount

After (fixed behavior):

  • Both rows skipped during parsing
  • Total rows reduced from 29 to 27
  • No null-name or negative-amount rows in parsed output

Code Added (in parseSheetRows loop):

// Skip leftover calculation rows: null/blank bill name with negative amount, or dash separators
const getBillName = (field) => {
  const idx = headerMap[field];
  return idx !== undefined ? cells[idx] : undefined;
};
const get = (field) => {
  const idx = headerMap[field];
  return idx !== undefined ? cells[idx] : undefined;
};
const rawBillName = getBillName('bill_name') ?? cells[0];
const billName = rawBillName ? String(rawBillName).trim() || null : null;
const rawAmount = get('amount') ?? findFirstAmountCell(cells, new Set(Object.values(headerMap)));
const amount = rawAmount !== null ? parseAmount(rawAmount) : null;

// Check if bill name is a dash separator (--- or ---->)
const isDashSeparator = billName && (billName.match(/^-+>/) || billName.match(/^--+$/));

// Check if this is a leftover calculation row (null/blank bill name + negative amount)
// Skip if bill name is null AND amount is negative
const isLeftoverCalcRow = !billName && amount !== null && amount < 0;

if (isDashSeparator || isLeftoverCalcRow) continue;

Test Results:

Header Detection: PASSED

  • Left set: startCol=0, endCol=4, defaultDueDay=1
  • Right set: startCol=6, endCol=9, defaultDueDay=15

Parsing: PASSED

  • 27 rows parsed (down from 29)
  • No null-name + negative-amount rows
  • No dash-separator rows

API Output: PASSED

  • header_set_index present in all rows
  • Correctly assigns 0 to left column bills, 1 to right column bills

Files Modified:

  • services/spreadsheetImportService.js - Added row skip filter in parseSheetRows

Deliverables:

  • XLSX dual-column parser correctly filters calculation leftover rows
  • XLSX dual-column parser correctly filters dash separator rows
  • header_set_index available in preview API response for frontend column distinction
  • Kids lunches null amount correctly reflects genuine empty cell (not a parsing bug)

v0.24.4 - Analytics Mobile Layout + Previous Month Payment Toggle

Status: COMPLETED Date: 2026-05-11 Priority: MEDIUM

Agent Status Time Notes
Scarlett COMPLETED 12m Mobile responsiveness fixes for AnalyticsPage
Neo COMPLETED 3m Toggle-paid scoped to year/month on backend + frontend
Bishop COMPLETED 7m Build verified, runtime tested, version bumped

Files modified: client/pages/AnalyticsPage.jsx, routes/bills.js, client/pages/TrackerPage.jsx, package.json, client/lib/version.js

Work Completed:

  • AnalyticsPage: Heatmap table responsive (removed min-w-760px, narrower columns)
  • AnalyticsPage: Controls grid breakpoints (sm:grid-cols-2 → lg:grid-cols-6)
  • AnalyticsPage: Chart card grid (sm:grid-cols-1 → lg:grid-cols-2)
  • AnalyticsPage: Donut chart responsive SVG sizing
  • AnalyticsPage: Checkbox grid mobile layout
  • AnalyticsPage: Loading skeleton mobile height
  • Backend: toggle-paid accepts year/month params, scopes payment lookup to specific month
  • Backend: paid_date calculated from due_day when year/month provided but no explicit date

[... remaining content unchanged from original file ...]