mahnung/CHANGELOG.md
Eduard Wisch 3e67a876c1
All checks were successful
Deploy mahnung / deploy (push) Successful in 13s
Vorschlagsliste UX: B2B/B2C-Filter wirkt direkt auf Kunden-Dropdown, Skip-Grund-Zelle harmonisiert [deploy]
Kundentyp filtert das Kunden-Dropdown:
- select_company bekommt SQL-Filter "s.tva_intra IS NOT NULL AND s.tva_intra <> ''"
  bzw. "s.tva_intra IS NULL OR s.tva_intra = ''" je nach B2B/B2C-Wahl.
- Das Kundentyp-Select hat onchange=this.form.submit, sodass das Dropdown
  ohne extra Klick auf "Suche" direkt neu geladen wird.

Skip-Grund-Zelle:
- opacitymedium-Klasse von td auf inneres span verschoben. Manche Themes
  rendern td.opacitymedium mit eigenem Border-Verhalten — das hatte zu
  sichtbarem Rahmen-Unterschied in der Uebersprungen-Tabelle gefuehrt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 12:34:57 +02:00

10 KiB
Raw Blame History

Changelog

[Unreleased]

UX-Fixes (Vorschlagsliste)

  • Kundentyp-Filter (B2B/B2C) wird jetzt direkt an select_company() durchgereicht — wenn B2C gewaehlt ist, zeigt das Kunden-Dropdown nur noch Drittparteien ohne TVA-Nummer (entsprechend umgekehrt fuer B2B).
  • Auto-Submit beim Wechsel des Kundentyps, damit das Dropdown ohne extra "Suche"-Klick aktualisiert wird.
  • Skip-Grund-Spalte in der Uebersprungen-Tabelle: opacitymedium jetzt am inneren span statt am td, damit Theme-spezifisches Zellen-Border-Verhalten konsistent bleibt.

Versand-Reminder (Cron + Ntfy)

  • Neuer Cron-Job MahnungCronVersandReminder (taeglich): sucht Mahnungen mit Status ERSTELLT deren PDF seit > N Tagen erstellt aber noch nicht versendet wurde, schickt Ntfy-Push und (falls aktiv) GlobalNotify-Badge.
  • Schwellenwert konfigurierbar via Konstante MAHNUNG_VERSAND_REMINDER_DAYS (Default 2).
  • Nachricht listet bis zu 8 Mahnungen (Ref + Stufe + Alter in Tagen + Kunde); Rest als "+N weitere".

Beleg-Scan mit Sendungsnummer-Erkennung

  • Neuer Button "Belege scannen" im Versand-Block der Mahnungs-Karte.
  • Beim Klick werden alle hochgeladenen Belege (PDF via pdftotext, sonst txt/html) durchsucht und gegen die konfigurierten Tracking-Patterns gematcht.
  • Erkannte Sendungsnummern werden als Vorschlag ueber dem Beleg-Bereich angezeigt (mit Dateiname, Provider-Label, Sendungsnummer + Deep-Link).
  • Per "Uebernehmen"-Button werden tracking_nr + tracking_provider in einem Klick gespeichert. "Verwerfen" entfernt den Vorschlag aus der Session.
  • Fallback: wenn pdftotext im Container fehlt, wird das im UI klar gemeldet — txt/html werden trotzdem durchsucht.
  • OCR (Tesseract fuer Bilder) bewusst noch nicht enthalten — kommt separat falls gewuenscht, ist Container-Aufwand.

Konfigurierbare Tracking-Patterns (Setup-Seite)

  • Neue Tabelle llx_mahnung_trackingpattern (Pro Eintrag: provider, label, regex, url_template, priority, active). Auto-Migration + Default-Seed beim Setup-Aufruf.
  • Default-Patterns: DHL Paket (20-stellig), DPAG Einschreiben (RR123456789DE), UPS (1Z…), DHL 11-stellig, Hermes 14-stellig, DPD 14-stellig — Prioritaeten so gesetzt dass spezifischere Patterns zuerst greifen.
  • Neue Setup-Seite admin/tracking_patterns.php mit CRUD: Pattern anlegen/bearbeiten/aktivieren-deaktivieren/loeschen.
  • Live-Vorschau: Beim Tippen von Regex/URL/Beispieltext wird via AJAX-Endpoint ajax/regex_preview.php direkt gezeigt ob der Regex syntaktisch gueltig ist, was er aus dem Beispieltext matcht und wie die finale Tracking-URL aussieht.
  • ReDoS-Schutz im AJAX-Endpoint: max 10 KB Sample, pcre.backtrack_limit=100k, Whitelist Delimiter / # ~.
  • Mahnung::trackingUrl() (hardcoded Fallback) bleibt — primaer wird MahnungTrackingPattern::urlFor() aus DB-Patterns benutzt.
  • Setup-Page-Link: Button "Tracking-Muster (Regex)" oben rechts auf der Modul-Setup-Seite.

