bericht/ChangeLog.md
Eduard Wisch a8d8291c3a API 1.5.1: Thumbnails, Aufnahmezeit, Seitenfelder, Textnotizen
Die API-Seite zur Baustelle-PWA holt nach, was der Editor mit 1.5.0 bekommen hat.

photo.php kann jetzt size=thumb&w=<px> und rendert ueber bericht_attachment_thumb()
(GD, Cache, EXIF-Rotation) statt die Originaldatei auszuliefern. size=small konnte nur
ein von Dolibarr vorgefertigtes thumbs/<name>_small.<ext> liefern - fuer Uploads ueber
orders.php?action=upload_photo gibt es das nicht, dort laeuft kein vignette(). Die PWA
lud dadurch fuer jede Kachel das komplette Foto: gemessen 9,8 KB statt 235 KB je Kachel.
Antwort mit ETag aus der mtime, Folgeaufrufe enden mit 304.

orders.php?action=photos liefert taken_at (EXIF-Aufnahmezeit ueber bericht_file_taken_at,
sonst Dateidatum) und sortiert danach statt nach filemtime.

reports.php gibt je Seite title und composite_path aus. title konnte ueber pages.php
gesetzt werden, kam aber nie zurueck. composite_path ist das im Editor gebaute
Seitenbild - ohne das zeigen Clients nur das Rohbild ohne Anmerkungen, bei
Raster-Layouts eines von bis zu sechs Bildern und bei title_only gar keins.

Neu: api/note.php - Textnotizen zum Auftrag, aufgebaut wie die Sprachnotiz. Die Notiz
liegt als notiz_<betreff>_<datum>.txt im Auftragsverzeichnis und ist damit auch im
Dolibarr-Auftrag und in der Anhaenge-Spalte des Editors sichtbar. Liste, Lesen, Anlegen,
Aendern, Loeschen. Der file-Parameter wird gegen ^notiz_[A-Za-z0-9_.-]*\.txt$ geprueft;
gegen Pfad-Ausbrueche getestet.

ROADMAP.md wiederhergestellt - sie war mit eb37a4b geloescht worden, weil alle Punkte
abgehakt waren. Sie bleibt ab jetzt liegen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 18:11:42 +02:00

20 KiB
Raw Blame History

Changelog

1.5.1 — 2026-08-22

Die API-Seite zur Baustelle-PWA holt nach, was der Editor mit 1.5.0 bekommen hat.

Thumbnails für die PWA

  • api/photo.php kann jetzt size=thumb&w=<px> und rendert damit über bericht_attachment_thumb() — dieselbe Funktion, die auch die Anhänge-Kacheln im Editor füllt (GD, Cache unter bericht/thumbs/, EXIF-Ausrichtung).
  • Bisher kannte der Endpoint nur size=small|mini, und das lieferte ausschließlich ein Thumbnail, das Dolibarr selbst unter thumbs/<name>_small.<ext> abgelegt hatte. Fotos aus der PWA kommen über orders.php?action=upload_photo herein, und dort läuft kein vignette() — es gab also nie eines, und die Fotoliste lud für jede Kachel die Originaldatei. Gemessen an einer Testdatei: 9,8 KB statt 235 KB je Kachel.
  • Antwort mit ETag aus der mtime und Cache-Control: max-age=30 Tage; ein wiederholter Aufruf endet mit 304. Ein ersetztes Original bekommt automatisch einen neuen ETag.
  • Nicht-Bilder (PDF, Video) fallen unverändert auf das Original zurück.

Aufnahmezeit in der Anhängeliste

  • api/orders.php?action=photos liefert taken_at — die EXIF-Aufnahmezeit über bericht_file_taken_at(), sonst das Dateidatum. Sortiert wird danach statt nach filemtime. Bei Uploads aus der Galerie war die Upload-Reihenfolge bisher die falsche Reihenfolge.

Bericht-Seiten: Titel und fertiges Seitenbild

  • api/reports.php gibt je Seite title und composite_path mit aus.
  • title konnte über api/pages.php gesetzt werden und wurde in der PWA auch gerendert, kam aber nie zurück — der Titel wirkte, als würde er nicht gespeichert.
  • composite_path ist das im Editor gebaute Seitenbild. Ohne dieses Feld zeigt ein Client nur source_path, also das Rohbild ohne Anmerkungen — und bei einem Raster-Layout eines von bis zu sechs Bildern. Bei title_only ist source_path leer, die PWA zeigte dort eine Fehler-Kachel.

