""" PDF generation service for acknowledgements """ from io import BytesIO from datetime import datetime from django.conf import settings from django.utils import translation from reportlab.lib import colors from reportlab.lib.pagesizes import letter, A4 from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib.units import inch from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer, Image from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT class AcknowledgementPDFService: """Service for generating PDF documents for acknowledgements""" @staticmethod def generate_pdf(user, acknowledgement, language='en'): """ Generate PDF for a user acknowledgement Args: user: User instance acknowledgement: UserAcknowledgement instance language: Language code ('en' or 'ar') Returns: BytesIO object containing PDF data """ # Set language for translation translation.activate(language) # Create buffer buffer = BytesIO() # Create PDF document doc = SimpleDocTemplate( buffer, pagesize=A4, rightMargin=72, leftMargin=72, topMargin=72, bottomMargin=18 ) # Build content story = [] styles = getSampleStyleSheet() # Custom styles title_style = ParagraphStyle( 'CustomTitle', parent=styles['Heading1'], fontSize=24, textColor=colors.HexColor('#2c3e50'), spaceAfter=30, alignment=TA_CENTER ) subtitle_style = ParagraphStyle( 'CustomSubtitle', parent=styles['Heading2'], fontSize=16, textColor=colors.HexColor('#3498db'), spaceAfter=20 ) body_style = ParagraphStyle( 'CustomBody', parent=styles['BodyText'], fontSize=11, spaceAfter=12, leading=16 ) heading_style = ParagraphStyle( 'CustomHeading', parent=styles['Heading3'], fontSize=14, textColor=colors.HexColor('#2c3e50'), spaceAfter=10, spaceBefore=20 ) # Title if language == 'ar': title = "إقرار الاستلام والتوقيع" else: title = "Acknowledgement Receipt" story.append(Paragraph(title, title_style)) story.append(Spacer(1, 0.2*inch)) # Header line header_data = [ ('Date', 'التاريخ'), ('Employee Name', 'اسم الموظف'), ('Employee ID', 'رقم الموظف'), ('Email', 'البريد الإلكتروني'), ] user_data = [ (acknowledgement.acknowledged_at.strftime('%Y-%m-%d %H:%M:%S')), (user.get_full_name()), (user.employee_id or 'N/A'), (user.email), ] # Create header table header_table_data = [] for i, (label_en, label_ar) in enumerate(header_data): if language == 'ar': header_table_data.append([ Paragraph(f"{label_ar}:", body_style), Paragraph(user_data[i], body_style) ]) else: header_table_data.append([ Paragraph(f"{label_en}:", body_style), Paragraph(user_data[i], body_style) ]) header_table = Table(header_table_data, colWidths=[2*inch, 3*inch]) header_table.setStyle(TableStyle([ ('BACKGROUND', (0, 0), (0, -1), colors.HexColor('#f8f9fa')), ('VALIGN', (0, 0), (-1, -1), 'TOP'), ('GRID', (0, 0), (-1, -1), 0.5, colors.grey), ('TOPPADDING', (0, 0), (-1, -1), 8), ('BOTTOMPADDING', (0, 0), (-1, -1), 8), ])) story.append(header_table) story.append(Spacer(1, 0.3*inch)) # Acknowledgement details story.append(Paragraph( "Acknowledgement Details" if language == 'en' else "تفاصيل الإقرار", subtitle_style )) # Get checklist item text based on language checklist_item = acknowledgement.checklist_item if language == 'ar' and checklist_item.text_ar: item_text = checklist_item.text_ar else: item_text = checklist_item.text_en if language == 'ar' and checklist_item.description_ar: item_desc = checklist_item.description_ar else: item_desc = checklist_item.description_en or checklist_item.description_en # Item details item_details = [ ('Acknowledgement Code', 'رمز الإقرار', checklist_item.code), ('Acknowledgement Item', 'بند الإقرار', item_text), ] if item_desc: item_details.append(('Description', 'الوصف', item_desc)) if checklist_item.content: if language == 'ar' and checklist_item.content.title_ar: content_title = checklist_item.content.title_ar else: content_title = checklist_item.content.title_en item_details.append(('Section', 'القسم', content_title)) # Create item table item_table_data = [] for label_en, label_ar, value in item_details: if language == 'ar': item_table_data.append([ Paragraph(f"{label_ar}:", body_style), Paragraph(value, body_style) ]) else: item_table_data.append([ Paragraph(f"{label_en}:", body_style), Paragraph(value, body_style) ]) item_table = Table(item_table_data, colWidths=[2*inch, 4*inch]) item_table.setStyle(TableStyle([ ('BACKGROUND', (0, 0), (0, -1), colors.HexColor('#e8f4f8')), ('VALIGN', (0, 0), (-1, -1), 'TOP'), ('GRID', (0, 0), (-1, -1), 0.5, colors.grey), ('TOPPADDING', (0, 0), (-1, -1), 8), ('BOTTOMPADDING', (0, 0), (-1, -1), 8), ])) story.append(item_table) story.append(Spacer(1, 0.3*inch)) # Signature section story.append(Paragraph( "Digital Signature" if language == 'en' else "التوقيع الرقمي", heading_style )) signature_text = ( "This acknowledgement was digitally signed by the employee above." if language == 'en' else "تم توقيع هذا الإقرار رقميًا بواسطة الموظف المذكور أعلاه." ) story.append(Paragraph(signature_text, body_style)) story.append(Spacer(1, 0.1*inch)) # IP and User Agent if acknowledgement.signature_ip: ip_text = f"IP Address: {acknowledgement.signature_ip}" if language == 'en' else f"عنوان IP: {acknowledgement.signature_ip}" story.append(Paragraph(f"{ip_text}", body_style)) if acknowledgement.signature_user_agent: ua_text = f"Device: {acknowledgement.signature_user_agent[:100]}..." if language == 'en' else f"الجهاز: {acknowledgement.signature_user_agent[:100]}..." story.append(Paragraph(f"{ua_text}", body_style)) story.append(Spacer(1, 0.5*inch)) # Declaration declaration_text_en = ( "I hereby acknowledge that I have read and understood the above acknowledgement " "and agree to comply with all policies and procedures outlined therein. " "I understand that this is a legally binding document." ) declaration_text_ar = ( "أقر هنا بأنني قرأت وفهمت الإقرار المذكور أعلاه وأوافق على الامتثال لجميع " "السياسات والإجراءات المنصوص عليها فيه. أفهم أن هذا وثيقة ملزمة قانونيًا." ) declaration = declaration_text_ar if language == 'ar' else declaration_text_en story.append(Paragraph(f"{declaration}", body_style)) story.append(Spacer(1, 1.5*inch)) # Signature line signature_label = "Digital Signature" if language == 'en' else "التوقيع الرقمي" story.append(Paragraph(f"{signature_label}", body_style)) story.append(Spacer(1, 0.2*inch)) # Add signature image if available if acknowledgement.signature: try: from base64 import b64decode sig_data = b64decode(acknowledgement.signature) sig_buffer = BytesIO(sig_data) sig_image = Image(sig_buffer, width=2*inch, height=1*inch) story.append(sig_image) except: pass # Footer story.append(Spacer(1, 0.5*inch)) footer_text = ( f"Generated by PX360 Patient Experience Management System on {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" if language == 'en' else f"تم الإنشاء بواسطة نظام إدارة تجربة المريض PX360 في {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" ) footer_style = ParagraphStyle( 'CustomFooter', parent=styles['BodyText'], fontSize=9, textColor=colors.grey, alignment=TA_CENTER ) story.append(Paragraph(footer_text, footer_style)) # Build PDF doc.build(story) # Get PDF value pdf_value = buffer.getvalue() buffer.close() return pdf_value