Versand & Belege (Mahnungs-Karte)

  • Neue Felder date_versand, versandweg, tracking_nr, tracking_provider an llx_mahnung_mahnung — idempotente Migration laeuft beim ersten Setup-Aufruf nach dem Deploy.
  • Neuer Block "Versand & Belege" auf der Mahnungs-Karte:
    • Erfassung Versanddatum + Versandweg (Brief/Einschreiben/DHL/DPD/Hermes/UPS/Fax/Mail/Persoenlich/Eigen).
    • Optionale Sendungsnummer + Anbieter — Mahnung-Klasse liefert Deep-Link zur Sendungsverfolgung (DHL, Deutsche Post, DPD, Hermes, UPS).
    • "Sendung verfolgen"-Button oeffnet die Provider-Seite mit eingesetzter Sendungsnummer.
  • Beleg-Upload via Dolibarrs formfile->showdocuments() — Dateien landen in DOL_DATA_ROOT/mahnung/<MAHN-Ref>/, voll integriert mit ECM/document.php.
  • Status springt automatisch auf STATUS_VERSENDET sobald ein Versanddatum gesetzt wird (sofern vorher <= ERSTELLT).
  • Neue Methoden Mahnung::setVersand(), Mahnung::trackingUrl(), Mahnung::defaultProviderForWeg(), Mahnung::getVersandwegLabel().

Vorschlagsliste — UX

  • Kunden-Filter: rowid-Input ersetzt durch Dolibarr-Standard select_company() (Ajax-Suche bzw. klassisches Dropdown, je nach Dolibarr-Konfiguration). Direkt-Links ?search_socid=74 bleiben funktional.
  • Neuer Filter "Mindestbetrag" (in EUR, Komma erlaubt).
  • Neuer Filter "Kundentyp" (B2B / B2C).
  • Neue Spalte "Kontakt" mit Telefon- und Mail-Direktlink-Icons.

Fixes

  • Kundenkarte: Tab "Mahnwesen" erschien doppelt, weil complete_head_from_modules() pro Karte mehrfach (core + external + remove) feuert. Hook filtert jetzt auf mode=add + filterorigmodule=external.

[0.2.0] — 2026-05-10 — ODT-Template-System, Widget, Dokumentenmodelle

ODT-Template-System

  • Abstrakte Basis-Klasse ModelePDFMahnung extends CommonDocGenerator (core/modules/mahnung/modules_mahnung.php)
  • ODT-Generator doc_generic_mahnung_odt mit Stufen-spezifischer Template-Auswahl (mahnung_stufe1/2/3.odt, Fallback mahnung.odt)
  • TCPDF-Generator pdf_standard_mahnung (refactored aus mahnungpdf.class.php)
  • mahnung.class.php: generateDocument() Methode via commonGenerateDocument()
  • Template-Variablen: Mahnung, Rechnung, Kunde, Bankverbindung, Dolibarr-Standard
  • ODT-Template-Upload auf Setup-Seite mit Benennungskonvention-Hinweis

Widget

  • box_mahnung_offen: Offene Kundenrechnungen mit Mahnstufe-Badge (basiert auf box_factures_imp)
  • Alle offenen Rechnungen (nicht nur überfällige), Status-Icon wie Original
  • Farbige Mahnstufe-Badges (blau/orange/rot) mit Link zur Mahnung-Detailseite
  • Strich (—) bei Rechnungen ohne Mahnung

Dokumentenliste auf card.php

  • Generierte Dokumente zur Mahnung auflisten (aus Rechnungsordner)
  • PDF-Vorschau (Lupe), Download-Button
  • Modellauswahl-Dropdown bei mehreren aktiven Dokumentenmodellen

Setup-Erweiterungen

  • Dokumentenmodell-Verwaltung (aktivieren/deaktivieren, Default setzen)
  • admin/templatevars.php: Referenzseite aller verfügbaren ODT-Template-Variablen
  • Link von Setup zur Variablen-Referenz

Modul-Descriptor

  • module_parts['models'] = 1
  • Neue Konstanten: MAHNUNG_ADDON_PDF, MAHNUNG_ADDON_PDF_ODT_PATH
  • Document-Model-Registrierung in init() (standard_mahnung + generic_mahnung_odt)
  • Widget box_mahnung_offen@mahnung registriert
  • Picto korrigiert: fa-envelope-open-text (FA5-Free)

Bugfixes

  • numero 500037 → 500038 (Kollision mit Eplan behoben)
  • verifCsrf() entfernt (existiert nicht in Dolibarr, CSRF via newToken())
  • f.statutf.fk_statut (Dolibarr 22.x Spaltenname)
  • actions_setmoduleoptions.inc.php vor llxHeader() verschoben (ODT-Upload)
  • Widget: require_once mahnung.class.php an Dateianfang (Fatal Error bei Klassen-Konstanten in SQL)

