9.6 KiB
PDF Generation Implementation for Complaints
Overview
Implemented professional PDF generation for complaints using WeasyPrint. This feature allows users to download a beautifully formatted PDF document containing all complaint details, including AI analysis, staff assignment, and resolution information.
Implementation Details
1. Dependencies
- Added
weasyprint>=60.0topyproject.toml - WeasyPrint provides CSS-based PDF generation with full support for modern CSS features
2. Files Created
templates/complaints/complaint_pdf.html
Professional PDF template with:
- Header: Complaint title, ID, status, severity, patient info
- Basic Information: Category, source, priority, encounter ID, dates
- Description: Full complaint details
- Staff Assignment: Assigned staff member (if any)
- AI Analysis:
- Emotion analysis with confidence score and intensity bar
- AI summary
- Suggested action
- Resolution: Resolution details (if resolved)
- Footer: Generation timestamp, system branding
Features:
- A4 page size with proper margins
- Professional purple gradient header
- Color-coded badges for status and severity
- Page numbers in footer
- Proper page breaks for multi-page documents
- Print-optimized CSS
3. Files Modified
apps/complaints/views.py
Added generate_complaint_pdf() function:
- Validates user permissions (PX Admin, Hospital Admin, Department Manager, or hospital staff)
- Renders HTML template with complaint context
- Converts HTML to PDF using WeasyPrint
- Returns PDF as downloadable attachment
- Logs PDF generation to audit trail
- Handles errors gracefully with user-friendly messages
apps/complaints/urls.py
- Added URL route:
<uuid:pk>/pdf/mapped togenerate_complaint_pdf - Named URL:
complaints:complaint_pdf
templates/complaints/complaint_detail.html
Added "PDF View" tab:
- New tab in complaints detail page
- Download PDF button with icon
- Description of PDF contents
- Informational alerts about what's included
- Note about WeasyPrint requirement
Usage
For Users
- Navigate to a complaint detail page
- Click the "PDF View" tab
- Click the "Download PDF" button
- The PDF will be generated and downloaded automatically
For Developers
Generating a PDF Programmatically
from django.template.loader import render_to_string
from weasyprint import HTML
# Render template
html_string = render_to_string('complaints/complaint_pdf.html', {
'complaint': complaint,
})
# Generate PDF
pdf_file = HTML(string=html_string).write_pdf()
# Return as HTTP response
response = HttpResponse(pdf_file, content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="complaint.pdf"'
Installation Requirements
System Dependencies (Linux/Ubuntu)
sudo apt-get install python3-dev python3-pip python3-cffi libcairo2 libpango-1.0-0 libgdk-pixbuf2.0-0 shared-mime-info
# For additional font support
sudo apt-get install fonts-liberation
Python Dependencies
pip install weasyprint>=60.0
Or using uv/pip with the project's pyproject.toml:
uv pip install weasyprint
# or
pip install -e .
macOS Dependencies
brew install cairo pango gdk-pixbuf libffi shared-mime-info
Windows Dependencies
Download and install GTK+ from: https://github.com/tschoonj/GTK-for-Windows-Runtime-Environment-Installer
PDF Template Customization
The PDF template uses standard CSS. You can customize:
Colors
Edit the gradient in the header:
.header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
Page Margins
Edit the @page rule:
@page {
size: A4;
margin: 2cm;
}
Badges
Modify badge colors by editing the CSS classes:
.status-open { background: #e3f2fd; color: #1976d2; }
.severity-high { background: #ffebee; color: #d32f2f; }
Fonts
Add custom fonts using @font-face:
@page {
@font-face {
src: url('path/to/font.ttf');
}
}
Features
Permission Control
Only authorized users can generate PDFs:
- PX Admins: All complaints
- Hospital Admins: Their hospital's complaints
- Department Managers: Their department's complaints
- Hospital Staff: Their hospital's complaints
Audit Logging
All PDF generations are logged:
- Event type:
pdf_generated - Description includes complaint title
- Metadata includes complaint ID
- Tracked by user and timestamp
Error Handling
- Graceful error messages if WeasyPrint is not installed
- Logs errors for debugging
- Returns user-friendly error responses
PDF Contents
Header Section
- Complaint title (large, prominent)
- Complaint ID (truncated to 8 characters)
- Status badge (color-coded)
- Severity badge (color-coded)
- Patient name and MRN
- Hospital name
- Department name (if assigned)
Basic Information
Grid layout with:
- Category (with subcategory if present)
- Source
- Priority
- Encounter ID
- Created date
- SLA deadline
Description
Full complaint text with line breaks preserved.
Staff Assignment (if assigned)
- Staff member name (English and Arabic)
- Job title
- Department
- AI-extracted staff name (if available)
- Staff match confidence score
AI Analysis (if available)
- Emotion Analysis:
- Emotion type with badge
- Confidence percentage
- Intensity bar visualization
- AI Summary: Brief summary of the complaint
- Suggested Action: AI-recommended action to take
Resolution (if resolved)
- Resolution text
- Resolved by (user name)
- Resolution date/time
Footer
- Generation timestamp
- PX360 branding
- AlHammadi Group branding
- Page numbers (for multi-page documents)
Styling Highlights
Color Scheme
- Primary purple gradient:
#667eea→#764ba2 - Status colors: Blue, Orange, Green, Gray, Red
- Severity colors: Green, Orange, Red, Dark Red
- AI section: Purple gradient background
- Resolution section: Green background
Typography
- Font family: Segoe UI, Tahoma, Geneva, Verdana, sans-serif
- Base font size: 11pt
- Labels: 9pt, uppercase, letter-spacing: 0.5px
- Values: 11pt
Layout
- Max-width: 210mm (A4 width)
- 2cm page margins
- Grid-based information layout
- Card-based sections with borders and shadows
- Proper spacing and padding
Browser Compatibility
WeasyPrint generates PDFs server-side, so the PDF will look the same regardless of the user's browser. The generated PDF can be viewed in:
- Adobe Acrobat Reader
- Chrome/Edge PDF viewer
- Firefox PDF viewer
- Safari PDF viewer
- Any modern PDF viewer
Performance Considerations
- PDF generation is synchronous (happens in the request/response cycle)
- For complaints with extensive updates or attachments, generation may take 1-3 seconds
- Consider adding caching for frequently accessed complaints
- For high-traffic scenarios, consider asynchronous generation
Future Enhancements
Potential improvements:
- Batch PDF generation: Generate PDFs for multiple complaints
- Email PDF: Option to email PDF directly
- Custom branding: Allow hospital-specific logos/colors
- PDF templates: Multiple template options (minimal, detailed, etc.)
- Digital signatures: Add digital signature capability
- Watermarks: Add watermarks for draft/official versions
- Barcodes/QR codes: Include complaint barcode for scanning
- Attachments: Include complaint attachments in PDF
- Bilingual PDF: Generate PDF in Arabic/English side-by-side
- Charts: Include complaint trend charts
Troubleshooting
WeasyPrint Import Error
Error: ImportError: No module named 'weasyprint'
Solution:
pip install weasyprint
Cairo Library Error
Error: ImportError: No module named 'cairo'
Solution: Install system dependencies (see Installation Requirements section)
Font Issues
Error: Text appears as squares or missing characters
Solution: Install additional fonts on the system:
sudo apt-get install fonts-liberation fonts-noto-cjk
Memory Issues
Error: PDF generation fails for large complaints
Solution:
- Reduce number of updates included
- Implement pagination for large content
- Increase server memory allocation
Testing
Manual Testing
- Create a test complaint with AI analysis
- Navigate to complaint detail page
- Click PDF View tab
- Download PDF
- Verify all sections are present
- Check styling and formatting
- Test with different complaint states (open, resolved, etc.)
Automated Testing
from django.test import TestCase
from django.urls import reverse
from apps.complaints.models import Complaint
class PDFGenerationTest(TestCase):
def test_pdf_generation(self):
complaint = Complaint.objects.first()
url = reverse('complaints:complaint_pdf', kwargs={'pk': complaint.pk})
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertEqual(response['Content-Type'], 'application/pdf')
self.assertGreater(len(response.content), 0)
References
Support
For issues or questions:
- Check WeasyPrint installation
- Review system dependencies
- Check Django logs for error details
- Verify user permissions
- Test with a simple PDF template first
Changelog
v1.0.0 (2025-01-10)
- Initial implementation
- Professional PDF template with complaint details
- AI analysis integration
- Staff assignment display
- Resolution information
- Permission-based access control
- Audit logging
- Download functionality