Remaining
0 ? 'text-foreground' : 'text-emerald-500')}>
@@ -1206,6 +1217,7 @@ function Bucket({ label, rows, year, month, refresh, onEditBill }) {
Bill
Due
Expected
+ Last Month
Paid
Paid Date
Status
@@ -1343,6 +1355,7 @@ export default function TrackerPage() {
+
{/* ── Empty state ── */}
diff --git a/package.json b/package.json
index 600b757..31afb6b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "bill-tracker",
- "version": "0.20.8",
+ "version": "0.20.9",
"description": "Monthly bill tracking system",
"main": "server.js",
"scripts": {
diff --git a/routes/tracker.js b/routes/tracker.js
index f46e5ff..b2d6423 100644
--- a/routes/tracker.js
+++ b/routes/tracker.js
@@ -19,6 +19,11 @@ router.get('/', (req, res) => {
const { start, end } = getCycleRange(year, month);
+ // Calculate previous month (with year wrapping)
+ const prevMonth = month === 1 ? 12 : month - 1;
+ const prevYear = month === 1 ? year - 1 : year;
+ const prevMonthRange = getCycleRange(prevYear, prevMonth);
+
const bills = db.prepare(`
SELECT b.*, c.name AS category_name
FROM bills b
@@ -31,6 +36,14 @@ router.get('/', (req, res) => {
'SELECT actual_amount, notes, is_skipped FROM monthly_bill_state WHERE bill_id=? AND year=? AND month=?'
);
+ // Prepare statement for previous month payments
+ const prevMonthPaymentsStmt = db.prepare(`
+ SELECT SUM(amount) as total_paid
+ FROM payments
+ WHERE bill_id = ? AND paid_date BETWEEN ? AND ?
+ AND deleted_at IS NULL
+ `);
+
const rows = bills.map(bill => {
// Only count non-deleted payments for status/totals
const payments = db.prepare(`
@@ -48,6 +61,10 @@ router.get('/', (req, res) => {
row.monthly_notes = mbs?.notes ?? null;
row.is_skipped = !!(mbs?.is_skipped);
+ // Get previous month paid amount
+ const prevMonthPayments = prevMonthPaymentsStmt.get(bill.id, prevMonthRange.start, prevMonthRange.end);
+ row.previous_month_paid = prevMonthPayments?.total_paid || 0;
+
return row;
});
@@ -68,6 +85,9 @@ router.get('/', (req, res) => {
const hasStartingAmounts = !!startingAmounts;
const activeTotalPaid = activeRows.reduce((s, r) => s + r.total_paid, 0);
const activeTotalExpected = activeRows.reduce((s, r) => s + r.expected_amount, 0);
+
+ // Calculate previous month total
+ const previousMonthTotal = activeRows.reduce((s, r) => s + r.previous_month_paid, 0);
res.json({
year, month, today: todayStr,
@@ -82,6 +102,7 @@ router.get('/', (req, res) => {
count_upcoming: activeRows.filter(r => r.status === 'upcoming' || r.status === 'due_soon').length,
count_late: activeRows.filter(r => r.status === 'late' || r.status === 'missed').length,
count_autodraft: activeRows.filter(r => r.status === 'autodraft').length,
+ previous_month_total: previousMonthTotal,
},
rows,
});