Entfernt

  • class/mahnungpdf.class.php — Logik in core/modules/mahnung/doc/pdf_standard_mahnung.modules.php

[0.1.0] — 2026-05-07 — Erstveröffentlichung (Phase 110)

DB-Schema (Phase 1)

  • llx_mahnung_mahnung — Mahnvorgänge mit Stufe, Beträgen, Zinsen, Status, Snapshot des Basiszinses für Reproduzierbarkeit
  • llx_mahnung_stufe — pro Stufe konfigurierbar: Frist, neue Frist, Gebühren B2C/B2B, optional Zinssatz-Override, Versandart, E-Mail-/PDF-Templates
  • 3 Default-Stufen werden bei Aktivierung idempotent eingefügt

Modul-Descriptor (Phase 1)

  • numero 500038, family financial, FA-Picto fa-envelope-open-text
  • Modul-Konstanten: MAHNUNG_BASISZINS, MAHNUNG_AUFSCHLAG_B2C, MAHNUNG_AUFSCHLAG_B2B, MAHNUNG_PAUSCHALE_B2B, MAHNUNG_NTFY_TOPIC
  • Rechte: read, write, send, delete, setup
  • Cron-Job MahnungCronBuildVorschlag (täglich, default deaktiviert)
  • Linkes Menü unter „Rechnungen" (mainmenu=billing) mit Vorschlagsliste / Archiv

CRUD + Setup (Phase 2)

  • class/mahnung.class.php — CRUD, Status-Konstanten, Verzugszinsen-Berechnung nach BGB §288
  • class/mahnungstufe.class.php — Stufen-Konfiguration, Override-Helfer für Zinsen/Gebühren
  • admin/setup.php — Stufen-Tabelle vollständig pflegbar, Konstanten persistent

Vorschlagsliste + Cron (Phase 3)

  • class/mahnungvorschlag.class.php — gemeinsamer Service: ermittelt pro überfälliger Rechnung die nächste vorgeschlagene Stufe, B2C/B2B-Erkennung via tva_intra, offener Betrag aus paiement_facture
  • class/mahnungcron.class.php — Cron sammelt Vorschläge, sendet Ntfy-Push (Topic aus Setup), schreibt zusätzlich GlobalNotify-Action wenn aktiv
  • class/mahnungntfy.class.php — schmaler Ntfy-Push-Wrapper
  • list.php — Vorschlagsliste-UI mit Multi-Select, Filter nach Stufe / Verzugstagen / Kunde, Buttons „Mahnungen erzeugen" und „Sammelbrief"

PDF-Generator + Erstellen (Phase 4)

  • TCPDF-basierter Generator (DIN-5008 Form A): Adressfenster, Bezugszeichenzeile, Tabelle, Gebührenblock, Verzugszinsen mit Snapshot-Zinssatz, neue Frist, Bankverbindungs-Footer
  • PDFs landen in documents/facture/{ref}/ und erscheinen automatisch im Dokumente-Tab der Rechnung
  • ajax/createmahnung.php — Bulk-Endpoint mit CSRF + Permission-Check, erzeugt Mahnung + PDF, behandelt §288 Abs. 5 Pauschale einmalig pro Rechnung

Hooks + Trigger (Phase 5)

  • core/triggers/interface_99_modMahnung_MahnungTriggers.class.phpBILL_PAYED und PAYMENT_CUSTOMER_CREATE setzen offene Mahnungen auf erledigt
  • class/actions_mahnung.class.php — Hook auf Rechnungs- und Kundenkarte: Tab „Mahnungen (n)" mit Badge, Button „Mahnung erstellen" wenn überfällig
  • card.php — Detailansicht eines Mahnvorgangs mit Storno-Aktion (formconfirm-Modal)

E-Mail + Sammelbrief (Phase 6)

  • ajax/sendmail.php — sendet Mahnung-PDF via CMailFile an die Kunden-Mail; Subject/Body mit Platzhaltern aus Stufen-Konfig
  • ajax/sammelbrief.php — erzeugt Mahnungen für Auswahl, konkateniert ihre PDFs via TCPDI in eine Datei, liefert Download

Integrationen (Phase 7 + 8)

  • GlobalNotify: Cron sendet zusätzlich actionRequired-Notification ins Dolibarr-UI (wenn Modul aktiv)
  • Tab „Mahnungen" auf Kundenkarte (thirdpartycard) zusätzlich zur Rechnungskarte

Pipeline (Phase 10)

  • .forgejo/workflows/deploy.yml — Deploy auf /mnt/appdata/firma/dolibarr-202509/modules/mahnung bei Push auf main mit [deploy] oder Tag v*, Ntfy-Notify auf Topic vk-builds