Neu: Textnotizen zum Auftrag (api/note.php)

  • Getippte Notiz zum Auftrag, aufgebaut wie die Sprachnotiz: die Notiz liegt als notiz_<betreff>_<datum>.txt im Auftrags-Verzeichnis und ist damit im Dolibarr-Auftrag und in der Anhänge-Spalte des Editors sichtbar.
  • GET (Liste mit Betreff, Vorschau und Zeitstempel), GET &file= (eine Notiz), POST (anlegen), POST &file= (ändern), POST &file=&delete=1 (löschen).
  • Dateikopf bis zur ersten Leerzeile trägt Betreff:, Erfasst: und Geändert: (jeweils mit Login), darunter der freie Text. Bewusst als Klartext lesbar, auch wenn jemand die .txt direkt im ECM öffnet.
  • Der file-Parameter wird gegen ^notiz_[A-Za-z0-9_.\-]*\.txt$ geprüft — ohne das ließe sich über ../ jede Datei unter DOL_DATA_ROOT überschreiben. Gegen Pfad-Ausbrüche getestet.

1.5.0 — 2026-08-21

Anhänge-Spalte: Miniaturen statt Dateinamen

  • Die linke Spalte im Editor ist jetzt ein Kachelraster mit Vorschaubildern. Bei Fotos mit Namen wie IMG_20260812_141233_HDR.jpg war in der 260 px schmalen Spalte vorher nicht zu erkennen, welches Bild gemeint ist.
  • Neuer Endpoint ajax/attachment_thumb.php: erzeugt Miniaturen serverseitig mit GD, legt sie unter bericht/thumbs/ ab und liefert sie mit ETag aus. Die Originale (Handyfotos mit mehreren MB) werden für die Spalte nicht mehr geladen. EXIF-Ausrichtung wird berücksichtigt — mit eigenem Mini-Parser, weil das exif-Modul im Prod-Container nicht geladen ist.
  • PDF-Anhänge bekommen Seite 1 als Miniatur (PDF.js, erst beim Scrollen gerendert).
  • Klick auf eine Kachel öffnet die Großansicht (/Esc schließt): Bilder mit Zoom, Pan und Wischen, PDFs im PDF-Viewer des Browsers.
  • Auswahl per Kachel-Checkbox, die Reihenfolge ist sichtbar (① ② ③) und bestimmt jetzt auch die Platzverteilung im Raster-Layout (vorher die Reihenfolge im Dokument).
  • Bereits verwendete Anhänge sind mit ✓ markiert, „alle"-Umschalter je Herkunft, Auswahlzähler, Umschalter zwischen Kachel- und Listenansicht (wird gemerkt).

Arbeitstisch zeigt die echte Seite

  • Der Editor stellt jetzt Blatt mit Kopfbereich, Seitenrändern und Fußbereich dar; die Arbeitsfläche ist exakt der Bereich, der gedruckt wird.
  • Neue gemeinsame Geometrie-Quelle bericht_page_geometry() — Editor und PDF-Erzeugung rechnen mit denselben Werten (Rand 10 mm, Kopf 30 mm, Fuß 16 mm, Notizzone 25 %).
  • Das PDF setzt die Arbeitsfläche 1:1 ein. Vorher wurde das komplette Blatt noch einmal in den Satzspiegel eingepasst, der Inhalt also ein zweites Mal verkleinert — daher der breite Rand und der Unterschied zur Vorschau.
  • Alle Layout-Zweige (Einzelbild, Raster, Vorher/Nachher, Notiz) nutzen dieselbe Geometrie. Seiten ohne gespeichertes Composite liefen vorher über den Kopfbereich mit Logo und Titel.
  • Umschalter „📐 Rand" blendet die Zonen aus.
  • Ältere Composites (Blatt-Proportion) werden erkannt und proportional eingepasst statt verzerrt.

Bild einer Seite austauschen

  • Neu: ajax/replace_page_source.php. Über „🔄" auf der Seitenminiatur lässt sich das Bild einer bestehenden Seite ersetzen — Reihenfolge, Notiz und Anmerkungen bleiben erhalten. Bisher musste man die Seite löschen und neu anhängen, wodurch sie ans Ende rutschte.
  • Bei Raster-Seiten ist der einzelne Platz austauschbar. Das dafür nötige set_slot_image.php existierte bereits, hatte aber keine Bedienung.
  • Finalisierte Berichte werden serverseitig abgelehnt.

