Spaces:
Sleeping
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
InvoiceGenerationService
get_available_tickets()- Find completed, uninvoiced ticketsgenerate_invoice_from_tickets()- Create invoice from ticketsexport_invoice_to_csv()- Generate CSV exportregenerate_viewing_token()- Refresh expired tokens
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
Navigate to Invoice Creation
- Access invoice generation page
- View list of completed, uninvoiced tickets
Select Tickets
- Filter by project, date range
- Multi-select tickets with checkboxes
- Preview ticket details and images
Generate Invoice
- Click "Generate Invoice"
- System creates invoice record
- Updates all tickets as invoiced
- Generates viewing token
- Creates notifications for all PMs
Share with Client
- Copy viewing link
- Download CSV
- Send via email/WhatsApp (manual for now)
Client Flow
Receive Link
- Client gets link:
https://app.com/invoices/view?token=abc123
- Client gets link:
View Invoice
- Opens in browser (no login required)
- Sees invoice header (number, dates, amounts)
- Expandable ticket sections
Review Work
- View ticket details
- See completion data (ONT serials, etc.)
- Browse image gallery
- View GPS locations on map
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_invoicedflag set to truecontractor_invoice_idlinks to invoiceinvoiced_attimestamp 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
Invoice Generation
- Can view available tickets
- Can select multiple tickets
- Invoice created successfully
- Tickets marked as invoiced
- Viewing token generated
- Notifications created for PMs
CSV Export
- CSV downloads correctly
- All ticket data included
- Image links accessible
- Sales order references correct
- Export tracked in database
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
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