Compare commits
2 commits
52489ad21d
...
d271b9a9ad
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d271b9a9ad | ||
|
|
2ec6686118 |
2 changed files with 116 additions and 13 deletions
51
CLAUDE.md
51
CLAUDE.md
|
|
@ -1,8 +1,8 @@
|
|||
# Bericht-Modul — Projekt-Status & Architektur
|
||||
|
||||
## Stand 2026-04-17
|
||||
## Stand 2026-05-27
|
||||
|
||||
Dolibarr-Custom-Modul für Arbeitsberichte mit Browser-PDF-Editor + PWA-API-Layer.
|
||||
Dolibarr-Custom-Modul für Arbeitsberichte mit Browser-PDF-Editor + PWA-API-Layer + Lieferschein-Unterschrift.
|
||||
|
||||
## Architektur (final)
|
||||
|
||||
|
|
@ -10,6 +10,7 @@ Dolibarr-Custom-Modul für Arbeitsberichte mit Browser-PDF-Editor + PWA-API-Laye
|
|||
- **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
|
||||
- **Lieferung (shipping/expedition)** — `element_type='shipment'`, fk_element = `llx_expedition.rowid`. Wird ausschließlich vom Signatur-Workflow der PWA verwendet (Anker für Audit-Spur), nicht für klassisches Berichte-Anlegen. Verknüpfung zum Auftrag über `llx_element_element` (sourcetype='commande', targettype='shipping').
|
||||
- **Kundenkarte (thirdparty)** — read-only Übersicht (Phase 1.7), zeigt alle Berichte des Kunden über Joins, **kein** Anlegen, **kein** Speicher-Ort
|
||||
|
||||
### Verknüpfung Auftrag → Rechnung
|
||||
|
|
@ -19,6 +20,7 @@ Berichte gehören 1:1 zu einem Parent (`element_type` + `fk_element`). Auf einer
|
|||
- `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)
|
||||
- `llx_bericht_signature_box` — Pro PDF-Template gespeicherte Signatur-Box-Geometrie (rowid, template_name, page, x_mm, y_mm, w_mm, h_mm, label, tms). Nur relevant für FPDI-Stempel-Fallback; der ODT-Workflow nutzt stattdessen den `{signature}`-Platzhalter.
|
||||
|
||||
### Permissions
|
||||
- `bericht/read` (Standard für alle)
|
||||
|
|
@ -124,6 +126,51 @@ PWA neue Komponenten (app.js):
|
|||
|
||||
Service Worker v5: Offline-Queue, Sync, Share Target API.
|
||||
|
||||
## Phase 1.8 — Lieferschein-Bestätigung ✅ (2026-05-27)
|
||||
|
||||
Vollständiger Workflow für Kunden-Unterschrift auf dem Handy. Source-Repo: `data/baustelle-pwa` + `data/bericht`.
|
||||
|
||||
### Backend (Bericht-Modul)
|
||||
- `element_type='shipment'` mit `fk_element = llx_expedition.rowid`
|
||||
- Reiter "Bericht" auf Expedition-Card (Konstante `BERICHT_TAB_ON_SHIPMENT`)
|
||||
- Hook-Klasse `class/actions_bericht.class.php`:
|
||||
- `beforeODTSave`-Hook ersetzt `{signature}` via `$odfHandler->setImage('signature', $path, $ratio)` durch eingebettetes PNG-Frame
|
||||
- Setzt zusätzlich `{signer_name}`, `{signed_at}`, `{gps}` per `setVars`
|
||||
- Hook MUSS in `llx_const` als `MAIN_MODULE_BERICHT_HOOKS = ["odtgeneration"]` registriert sein — wird beim Modul-Activate gesetzt
|
||||
- `lib/bericht.lib.php`:
|
||||
- `bericht_fetch_shipment_with_order()` — Expedition + verknüpfter Auftrag via `llx_element_element`
|
||||
- `bericht_get_shipment_pdf($db, $shipment, $include_signed=false)` — Standard-Lieferschein-PDF, filtert `-signed.pdf` raus per Default
|
||||
- `bericht_get_signature_box($db, $template)` — pro-Template-Geometrie aus DB oder Default-JSON
|
||||
- `bericht_stamp_signature_on_pdf(...)` — FPDI-basierter Stempel (Fallback für PDF-Module ohne ODT)
|
||||
- API: `api/shipments.php`
|
||||
- `GET ?order_id=<id>` → Liste
|
||||
- `GET ?id=<id>` → Detail
|
||||
- `GET ?id=<id>&action=pdf&variant=auto|signed|unsigned` → PDF-Stream
|
||||
- `POST ?id=<id>&action=confirm` → Signatur stempeln, signed.pdf erzeugen, Expedition signed_status=1 + ggf. validieren+schließen
|
||||
- Backup-Roundtrip im confirm: Original kopieren → `generateDocument()` mit Hook → Ergebnis als `<ref>-signed.pdf` kopieren → Original aus Backup wiederherstellen (`generateDocument` überschreibt sonst das Original-PDF)
|
||||
|
||||
### Admin
|
||||
- `admin/setup.php`: Toggle Tab on Shipment, Slider `BERICHT_SIGNATURE_IMAGE_RATIO` (Default 0.35)
|
||||
- `admin/signature_box_editor.php`: visueller PDF-Editor für mm-Box-Geometrie (PDF.js + Fabric.js). Nur relevant für PDF-Module-Fallback; bei ODT-Templates wird stattdessen `{signature}`-Platzhalter empfohlen.
|
||||
- `admin/signature_box_preview.php`: Beispiel-PDF-Renderer
|
||||
- `ajax/save_signature_box.php`: UPSERT in `llx_bericht_signature_box`
|
||||
|
||||
### PWA-Frontend (Baustelle)
|
||||
- Routes `#/orders/:id/shipments` + `#/shipments/:id` in `app.js`
|
||||
- Fullscreen-Landscape Modal `openShipmentSignatureModal()`:
|
||||
- `requestFullscreen()` + `screen.orientation.lock('landscape')` (best-effort, iOS ignoriert lock)
|
||||
- HiDPI-Canvas (`devicePixelRatio`), transparent (kein fillRect)
|
||||
- `trimCanvasToInk()` schneidet auf bemalte Fläche (Alpha > 16)
|
||||
- Name vorausgefüllt mit Kundenname
|
||||
- GPS-Abfrage timeout 3s, graceful bei Verweigerung
|
||||
- Direkt nach Bestätigung: PDF-Viewer mit `?variant=signed`
|
||||
|
||||
### Wichtige Fallen
|
||||
- `EXPEDITION_ADDON_PDF_ODT_PATH` enthält wörtlich den String `"DOL_DATA_ROOT/..."` → muss mit `preg_replace('/DOL_DATA_ROOT/', DOL_DATA_ROOT, $d)` aufgelöst werden
|
||||
- `llx_element_element`-Richtung: **commande = source, shipping = target** (NICHT umgekehrt)
|
||||
- JWT für `<img>`/`<object>`-Tags: Query-Param `?jwt=<token>` als Fallback in `api/_jwt.php`, da diese Tags keine Authorization-Header senden
|
||||
- ODT-Templates für Expedition liegen unter `DOL_DATA_ROOT/doctemplates/shipments/*.odt`
|
||||
|
||||
## Phase 5 — PWA Erweiterungen (geplant)
|
||||
- Sprachnotizen-Transkription via Whisper (POST /api/transcribe.php)
|
||||
- PIN-Schutz / WebAuthn
|
||||
|
|
|
|||
78
README.md
78
README.md
|
|
@ -5,7 +5,7 @@ Bilder und PDFs lassen sich im Browser annotieren (Pfeile, Kreise, Rechtecke, Te
|
|||
|
||||
## Funktionen
|
||||
|
||||
- **Reiter „Bericht"** auf Rechnungen, Aufträgen und Angeboten (jeweils per Konstante deaktivierbar)
|
||||
- **Reiter „Bericht"** auf Rechnungen, Aufträgen, Angeboten und Lieferungen (jeweils per Konstante deaktivierbar)
|
||||
- **Anhänge-Browser** zeigt alle Dateien des aktuellen Dokuments **und** der direkt verknüpften Objekte (z. B. der Auftrag zur Rechnung)
|
||||
- **Auswahl per Checkbox** — markierte Dateien werden als Seiten in den Bericht übernommen
|
||||
- **Browser-Editor** mit PDF.js + Fabric.js: Pfeile, Kreise, Rechtecke, Freihand, Text, Farbe, Strichstärke, Undo/Redo
|
||||
|
|
@ -16,7 +16,8 @@ Bilder und PDFs lassen sich im Browser annotieren (Pfeile, Kreise, Rechtecke, Te
|
|||
- **Auftragsnummer** wird automatisch aus dem Extrafield `options_auftragsnummer` der Rechnung gezogen
|
||||
- **Mehrere Berichte pro Dokument** möglich
|
||||
- Berichte als **Entwurf** speichern (jederzeit wieder editierbar) oder **finalisieren** (PDF erzeugen)
|
||||
- **PWA-API** für Mobile-Nutzung: Aufträge, Fotos, Sprachnotizen, Materiallisten, Signaturen
|
||||
- **Lieferschein-Bestätigung mit Kunden-Unterschrift**: Vollbild-Querformat-Signatur in der PWA, Unterschrift wird via ODT-Hook (Platzhalter `{signature}`) ins Lieferschein-PDF gestempelt, Expedition wird automatisch validiert und geschlossen
|
||||
- **PWA-API** für Mobile-Nutzung: Aufträge, Fotos, Sprachnotizen, Materiallisten, Lieferungen, Signaturen
|
||||
- **PDF-Viewer in PWA** mit PDF.js Canvas-Rendering (Zoom, Seitennummerierung, Download)
|
||||
|
||||
## Voraussetzungen
|
||||
|
|
@ -60,6 +61,10 @@ Bilder und PDFs lassen sich im Browser annotieren (Pfeile, Kreise, Rechtecke, Te
|
|||
| `{hinweis}` | extrafield `options_hinweis` |
|
||||
| `{bericht_titel}` | Titel des Berichts |
|
||||
| `{ersteller}` | Login-Name des erstellenden Users |
|
||||
| `{signature}` | Kunden-Unterschrift als Bild (nur Lieferschein-Workflow, ersetzt Text-Platzhalter durch eingebettetes PNG; Größe via `BERICHT_SIGNATURE_IMAGE_RATIO`) |
|
||||
| `{signer_name}` | Name des unterschreibenden Kunden |
|
||||
| `{signed_at}` | Zeitstempel der Unterschrift |
|
||||
| `{gps}` | GPS-Koordinaten zum Zeitpunkt der Unterschrift (falls erlaubt) |
|
||||
|
||||
## PWA-Integration (Baustelle Mobile App)
|
||||
|
||||
|
|
@ -103,20 +108,71 @@ POST /custom/bericht/api/pages.php?action=signature&bericht_id=<id>
|
|||
Body: FormData mit file=<PNG-Blob>, signer_name, gps_lat, gps_lon
|
||||
```
|
||||
|
||||
### Lieferungen + Unterschrift (PWA)
|
||||
```
|
||||
GET /custom/bericht/api/shipments.php?order_id=<id>
|
||||
Liste aller Expeditionen zum Auftrag (id, ref, date_delivery, status, signed_status, has_bericht)
|
||||
|
||||
GET /custom/bericht/api/shipments.php?id=<id>
|
||||
Detail einer Lieferung inkl. bericht_id
|
||||
|
||||
GET /custom/bericht/api/shipments.php?id=<id>&action=pdf[&variant=auto|signed|unsigned]
|
||||
Liefert Lieferschein-PDF (Default auto: signed wenn vorhanden, sonst Original)
|
||||
|
||||
POST /custom/bericht/api/shipments.php?id=<id>&action=confirm
|
||||
FormData mit signature_png, signer_name, gps_lat, gps_lon, signed_at
|
||||
Stempelt Unterschrift via ODT-Hook ({signature}-Platzhalter), legt <ref>-signed.pdf
|
||||
in documents/expedition/<ref>/, setzt signed_status=1, validiert+schließt Expedition
|
||||
wenn noch Draft. Response: { ok: true, pdf_url, bericht_id }
|
||||
```
|
||||
|
||||
## Konfigurations-Konstanten
|
||||
|
||||
Per `admin/setup.php` oder `llx_const`:
|
||||
|
||||
| Konstante | Default | Zweck |
|
||||
|---|---|---|
|
||||
| `BERICHT_TAB_ON_INVOICE` | 1 | Reiter "Bericht" auf Rechnungen anzeigen |
|
||||
| `BERICHT_TAB_ON_ORDER` | 1 | Reiter "Bericht" auf Aufträgen anzeigen |
|
||||
| `BERICHT_TAB_ON_PROPAL` | 1 | Reiter "Bericht" auf Angeboten anzeigen |
|
||||
| `BERICHT_TAB_ON_SHIPMENT` | 1 | Reiter "Bericht" auf Lieferungen anzeigen |
|
||||
| `BERICHT_TAB_ON_THIRDPARTY` | 0 | Read-only Bericht-Tab auf Kundenkarte |
|
||||
| `BERICHT_SIGNATURE_IMAGE_RATIO` | 0.35 | Größen-Faktor für `{signature}`-Platzhalter im ODT (höher = größer) |
|
||||
| `BERICHT_SIGNATURE_BOX_DEFAULT` | JSON | Default-Geometrie für FPDI-Stempel-Fallback (`{"page":"last","x_mm":120,"y_mm":230,"w_mm":70,"h_mm":35,"label":"Unterschrift Kunde"}`) |
|
||||
| `BERICHT_BURN_ANNOTATIONS` | 0 | Annotationen ins PDF einbrennen statt als PDF-Annotation einbetten |
|
||||
| `BERICHT_LIBREOFFICE_BIN` | `soffice` | Pfad zur LibreOffice-Binary (für ODT→PDF) |
|
||||
|
||||
## Datenbank
|
||||
|
||||
| Tabelle | Zweck |
|
||||
|---|---|
|
||||
| `llx_bericht` | Bericht-Header (element_type ∈ {invoice, order, propal, shipment}, fk_element, status, …) |
|
||||
| `llx_bericht_page` | Einzelne Seiten mit Fabric-JSON-Annotationen, Layout, Notiz |
|
||||
| `llx_bericht_page_image` | Multi-Image-Layout pro Seite (Phase 1.4) |
|
||||
| `llx_bericht_upload_token` | Mobile-Upload-Tokens (geplant) |
|
||||
| `llx_bericht_signature_box` | Pro Lieferschein-Template gespeicherte Signatur-Box-Geometrie (mm) |
|
||||
|
||||
## Architektur
|
||||
|
||||
```
|
||||
bericht/
|
||||
├── core/modules/modBericht.class.php Modul-Descriptor, Tabs, Extrafields-Init
|
||||
├── class/bericht.class.php Bericht + BerichtPage CRUD
|
||||
├── lib/bericht.lib.php Helper (Anhänge sammeln, Auftragsnr., Templates)
|
||||
├── core/modules/modBericht.class.php Modul-Descriptor, Tabs, Extrafields-Init, Konstanten
|
||||
├── class/
|
||||
│ ├── bericht.class.php Bericht + BerichtPage CRUD
|
||||
│ └── actions_bericht.class.php Hook: beforeODTSave setzt {signature} + Meta-Variablen
|
||||
├── lib/bericht.lib.php Helper (Anhänge, Auftragsnr., Templates, Shipment-PDF,
|
||||
│ Signature-Box, FPDI-Stempel-Fallback)
|
||||
├── bericht_card.php Editor-Seite (Tab-Inhalt)
|
||||
├── admin/setup.php Admin: ODT-Templates, Konstanten
|
||||
├── admin/
|
||||
│ ├── setup.php Admin: ODT-Templates, Konstanten, Signatur-Größe
|
||||
│ ├── signature_box_editor.php Visueller PDF-Editor für Signatur-Box-Position
|
||||
│ └── signature_box_preview.php Beispiel-PDF-Renderer für den Editor
|
||||
├── ajax/ Legacy Endpoints (Token-geschützt)
|
||||
│ ├── _inc.php Gemeinsamer Header
|
||||
│ ├── add_attachment.php Anhang als Seite hinzufügen
|
||||
│ ├── upload_extra.php Direkter Upload
|
||||
│ ├── save_annotations.php Fabric-JSON speichern
|
||||
│ ├── save_signature_box.php UPSERT der Signatur-Box pro Template
|
||||
│ ├── page_meta.php Annotationen + Notiz laden
|
||||
│ ├── page_image.php Seitenbild/PDF ausliefern
|
||||
│ ├── delete_page.php
|
||||
|
|
@ -124,9 +180,10 @@ bericht/
|
|||
│ └── generate_pdf.php Finalisierung: TCPDF + FPDI + ODT-Deckblatt
|
||||
├── api/ REST-API (JWT-Auth)
|
||||
│ ├── _inc.php JWT-Authentifizierung + Dolibarr-Init
|
||||
│ ├── _jwt.php JWT encoding/decoding
|
||||
│ ├── _jwt.php JWT encoding/decoding (mit ?jwt= Query-Fallback)
|
||||
│ ├── auth.php Login-Endpoint
|
||||
│ ├── orders.php Order-Liste, Detail, Fotos, Create
|
||||
│ ├── shipments.php Lieferungen-Liste, PDF-Stream, Unterschrift-Confirm
|
||||
│ ├── photo.php Datei-Serving mit Whitelist
|
||||
│ ├── pdf.php Finalized Bericht-PDF
|
||||
│ ├── pages.php Seiten-Verwaltung (Note, Rotation, Signature)
|
||||
|
|
@ -140,10 +197,9 @@ bericht/
|
|||
│ └── lib/ PDF.js, Fabric.js, SortableJS (lokal)
|
||||
├── css/bericht.css
|
||||
├── sql/
|
||||
│ ├── llx_bericht.sql
|
||||
│ ├── llx_bericht.key.sql
|
||||
│ ├── llx_bericht_page.sql
|
||||
│ └── llx_bericht_page.key.sql
|
||||
│ ├── llx_bericht.sql / .key.sql
|
||||
│ ├── llx_bericht_page.sql / .key.sql
|
||||
│ └── llx_bericht_signature_box.sql / .key.sql
|
||||
└── langs/{de_DE,en_US}/bericht.lang
|
||||
```
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue