Description
calculateNextRenewal() in the billing simulation service uses hardcoded fixed-day math:
case 'monthly': return addDays(date, 30); // ← wrong: Feb has 28 days, July has 31
case 'quarterly': return addDays(date, 90); // ← drifts ~3 days per year
case 'annual': return addDays(date, 365); // ← misses leap years
For a monthly subscription starting January 31st:
- Fixed 30 days: next renewal = March 2nd (skips February entirely)
- Correct calendar month: next renewal = February 28th (end of month)
Over 12 months, a 30-day interval drifts ~5 days from the actual calendar date. Reminder notifications fire at the wrong time, and billing projections show incorrect dates.
Fix
Use date-fns calendar-aware functions (already installed):
import { addMonths, addQuarters, addYears } from 'date-fns';
function calculateNextRenewal(date: Date, billingCycle: string): Date {
switch (billingCycle) {
case 'monthly': return addMonths(date, 1);
case 'quarterly': return addQuarters(date, 1);
case 'annual': return addYears(date, 1);
case 'weekly': return addWeeks(date, 1);
default: throw new Error(`Unknown billing cycle: ${billingCycle}`);
}
}
addMonths correctly handles end-of-month edge cases (Jan 31 → Feb 28/29 → Mar 31).
Additional Locations to Fix
/backend/src/services/auto-expiry-service.ts — any date arithmetic for billing cycles
/backend/src/services/reminder-engine.ts — reminder date calculation
/client/lib/ — any client-side date math for renewal displays
Acceptance Criteria
Description
calculateNextRenewal()in the billing simulation service uses hardcoded fixed-day math:For a monthly subscription starting January 31st:
Over 12 months, a 30-day interval drifts ~5 days from the actual calendar date. Reminder notifications fire at the wrong time, and billing projections show incorrect dates.
Fix
Use
date-fnscalendar-aware functions (already installed):addMonthscorrectly handles end-of-month edge cases (Jan 31 → Feb 28/29 → Mar 31).Additional Locations to Fix
/backend/src/services/auto-expiry-service.ts— any date arithmetic for billing cycles/backend/src/services/reminder-engine.ts— reminder date calculation/client/lib/— any client-side date math for renewal displaysAcceptance Criteria
addMonths/addYears/addQuartersfromdate-fns