Skip to content

Documents

The apps.documents module manages document storage with pluggable backends and PDF generation for system-generated documents.

Document Model

Field Description
document_type Type of document (see below)
file_name Original file name
mime_type MIME type (e.g., application/pdf)
file_size File size in bytes
file_hash SHA-256 hash for integrity verification
status pending, uploaded, processed, or failed
storage_key Key/path in the storage backend
storage_provider Which provider stores this document
borrower Optional FK to borrower
loan Optional FK to loan

Document Types

Type Description
statement Monthly/periodic statement
disclosure TILA, privacy notices
notice Regulatory or adverse action notices
correspondence General correspondence
application Loan application documents
identity Identity verification documents
collateral Collateral-related documents
other Miscellaneous

Storage Providers

Two implementations of DocumentStorageProtocol:

Provider Use Case Features
AWS S3 Production Pre-signed upload/download URLs, tenant-scoped prefixes
Local filesystem Development Direct file I/O, no external dependencies

Storage Key Structure

tenants/{tenant_slug}/documents/{year}/{month}/{document_id}/{file_name}

Tenant-scoped prefixes ensure document isolation between tenants.

See Provider Pattern for how storage providers are configured.

Upload Flow

Document uploads use a three-step presigned URL flow:

  1. Request upload URL: Client calls the API to get a presigned upload URL
  2. Direct upload: Client uploads the file directly to the storage provider (bypasses the backend)
  3. Confirm upload: Client notifies the backend that the upload is complete; backend records metadata and computes file hash

This pattern keeps large file transfers off the backend servers.

Download

Downloads use time-limited presigned URLs:

  1. Client requests a download URL from the API
  2. Backend generates a presigned URL from the storage provider
  3. Client downloads directly from the storage provider

File Integrity

A SHA-256 hash is computed and stored for every uploaded document. This enables:

  • Integrity verification on download
  • Duplicate detection
  • Audit trail for document authenticity

PDF Generation

System-generated documents use Jinja2 templates rendered to PDF via WeasyPrint:

Generated Document Types

Document Trigger Description
Monthly statements Scheduled Celery task Periodic account statement
TILA disclosures Loan origination APR, finance charge, total payments
Adverse action notices Loan denial Reason for denial
Collection letters Dunning workflow Dunning correspondence

Language Variants

All PDF templates support language variants:

  • Templates follow the naming convention {template_name}_{lang}.html (e.g., tila_disclosure_es.html)
  • The render_pdf() function tries the language-specific template first, then falls back to the default
  • Document generation reads borrower.language_preference to select the correct template

Template Filters

Jinja2 filters are available in PDF templates for locale-aware formatting:

Filter Example Output
currency {{ amount \| currency(locale) }} $1,234.56
date {{ due_date \| date(locale) }} January 15, 2026
number {{ count \| number(locale) }} 1,234
percent {{ rate \| percent(locale) }} 6.5%

See Also

  • Provider Pattern --- Document storage provider configuration
  • Communications --- Communication templates (related but separate from document templates)
  • Compliance --- Regulatory document requirements (TILA, adverse action)