Practitionist/familiarise_web

Invoice System: PDF Generation, Download & Email Delivery

Closed

#438 opened on Feb 14, 2026

 (1 comment) (0 reactions) (1 assignee)TypeScript (4 forks)auto 404
Enterpriseenhancementgood first issue

Repository metrics

Stars
 (4 stars)
PR merge metrics
 (PR metrics pending)

Description

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:

  1. Consultee clicks "Download" on invoice row
  2. API route /api/invoices/[id]/pdf renders React component → PDF buffer
  3. Returns PDF as response (Content-Type: application/pdf)
  4. 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:

  1. Create /invoices/[id]/view page with full HTML/CSS invoice
  2. API route spins up headless browser → navigates to page → prints PDF
  3. 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:

  1. On payment success, call external API to create invoice
  2. Store returned PDF URL in pdfUrl
  3. 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:

  1. Invoice data loaded from API
  2. Client-side JavaScript builds PDF using jsPDF
  3. 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:

  1. Works on Vercel — pure Node.js, no headless browser
  2. React-native DX — templates are React components, easy for the team
  3. On-demand generation — no need to pre-generate and store (generate when user clicks download)
  4. Email-ready — same PDF can be attached to post-payment notification email
  5. 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

  1. Do we need invoices before company/GSTIN registration? (Can we issue "receipts" instead of "tax invoices" until then?)
  2. Should consultants also get payout receipts/statements?
  3. Should invoice generation block the payment flow (sync) or be best-effort (async, current behavior)?
  4. Do we want a web-viewable invoice page (/invoices/[id]) in addition to PDF download?

Contributor guide