Phase 8: Customizable PDF Templates — locale support, admin editor, seed templates

Backend:
- PdfTemplate model with locale field + UNIQUE(name, locale) constraint
- Migration 007: pdf_templates table + template_id FK on generated_pdfs
- Template service: CRUD, Jinja2 validation, render preview with sample data
- Admin endpoints: CRUD /admin/pdf-templates + POST preview
- User endpoint: GET /pdf/templates (active templates list)
- pdf_service: resolves template from DB by ID or falls back to default
  for the appropriate locale
- AI generate_pdf tool accepts optional template_id
- Seed script + 4 HTML template files:
  - Basic Report (en/ru) — general-purpose report
  - Medical Report (en/ru) — health-focused with disclaimers

Frontend:
- Admin PDF templates page with editor, locale selector, live preview (iframe),
  template variables reference panel
- PDF page: template selector dropdown in generation form
- API clients for admin CRUD + user template listing
- Sidebar: admin templates link
- English + Russian translations

Also added Phase 9 (OAuth) and Phase 10 (Rate Limits) placeholders to GeneralPlan.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-19 15:32:35 +03:00
parent b0790d719c
commit bb53eeee8e
26 changed files with 1077 additions and 16 deletions

View File

@@ -0,0 +1,48 @@
# Phase 8: Customizable PDF Templates — Subplan
## Goal
Allow admins to manage Jinja2 HTML PDF templates in the database, and let users (or AI) select a template when generating PDFs, with a live preview editor.
## Prerequisites
- Phase 6-7 completed (PDF generation with WeasyPrint, admin patterns)
---
## Tasks
- [x] **8.1** Create `backend/app/models/pdf_template.py`: PdfTemplate model (name, description, html_content, is_default, is_active). Register in `models/__init__.py`.
- [x] **8.2** Create migration `007_create_pdf_templates.py`: table + seed default template from current report.html. Add `template_id` FK to `generated_pdfs`.
- [x] **8.3** Create `backend/app/services/pdf_template_service.py`: CRUD + `validate_jinja2()` helper.
- [x] **8.4** Create `backend/app/schemas/pdf_template.py`. Add `template_id` to `GeneratePdfRequest` and `PdfResponse`.
- [x] **8.5** Add admin endpoints to `admin.py`: CRUD `/admin/pdf-templates` + POST `/admin/pdf-templates/preview`.
- [x] **8.6** Add `GET /pdf/templates` user endpoint (active templates list).
- [x] **8.7** Update `pdf_service.generate_pdf_report`: accept template_id, load from DB, render via `from_string()`.
- [x] **8.8** Update AI tool `generate_pdf` with optional template_id.
- [x] **8.9** Frontend API: `admin-pdf-templates.ts` CRUD + update `pdf.ts` with template support.
- [x] **8.10** Update `frontend/src/pages/pdf.tsx`: template selector dropdown.
- [x] **8.11** Create `frontend/src/pages/admin/pdf-templates.tsx`: editor with live preview.
- [x] **8.12** Template variables documentation panel in editor.
- [x] **8.13** Update routes, sidebar, en/ru translations.
- [x] **8.14** Tests + verification.
---
## Acceptance Criteria
1. Default template seeded by migration, identical output to current
2. Admin CRUD for templates; cannot delete default
3. Invalid Jinja2 rejected with clear error
4. Users select template when generating PDF; default used if omitted
5. AI tool works with/without template_id
6. Live preview in admin editor
7. generated_pdfs.template_id records which template was used
8. All UI text in en/ru
9. Frontend builds clean, backend tests pass
---
## Status
**COMPLETED**