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: 'Tecnostac', 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)', () => { const db = openDb(':memory:') const a = 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 = 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(listQueue(db)).toHaveLength(1) expect(db.prepare(`SELECT COUNT(*) AS n FROM audit_log WHERE entity='reminder'`).get()).toMatchObject({ n: 1 }) }) it('transitions and dismisses, refusing to dismiss a sent reminder', () => { const db = openDb(':memory:') const { id } = upsertReminder(db, { ruleKind: 'follow_up', subjectId: 'i1', duePeriod: '2026-07-08', clientId: 'c1', now: '2026-07-10T00:00:00Z' }) const dismissed = dismissReminder(db, 'u1', id) expect(dismissed.status).toBe('dismissed') const { id: id2 } = upsertReminder(db, { ruleKind: 'invoice_overdue', subjectId: 'inv2', duePeriod: '2026-07', clientId: 'c1', docId: 'inv2', now: '2026-07-10T00:00:00Z' }) setReminderStatus(db, 'u1', id2, 'sent', { sentAt: '2026-07-10T09:00:00Z' }) expect(getReminder(db, id2)!.status).toBe('sent') expect(() => dismissReminder(db, 'u1', id2)).toThrow(/sent/i) }) it('reads number settings with a fallback', () => { const db = openDb(':memory:') expect(getNumberSetting(db, 'reminders.overdue_days', 7)).toBe(7) setSetting(db, 'u1', 'reminders.overdue_days', '10') expect(getNumberSetting(db, 'reminders.overdue_days', 7)).toBe(10) }) })