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¶
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:
- Request upload URL: Client calls the API to get a presigned upload URL
- Direct upload: Client uploads the file directly to the storage provider (bypasses the backend)
- 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:
- Client requests a download URL from the API
- Backend generates a presigned URL from the storage provider
- 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_preferenceto 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)