|
All checks were successful
Deploy mahnung / deploy (push) Successful in 14s
tms war als reines TIMESTAMP angelegt -> unter explicit_defaults_for_timestamp NULL DEFAULT NULL, blieb daher bei jedem UPDATE leer. Jetzt Dolibarr-Standard DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP fuer mahnung/stufe/ trackingpattern. Neue idempotente Migration migrateTimestampSpalten() im init() befuellt Alt-NULLs aus datec und stellt die Spalte per ALTER TABLE um. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .forgejo/workflows | ||
| admin | ||
| ajax | ||
| class | ||
| core | ||
| langs | ||
| sql | ||
| card.php | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| list.php | ||
| README.md | ||
Modul Mahnung — 3-stufiges Mahnwesen für Dolibarr
Mahnwesen-Modul für Dolibarr ERP: tägliche Vorschlagsliste überfälliger Rechnungen, 3-stufiger Workflow (Erinnerung → Mahnung → Letzte Mahnung), Mahngebühren + tagesgenaue Verzugszinsen nach BGB §288, PDF- und ODT-Mahnschreiben, E-Mail-Versand, Sammelbrief, Trigger auf Zahlungseingang.
Status
Version 0.2.0 + Phasen 1-6 (Unreleased) — UX-Vorschlagsliste, Versand-Erfassung, Sendebeleg-Upload, konfigurierbare Tracking-Patterns mit Live-Vorschau, Beleg-Scan via pdftotext, Versand-Reminder, Bonitäts-Workflow + Uneinbringlich-Klassifikation.
Features
| Feature | Implementierung |
|---|---|
| Tägliche Vorschlagsliste überfälliger Rechnungen | Cron MahnungCronBuildVorschlag |
| Push-Benachrichtigung mit Anzahl je Stufe | Ntfy + GlobalNotify |
| 3 Stufen pflegbar (Frist, neue Frist, Gebühr B2C/B2B, Versandart, E-Mail-Template, PDF-Intro) | admin/setup.php |
| B2C / B2B-Erkennung | über llx_societe.tva_intra |
| Verzugszinsen | tagesgenau, B2C: Basiszins +5 %, B2B: +9 %; Override pro Stufe möglich |
| §288 Abs. 5 Pauschale 40 € | nur bei B2B, einmalig pro Rechnung |
| PDF-Mahnschreiben (DIN 5008) | Standard-TCPDF-Generator pdf_standard_mahnung |
| ODT-Mahnschreiben (je Stufe) | ODT-Template-Generator doc_generic_mahnung_odt mit Stufen-Auswahl |
| Dokumentenmodell-Verwaltung | Setup-Seite: Modelle aktivieren, Default wählen, ODT-Templates hochladen |
| Template-Variablen-Referenz | admin/templatevars.php — alle verfügbaren ODT-Variablen |
| Dokumentenliste auf Mahnungs-Karte | Vorschau (Lupe), Download, Modellauswahl |
| Bulk-Erstellung + Sammelbrief | TCPDI-basiert |
| E-Mail-Versand mit PDF-Anhang | CMailFile, Subject/Body mit Platzhaltern |
| Auto-Erledigung bei Zahlungseingang | Trigger BILL_PAYED + PAYMENT_CUSTOMER_CREATE |
| Tab "Mahnungen (n)" auf Rechnungs- + Kundenkarte | Hook completeTabsHead (filtert auf add/external) |
| Widget: Offene Rechnungen mit Mahnstufe | box_mahnung_offen |
| Vorschlagsliste-Filter (Mahnstufe, Tage Verzug, Mindestbetrag, Kundentyp B2B/B2C, Kunden-Select2 mit Ajax) | list.php — Kundentyp-Wechsel filtert das Kunden-Dropdown sofort per Auto-Submit |
| Kontakt-Spalte in Vorschlagsliste (Telefon-/Mail-Icons mit Direktlink) | tel:/mailto: aus llx_societe.phone/email |
| Versand-Erfassung pro Mahnung (Datum, Versandweg, Sendungsnummer, Tracking-Provider) | card.php Versand-Block; setzt automatisch Status auf VERSENDET |
| Tracking-Deep-Links für DHL, DPAG, DPD, Hermes, UPS | konfigurierbar via Tracking-Pattern-Tabelle |
| Sendebeleg-Upload pro Mahnung | Dolibarrs formfile->showdocuments('mahnung', ...) → DOL_DATA_ROOT/mahnung/<MAHN-Ref>/ |
| Konfigurierbare Tracking-Patterns (Regex + URL-Template, Priorität, Aktivierung) | admin/tracking_patterns.php CRUD + Live-Vorschau |
| Live-Regex-Vorschau (Treffer + URL-Preview während Eingabe) | ajax/regex_preview.php (debounced 300ms, ReDoS-Schutz) |
| Beleg-Scan (pdftotext + Pattern-Matching → Sendungsnummer-Vorschlag) | Button "Belege scannen" auf card.php |
| Versand-Reminder (Mahnung > N Tage unversendet → Ntfy-Push) | Cron MahnungCronVersandReminder, Schwellenwert via MAHNUNG_VERSAND_REMINDER_DAYS |
Bonitäts-Box auf Kundenkarte (Anzahl + Summe + letztes Datum der badcustomer abandoned Rechnungen) |
Hook tabContentViewThirdparty |
| Bonitäts-Warning bei Auftrag-/Rechnungs-Karte | Hook formObjectOptions (invoicecard + ordercard) |
| "Als uneinbringlich klassifizieren"-Button auf Mahnung Stufe 3 | Bestätigungs-Dialog mit Begründung → Facture::setCanceled($user, CommonInvoice::CLOSECODE_BADDEBT, $note) |
Voraussetzungen
- Dolibarr ≥ 19
- PHP ≥ 7.4
- TCPDF (Dolibarr-Standard) für PDF
- Optional: ODTPHP (Dolibarr-Standard) für ODT-Templates
- Optional: TCPDI (Dolibarr
includes/tcpdf/tcpdi.php) für Sammelbrief-Konkatenation - Optional:
GlobalNotifyfür In-App-Notification-Badges - Empfohlen:
BankImport(automatischer Zahlungseingang via FinTS triggert die Mahnungs-Erledigung sauber)
Installation
git clone https://git.data-it-solution.de/data/mahnung.git \
/pfad/zu/dolibarr/htdocs/custom/mahnung
Dann Startseite → Setup → Module → Finanzwesen → Mahnung aktivieren.
Bei Aktivierung werden llx_mahnung_mahnung und llx_mahnung_stufe angelegt; drei Default-Stufen werden idempotent eingefügt. Dokumentenmodelle (standard_mahnung, generic_mahnung_odt) werden in llx_document_model registriert.
Nach Aktivierung in Setup → Mahnwesen Einstellungen:
- Basiszins prüfen
- Stufen-Texte (PDF-Intro, E-Mail-Body) anpassen
- Dokumentenmodell wählen und ggf. ODT-Templates hochladen
- Cron-Job
MahnungCronBuildVorschlagaktivieren
ODT-Templates
Templates werden unter Setup → Mahnwesen Einstellungen → Dokumentenmodelle hochgeladen.
Dateinamen-Konvention
| Dateiname | Verwendung |
|---|---|
mahnung_stufe1.odt |
Zahlungserinnerung (Stufe 1) |
mahnung_stufe2.odt |
1. Mahnung (Stufe 2) |
mahnung_stufe3.odt |
Letzte Mahnung (Stufe 3) |
mahnung.odt |
Fallback für alle Stufen |
Verfügbare Template-Variablen (Auswahl)
| Variable | Beispiel |
|---|---|
{mahnung_ref} |
MAHN2026-0001 |
{mahnung_stufe} |
1 |
{mahnung_stufe_label} |
Zahlungserinnerung |
{mahnung_date} |
10.05.2026 |
{mahnung_betrag_offen} |
131,34 |
{mahnung_mahngebuehr} |
5,00 |
{mahnung_verzugszinsen} |
1,23 |
{mahnung_summe} |
137,57 |
{mahnung_kundentyp} |
B2C |
{facture_ref} |
IN2604-0036 |
{facture_total_ttc} |
131,34 |
{company_name} |
Kundenname |
{mycompany_name} |
Eigene Firma |
{mahnung_bank_iban} |
DE89... |
Vollständige Liste: Setup → Mahnwesen → Verfügbare Template-Variablen
Rechte
| Recht | Standard | Bedeutung |
|---|---|---|
mahnung.read |
aktiv | Mahnungen einsehen |
mahnung.write |
inaktiv | Mahnungen erstellen / bearbeiten |
mahnung.send |
inaktiv | Mahnungen versenden (E-Mail / Druck) |
mahnung.delete |
inaktiv | Mahnungen stornieren |
mahnung.setup |
inaktiv | Stufen, Basiszins, Versand konfigurieren |
Modul-Konstanten
| Name | Default | Bedeutung |
|---|---|---|
MAHNUNG_BASISZINS |
1.27 |
BGB-Basiszins (%) — halbjährlich pflegen (1.1./1.7.) |
MAHNUNG_AUFSCHLAG_B2C |
5.0 |
Verzugszins-Aufschlag B2C (BGB §288 Abs. 1) |
MAHNUNG_AUFSCHLAG_B2B |
9.0 |
Verzugszins-Aufschlag B2B (BGB §288 Abs. 2) |
MAHNUNG_PAUSCHALE_B2B |
40.00 |
Pauschale B2B (EUR, BGB §288 Abs. 5, einmalig) |
MAHNUNG_ADDON_PDF |
standard_mahnung |
Standard-Dokumentenmodell |
MAHNUNG_ADDON_PDF_ODT_PATH |
DOL_DATA_ROOT/doctemplates/mahnung |
ODT-Template-Verzeichnis |
MAHNUNG_NTFY_TOPIC |
vk-builds |
Ntfy-Topic für Vorschlags-Push |
MAHNUNG_VERSAND_REMINDER_DAYS |
2 |
Schwelle (Tage) für Versand-Reminder Ntfy-Push |
Datenbank
| Tabelle | Zweck |
|---|---|
llx_mahnung_mahnung |
Mahnvorgänge — inkl. Versand-Felder date_versand, versandweg, tracking_nr, tracking_provider (idempotente Migration via migrateVersandFelder() beim Setup-Aufruf) |
llx_mahnung_stufe |
Stufen-Konfiguration (Stufe 1/2/3 mit Fristen, Gebühren, Templates) |
llx_mahnung_trackingpattern |
Konfigurierbare Tracking-Regex + URL-Template pro Provider, Default-Seed mit DHL/DPAG/DPD/Hermes/UPS |
AJAX-Endpoints
| Endpoint | Zweck | Parameter | Auth |
|---|---|---|---|
ajax/createmahnung.php |
Bulk-Mahnung-Erzeugung | facture_ids[], stufe, token |
mahnung.write |
ajax/sammelbrief.php |
Sammelbrief-PDF | facture_ids[], token |
mahnung.send |
ajax/sendmail.php |
E-Mail-Versand | mahnung_id, token |
mahnung.send |
ajax/regex_preview.php |
Live-Vorschau für Tracking-Patterns | regex, sample, url_template (POST) |
mahnung.setup oder Admin |
Hooks & Trigger
Hook-Klasse: class/actions_mahnung.class.php — registriert für invoicecard, thirdpartycard, ordercard.
| Hook | Zweck |
|---|---|
addMoreActionsButtons |
"Mahnung erstellen"-Button auf Rechnungs-Karte |
completeTabsHead |
Tab "Mahnungen (n)" — filtert auf mode=add + filterorigmodule=external (sonst doppelter Tab, siehe KB #601) |
tabContentViewThirdparty |
Bonitäts-Warnbox auf Kundenkarte wenn badcustomer abandoned Rechnungen existieren |
formObjectOptions |
Bonitäts-Warning bei Auftrag-/Rechnungs-Karten |
Trigger: core/triggers/interface_99_modMahnung_MahnungTriggers.class.php
BILL_PAYED+BILL_VALIDATE+PAYMENT_CUSTOMER_CREATE→ setzt offene Mahnungen aufSTATUS_ERLEDIGT
Cron-Jobs:
MahnungCronBuildVorschlag— täglich, Vorschlagsliste aufbauen + Ntfy-PushMahnungCronVersandReminder— täglich, Reminder für unversendete Mahnungen
Workflow
Cron 06:00 (MahnungCronBuildVorschlag)
|
|--> ueberfaellige Rechnungen einsammeln
|--> Stufe ermitteln (Stufe 1 ab frist_tage Verzug,
| Folgestufen nach neue_frist_tage seit Vor-Mahnung)
|--> Ntfy-Push mit Anzahl je Stufe + Gesamt-EUR
|--> GlobalNotify "actionRequired" (wenn Modul aktiv)
|
v
list.php (Vorschlagsliste)
| Filter: Mahnstufe, min. Verzug, min. Betrag, Kundentyp (B2B/B2C), Kunde (Select2)
| Spalten: Rechnung, Kunde, Kontakt (tel/mail), Typ, Faelligkeit, Verzug,
| Betrag, letzte Mahnung, vorgeschlagene Stufe
|
|--> User waehlt aus + klickt "Mahnungen erzeugen"
| -> ajax/createmahnung.php berechnet Gebuehr + Verzugszinsen,
| persistiert llx_mahnung_mahnung, generiert PDF/ODT
|
|--> Alternativ "Sammelbrief erzeugen"
| -> ajax/sammelbrief.php generiert + konkateniert PDFs
|
v
card.php (Mahnung-Detailansicht)
| Documents: generierte PDFs + Modellauswahl + Regenerate
| Versand: Datum, Versandweg, Sendungsnummer, Tracking-Provider -> Deep-Link
| Sendebelege: Upload (formfile->showdocuments), Scan-Button
| Aktionen: Stornieren | Als uneinbringlich klassifizieren (nur Stufe 3)
|
Cron 06:00 (MahnungCronVersandReminder)
|--> Mahnungen mit Status=ERSTELLT > N Tage unversendet -> Ntfy-Push
|
Zahlungseingang (BankImport / Manual)
|
v Trigger BILL_PAYED / PAYMENT_CUSTOMER_CREATE
|--> alle offenen Mahnvorgaenge zur Rechnung -> status=erledigt
|
Endgueltig uneinbringlich (Mahnbescheid + Vollstreckung erfolglos)
|
v Stufe-3-Mahnung -> Button "Als uneinbringlich klassifizieren"
|--> Facture::setCanceled($user, CLOSECODE_BADDEBT, $note)
| -> fk_statut=3 (ABANDONED), close_code='badcustomer'
| -> Mahnung wird storniert, Begruendung in note_private
|--> Auf Kundenkarte erscheint rote Bonitaets-Warnbox
|--> Beim Anlegen neuer Auftraege/Rechnungen: Warning-Banner
|
Steuerlich (Steuer-Modul):
|--> EÜR ignoriert (liest llx_paiement, keine Zahlung = keine Einnahme)
|--> UStVA filtert fk_statut IN (1,2) -> abandoned automatisch ausgeschlossen
Dateibaum
mahnung/
├── core/modules/modMahnung.class.php Descriptor, Rechte, Cron, Hooks, Models
│ (migrateVersandFelder + Pattern-Seed)
├── core/modules/mahnung/
│ ├── modules_mahnung.php Abstrakte Basis ModelePDFMahnung
│ └── doc/
│ ├── pdf_standard_mahnung.modules.php TCPDF-Generator (DIN 5008)
│ └── doc_generic_mahnung_odt.modules.php ODT-Template-Generator
├── core/triggers/interface_99_modMahnung_MahnungTriggers.class.php
├── core/boxes/box_mahnung_offen.php Widget: Offene Rechnungen + Mahnstufe
├── class/mahnung.class.php CRUD Mahnvorgang + generateDocument()
│ + setVersand + trackingUrl + defaultProviderForWeg
├── class/mahnungstufe.class.php CRUD Stufen-Konfig
├── class/mahnungvorschlag.class.php Vorschlags-Service (Stufenermittlung,
│ kundentyp/min_betrag-Filter, soc_phone/email)
├── class/mahnungtrackingpattern.class.php CRUD Tracking-Patterns + detectFromText
├── class/mahnungcron.class.php buildVorschlagsliste + versandReminder
├── class/mahnungntfy.class.php Ntfy-Wrapper
├── class/actions_mahnung.class.php Hook-Klasse:
│ - addMoreActionsButtons (invoicecard)
│ - completeTabsHead (invoice+thirdparty)
│ - tabContentViewThirdparty (Bonitaets-Box)
│ - formObjectOptions (invoice+ordercard Warning)
├── admin/setup.php Setup + Dokumentenmodell + Auto-Migration
├── admin/templatevars.php Template-Variablen-Referenz
├── admin/tracking_patterns.php CRUD + Live-Vorschau fuer Tracking-Patterns
├── ajax/createmahnung.php Bulk-Mahnung-Erzeugung
├── ajax/sammelbrief.php Sammelbrief-PDF-Konkatenation
├── ajax/sendmail.php E-Mail-Versand
├── ajax/regex_preview.php Live-Vorschau-Endpoint fuer Pattern-Setup
├── list.php Vorschlagsliste / Archiv (Select2-Filter)
├── card.php Detailansicht: Versand, Belege, Tracking,
│ Uneinbringlich-Workflow
├── sql/llx_mahnung_*.sql Schema + Seed
└── langs/{de_DE,en_US}/mahnung.lang
Lizenz
GPL-3.0