# Bericht — Arbeitsberichte für Dolibarr

Erstellt aus den Anhängen einer Rechnung (oder eines Auftrags / Angebots) einen Arbeitsbericht als PDF.
Bilder und PDFs lassen sich im Browser annotieren (Pfeile, Kreise, Rechtecke, Text, Freihand) — der fertige Bericht wird unter *Verknüpfte Dokumente* der Rechnung abgelegt.

## Funktionen

- **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
- **Seiten-Verwaltung** per Drag&Drop (SortableJS): umordnen, löschen, drehen, neue Seiten hochladen
- **Notizen pro Seite** — werden im finalen PDF unten auf der Seite gedruckt
- **Deckblatt aus ODT-Vorlage** mit Platzhaltern (`{auftragsnummer}`, `{kunde_name}`, `{datum}`, …)
- **ODT-Templates** im Admin-Bereich verwaltbar (mehrere Vorlagen, Standard wählbar)
- **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)
- **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

- Dolibarr ≥ 19.0
- PHP ≥ 7.4
- TCPDF (in Dolibarr enthalten)
- **FPDI** (für PDF-Anhänge in den Bericht zu mergen) — empfohlen, optional
- **LibreOffice headless** (für ODT→PDF Konvertierung der Deckblätter)
- Optional: `pdfinfo` oder `imagick` für PDF-Seitenanzahl-Erkennung

## Installation

1. Modul-Verzeichnis nach `dolibarr/htdocs/custom/bericht/` (oder per Symlink aus dem Module-Mount-Pfad) kopieren
2. In Dolibarr unter **Konfiguration → Module/Anwendungen** das Modul **Bericht** aktivieren
3. Beim Aktivieren werden die SQL-Tabellen `llx_bericht` und `llx_bericht_page` angelegt
4. Vorhandene Extrafields auf `llx_facture_extrafields` (`auftragsnummer`, `angebotsnummer`, …) werden erkannt und nicht überschrieben — fehlende werden angelegt
5. Im Admin-Bereich (`/bericht/admin/setup.php`) die ODT-Templates hochladen und Standard-Template setzen

## Verwendung

1. Eine Rechnung öffnen (`/compta/facture/card.php?id=…`)
2. Reiter **Bericht** auswählen
3. **+ Neuer Bericht** klicken — die Auftragsnummer wird automatisch übernommen
4. Im Editor links die gewünschten Anhänge ankreuzen → **Auswahl in Bericht übernehmen**
5. Im mittleren Editor mit den Werkzeugen Pfeile, Texte etc. zeichnen
6. Seiten rechts per Drag&Drop sortieren, einzelne Seiten löschen, neue Dateien hochladen
7. **Bericht finalisieren** — PDF wird erzeugt, Deckblatt aus der ODT-Vorlage gerendert und unter den verknüpften Dokumenten der Rechnung abgelegt

## ODT-Template Platzhalter

| Platzhalter | Inhalt |
|---|---|
| `{auftragsnummer}` | Aus extrafield `options_auftragsnummer` der Rechnung |
| `{angebotsnummer}` | Aus extrafield `options_angebotsnummer` |
| `{rechnungsnummer}` | `ref` der Rechnung |
| `{kunde_name}` | Name des Kunden (Société) |
| `{kunde_adresse}` | Adresse des Kunden, mehrzeilig |
| `{datum}` | Heutiges Datum |
| `{beschreibung}` | extrafield `options_beschreibung` |
| `{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)

Die **Baustelle-PWA** (`https://awl.data-it-solution.de/baustelle/`) nutzt die folgenden API-Endpoints des Bericht-Moduls:

### Authentifizierung
```
POST /custom/bericht/api/auth.php
Body: { login: string, password: string }
Response: { ok: true, token: JWT, user: {...} }
```

JWT-Token hat 7 Tage Gültigkeit und enthält: `sub` (user id), `login`, `name`, `perms` (read/write/delete/admin).

### Order-APIs
```
GET    /custom/bericht/api/orders.php
GET    /custom/bericht/api/orders.php?id=<id>
GET    /custom/bericht/api/orders.php?id=<id>&action=photos
POST   /custom/bericht/api/orders.php?action=create
       Body: { socid, ref_client, title?, note_private?, date?, date_livraison?, validate? }
       ref_client ("Ihr Zeichen") ist PFLICHT. validate=true legt vor der Freigabe automatisch
       eine Std-Lohn-Zeile an (Kundenkarten-Default options_stundenzettel_default_service,
       sonst Fallback BERICHT_ORDER_DEFAULT_SERVICE_REF; Kundenpreis vor Standardpreis).
```

### Dateien
```
GET    /custom/bericht/api/photo.php?relpath=<path>&jwt=<token>
       Liefert Dateien aus DOL_DATA_ROOT (Whitelist: facture/, commande/, propal/, bericht/)
       Optional: ?size=small|mini (Thumbnails), ?download=1 (Attachment-Header)
```

### PDF-Ansicht
```
GET    /custom/bericht/api/pdf.php?id=<bericht_id>&jwt=<token>
       Liefert finalisiertes Bericht-PDF als Blob
```

### Seiten-Verwaltung (PWA)
```
DELETE /custom/bericht/api/pages.php?id=<page_id>
POST   /custom/bericht/api/pages.php?id=<page_id>  Body: { note: string }
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) |
| `BERICHT_ORDER_DEFAULT_SERVICE_REF` | `ELEK-STD-M` | Fallback-Produkt-Ref für die Std-Lohn-Zeile beim Direkt-Freigeben (wenn Kunde keinen `stundenzettel_default_service` gesetzt hat) |

## 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, 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, 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
│   ├── reorder_pages.php
│   └── generate_pdf.php                Finalisierung: TCPDF + FPDI + ODT-Deckblatt
├── api/                                REST-API (JWT-Auth)
│   ├── _inc.php                        JWT-Authentifizierung + Dolibarr-Init
│   ├── _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)
│   ├── reports.php                     Bericht-CRUD
│   ├── templates.php                   ODT-Templates
│   ├── materials.php                   Materiallisten
│   ├── voice.php                       Sprachnotizen (Upload + Transkription)
│   └── transcribe.php                  Whisper-Transkription
├── js/
│   ├── editor.js                       PDF.js + Fabric.js Integration
│   └── lib/                            PDF.js, Fabric.js, SortableJS (lokal)
├── css/bericht.css
├── 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
```

## Lizenz

GPL v3+