Arbeiten ohne ständiges Neuladen

  • Hinzufügen, Löschen, Hochladen, Bildtausch und der QR-Upload luden bisher die ganze Seite neu. Der Editor sprang dabei auf Seite 1 zurück und der Zoom war weg — bei 20 Fotos hintereinander entsprechend zäh. Jetzt werden nur noch die betroffenen Listen aktualisiert.
  • Neuer Endpoint ajax/fragments.php liefert Seiten- und Anhängeliste als HTML. Gerendert wird über bericht_print_page_list() / bericht_print_attachment_list() — dieselben Funktionen, die auch die Karte aufbauen, damit beide Darstellungen nicht auseinanderlaufen.
  • Nach dem Finalisieren wird weiterhin neu geladen: der Bericht wechselt den Status.

Automatisches Speichern

  • Änderungen werden 4 Sekunden nach der letzten Aktion automatisch gespeichert, außerdem beim Seitenwechsel und beim Wegschalten des Browser-Tabs. Bisher gab es nur „💾 Entwurf speichern".
  • In der Fußleiste steht der Stand („● nicht gespeichert" / „✓ gespeichert"), beim Verlassen der Seite mit offenen Änderungen warnt der Browser.

Sortieren und Filtern der Anhänge

  • Sortierung nach Aufnahmezeit (auf/ab), Name oder Größe — bei Baustellenfotos ist die zeitliche Reihenfolge meist genau die richtige. Filter: alle · nur Bilder · nur PDFs · noch nicht verwendet.
  • Die Aufnahmezeit steht unter der Kachel. Ausgelesen wird sie mit einem eigenen EXIF-Parser, weil das exif-Modul im Prod-Container nicht geladen ist; gegen das PHP-Modul geprüft, identische Werte. Ohne EXIF gilt das Dateidatum.

Bedienung: Tastenkürzel, Spaltenbreite, Ziehen und Ablegen

  • Tastenkürzel: V Auswahl, P Zeichnen, R Rechteck, K Kreis, A Pfeil, T Text, Entf löscht die Auswahl, Strg+Z/Strg+Y Rückgängig/Wiederholen, Strg+S speichern, / blättert durch die Seiten. In Eingabefeldern und bei offenem Dialog greifen sie nicht; das Hintergrundbild lässt sich mit Entf nicht versehentlich entfernen.
  • Anhänge-Spalte in der Breite ziehbar (150620 px, Doppelklick auf die Trennlinie setzt zurück) und über „«" einklappbar — die Arbeitsfläche wird dabei neu gezeichnet.
  • Kachelgröße in drei Stufen über „⤢".
  • Ziehen und Ablegen: Kachel auf die Seitenliste legt neue Seiten an, Kachel auf die Arbeitsfläche ersetzt das Bild der offenen Seite, Kachel auf einen Raster-Platz setzt genau diesen. Dateien vom Rechner auf die Anhänge-Spalte werden hochgeladen.

Seiten: mehrere auf einmal, verdoppeln

  • Klick auf die Seitennummer markiert eine Seite, Umschalt erweitert bis dorthin. Über die Sammelleiste lassen sich markierte Seiten verdoppeln oder löschen.
  • Neuer Endpoint ajax/page_bulk.php. Kopien werden direkt hinter ihrem Original einsortiert, nach dem Löschen wird die Reihenfolge lückenlos neu nummeriert. Anmerkungen, Notiz und — bei Rastern — die Bilder in den Plätzen werden mitkopiert; das gespeicherte Seitenbild bewusst nicht, sonst zeigten Original und Kopie auf dieselbe Datei.

Raster-Plätze direkt auf der Seite

  • Bei Raster-Layouts liegt über der Arbeitsfläche ein Gitter mit einer Schaltfläche je Platz (bei Vorher/Nachher entsprechend beschriftet). Ein Klick setzt das links ausgewählte Bild, ein abgelegtes Bild setzt genau diesen Platz. Bisher ließen sich Raster nur beim Anlegen befüllen — der Endpoint dafür existierte, hatte aber keine Bedienung.
  • Die Plätze reagieren nur im Auswahlmodus; sobald ein Zeichenwerkzeug aktiv ist, haben die Werkzeuge Vorrang.

