38686-vm/core/utils.py
Konrad du Plessis c8c78dd88e Add payslip feature: detail page, PDF generation, and email to Spark
- core/utils.py: render_to_pdf() wrapper for xhtml2pdf
- core/templates/core/pdf/payslip_pdf.html: A4 PDF payslip (matches V2 layout)
- core/templates/core/email/payslip_email.html: HTML email body for Spark
- core/templates/core/payslip.html: browser payslip detail page with print
- core/views.py: add payslip_detail view, wire email+PDF into process_payment
- core/urls.py: add payroll/payslip/<pk>/ route
- config/settings.py: add SPARK_RECEIPT_EMAIL setting
- payroll_dashboard.html: add "View" payslip link in Payment History tab

All templates show adjustments (bonuses, deductions, overtime, loan repayments)
as line items. Amounts always show 2 decimal places. Email failure does not
roll back payment — handled gracefully with warning message.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 20:37:04 +02:00

35 lines
946 B
Python

# === PDF GENERATION ===
# Converts a Django HTML template into a PDF file using xhtml2pdf.
# Used for payslip and receipt PDF attachments sent via email.
from io import BytesIO
from django.template.loader import get_template
from xhtml2pdf import pisa
def render_to_pdf(template_src, context_dict=None):
"""
Render a Django template to PDF bytes.
Args:
template_src: Path to the template (e.g. 'core/pdf/payslip_pdf.html')
context_dict: Template context variables
Returns:
PDF content as bytes, or None if there was an error.
"""
if context_dict is None:
context_dict = {}
# Load and render the HTML template
template = get_template(template_src)
html = template.render(context_dict)
# Convert HTML to PDF
result = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("UTF-8")), result)
if not pdf.err:
return result.getvalue()
return None