# PDF Implementation Guide This guide explains how to implement PDF generation (view, download, email) for all clinical documents using the reusable `BasePDFGenerator` service. ## Overview We've created a centralized PDF service (`core/pdf_service.py`) that provides: - ✅ Tenant branding (logo + name) - ✅ Arabic font support with proper text rendering - ✅ Bilingual labels (English/Arabic) - ✅ Consistent professional styling - ✅ Email functionality with PDF attachment - ✅ View inline or download options ## Implementation Steps for Each Module ### Step 1: Create PDF Generator Class In each module's `views.py`, create a PDF generator class that extends `BasePDFGenerator`: ```python from core.pdf_service import BasePDFGenerator class MedicalConsultationPDFGenerator(BasePDFGenerator): """PDF generator for Medical Consultation (MD-F-1).""" def get_document_title(self): """Return document title in English and Arabic.""" consultation = self.document return ( f"Medical Consultation - {consultation.patient.mrn}", "استشارة طبية" ) def get_pdf_filename(self): """Return PDF filename.""" consultation = self.document return f"medical_consultation_{consultation.patient.mrn}_{consultation.consultation_date}.pdf" def get_document_sections(self): """Return document sections to render.""" consultation = self.document patient = consultation.patient sections = [] # Patient Information Section sections.append({ 'heading_en': 'Patient Information', 'heading_ar': 'معلومات المريض', 'type': 'table', 'content': [ ('Name', 'الاسم', f"{patient.first_name_en} {patient.last_name_en}", f"{patient.first_name_ar} {patient.last_name_ar}" if patient.first_name_ar else ""), ('MRN', 'رقم السجل الطبي', patient.mrn, ""), ('Date of Birth', 'تاريخ الميلاد', patient.date_of_birth.strftime('%Y-%m-%d'), ""), ('Gender', 'الجنس', patient.get_sex_display(), ""), ] }) # Consultation Details Section sections.append({ 'heading_en': 'Consultation Details', 'heading_ar': 'تفاصيل الاستشارة', 'type': 'table', 'content': [ ('Date', 'التاريخ', consultation.consultation_date.strftime('%Y-%m-%d'), ""), ('Provider', 'مقدم الخدمة', consultation.provider.get_full_name(), ""), ('Chief Complaint', 'الشكوى الرئيسية', consultation.chief_complaint or 'N/A', ""), ] }) # Add more sections as needed... return sections ``` ### Step 2: Create PDF View ```python from django.contrib.auth.mixins import LoginRequiredMixin from django.shortcuts import get_object_or_404 from django.views import View from core.mixins import TenantFilterMixin class MedicalConsultationPDFView(LoginRequiredMixin, TenantFilterMixin, View): """Generate PDF for medical consultation.""" def get(self, request, pk): """Generate and return PDF.""" # Get consultation consultation = get_object_or_404( MedicalConsultation.objects.select_related( 'patient', 'provider', 'tenant' ), pk=pk, tenant=request.user.tenant ) # Create PDF generator pdf_generator = MedicalConsultationPDFGenerator(consultation, request) # Get view mode from query parameter view_mode = request.GET.get('view', 'download') # Generate and return PDF return pdf_generator.generate_pdf(view_mode=view_mode) ``` ### Step 3: Create Email PDF View ```python from django.contrib import messages from django.shortcuts import redirect from django.utils.translation import gettext as _ class MedicalConsultationEmailPDFView(LoginRequiredMixin, TenantFilterMixin, View): """Email medical consultation PDF to patient.""" def post(self, request, pk): """Send PDF via email.""" # Get consultation consultation = get_object_or_404( MedicalConsultation.objects.select_related( 'patient', 'provider', 'tenant' ), pk=pk, tenant=request.user.tenant ) # Get form data email_address = request.POST.get('email_address', '').strip() custom_message = request.POST.get('email_message', '').strip() if not email_address: messages.error(request, _('Email address is required.')) return redirect('medical:consultation_detail', pk=pk) # Create PDF generator pdf_generator = MedicalConsultationPDFGenerator(consultation, request) # Prepare email content subject = f"Medical Consultation - {consultation.patient.mrn}" body = f""" Dear {consultation.patient.first_name_en} {consultation.patient.last_name_en}, Please find attached your medical consultation details. Consultation Date: {consultation.consultation_date.strftime('%Y-%m-%d')} Provider: {consultation.provider.get_full_name()} Best regards, {consultation.tenant.name} """ # Send email success, message = pdf_generator.send_email( email_address=email_address, subject=subject, body=body, custom_message=custom_message ) if success: messages.success(request, _('PDF sent to %(email)s successfully!') % {'email': email_address}) else: messages.error(request, _('Failed to send email: %(error)s') % {'error': message}) return redirect('medical:consultation_detail', pk=pk) ``` ### Step 4: Add URL Routes In the module's `urls.py`: ```python urlpatterns = [ # ... existing routes ... path('/pdf/', views.MedicalConsultationPDFView.as_view(), name='consultation_pdf'), path('/email-pdf/', views.MedicalConsultationEmailPDFView.as_view(), name='consultation_email_pdf'), ] ``` ### Step 5: Update Detail Template Add PDF options dropdown to the detail template: ```html ``` ## Modules to Implement ### Priority 1 (Week 1) 1. ✅ **Appointments** - Already implemented 2. ✅ **Finance/Invoices** - Already implemented 3. ⏳ **Medical Consultation** (MD-F-1) 4. ⏳ **Medical Follow-up** (MD-F-2) 5. ⏳ **Nursing Encounter** ### Priority 2 (Week 2) 6. ⏳ **OT Consultation** (OT-F-1) 7. ⏳ **OT Session** (OT-F-3) 8. ⏳ **SLP Consultation** (SLP-F-1) ### Priority 3 (Week 3) 9. ⏳ **SLP Assessment** (SLP-F-2) 10. ⏳ **SLP Intervention** (SLP-F-3) 11. ⏳ **ABA Consult** (ABA-F-1) ### Priority 4 (Week 4) 12. ⏳ **Consent Forms** 13. ⏳ **Patient Summary** ## Tips for Implementation 1. **Keep sections modular**: Each clinical form has different sections, so structure them clearly in `get_document_sections()` 2. **Handle optional fields**: Use `or 'N/A'` for fields that might be empty 3. **Format dates consistently**: Use `strftime('%Y-%m-%d')` for dates 4. **Test Arabic text**: Make sure Arabic names and content display correctly 5. **Check permissions**: Ensure only authorized users can generate/email PDFs 6. **Validate email addresses**: Always validate before sending emails 7. **Handle errors gracefully**: Wrap email sending in try-except blocks ## Testing Checklist For each implementation, test: - [ ] PDF generates without errors - [ ] Tenant logo displays correctly - [ ] Arabic text renders properly - [ ] All sections display complete data - [ ] View inline opens in browser - [ ] Download saves file correctly - [ ] Email sends successfully - [ ] Email contains correct PDF attachment - [ ] Custom message appears in email - [ ] Permissions are enforced ## Next Steps 1. Start with Medical Consultation (most used) 2. Test thoroughly 3. Use as template for other modules 4. Iterate and improve based on feedback