Behobene Fehler

  • dol_dir_list() wurde ohne $mode = 1 aufgerufen — size und date blieben leer, in der Anhängeliste stand „ Bytes" ohne Zahl.
  • Der PDF.js-Worker-Pfad war ohne /custom-Präfix hartkodiert. PDF.js fiel auf den „fake worker" zurück und rendert seitdem wieder im Worker statt auf dem Hauptthread.
  • PDF-Anhänge wurden über document.php ohne attachment=0 verlinkt und dadurch heruntergeladen statt angezeigt.
  • Die Größen-Auswahl einer Seite blieb leer: der DB-Wert 1 traf die Option 1.0 nicht.
  • Der Datei-Upload verarbeitete nur die erste Datei einer Mehrfachauswahl.
  • Eingabefelder im Editor nutzen jetzt --inputbackgroundcolor/--inputbordercolor. Die Modul-Doku hielt die Variablen für im AwlDark nicht vorhanden — sie sind gesetzt (KB #512).
  • Schneller Seitenwechsel konnte Inhalte vertauschen: zwei Durchläufe von loadPage() liefen ineinander — der zweite speicherte die noch nicht umgeschaltete Seite ein weiteres Mal, und beide zeichneten in denselben Canvas. Dabei konnte die Notiz der einen Seite bei der anderen landen. Seitenwechsel laufen jetzt nacheinander; ein überholter Durchlauf bricht ab.
  • Der Dialog beim Löschen eines Anhangs sagt jetzt, dass die Datei endgültig aus den Dokumenten des Belegs verschwindet, und warnt, wenn sie im Bericht in Gebrauch ist.

1.4.0 — 2026-08-15

Kein Stunden-Dummy mehr beim Direkt-Freigeben

  • api/orders.php?action=create: Mit validate=true wird der Auftrag jetzt ohne jede Position freigegeben. Bisher hängte das Backend vorher eine Std-Lohn-Zeile mit Menge 1 an (Kundenkarten-Default options_stundenzettel_default_service, sonst Fallback-Produkt).
  • Warum: Die Annahme, Commande::valid() scheitere an einem leeren Auftrag, ist falsch — weder valid() noch der Handler confirm_validate prüfen auf Zeilen, gesperrt ist nur die Button-Darstellung in commande/card.php (verifiziert gegen Dolibarr 22.0.2, KB #355/#989). Die Alibi-Zeile verfälschte total_ht, tauchte als offene Restmenge in der Lieferauflistung auf, stand im Kunden-PDF und ließ sich nach der Freigabe nicht mehr per deleteLine() entfernen. Die Leistungen kommen aus dem Stundenzettel.
  • Das Antwortfeld added_line entfällt (wurde von der Baustelle-PWA nie ausgewertet).
  • Die Konstante BERICHT_ORDER_DEFAULT_SERVICE_REF wird nicht mehr verwendet.
  • Gleiche Umstellung in der Stunden-App: stundenzettel/ajax/pwa_api.php (Aktion validate_order) fügt ebenfalls keine Fallback-Position mehr ein, und legt mit der neuen Aktion create_order selbst Aufträge an (Stundenzettel 2.17.0).

1.3.1 — 2026-07-18

Fixes rund um die PWA-Auftragsanlage

  • api/customers.php: Zahlart und Zahlungsbedingung im Kunden-Detail werden jetzt übersetzt — über die Dolibarr-Sprachkeys PaymentTypeShort<code> / PaymentConditionShort<code> (Sprachdatei bills) statt der rohen englischen libelle-Werte aus c_paiement/c_payment_term. Behebt die Anzeige „💳 Payment Condition · 🏦 Credit transfer" in der „Übernommen"-Zeile. Fallback auf libelle, wenn kein Sprachkey existiert (z. B. Custom-Einträge ohne code).
  • Baustelle-PWA (Repo baustelle-pwa): „Neuer Auftrag"-Formular saß vertikal zu weit unten (der gemeinsame .fs-body erbte justify-content:center, was bei flex-direction:column vertikal zentriert) und wurde von der Bildschirmtastatur verdeckt → justify-content:flex-start im Modal + scrollIntoView({block:'center'}) beim Feld-Fokus.

1.3.0 — 2026-07-18

PWA Auftrag-Anlegen überarbeitet (Formular + Freigabe)

Formular (Baustelle-PWA, openNewOrderModal)

  • Feld-Reihenfolge/Beschriftung angepasst: „Ihr Zeichen" (= ref_client) steht jetzt an erster Stelle und ist Pflicht; „Auftragsbeschreibung" (= Extrafield options_auftragsbeschreibung) an zweiter Stelle und optional. (Vorher genau umgekehrt: Titel Pflicht, Kunden-Referenz optional.)
  • Neues Feld „Geplanter Liefertermin" (datetime-local, Datum + Uhrzeit in einem Feld) → Auftrag-Spalte date_livraison.
  • Neue Checkbox „Auftrag direkt freigeben".

Backend (api/orders.php?action=create)

  • ref_client ist jetzt serverseitig Pflicht (Geschäftsregel — Dolibarr-Core verlangt nur den Kunden).
  • Neuer Parameter date_livraison (Unix-TS) → Commande->delivery_date.
  • Neuer Parameter validate: legt vor der Freigabe automatisch eine Std-Lohn-Zeile an und ruft dann Commande::valid().
    • Produkt: Kundenkarten-Default options_stundenzettel_default_service, sonst Fallback-Produkt über Ref BERICHT_ORDER_DEFAULT_SERVICE_REF (Default ELEK-STD-M, „Stundenlohn Meister" 45 €).
    • Preis: kundenspezifischer Preis (PRODUIT_CUSTOMER_PRICES) hat Vorrang, sonst Produkt-Standardpreis. Menge 1.
  • Response erweitert um ref_client, date_livraison, validated, added_line, validate_warning.

1.2.0 — 2026-05-27

Phase 1.8 Lieferschein-Bestätigung in der PWA

Neuer element_type='shipment'

  • Bericht-Modul unterstützt jetzt element_type='shipment' mit fk_element = llx_expedition.rowid
  • Tab "Bericht" erscheint auf der Lieferung-Card (Konstante BERICHT_TAB_ON_SHIPMENT)
  • bericht_fetch_parent() und bericht_fetch_shipment_with_order() laden Expedition + verknüpften Auftrag

Signatur auf Lieferschein-PDF stempeln

  • Neue Tabelle llx_bericht_signature_box: Pro PDF-Template (merou/rouget/espadon/...) konfigurierbare Box-Geometrie (x/y/w/h in mm, Seite first/last, Label)
  • Konstante BERICHT_SIGNATURE_BOX_DEFAULT als JSON-Default ({"page":"last","x_mm":120,"y_mm":230,"w_mm":70,"h_mm":35,"label":"Unterschrift Kunde"})
  • bericht_stamp_signature_on_pdf(): FPDI importiert Original-Lieferschein, TCPDF stempelt PNG + Name + Datum + GPS in die konfigurierte Box

Visueller Admin-Editor (admin/signature_box_editor.php)

  • PDF.js rendert ein Beispiel-Lieferschein-PDF
  • Fabric.js-Rechteck zum Drag&Resize der Signatur-Box auf dem Canvas
  • Eingabefelder für X/Y/W/H/Label/Seite werden live synchronisiert
  • "Speichern" persistiert via AJAX (ajax/save_signature_box.php) in llx_bericht_signature_box (UPSERT auf template_name)
  • Reset-Button setzt zurück auf Default-Konstante

Neue PWA-Route (Baustelle-App)

  • Order-Detail bekommt Button "🚚 Lieferungen"
  • #/orders/:id/shipments zeigt Liste aller verknüpften Expeditionen mit Status- und Signed-Badge
  • #/shipments/:id zeigt Lieferschein-PDF inline (PDF.js Canvas) + großen Button "Lieferung unterschreiben lassen"

Vollbild-Querformat-Signatur (openShipmentSignatureModal)

  • requestFullscreen() + screen.orientation.lock('landscape') (Best-Effort)
  • 2-Spalten-Layout: links Lieferschein-Info + Namens-Input + GPS-Toggle, rechts Vollbild-Canvas
  • HiDPI-aware Canvas (devicePixelRatio), Pointer/Touch-Events mit quadratischer Glättung
  • Beim Bestätigen: PNG → POST /api/shipments.php?action=confirm → Backend stempelt in PDF und legt es in documents/expedition/<ref>/<ref>-signed.pdf

Auto-Workflow auf der Expedition

  • signed_status=1 (via CommonSignedObject::setSignedStatus)
  • Wenn Expedition noch Draft (Status 0): erst valid(), dann setClosed()
  • Bericht-Record (element_type='shipment') wird angelegt/aktualisiert mit final_pdf_path zum signierten PDF
  • <sig>.meta.json neben der PNG mit voller Audit-Spur (signer, user, GPS, IP, Box, Template, signed_at)

Neue API-Endpoints

  • GET /api/shipments.php?order_id=<id> — Liste der Lieferungen zu einem Auftrag
  • GET /api/shipments.php?id=<id> — Detail einer Lieferung + Bericht-ID falls vorhanden
  • GET /api/shipments.php?id=<id>&action=pdf — PDF-Stream (Original oder gestempelt)
  • POST /api/shipments.php?id=<id>&action=confirm — Unterschrift einstempeln + Status-Workflow

1.1.0 — 2026-04-08

Phase 1 Bericht-Modul Erweiterungen

1.6 Verknüpfte Sicht Auftrag↔Rechnung

  • Bericht-Übersicht zeigt drei Sektionen: direkt zugeordnet, zusätzlich verknüpft, aus verknüpften Aufträgen
  • "→ Übernehmen"-Button erstellt llx_element_element-Eintrag (n:m-Verknüpfung)
  • "Lösen"-Button entfernt Verknüpfung
  • Beim Finalisieren landet das PDF auch unter den verknüpften Elementen im ECM

1.1 Live-PDF-Vorschau

  • 👁️ Vorschau-Button im Editor → Modal mit eingebettetem PDF
  • Neuer Endpoint ajax/preview_pdf.php (kein ECM-Insert, kein Status-Wechsel)
  • ESC oder Klick auf Backdrop schließt das Modal

1.2 Anhänge löschen

  • 🗑️ Icon neben jedem Anhang in der linken Spalte
  • Confirm-Dialog mit Auftrags-/Rechnungs-Referenz
  • Path-Whitelist (nur facture/, commande/, propal/), Thumbs + ECM-Eintrag werden mitgelöscht

1.3 Seitengröße A4/A3/A5/Letter + Hoch/Quer

  • Format und Orientation in der Bericht-Meta wählbar
  • Auto-Save bei Änderung
  • Bilder werden dynamisch auf die Seitengröße skaliert

1.4 + 1.5 Mehrere Bilder pro Seite (DB-Schema)

  • Neue Tabelle llx_bericht_page_image für Multi-Image-Seiten
  • Spalten layout, image_scale, image_align in llx_bericht_page
  • Grid-Rendering im Editor + PDF folgt im nächsten Commit

1.7 Tab „Berichte" auf Kundenkarte

  • Read-only Übersicht aller Berichte des Kunden
  • Flache Tabelle sortiert nach Datum
  • Springt zum Bericht oder zur Quelle (Auftrag/Rechnung/Angebot)
  • Konstante BERICHT_TAB_ON_THIRDPARTY zum Aktivieren

Sonstiges

  • DB-Migrationen im init() für bestehende Installationen (ALTER TABLE mit Error-Suppress)
  • bericht_burn_annotations und bericht_render_cover_internal in lib/bericht.lib.php zentralisiert (gemeinsam von generate_pdf + preview_pdf genutzt)
  • Modal-CSS für Vorschau im Dolibarr Dark-Theme

1.0.0 — 2026-04-08

Initiales Release.

  • Modul-Scaffold mit Reiter „Bericht" auf Rechnungen, Aufträgen und Angeboten
  • CRUD für Bericht und BerichtPage (Tabellen llx_bericht, llx_bericht_page)
  • Browser-Editor mit PDF.js + Fabric.js: Pfeile, Kreise, Rechtecke, Freihand, Text, Undo/Redo
  • Anhänge-Browser zeigt eigene Anhänge + Anhänge verknüpfter Objekte
  • Datei-Upload direkt in den Bericht
  • Seiten-Verwaltung mit Drag&Drop (SortableJS), Löschen, Drehen
  • Notizen pro Seite (werden im PDF gedruckt)
  • Admin-Setup mit ODT-Template-Verwaltung (Upload, Löschen, Standard wählen)
  • Platzhalter-System für ODT-Templates ({auftragsnummer}, {kunde_name}, …)
  • PDF-Finalisierung mit TCPDF + FPDI, ODT→PDF Konvertierung des Deckblatts via LibreOffice
  • Annotationen werden beim Export ins PDF eingebrannt
  • Auftragsnummer wird automatisch aus dem vorhandenen Extrafield options_auftragsnummer geholt
  • Beim Aktivieren werden fehlende Extrafields auf llx_facture_extrafields angelegt, vorhandene NICHT überschrieben
  • Mehrere Berichte pro Dokument möglich
  • Forgejo-Workflow für Deploy nach Dolibarr (Tag [deploy])