From 3ab13e2e23ab899beb4bcdf25a589e42419fc9b0 Mon Sep 17 00:00:00 2001 From: Eduard Wisch Date: Sat, 15 Aug 2026 16:25:59 +0200 Subject: [PATCH] Kein Stunden-Dummy mehr beim Direkt-Freigeben (1.4.0) api/orders.php?action=create gibt den Auftrag mit validate=true jetzt ohne jede Position frei. Bisher hing das Backend vorher eine Std-Lohn-Zeile mit Menge 1 an (Kundenkarten-Default, sonst Fallback-Produkt). Die Annahme, Commande::valid() scheitere an einem leeren Auftrag, ist falsch - weder valid() noch confirm_validate pruefen auf Zeilen, gesperrt ist nur die Button-Darstellung in commande/card.php (KB #355/#989, gegen Dolibarr 22.0.2 verifiziert). Die Alibi-Zeile verfaelschte total_ht, tauchte als offene Rest- menge in der Lieferauflistung auf, stand im Kunden-PDF und liess sich nach der Freigabe nicht mehr per deleteLine() entfernen. Die Leistungen kommen aus dem Stundenzettel. - Antwortfeld added_line entfaellt (die Baustelle-PWA hat es nie ausgewertet) - Konstante BERICHT_ORDER_DEFAULT_SERVICE_REF wird nicht mehr verwendet - Gleiche Umstellung in der Stunden-App (Stundenzettel 2.17.0), die mit der neuen Aktion create_order jetzt ebenfalls Auftraege anlegen kann Co-Authored-By: Claude Opus 5 (1M context) --- ChangeLog.md | 10 +++++ README.md | 7 ++-- api/orders.php | 65 ++++++------------------------- core/modules/modBericht.class.php | 2 +- 4 files changed, 25 insertions(+), 59 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 4e9226b..61e4efb 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,15 @@ # Changelog +## 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 diff --git a/README.md b/README.md index 6dd815a..e32c4eb 100644 --- a/README.md +++ b/README.md @@ -86,9 +86,9 @@ GET /custom/bericht/api/orders.php?id= GET /custom/bericht/api/orders.php?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). + ref_client ("Ihr Zeichen") ist PFLICHT. validate=true gibt den Auftrag direkt frei — + OHNE Position (Commande::valid() verlangt keine, verifiziert gegen Dolibarr 22.0.2). + Die Leistungen kommen später aus dem Stundenzettel. ``` ### Dateien @@ -145,7 +145,6 @@ Per `admin/setup.php` oder `llx_const`: | `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 diff --git a/api/orders.php b/api/orders.php index 3ff9539..c58ace2 100644 --- a/api/orders.php +++ b/api/orders.php @@ -13,11 +13,10 @@ * - ref_client ("Ihr Zeichen") ist PFLICHT (Geschäftsregel; Dolibarr selbst verlangt es nicht). * - title (Auftragsbeschreibung) optional -> Extrafield options_auftragsbeschreibung. * - date_livraison (Unix-TS) optional -> geplanter Liefertermin (Spalte date_livraison). - * - validate (bool) optional -> Auftrag direkt freigeben. Vorher wird automatisch eine - * Std-Lohn-Zeile ergänzt (Kundenkarten-Default options_stundenzettel_default_service, - * sonst Fallback-Produkt BERICHT_ORDER_DEFAULT_SERVICE_REF, Default 'ELEK-STD-M'). - * Preis = kundenspezifischer Preis (PRODUIT_CUSTOMER_PRICES) falls vorhanden, - * sonst Produkt-Standardpreis. + * - validate (bool) optional -> Auftrag direkt freigeben. Der Auftrag bleibt dabei LEER: + * Commande::valid() verlangt keine Position (verifiziert gegen Dolibarr 22.0.2, + * KB #355/#989 - nur der Button in commande/card.php ist bei 0 Zeilen gesperrt). + * Die Leistungen kommen später aus dem Stundenzettel. * Legt einen Draft-Auftrag an und übernimmt Kunden-Defaults (Zahlungsbedingungen, * Zahlart, Bankkonto, Incoterms, Lieferadresse, Default-Ansprechpartner). */ @@ -89,58 +88,17 @@ if ($action === 'create' && $_SERVER['REQUEST_METHOD'] === 'POST') { $cmd->add_contact((int) $oc->rowid, 'CUSTOMER', 'external'); } - /* ----- Optional: Std-Lohn-Zeile ergänzen und Auftrag direkt freigeben ----- */ + /* ----- Optional: Auftrag direkt freigeben ----- + * Ohne Positionen. Früher wurde hier eine Std-Lohn-Zeile mit Menge 1 angehängt, weil + * angenommen wurde, valid() scheitere am leeren Auftrag. Das stimmt nicht (KB #355/#989, + * gegen Dolibarr 22.0.2 verifiziert) und die Zeile hatte nur Nachteile: sie verfälscht + * total_ht, taucht als offene Restmenge in der Lieferauflistung auf, steht im Kunden-PDF + * und ist nach der Freigabe nicht mehr löschbar. Die Leistungen liefert der Stundenzettel. + */ $validated = false; $validate_warning = ''; - $added_line = null; if ($do_validate) { - require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; - - // 1) Leistungs-Produkt bestimmen: Kundenkarten-Default, sonst Fallback über Ref - // (Ref statt rowid, da rowids zwischen Test-/Prod-DB verschieden sind) - if (method_exists($soc, 'fetch_optionals')) $soc->fetch_optionals(); - $svc_id = (int) ($soc->array_options['options_stundenzettel_default_service'] ?? 0); - if ($svc_id <= 0) { - $fallback_ref = getDolGlobalString('BERICHT_ORDER_DEFAULT_SERVICE_REF', 'ELEK-STD-M'); - $rp = $db->query("SELECT rowid FROM ".$db->prefix()."product" - ." WHERE ref = '".$db->escape($fallback_ref)."'" - ." AND entity IN (".getEntity('product').") LIMIT 1"); - if ($rp && ($op = $db->fetch_object($rp))) $svc_id = (int) $op->rowid; - } - - if ($svc_id > 0) { - $prod = new Product($db); - if ($prod->fetch($svc_id) > 0) { - $pu_ht = (float) $prod->price; - $tva = (float) $prod->tva_tx; - - // 2) Kundenspezifischer Preis (PRODUIT_CUSTOMER_PRICES) hat Vorrang - if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES')) { - $rcp = $db->query("SELECT price, tva_tx FROM ".$db->prefix()."product_customer_price" - ." WHERE fk_product = ".((int) $svc_id)." AND fk_soc = ".((int) $socid) - ." ORDER BY rowid DESC LIMIT 1"); - if ($rcp && ($cp = $db->fetch_object($rcp))) { - $pu_ht = (float) $cp->price; - if ($cp->tva_tx !== null && $cp->tva_tx !== '') $tva = (float) $cp->tva_tx; - } - } - - // Menge 1 als Start; Monteur trägt die echten Stunden später ein - $rl = $cmd->addline($prod->label, $pu_ht, 1, $tva, 0, 0, $svc_id, 0, 0, 0, 'HT', 0, '', '', (int) $prod->type); - if ($rl > 0) { - $added_line = array( - 'product' => $prod->ref, - 'label' => $prod->label, - 'pu_ht' => $pu_ht, - 'tva_tx' => $tva, - ); - } - } - } - - // Zeilen neu laden, dann freigeben $cmd->fetch($newid); - $cmd->fetch_lines(); $vr = $cmd->valid($user); if ($vr > 0) $validated = true; else $validate_warning = 'Freigabe fehlgeschlagen: '.$cmd->error; @@ -173,7 +131,6 @@ if ($action === 'create' && $_SERVER['REQUEST_METHOD'] === 'POST') { 'phone' => $cmd->thirdparty->phone ?? '', 'email' => $cmd->thirdparty->email ?? '', ), - 'added_line' => $added_line, 'validate_warning' => $validate_warning, )); } diff --git a/core/modules/modBericht.class.php b/core/modules/modBericht.class.php index 6e86766..5588bc2 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.3.1'; + $this->version = '1.4.0'; $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); $this->picto = 'fa-file-pdf';