swiftops-backend / docs /features /invoicing /invoice-generation-system.md
kamau1's picture
Implement full end-to-end invoice generation & public viewing system (migrations, models, schemas, services, routes)
93efe54

Invoice Generation System

Overview

The Invoice Generation System allows Project Managers and Dispatchers to create proof-of-work invoices from completed tickets. The system generates both CSV exports (for traditional workflows) and web-based viewing links (for modern collaboration).

Key Features

1. Bulk Invoice Generation

  • Select multiple completed tickets
  • Generate single invoice with all tickets as line items
  • Automatic ticket linking and status updates
  • No pricing required (proof of work only)

2. CSV Export

  • Traditional format for Kenyan business workflows
  • Includes ticket details, sales orders, completion data
  • Image links in accessible format
  • One row per ticket

3. Public Invoice Viewing

  • Shareable link with secure token
  • No authentication required for clients
  • View ticket details, images, completion data
  • Token expires after 30 days (configurable)

4. Notification System

  • Automatic notifications to all PMs
  • Includes viewing link and CSV download link
  • Tracks invoice generation in audit logs

Architecture

Database Schema

-- New fields in contractor_invoices table
viewing_token VARCHAR(255) UNIQUE
viewing_token_expires_at TIMESTAMP WITH TIME ZONE
viewing_token_created_by UUID REFERENCES users(id)
times_viewed INTEGER DEFAULT 0
last_viewed_at TIMESTAMP WITH TIME ZONE
csv_exported BOOLEAN DEFAULT FALSE
csv_exported_at TIMESTAMP WITH TIME ZONE
csv_exported_by_user_id UUID REFERENCES users(id)
client_comments TEXT
client_viewed_at TIMESTAMP WITH TIME ZONE

Services

  1. InvoiceGenerationService

    • get_available_tickets() - Find completed, uninvoiced tickets
    • generate_invoice_from_tickets() - Create invoice from tickets
    • export_invoice_to_csv() - Generate CSV export
    • regenerate_viewing_token() - Refresh expired tokens
  2. InvoiceViewingService

    • get_invoice_by_token() - Public invoice viewing
    • Enriches invoice with ticket details and images
    • Tracks views automatically

API Endpoints

Invoice Generation (Authenticated)

GET  /api/v1/invoices/available-tickets
POST /api/v1/invoices/generate
GET  /api/v1/invoices/{invoice_id}/export/csv
POST /api/v1/invoices/{invoice_id}/regenerate-token

Invoice Viewing (Public - No Auth)

GET  /api/v1/invoices/view?token={token}

Workflow

PM/Dispatcher Flow

  1. Navigate to Invoice Creation

    • Access invoice generation page
    • View list of completed, uninvoiced tickets
  2. Select Tickets

    • Filter by project, date range
    • Multi-select tickets with checkboxes
    • Preview ticket details and images
  3. Generate Invoice

    • Click "Generate Invoice"
    • System creates invoice record
    • Updates all tickets as invoiced
    • Generates viewing token
    • Creates notifications for all PMs
  4. Share with Client

    • Copy viewing link
    • Download CSV
    • Send via email/WhatsApp (manual for now)

Client Flow

  1. Receive Link

    • Client gets link: https://app.com/invoices/view?token=abc123
  2. View Invoice

    • Opens in browser (no login required)
    • Sees invoice header (number, dates, amounts)
    • Expandable ticket sections
  3. Review Work

    • View ticket details
    • See completion data (ONT serials, etc.)
    • Browse image gallery
    • View GPS locations on map
  4. Provide Feedback (Future)

    • Add comments
    • Approve/dispute items

Line Item Structure

Since this is proof-of-work (not pricing), line items include:

{
  "id": "unique-line-item-id",
  "type": "ticket",
  "ticket_id": "uuid",
  "sales_order_id": "uuid",
  "sales_order_number": "SO-2025-001",
  "description": "Installation - Customer ABC",
  "ticket_type": "installation",
  "completed_at": "2025-12-15T10:30:00Z",
  "quantity": 1,
  "unit_price": 0.00,
  "total": 0.00
}

