diff --git a/ChangeLog.md b/ChangeLog.md index add57c8..730a270 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,21 @@ # Changelog +## 1.9.0 — 2026-10-21 + +### Auftragsbeschreibung aus der Baustellen-App ändern +„Notizen ist gut, aber als extra Datei brauche ich das selten — Sachen, die ich mir merken will für den Auftrag, +lieber in der Auftragsbeschreibung festhalten" (Eddy, 21.10.2026). + +- **`api/orders.php?id=&action=set_beschreibung`** (POST, JSON `{ text, vorher }`) schreibt das Zusatzfeld + `auftragsbeschreibung` am Auftrag — wie „Zusatzfelder ändern" auf der Auftragskarte (`updateExtraField`, Trigger + `ORDER_MODIFY`). Recht: Aufträge ändern (`commande creer`). Bis 20 000 Zeichen, Zeilenenden vereinheitlicht. +- **Kein stilles Überschreiben:** `vorher` ist der Stand, den die App angezeigt hat. Weicht der Server-Stand ab (im Büro + geändert), kommt **409** mit dem aktuellen Text — die App fragt, statt die Büro-Änderung zu verlieren. +- ⚠ Die Auftragsbeschreibung steht auch auf dem **Stundenzettel-PDF für den Kunden** (Modul Stundenzettel) — Eddy hat + sich bewusst dafür entschieden; die App weist im Dialog darauf hin. +- Geprüft (Testinstanz über die App): speichern mehrzeilig, Konflikt 409 bei Büro-Änderung, „Büro-Stand + meine + Ergänzung" behält beides. + ## 1.8.0 — 2026-10-19 ### Videos aus der Baustellen-App diff --git a/README.md b/README.md index 683623b..c94ecd2 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Bilder und PDFs lassen sich im Browser annotieren (Pfeile, Kreise, Rechtecke, Te - **Bild einer Seite austauschen** ohne sie zu löschen — Reihenfolge, Notiz und Anmerkungen bleiben erhalten. Bei Raster-Layouts lässt sich jeder Platz einzeln tauschen, direkt auf der Seite anklickbar. - **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. - **Mobiler Upload per QR-Code** — Handy scannt, lädt Fotos direkt in den offenen Bericht (zeitlich begrenzte Token) +- **Auftragsbeschreibung aus der Baustellen-App (1.9.0)** — `orders.php?action=set_beschreibung` schreibt das Zusatzfeld `auftragsbeschreibung` (Merkzettel zum Auftrag), mit Konfliktschutz (409 bei Büro-Änderung). Steht auch auf dem Stundenzettel-PDF. - **Videos aus der Baustellen-App (1.8.0)** — `orders.php?action=upload_photo` nimmt mp4/m4v/mov/webm (Inhalt geprüft, Name `video_…`, Aufnahmezeit aus `taken_at` bzw. dem MP4-Kopf), `photo.php` liefert Teilbereiche (Range) zum Abspielen und Spulen, `config.php` meldet `upload_max`, zu groß → 413. Im Editor 🎬-Kachel, nicht in Berichte übernehmbar. - **AVIF- und WebP-Bilder (1.7.4/1.7.5)** — beim Hochladen (Editor, PWA, Handy-Upload) am Inhalt erkannt und in JPG bzw. PNG (mit Transparenz) umgewandelt (`lib/bericht_avif.lib.php`, `bericht_upload_bild_umwandeln()`, KB #1698, #447). Bewegte WebP werden mit Meldung abgelehnt. - **Ablage am Beleg als Beilage (1.7.2)** — Fotos, Notizen, Sprachnotizen, Scans und Bericht-PDFs, die im Belegordner landen, stehen im ECM-Index als `uploaded` (`lib/bericht_index.lib.php`): nur im Reiter „Verknüpfte Dokumente", nie vorne im Kasten der Belegkarte (KB #1641) @@ -106,6 +107,10 @@ GET /custom/bericht/api/orders.php?id= GET /custom/bericht/api/orders.php?id=&action=photos Je Datei: filename, size, mime, date (mtime), taken_at (EXIF-Aufnahmezeit, sonst Dateidatum), relpath. Sortiert nach taken_at, neuste zuerst. +POST /custom/bericht/api/orders.php?id=&action=set_beschreibung (1.9.0) + Body: { text, vorher? } — Auftragsbeschreibung (Zusatzfeld auftragsbeschreibung) ändern, + Recht „Aufträge ändern". Weicht der Server-Stand von `vorher` ab → 409 mit aktuellem Text. + Achtung: die Beschreibung steht auch auf dem Stundenzettel-PDF für den Kunden. 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 gibt den Auftrag direkt frei — diff --git a/api/orders.php b/api/orders.php index bca6464..d5c2323 100644 --- a/api/orders.php +++ b/api/orders.php @@ -21,6 +21,12 @@ * Die Leistungen kommen später aus dem Stundenzettel. * Legt einen Draft-Auftrag an und übernimmt Kunden-Defaults (Zahlungsbedingungen, * Zahlart, Bankkonto, Incoterms, Lieferadresse, Default-Ansprechpartner). + * POST /api/orders.php?id=&action=set_beschreibung (1.9.0) + * JSON-Body: { text, vorher? } — Auftragsbeschreibung (Extrafield auftragsbeschreibung) ändern. + * Eddy: „Sachen, die ich mir merken will, lieber in der Auftragsbeschreibung festhalten." + * `vorher` = Stand, den die App angezeigt hat: weicht der Server-Stand ab (im Büro geändert), + * antwortet die API mit 409 und dem aktuellen Text statt ihn zu überschreiben. + * ⚠ Die Beschreibung steht auch auf dem Stundenzettel-PDF für den Kunden (Eddy wollte es so). */ require_once __DIR__.'/_inc.php'; @@ -302,6 +308,28 @@ if ($action === 'upload_photo' && $_SERVER['REQUEST_METHOD'] === 'POST') { )); } +/* ----- AUFTRAGSBESCHREIBUNG ÄNDERN (1.9.0) ----- */ +if ($action === 'set_beschreibung' && $_SERVER['REQUEST_METHOD'] === 'POST') { + if (!$user->hasRight('commande', 'creer')) api_fail('Keine Berechtigung, Aufträge zu ändern', 403); + $in = api_input(); + // Zeilenenden vereinheitlichen, Leerzeichen am Ende weg — sonst gilt jeder Handy-Text als „geändert" + $norm = function ($t) { return rtrim(str_replace(array("\r\n", "\r"), "\n", (string) $t)); }; + $text = $norm($in['text'] ?? ''); + if (mb_strlen($text, 'UTF-8') > 20000) api_fail('Die Beschreibung ist zu lang'); + $aktuell = $norm($cmd->array_options['options_auftragsbeschreibung'] ?? ''); + if (array_key_exists('vorher', $in) && $norm($in['vorher']) !== $aktuell) { + api_send(array('error' => 'Die Beschreibung wurde inzwischen geändert — bitte den neuen Stand ansehen.', + 'auftragsbeschreibung' => $aktuell), 409); + } + if ($text === $aktuell) api_ok(array('auftragsbeschreibung' => $aktuell, 'unveraendert' => true)); + $cmd->array_options['options_auftragsbeschreibung'] = ($text === '') ? null : $text; + // Wie „Zusatzfelder ändern" auf der Auftragskarte: Trigger ORDER_MODIFY (Ereignis, Benachrichtigungen) + if ($cmd->updateExtraField('auftragsbeschreibung', 'ORDER_MODIFY', $user) < 0) { + api_fail('Speichern fehlgeschlagen: '.($cmd->error ?: $db->lasterror()), 500); + } + api_ok(array('auftragsbeschreibung' => $text)); +} + // Default: Auftrags-Detail $berichte = Bericht::fetchAllForElement($db, 'order', $cmd->id); $berichte_out = array(); diff --git a/core/modules/modBericht.class.php b/core/modules/modBericht.class.php index 5ff40fb..8c1a1a8 100644 --- a/core/modules/modBericht.class.php +++ b/core/modules/modBericht.class.php @@ -27,7 +27,7 @@ class modBericht extends DolibarrModules $this->editor_name = 'Alles Watt läuft'; $this->editor_url = ''; - $this->version = '1.8.0'; + $this->version = '1.9.0'; $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); $this->picto = 'fa-file-pdf';