Problem
Three issues in the loyalty points expiry system:
1. Dead setting: loyalty_expiry_enabled
loyalty_expiry_enabled is seeded in db.ts:575 (default '0') but never read or checked anywhere:
bills.ts:221 only checks loyalty_enabled — expiry always runs when loyalty is on
- Frontend settings page has no toggle for it — just the months input (
settings/page.tsx:910-920)
Result: Expiry is always active when loyalty is enabled, with no way to disable it. The setting is dead code.
Fix: Either wire it up (check loyalty_expiry_enabled before setting expires_at in bills.ts) or remove it from db.ts.
2. No cleanup of expired loyalty ledger entries
Expired credits stay in loyalty_ledger forever. They're correctly excluded from balance calculations (expires_at > datetime('now')), but the table grows indefinitely with no purge mechanism.
Fix: Add a periodic cleanup query or a startup cleanup that deletes expired credit entries:
DELETE FROM loyalty_ledger WHERE type = 'credit' AND expires_at IS NOT NULL AND expires_at < datetime('now')
3. "Next expiry" shows only the earliest date
customers.ts:132-135 uses MIN(expires_at) — returns a single date. If a customer has multiple batches expiring on different dates, only the earliest is shown. This can be misleading (e.g., customer sees "expires Aug 1" but has another batch expiring Dec 1).
Fix: Return a summary of upcoming expirations, or at minimum indicate that more batches exist beyond the shown date.
Problem
Three issues in the loyalty points expiry system:
1. Dead setting:
loyalty_expiry_enabledloyalty_expiry_enabledis seeded indb.ts:575(default'0') but never read or checked anywhere:bills.ts:221only checksloyalty_enabled— expiry always runs when loyalty is onsettings/page.tsx:910-920)Result: Expiry is always active when loyalty is enabled, with no way to disable it. The setting is dead code.
Fix: Either wire it up (check
loyalty_expiry_enabledbefore settingexpires_atinbills.ts) or remove it fromdb.ts.2. No cleanup of expired loyalty ledger entries
Expired credits stay in
loyalty_ledgerforever. They're correctly excluded from balance calculations (expires_at > datetime('now')), but the table grows indefinitely with no purge mechanism.Fix: Add a periodic cleanup query or a startup cleanup that deletes expired credit entries:
3. "Next expiry" shows only the earliest date
customers.ts:132-135usesMIN(expires_at)— returns a single date. If a customer has multiple batches expiring on different dates, only the earliest is shown. This can be misleading (e.g., customer sees "expires Aug 1" but has another batch expiring Dec 1).Fix: Return a summary of upcoming expirations, or at minimum indicate that more batches exist beyond the shown date.