CSV Format

Invoice Number,Invoice Date,Ticket ID,Sales Order Number,Ticket Name,Ticket Type,Work Description,Completed Date,Completion Data,Image Count,Image Links
INV-ACME-2025-00142,2025-12-10,uuid-123,SO-2025-001,Customer ABC,installation,Fiber installation,2025-12-15T10:30:00Z,"{""ont_serial"":""ABC123""}",5,before:https://... | after:https://...

Security

Token-Based Access

  • Tokens are 32-byte URL-safe random strings
  • Expire after 30 days (configurable)
  • Can be regenerated if lost/expired
  • No authentication required for viewing

View Tracking

  • Every view increments counter
  • Last viewed timestamp recorded
  • Helps detect suspicious activity

Authorization

  • Only PMs and Dispatchers can generate invoices
  • Must belong to the contractor
  • Platform admins have full access

Integration Points

Ticket Model

  • is_invoiced flag set to true
  • contractor_invoice_id links to invoice
  • invoiced_at timestamp recorded

Notification System

  • Creates in-app notifications for all PMs
  • Includes viewing link and CSV link
  • Metadata includes ticket IDs and sales order numbers

Audit Logs

  • Invoice generation logged
  • CSV exports tracked
  • Token regeneration recorded

Future Enhancements

Phase 2: Client Feedback

  • Add comment system
  • Approve/dispute workflow
  • Email notifications on feedback

Phase 3: Automated Delivery

  • Auto-send email with link on generation
  • WhatsApp integration
  • SMS notifications

Phase 4: Pricing Support

  • Optional manual pricing per ticket
  • Automatic pricing from rate cards
  • Tax calculations
  • Payment tracking

Configuration

Environment Variables

APP_BASE_URL=https://your-app.com  # For generating viewing links

Token Expiration

Default: 30 days Configurable via regenerate_viewing_token(expires_in_days=X)

Testing

Manual Testing Checklist

  1. Invoice Generation

    • Can view available tickets
    • Can select multiple tickets
    • Invoice created successfully
    • Tickets marked as invoiced
    • Viewing token generated
    • Notifications created for PMs
  2. CSV Export

    • CSV downloads correctly
    • All ticket data included
    • Image links accessible
    • Sales order references correct
    • Export tracked in database
  3. Public Viewing

    • Can access with valid token
    • Cannot access with invalid token
    • Cannot access with expired token
    • View count increments
    • Images load correctly
    • Completion data displays
  4. Token Regeneration

    • Can regenerate expired token
    • New link works
    • Old link stops working

Troubleshooting

Common Issues

Issue: Token expired

  • Solution: Use regenerate token endpoint
  • PM can generate new link from invoice details page

Issue: Images not loading

  • Check Cloudinary URLs are public
  • Verify document records exist
  • Check ticket_images relationships

Issue: Tickets not appearing in available list

  • Verify tickets are status=completed
  • Check is_invoiced=false
  • Ensure tickets belong to correct project

Issue: CSV missing data

  • Check ticket relationships (sales_order, images)
  • Verify completion_data is valid JSON
  • Ensure documents table has file_url

Migration

Run the migration to add new fields:

# Apply migration
psql -d your_database -f supabase/migrations/20251210_add_invoice_viewing_fields.sql

API Examples

Get Available Tickets

GET /api/v1/invoices/available-tickets?contractor_id={uuid}&project_id={uuid}

Generate Invoice

POST /api/v1/invoices/generate
{
  "contractor_id": "uuid",
  "client_id": "uuid",
  "project_id": "uuid",
  "ticket_ids": ["uuid1", "uuid2"],
  "title": "Q4 2025 Installations",
  "notes": "All work completed as per contract"
}

View Invoice (Public)

GET /api/v1/invoices/view?token=abc123xyz

Export CSV

GET /api/v1/invoices/{invoice_id}/export/csv

Support

For issues or questions:

  • Check logs: app.services.invoice_generation_service
  • Review audit logs for invoice operations
  • Contact platform admin for access issues