|
All checks were successful
Deploy mahnung / deploy (push) Successful in 13s
Wenn pdftotext keinen Text findet, wird ocrmypdf (Tesseract OCR) auf das PDF angewendet bevor erneut nach Sendungsnummern gesucht wird. Bei leerem Ergebnis erscheint jetzt eine Hinweismeldung statt stummem Seiten-Reload. Co-Authored-By: Claude Opus 4.6 (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