import { describe, it, expect } from 'vitest' import { openDb } from '../src/db' import { reminderEmail } from '../src/reminder-templates' import { upsertReminder, listQueue, dismissReminder, setReminderStatus, getReminder, getNumberSetting, setSetting, } from '../src/repos-reminders' describe('reminder templates', () => { it('renders an overdue dunning email with the amount and a polite tone', () => { const mail = reminderEmail('invoice_overdue', { clientName: 'Malabar Stores', companyName: 'SiMS', docNo: 'INV/26-27-0007', amountPaise: 11_800_00, daysOverdue: 12, }) expect(mail.subject).toContain('INV/26-27-0007') expect(mail.bodyText).toContain('₹11,800.00') expect(mail.bodyText).toContain('12 day') }) }) describe('reminder repo', () => { it('is idempotent on (rule_kind, subject_id, due_period)', async () => { const db = openDb(':memory:') const a = await upsertReminder(db, { ruleKind: 'invoice_overdue', subjectId: 'inv1', duePeriod: '2026-07', clientId: 'c1', docId: 'inv1', now: '2026-07-10T00:00:00Z' }) expect(a.created).toBe(true) const b = await upsertReminder(db, { ruleKind: 'invoice_overdue', subjectId: 'inv1', duePeriod: '2026-07', clientId: 'c1', docId: 'inv1', now: '2026-07-10T06:00:00Z' }) expect(b.created).toBe(false) expect(b.id).toBe(a.id) // same row returned, not a duplicate expect((await listQueue(db)).rows).toHaveLength(1) // Phase 6: listQueue paginates ({ rows, total, page, pageSize }) expect((await listQueue(db)).total).toBe(1) expect(await db.get(`SELECT COUNT(*) AS n FROM audit_log WHERE entity='reminder'`)).toMatchObject({ n: 1 }) }) it('transitions and dismisses, refusing to dismiss a sent reminder', async () => { const db = openDb(':memory:') const { id } = await upsertReminder(db, { ruleKind: 'follow_up', subjectId: 'i1', duePeriod: '2026-07-08', clientId: 'c1', now: '2026-07-10T00:00:00Z' }) const dismissed = await dismissReminder(db, 'u1', id) expect(dismissed.status).toBe('dismissed') const { id: id2 } = await upsertReminder(db, { ruleKind: 'invoice_overdue', subjectId: 'inv2', duePeriod: '2026-07', clientId: 'c1', docId: 'inv2', now: '2026-07-10T00:00:00Z' }) await setReminderStatus(db, 'u1', id2, 'sent', { sentAt: '2026-07-10T09:00:00Z' }) expect((await getReminder(db, id2))!.status).toBe('sent') await expect(dismissReminder(db, 'u1', id2)).rejects.toThrow(/sent/i) }) it('reads number settings with a fallback', async () => { const db = openDb(':memory:') expect(await getNumberSetting(db, 'reminders.overdue_days', 7)).toBe(7) await setSetting(db, 'u1', 'reminders.overdue_days', '10') expect(await getNumberSetting(db, 'reminders.overdue_days', 7)).toBe(10) }) })