Phase 1.6 Verknüpfte Sicht Auftrag↔Rechnung: - Bericht::fetchLinkedForElement liest llx_element_element-Verknüpfungen - linkToElement/unlinkFromElement n:m-API - Bericht-Übersicht zeigt drei Sektionen: direkt zugeordnet, zusätzlich verknüpft, aus verknüpften Aufträgen (read-only) - 'Übernehmen'-Button erstellt llx_element_element-Eintrag - 'Lösen'-Button entfernt Verknüpfung - generate_pdf legt das fertige PDF auch unter den verknüpften Elementen ab + ECM-Eintrag Phase 1.1 Live-PDF-Vorschau: - Neuer Endpoint ajax/preview_pdf.php — wie generate_pdf, aber: schreibt nicht in ECM, ändert nicht den Status, streamt direkt - 👁️ Vorschau-Button im Editor öffnet Modal mit iframe (PDF.js Viewer des Browsers) - bericht_burn_annotations und bericht_render_cover_internal in lib/bericht.lib.php verschoben (gemeinsam genutzt) - ESC-Key + Backdrop-Click schließen das Modal Phase 1.2 Anhänge löschen: - Neuer Endpoint ajax/delete_attachment.php mit Path-Whitelist (nur facture/, commande/, propal/), löscht Datei + thumbs + llx_ecm_files-Eintrag - 🗑️-Button in jeder Anhang-Zeile, Confirm-Dialog mit Quell-Auftrag/Rechnung im Text - Inline-Remove ohne Page-Reload Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> [deploy]
6.7 KiB
Bericht-Modul — Projekt-Status & Architektur
Stand 2026-04-08
Dolibarr-Custom-Modul für Arbeitsberichte mit Browser-PDF-Editor.
Architektur (final)
Tab-Verteilung
- Auftrag (commande) — primärer Erstellungsort, Berichte mit
element_type='order', Auftragsnummer =commande->refdirekt - Rechnung (facture) — Berichte mit
element_type='invoice', Auftragsnummer ausarray_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(NICHTdata-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(NICHThttp)
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 (in Arbeit)
- 1.6 Verknüpfte Sicht Auftrag→Rechnung — Übersicht zeigt zwei Sektionen, Übernahme-Button erzeugt llx_element_element. (in Arbeit)
- 1.1 Live-PDF-Vorschau — neuer Endpoint
ajax/preview_pdf.php(wie generate_pdf, aber ohne ECM-Insert + status), JS-Modal mit PDF.js - 1.2 Anhänge löschen — neuer Endpoint
ajax/delete_attachment.php, 🗑️-Icon neben Checkbox in Anhänge-Liste, Path-Whitelist, ECM-Cleanup - 1.3 Seitengröße A4/A3/Letter + Hoch/Quer — neue Spalten in
llx_bericht(format, orientation), pro Seite überschreibbar inllx_bericht_page(format_override) - 1.4 Mehrere Bilder pro Seite — Layout-Picker (1/2/4/6 Grid), neue Spalte
layoutinllx_bericht_page, n:m-Bilder evtl. neue Tabelle - 1.5 Bildgröße pro Seite — Spalten image_scale, image_align, image_x, image_y in llx_bericht_page
- 1.7 Kunden-Tab — Tab "Berichte" auf thirdparty, read-only, flache Tabelle sortiert nach Datum, Konstante BERICHT_TAB_ON_THIRDPARTY (default 0)
Phase 2 — Mobile-Vorbereitung + API-Layer (geplant)
- 2.1 Mobile-Upload-Token Tabelle + Cleanup-Cron
- 2.2 QR-Upload Lite Modal im Editor
- 2.3 API-Layer unter
bericht/api/mit JWT-Auth - 2.4 REST-Endpoints: /auth/login, /orders, /orders/{id}, /orders/{id}/photos, /reports, /reports/{id}/pages
JWT-Secret aus $dolibarr_main_instance_unique_id, 7 Tage Lifetime, Multi-Device OK (stateless).
Auftragsfilter pro User: fk_user_author, fk_user_valid, fk_user_modif ODER llx_element_contact mit "intern verantwortlich".
Phase 3 — PWA MVP (geplant)
- Repo:
data-it/baustelle-pwa(separates SvelteKit-Projekt) - Hosting:
awl.data-it-solution.de/baustelle/(Apache-Alias) - Stack: SvelteKit + Workbox + idb-keyval
- MVP: Login → Auftragsliste → Detail → Foto-Aufnahme → Offline-Queue → Sync
Phase 4 — PWA Voll (geplant)
- Sprachnotizen (MediaRecorder)
- Touch-Skizzen-Editor
- Schnell-Bericht in PWA
- Touch-Unterschrift
- PIN-Schutz / WebAuthn
- Push-Notifications
- Web Share Target API
Phase 5 — Optional Später
Stamps, Vorher/Nachher, Versionierung, Mess-Werkzeug, Bericht-Vorlagen, Batch-Modus, Whisper-Transkription, Offline-Map
Wichtige Lessons Learned (für andere Dolibarr-Module)
- Numero muss kollisionsfrei sein — sonst werden Permissions stillschweigend verworfen
- Permission-Array-Format: [4]=perms (action), [5]=subperms (leer) — NICHT [4]=Modulname
- CSS-Variablen über Theme nutzen, nicht hardcoded Hex
- JS-Libs lokal in
js/lib/(Eddys Regel: kein CDN) - Fabric.js wickelt Canvas in
.canvas-container— den positionieren, nicht das innere Canvas - PDF.js Buffer wird konsumiert — beim Re-Render
arrayBuffer.slice(0)nutzen - Lokales Dolibarr läuft als User
data, mit Symlinks aus/var/www/dolibarr/custom/<modul>zu/mnt/17 - Entwicklungen/... - Niemals direkt in
/var/www/dolibarroder/mnt/appdataeditieren — alles über Git - Niemals schreibend in
dolibarr_testMySQL — nur lesend für Debugging - Computed Extrafields mit
$object->refbrauchen Null-Check, sonst PHP-Output beim eval → "headers already sent"