2.9 KiB
2.9 KiB
Document Templates — admin-managed forms (feature)
A from-scratch subsystem (2026-06-14): admins upload .docx templates with Jinja
{{ placeholders }}; applicants fill a form generated from each template's fields and download a
server-rendered PDF. Independent of the hardcoded sáng kiến form pipeline (which stays as-is).
Data + storage
- Table
document_templates(migration015_document_templates.sql, modelDocumentTemplate):id, name, description, storage_key, original_filename, content_sha256, fields JSONB ([{key,label,type}]), is_active, created_by, created_at, updated_at. - MinIO bucket
initiative-templates(S3Settings.s3_bucket_templates, has a default; created byensure_buckets_exist). Server-side only — no browser CORS / presign needed.
Backend — be0/src/template_routes.py (mounted /api/v1/templates)
POST /templates(admin) — multipart.docx→ extract{{placeholders}}→ MinIO + row.GET /templates(authed; admin sees inactive too) ·GET /{id}·GET /{id}/file(admin, raw docx).PUT /{id}(admin) metadata ·DELETE /{id}(admin) soft-delete,?hard=trueremoves row + object.POST /{id}/render(authed) — fill withvalues→ DOCX (docxtpl) or PDF (reusessrc.be01.docx_to_pdf.convert_docx_bytes_to_pdf, LibreOffice).- Placeholder extraction: docxtpl
get_undeclared_template_variables()with a regex-on-stripped-XML fallback — DOCX often splits{{ }}across<w:r>runs, so stripping tags first recovers them. - Auth mirrors the extracted admin routers (
decode_access_token_user_id/decode_bearer_token; admin ="admin"in JWT roles).
Frontend
@ump/shared/lib/templateApi.ts—DocumentTemplate/TemplateFieldtypes + list/get/create (FormData)/update/delete/render (postArrayBuffer)/downloadFile +saveArrayBufferAs/arrayBufferToObjectUrl.- frontend_admin
pages/TemplatesPage.tsx(+layouts/AdminLayout.tsxshell; route/templates, admin-gated) — upload / list / edit meta / activate-deactivate / download / hard-delete (alert-dialog). Its first real feature. - frontend_user
pages/TemplatesFillPage.tsx(route/dashboard/templates, sidebar « Mẫu tài liệu ») — pick a template → form generated from its fields → server PDF → iframe preview + download.
Verified
Backend e2e live against the dev stack: create → extract fields → render (filled values) → delete.
@ump/shared + frontend_user + frontend_admin tsc --noEmit + vite build all clean. Commits
c6d003c (BE) + 4f1cb3e (FE).
Deferred (v1 limitations)
- No file-replace endpoint — delete + re-create to change a template's
.docx(metadata edit works). - All fields render as single-line text — no type/date/number/long-text per field.
- No audit-log entries on template create/update/delete (the rest of the app audits admin mutations).