# Bericht-Modul — Projekt-Status & Architektur ## Stand 2026-04-17 Dolibarr-Custom-Modul für Arbeitsberichte mit Browser-PDF-Editor + PWA-API-Layer. ## Architektur (final) ### Tab-Verteilung - **Auftrag (commande)** — primärer Erstellungsort, Berichte mit `element_type='order'`, Auftragsnummer = `commande->ref` direkt - **Rechnung (facture)** — Berichte mit `element_type='invoice'`, Auftragsnummer aus `array_options['options_auftragsnummer']` - **Angebot (propal)** — möglich, gleiche Logik - **Kundenkarte (thirdparty)** — read-only Übersicht (Phase 1.7), zeigt alle Berichte des Kunden über Joins, **kein** Anlegen, **kein** Speicher-Ort ### Verknüpfung Auftrag → Rechnung Berichte gehören 1:1 zu einem Parent (`element_type` + `fk_element`). Auf einer Rechnungs-Seite werden ZUSÄTZLICH die Berichte der verknüpften Aufträge angezeigt — über `fetchObjectLinked()` der Rechnung. Mit Button "→ Dieser Rechnung zuordnen" erzeugt man einen Eintrag in `llx_element_element` (Standard-Dolibarr-n:m-Verknüpfung), damit der Bericht beim Finalisieren auch im ECM der Rechnung landet. ### DB-Tabellen - `llx_bericht` — Bericht (rowid, ref, titel, element_type, fk_element, auftragsnummer, template_odt, status, final_pdf_path, format, orientation, ...) - `llx_bericht_page` — Seite (rowid, fk_bericht, page_order, source_type, source_path, source_page, rotation, fabric_json, note, layout, image_scale, image_align, ...) - `llx_bericht_upload_token` — Phase 2: Mobile-Upload-Tokens (rowid, token, fk_bericht, expires_at, created_by) ### Permissions - `bericht/read` (Standard für alle) - `bericht/write` (Standard für alle) - `bericht/delete` (Standard für alle) - `bericht/admin` (nur explizit) **WICHTIG:** `$this->rights[$r][4]` = perms-Name (`'read'`), `[5]` = subperms (leer). NICHT Modul-Name in [4]! ### Modul-Numero **500033** — kollidiert NICHT mit BankImport (500021). Permission-IDs sind 500033 + n. ### CSS-Variablen (Dolibarr awl-dark Theme) Verwendete: `--colorbacktitle1`, `--colortext`, `--colorbackbody`, `--colorboxbordertitle1`, `--colortextlink`, `--colorbackhmenu1`, `--colortextbackhmenu`, `--colorbackvmenu1` NICHT vorhanden im awl-dark: `--inputbackgroundcolor`, `--inputtextcolor` — stattdessen Fallbacks nutzen. ### JS-Libraries (lokal in js/lib/) - pdf.min.js (PDF.js 3.11) - pdf.worker.min.js - fabric.min.js (Fabric.js 5.3) - Sortable.min.js (SortableJS 1.15) ### LocalStorage Settings Key: `bericht.editor.settings.v1` Speichert: color, stroke, fontFamily, fontSize, bold, italic, zoom ### Forgejo - Repo: `data/bericht` (NICHT `data-it/bericht` — Token hat keine org-write rechte) - Workflow: `[deploy]`-Tag triggert rsync nach `/mnt/appdata/firma/dolibarr-202509/modules/bericht` - Lokaler Symlink: `/var/www/dolibarr/custom/bericht` → `/mnt/17 - Entwicklungen/30 - Scripts/php/Dolibarr - Module/Bericht/repo` - Lokales Apache läuft als User `data` (NICHT `http`) --- ## Phase 1 — Bericht-Modul-Erweiterungen (in Arbeit) ### ✅ Erledigt vor Phase 1 - Modul-Scaffold (modBericht, SQL, Lang, Rechte korrekt nach Stundenzettel-Format) - Editor mit PDF.js + Fabric.js - Toolbar 2-zeilig, einheitliche Höhe 30px - Schriftart/Größe/Bold/Italic mit localStorage-Persistenz - Zoom (-/+/Reset), Seitenrotation, Pfeil mit Spitze (drag, drehbar) - Seiten-Thumbnails als echte Vorschau (PDF.js + Image), Hell/Dunkel-Toggle - ResizeObserver für Console-Open-Resize - ODT-Template-Verwaltung im Admin - Generate-PDF mit FPDI + Annotationen einbrennen - Mobile-Upload-Idee dokumentiert (Phase 2) ### Phase 1 Features - [x] **1.6 Verknüpfte Sicht Auftrag→Rechnung** ✅ - [x] **1.1 Live-PDF-Vorschau** ✅ - [x] **1.2 Anhänge löschen** ✅ - [x] **1.3 Seitengröße A4/A3/Letter + Hoch/Quer** ✅ — global pro Bericht (nicht pro Seite override) - [/] **1.4 Mehrere Bilder pro Seite** — DB + Klassen-Skelett da, Grid-Rendering im PDF + Editor noch offen (siehe TODO unten) - [/] **1.5 Bildgröße pro Seite** — image_scale/image_align Spalten da, UI noch offen - [ ] **1.7 Kunden-Tab** — Tab "Berichte" auf thirdparty ### TODO Phase 1.4 + 1.5 (Folge-Commit) - BerichtPage::getImages() liest llx_bericht_page_image - Editor: Layout-Dropdown pro Seite (1/2/4/6 Slots) - Drag&Drop von Anhängen in Slots oder "Als Grid hinzufügen"-Button - generate_pdf/preview_pdf: Grid-Rendering (calculate slot rects) - Bei `single`-Layout: image_scale (1.0/0.7/0.5) + image_align (fit/center/topleft/topright) --- ## Phase 3 — PWA MVP ✅ (2026-04-17) - Repo: `data-it/baustelle-pwa` (SvelteKit-Projekt) - Hosting: `awl.data-it-solution.de/baustelle/` (Apache-Alias) - Stack: SvelteKit + Workbox + idb-keyval - Features: Login → Auftragsliste → Order-Detail → Foto/Sprachnotiz/Materialliste → PDF-Viewing - **PDF-Viewer implementiert**: PDF.js Canvas-Rendering, Datei-Typ-Unterscheidung (Bilder/Audio/PDFs/Dokumente) - **Weitere Dokumente**: Order-Dateien aus `commande//` als Inline-Viewer (PDF.js) oder Download ## Phase 4 Block 1 ✅ (2026-04-09 bis 2026-04-17) PWA-API-Layer + Usability-Features: - ✅ 2.3 API-Layer unter `bericht/api/` mit JWT-Auth (Login, Orders, Photos, Reports) - ✅ 2.4 REST-Endpoints: /auth.php, /orders, /orders/{id}, /orders/{id}/photos, /photo.php (Whitelist) - ✅ 4.j PDF-Vorschau-Modal + Inline-Viewing (PDF.js Canvas) - ✅ 4.g Seite löschen in PWA (DELETE /api/pages.php) - ✅ 4.h Notiz pro Seite (POST /api/pages.php {note}) - ✅ 4.b Touch-Unterschrift (POST /api/pages.php?action=signature) - ✅ Datei-Typ-Unterscheidung: Bilder (Modal), Audio (Player), PDFs (Canvas), Dokumente (Download) API-Endpoints (neue): - POST /api/auth.php — JWT-Login (username, password) - GET /api/orders.php — Aufträge des Users (filter: q, open) - GET /api/orders.php?id= — Order-Detail - GET /api/orders.php?id=&action=photos — Order-Dateien (Bilder/Audio/PDFs/Dokumente) - POST /api/orders.php?action=create — Neuer Order (socid, title, ref_client, date) - GET /api/photo.php?relpath= — Datei-Serving (JWT via Header oder Query-Param, Whitelist: facture|commande|propal|bericht) - POST /api/pages.php?action=signature&bericht_id= — Touch-Unterschrift - DELETE /api/pages.php?id= — Seite löschen - POST /api/pages.php?id= — Seite-Notiz / Rotation PWA neue Komponenten (app.js): - openFileViewer() — Generischer Dateibetrachter (Bilder/PDFs/Audio/Download) - openPdfViewer() — PDF.js Canvas mit Zoom/Seitennavigation/Download - docIconFor(), formatFileSize(), formatShortDate() — Hilfsfunktionen - Unterschrift-Modal, Notiz-Modal, Seiten-Verwaltung Service Worker v5: Offline-Queue, Sync, Share Target API. ## Phase 5 — PWA Erweiterungen (geplant) - Sprachnotizen-Transkription via Whisper (POST /api/transcribe.php) - PIN-Schutz / WebAuthn - Push-Notifications bei neuen Aufträgen - Offline-Queue Optimierung (Sync bei Netzwechsel) - QR-Code Scanner (Order-Lookup) - Batch-Unterschriften (mehrere Orders auf einmal) ## Phase 6 — Optional Später Stamps, Vorher/Nachher, Versionierung, Mess-Werkzeug, Bericht-Vorlagen, Offline-Map, Geofencing --- ## Wichtige Lessons Learned (für andere Dolibarr-Module) 1. **Numero muss kollisionsfrei sein** — sonst werden Permissions stillschweigend verworfen 2. **Permission-Array-Format**: [4]=perms (action), [5]=subperms (leer) — NICHT [4]=Modulname 3. **CSS-Variablen** über Theme nutzen, nicht hardcoded Hex 4. **JS-Libs lokal** in `js/lib/` (Eddys Regel: kein CDN) 5. **Fabric.js wickelt Canvas** in `.canvas-container` — den positionieren, nicht das innere Canvas 6. **PDF.js Buffer wird konsumiert** — beim Re-Render `arrayBuffer.slice(0)` nutzen 7. **Lokales Dolibarr** läuft als User `data`, mit Symlinks aus `/var/www/dolibarr/custom/` zu `/mnt/17 - Entwicklungen/...` 8. **Niemals direkt** in `/var/www/dolibarr` oder `/mnt/appdata` editieren — alles über Git 9. **Niemals schreibend** in `dolibarr_test` MySQL — nur lesend für Debugging 10. **Computed Extrafields** mit `$object->ref` brauchen Null-Check, sonst PHP-Output beim eval → "headers already sent"