Invoice System: PDF Generation, Download & Email Delivery
#438 建立於 2026年2月14日
倉庫指標
- 星標
- (4 顆星)
- PR 合併指標
- (PR 指標待抓取)
描述
Current State
The invoice data infrastructure is built and working — but the rendering and delivery layer is completely missing.
What Exists
| Component | Status | Details |
|---|---|---|
Prisma Invoice model |
Done | invoiceNumber, amount, tax, items (JSON), pdfUrl, HSN codes |
| Auto-creation on payment | Done | handlePaymentSuccess() → Phase 2 → createInvoiceFromPayment() |
| Invoice number format | Done | FAM-YYYYMM-XXXXX with collision retry |
| GST/tax calculation | Done | 18% GST, SAC codes (999293 consulting, 999294 education) |
| API routes | Done | /api/invoices, /api/invoices/[id], staff/admin views |
| Line items with HSN | Done | Stored as JSON in items field |
| Consultee dashboard tab | Done | Invoices tab in Payments page (currently shows empty) |
What's Missing
| Component | Status | Impact |
|---|---|---|
| PDF generation | Not built | No downloadable invoices |
| PDF storage | Not built | pdfUrl field exists but is never populated |
| Invoice view page | Not built | No way to view invoice details in browser |
| Email delivery | Not built | No invoice sent to consultee after payment |
| Consultant invoice/receipt | Not built | Consultants have no payout receipts |
| Invoice template/branding | Not built | No Familiarise-branded invoice design |
| PDF library | Not installed | No pdfkit, jsPDF, react-pdf, or puppeteer in package.json |
Requirements
Legal/Tax Compliance (India)
GST-compliant invoices must include:
- Supplier name, address, GSTIN (Familiarise)
- Recipient name and address
- Invoice number (sequential, unique — already done:
FAM-YYYYMM-XXXXX) - Date of issue
- HSN/SAC code for each line item (already stored)
- Taxable value, GST rate (18%), CGST/SGST or IGST breakdown
- Total amount in words
- Digital signature (optional for <₹50K invoices)
User-Facing
- Consultees should be able to view and download invoices for every successful payment
- Invoice should be available within seconds of payment (not async/delayed)
- Should work for all 4 service types (Consultation, Subscription, Webinar, Class)
- Credits/discounts applied should be reflected on the invoice
Options
Option A: Server-Side PDF with @react-pdf/renderer (Recommended)
Generate PDFs on-demand using React components rendered to PDF on the server.
How it works:
- Consultee clicks "Download" on invoice row
- API route
/api/invoices/[id]/pdfrenders React component → PDF buffer - Returns PDF as response (
Content-Type: application/pdf) - Optionally cache to Supabase Storage and save URL to
pdfUrl
Pros:
- React-based templates (easy to design and maintain)
- No headless browser needed (pure Node.js)
- Can render both server-side and in-browser
- Good TypeScript support
- Popular in Next.js ecosystem
Cons:
- Limited styling (no full CSS — uses its own style system)
- Can be slow for complex layouts (~500ms per PDF)
Cost: Free (open source)
Option B: HTML → PDF with Puppeteer/Playwright
Render an HTML invoice page, then screenshot/print to PDF.
How it works:
- Create
/invoices/[id]/viewpage with full HTML/CSS invoice - API route spins up headless browser → navigates to page → prints PDF
- Store PDF in Supabase Storage
Pros:
- Full CSS/HTML control (pixel-perfect invoices)
- Can reuse the same template for web view and PDF
- Supports complex layouts, fonts, images
Cons:
- Requires headless browser (heavy dependency ~200MB)
- Slow (~2-5 seconds per PDF)
- Won't work on Vercel serverless (needs long-running process or separate service)
- Memory intensive
Cost: Free, but needs infrastructure for headless browser (separate container or Vercel Edge function won't work)
Option C: External Invoice Service (Zoho Invoice / Razorpay Invoice API)
Use a third-party service to generate and host invoices.
How it works:
- On payment success, call external API to create invoice
- Store returned PDF URL in
pdfUrl - Link to external hosted invoice
Pros:
- Zero implementation effort for PDF generation
- Professionally formatted, legally compliant
- Razorpay has built-in invoice API (we already use Razorpay)
- Handles email delivery too
Cons:
- Dependency on external service
- Less control over branding/layout
- Razorpay Invoice API: Free for Razorpay payments, but doesn't work for Stripe payments
- Zoho Invoice: ₹0 for <1000 invoices/year, then ₹750/month
Cost: Free to low (depends on volume)
Option D: Static Template with jsPDF (Client-Side)
Generate PDFs in the browser using jsPDF.
How it works:
- Invoice data loaded from API
- Client-side JavaScript builds PDF using jsPDF
- Downloads directly to user's browser
Pros:
- No server-side generation needed
- Instant download
- Zero infrastructure cost
Cons:
- Limited layout control (coordinate-based positioning)
- Hard to maintain complex templates
- No server-side caching/storage
- Can't email invoices (no server-side PDF)
- Inconsistent across browsers
Cost: Free
Recommendation
Option A (@react-pdf/renderer) for these reasons:
- Works on Vercel — pure Node.js, no headless browser
- React-native DX — templates are React components, easy for the team
- On-demand generation — no need to pre-generate and store (generate when user clicks download)
- Email-ready — same PDF can be attached to post-payment notification email
- Caching optional — can store to Supabase Storage for repeat downloads if needed
Suggested Implementation
Phase 1: Core PDF Generation
├── Install @react-pdf/renderer
├── Create invoice template component (GST-compliant)
├── Add GET /api/invoices/[id]/pdf endpoint
├── Add "Download" button to consultee Payments → Invoices tab
└── Test with all 4 service types
Phase 2: Storage & Email
├── Generate PDF on payment success (webhook Phase 2)
├── Upload to Supabase Storage
├── Save URL to Invoice.pdfUrl
├── Attach PDF to payment confirmation email (Novu/Resend)
└── Add invoice link to consultant earnings view
Phase 3: Polish
├── Branded template (Familiarise logo, colors)
├── Amount in words (Indian numbering: lakhs/crores)
├── CGST/SGST split (intra-state) vs IGST (inter-state)
├── Credit/discount line items on invoice
└── Bulk download for date range (admin/staff)
Invoice Template Fields
┌──────────────────────────────────────────────┐
│ FAMILIARISE INVOICE │
│ [Address] │
│ GSTIN: [TBD] │
│ │
│ Invoice No: FAM-202602-00001 │
│ Date: 14 Feb 2026 │
│ Due: Paid │
│ │
│ Bill To: │
│ Aarav Brown │
│ aarav.brown@protonmail.com │
│ │
│ ┌────────────────────┬────┬───────┬───────┐ │
│ │ Description │Qty │ Rate │Amount │ │
│ ├────────────────────┼────┼───────┼───────┤ │
│ │ Consultation: │ 1 │₹500 │₹500 │ │
│ │ Basic Consultation │ │ │ │ │
│ │ SAC: 999293 │ │ │ │ │
│ ├────────────────────┼────┼───────┼───────┤ │
│ │ Subtotal │ │ │₹500 │ │
│ │ CGST @ 9% │ │ │₹45 │ │
│ │ SGST @ 9% │ │ │₹45 │ │
│ │ Discount (WELCOME) │ │ │-₹100 │ │
│ │ Credit Applied │ │ │-₹200 │ │
│ ├────────────────────┼────┼───────┼───────┤ │
│ │ TOTAL │ │ │₹290 │ │
│ └────────────────────┴────┴───────┴───────┘ │
│ │
│ Payment: UPI via Razorpay │
│ Status: Paid on 14 Feb 2026 │
│ │
│ Amount in words: Two Hundred Ninety Rupees │
└──────────────────────────────────────────────┘
Dependencies
- Company registration / GSTIN (needed for legal invoices — currently Sole Proprietorship not yet registered)
- Supabase Storage bucket for invoice PDFs (Phase 2)
- Novu/Resend email template for invoice attachment (Phase 2)
Questions
- Do we need invoices before company/GSTIN registration? (Can we issue "receipts" instead of "tax invoices" until then?)
- Should consultants also get payout receipts/statements?
- Should invoice generation block the payment flow (sync) or be best-effort (async, current behavior)?
- Do we want a web-viewable invoice page (
/invoices/[id]) in addition to PDF download?