Skip to content

Hard-Coded Document Implementation Guide

This guide explains how to create and integrate a new hard-coded document into the document generation system.

Overview

Hard-coded documents are PDF templates with mostly static content and some dynamic fields (like borrower names, dates, etc.). They are used for standardized forms and disclosures.

Step-by-Step Implementation

1. Analyze the Source PDF

  • Carefully review the PDF document to identify:
  • Static content (disclosure text, headers, instructions)
  • Dynamic fields (borrower names, dates, loan information)
  • Page structure and breaks
  • Footer information
  • Tables and formatting requirements

2. Create the HTML Template

Create your HTML file in: documents/hard_coded_documents/html_templates/YOUR_DOCUMENT_NAME.html

Basic HTML Structure:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        @page {
            size: Letter;
            margin: 0.75in 0.44in;
            font-family: Arial, Helvetica, sans-serif;

            /* Footer configuration */
            @bottom-left {
                content: "Loan Officer Company NMLS #:\A{{ loan_officer_company_nmls }}\A...";
                font-size: 8px;
                white-space: pre;
            }
            @bottom-center {
                content: "Page " counter(page) " of X";
                font-size: 8px;
            }
            @bottom-right {
                content: "{{ footer_text }}\APrinted:{{ printed_date }}";
                font-size: 8px;
                white-space: pre;
            }
        }

        body {
            font-family: Arial, Helvetica, sans-serif;
            margin: 0;
            padding: 0;
            font-size: 11px;
        }

        /* Page break */
        .break-before {
            page-break-before: always;
        }

        /* Add other styles as needed */
    </style>
</head>
<body>
    <div class="page-content">
        <!-- Your content here -->
        {{ dynamic_field }}
    </div>
</body>
</html>

Key HTML Elements:

  • Headers: Use company logo and QR code if needed html <img src="{{ company_logo }}" alt="Company Logo" class="logo"> <img src="data:image/png;base64,{{ qr_code_base64 }}" alt="QR Code">

  • Dynamic Fields: Use Jinja2 template syntax html {{ borrower_name }} {{ printed_date }}

  • Signatures: Create empty fields for signatures ```html

{{ borrower.name }}

```

  • Tables: Use standard HTML tables with borders ```html
    Header {{ data }}

```

3. Create the Python Data Generator

Create your Python file in: documents/hard_coded_documents/input_jsons/YOUR_DOCUMENT_NAME.py

Basic Python Structure:

from datetime import datetime


def get_your_document_name_data(loan):
    """
    Generate data for Your Document Name
    """

    # Get current date
    printed_date = datetime.now().strftime("%m/%d/%Y")

    # Get borrower information
    borrowers = []
    youngest_borrower = loan.get_youngest_borrower()

    if youngest_borrower:
        borrowers.append({
            "name": youngest_borrower.get_full_name(),
            "signature": "",  # Empty for signature
            "date": ""  # Empty for date
        })

    # Get loan officer information
    loan_officer_nmls = loan.get_loan_officer_nmls_id() or "DEFAULT_VALUE"
    loan_officer_company_nmls = loan.get_loan_officer_company_nmls_id() or "DEFAULT_VALUE"

    # Return all data needed by the template
    return {
        # REQUIRED: URL for QR code generation
        "url": f"https://example.com/loan/{loan.id}",

        # Dynamic fields from loan object
        "borrowers": borrowers,
        "loan_officer_nmls": loan_officer_nmls,
        "loan_officer_company_nmls": loan_officer_company_nmls,
        "printed_date": printed_date,

        # Static/hard-coded values
        "footer_text": "YourDocumentFooter-2024",
        "document_id": "12345",

        # Any other fields your template needs
        "custom_field": "value",
    }

4. Register the Document in generator.py

Add your import at the top of documents/hard_coded_documents/generator.py:

from .input_jsons.YOUR_DOCUMENT_NAME import get_your_document_name_data

Add your case in the get_template_data function:

elif template_name == "YOUR_DOCUMENT_NAME":
    return get_your_document_name_data(loan)

5. Add to Constants

In documents/hard_coded_documents/constants.py, add your document to HARD_CODED_DOCUMENT_TYPES:

{"name": "Your Document Display Name", "value": "YOUR_DOCUMENT_NAME"},

6. Test Your Document

  1. Restart your application
  2. The document should now appear in the UI document list
  3. Generate a test document to verify:
  4. All dynamic fields populate correctly
  5. Page breaks work as expected
  6. Footer appears on all pages
  7. Formatting matches the original PDF

Common Patterns

Multiple Borrowers

borrowers = []
for borrower in loan.borrowers.all():
    borrowers.append({
        "name": borrower.get_full_name(),
        "signature": "",
        "date": ""
    })

Conditional Content

{% if condition %}
    <p>Show this content</p>
{% endif %}

Loops in Templates

{% for item in items %}
    <div>{{ item.name }}</div>
{% endfor %}

Page Numbers

The CSS @page rule handles automatic page numbering:

@bottom-center {
    content: "Page " counter(page) " of " counter(pages);
}

Best Practices

  1. Keep Static Content Static: Don't make fields dynamic unless they actually change
  2. Use Consistent Naming: Match file names with the value in constants.py
  3. Handle Missing Data: Provide defaults for optional fields
  4. Test Pagination: Ensure content doesn't overflow pages
  5. Match Original Formatting: Pay attention to fonts, sizes, and spacing

Troubleshooting

  • Document doesn't appear in UI: Check that all 4 integration steps are complete
  • Import errors: Verify file names match exactly
  • Missing data: Check loan object methods and provide defaults
  • Formatting issues: Use browser developer tools to inspect generated HTML
  • QR code not showing: Ensure url field is included in data dictionary

Example Documents

For reference, see these existing implementations: - HECM_NOTE.html / HECM_NOTE.py - HECM_DOT.html / HECM_DOT.py - HECM_TIL_APPLICATION.html / HECM_TIL_APPLICATION.py