feat(L1-L3): Dokumente-Generator — Briefpapier+Block-System+Drag&Drop-Editor+Renderer
Check Cross-Plugin Imports / check (push) Has been cancelled
Check Cross-Plugin Imports / check (push) Has been cancelled
- Briefpapier (letterheads): Seiten-Setup (A4/A5/Letter, Ränder), Header/Footer-Blöcke, Wasserzeichen, Logo-Upload (DocumentAsset, data:-URI-only) - Druckvorlagen (print_templates): Block-Komposition mit Briefpapier-Ref + entity_type - Block-Registry (document_blocks.py): text/image/shape(line/rect/circle)/table/spacer/divider/placeholder/pagebreak + Modul-Beiträge via document_blocks()-Contract - Renderer (document_renderer.py): Blocks→HTML→PDF via WeasyPrint (SSRF-Sandbox data:-URI-only), @page-Frame mit running header/footer, Placeholder-Beispiel-Defaults gegen StrictUndefined - Contract-Beitrag contacts: document_placeholders/document_data (#359-Muster wie importexport_entities) - 13 neue Endpoints in documents.py: Letterhead-CRUD, Template-CRUD, Assets, document-blocks, document-placeholders, preview (HTML), render (PDF) - Migration: Plugin-SQL 0003 (idempotent) + Alembic 0143 (Dual-Path, RLS fail-closed crm_api) - Frontend: api/documents.ts, Settings→Dokumente (settings_pages), BlockEditor (@dnd-kit Palette/Canvas/Config/Live-Preview-iframe), LetterheadEditor, PrintTemplateEditor, DocumentGenerationDialog (global, ContactDetailPage-Integration) - i18n de/en, api-documentation.md, plugin-development-guide.md, PROGRESS.md Verifikation: 32/32 neue Tests + 9/9 Regressionen, tsc exit 0, Build OK 2.79s, Alembic-Fresh-DB 0143 mit RLS bewiesen, ruff clean
This commit is contained in:
@@ -2652,3 +2652,41 @@ LeoCRM ships pre-built agents in the automation plugin. Plugins can register add
|
||||
---
|
||||
|
||||
*This document is authoritative for all plugin development at LeoCRM.*
|
||||
|
||||
## Dokumente-Generator-Beitrag (Phase L)
|
||||
|
||||
Module koennen dem Dokumente-Generator Bloecke, Platzhalter und Daten beisteuern — Contract-Muster wie Import/Export (`#359`-Philosophie). Alle drei Hooks sind optional:
|
||||
|
||||
```python
|
||||
# contracts.py des Plugins
|
||||
class MyContract:
|
||||
@staticmethod
|
||||
def document_entity_types() -> list[str]:
|
||||
return ["myentity"]
|
||||
|
||||
@staticmethod
|
||||
def document_placeholders(entity_type: str) -> list[dict]:
|
||||
"""[{key, label, example}] — speist Editor-Palette + Preview-Defaults."""
|
||||
if entity_type != "myentity":
|
||||
return []
|
||||
return [{"key": "title", "label": "Titel", "example": "Beispiel AG"}]
|
||||
|
||||
@staticmethod
|
||||
async def document_data(db, tenant_id, entity_id, entity_type: str) -> dict:
|
||||
"""Eine Entitaet als Template-Daten laden ({} wenn nicht gefunden)."""
|
||||
obj = await db.get(MyModel, entity_id)
|
||||
if obj is None or obj.tenant_id != tenant_id:
|
||||
return {}
|
||||
return {"title": obj.title}
|
||||
|
||||
@staticmethod
|
||||
def document_blocks() -> list[dict]:
|
||||
"""Zusaetzliche Palette-Bloecke (generisch als Key-Value-Tabelle gerendert)."""
|
||||
return [{"type": "myentity_summary", "label": "Entitaets-Uebersicht", "category": "modul", "fields": ["title", "status"]}]
|
||||
```
|
||||
|
||||
**Regeln:**
|
||||
- Rendering uebernimmt report_generator (document_renderer.py) — Module liefern NIE Markup (XSS/SSRF-Sandbox bleibt intakt)
|
||||
- `document_placeholders`-Beispiele dienen als Preview-Fallbacks (StrictUndefined-vermeidend)
|
||||
- Built-in-Bloecke duerfen nicht ueberschrieben werden (Contributions mit existierendem Typ werden ignoriert)
|
||||
- Bilder laufen ausschliesslich als DocumentAsset/data:-URI (WeasyPrint-URL-Fetcher blockt extern)
|
||||
|
||||
Reference in New Issue
Block a user