All checks were successful
Deploy mahnung / deploy (push) Successful in 12s
Wenn alle Rechnungen bezahlt sind, blieb info_box_contents leer und ModeleBoxes::showBox renderte keinen Widget-Rahmen mehr. Widget kam auch nach neuen Rechnungen nicht zurück. Fix: bei 0 Treffern eine Platzhalter-Zeile "Keine offenen Kundenrechnungen" einfügen. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4.4 KiB
4.4 KiB
CLAUDE.md — Mahnung-Modul
Projekt
Dolibarr Custom-Modul: 3-stufiges Mahnwesen nach BGB §288 + Versand-Tracking + Forderungsausfall-Workflow.
Technisches
- numero: 500038 (NICHT ändern — 500037 ist Eplan)
- Deploy: nur via Pipeline (
[deploy]in Commit-Message), NIEMALS manuell kopieren - Prod-Pfad: /mnt/appdata/firma/dolibarr-202509/modules/mahnung/
- Lokal: Symlink /var/www/dolibarr/custom/mahnung → repo/
- Test-DB: dolibarr_test auf 192.168.155.11
- Forgejo-Repo: data/mahnung (NICHT data-it/ — historisch, soll bleiben)
Schema-Migration
modMahnung::migrateVersandFelder()läuft automatisch beim Setup-Page-Aufruf- Idempotent via
SHOW COLUMNS LIKE→ fehlende Spalten viaALTER TABLE ADD COLUMN - Default-Tracking-Patterns werden via
MahnungTrackingPattern::seedDefaults()geseedet (Check:COUNT(*) > 0→ skip) - Nach Deploy: User muss Setup-Page einmal aufrufen, sonst fehlen die neuen Spalten
Dokumentenmodell-System
commonGenerateDocument()fügt automatischdoc_/pdf_Prefix hinzu- DB-Einträge in
llx_document_model.nomOHNE Prefix speichern actions_setmoduleoptions.inc.phpMUSS vorllxHeader()stehen (Upload)- ODT-Templates: mahnung_stufe1.odt, mahnung_stufe2.odt, mahnung_stufe3.odt, mahnung.odt (Fallback)
Widget
box_mahnung_offenbasiert 1:1 aufbox_factures_imp.php(Standard-Widget)- Zeigt ALLE offenen Rechnungen, nicht nur überfällige
- Mahnstufe-Badge nur wenn Mahnung existiert, sonst Strich
Hooks-Stolperfallen
completeTabsHeadwird bei jedem Aufruf voncomplete_head_from_modules()getriggert — pro Karte mehrfach (core + external + remove). Filter aufmode=add+filterorigmodule=external, sonst doppelter Tab. (KB #601)- Hook-Kontexte:
invoicecard,thirdpartycard,ordercard— letztere für Bonitäts-Warnings.
Filter-Syntax-Stolperfallen
$form->select_company($selected, $htmlname, $filter, ...): der$filter-Parameter erwartet USC-Syntax(feld:operator:wert), NICHT plain SQL. Beispiel B2C:(s.tva_intra:is:NULL) OR (s.tva_intra:=:''). Sonst SQL-Syntax-Error + 500. (KB #602)search_socid=-1wird vonselect_companyals "nichts ausgewählt" geliefert → im Filter-Check> 0statt!empty()nutzen.
Pipeline-Stolperfallen
${{ github.event.head_commit.message }}NIE direkt inrun:-Skript interpolieren — bei Sonderzeichen (Klammern, Backticks) bricht Bash. Immer viaenv:durchreichen. (KB #603)[deploy]-Tag im Commit nötig, sonst kein Auto-Deploy.
Verzugszinsen-Override
zinssatz_b2c_uebersteuern/zinssatz_b2b_uebersteuerninllx_mahnung_stufe: NULL = Standard (Basiszins + Aufschlag), 0 = keine Zinsen, Wert = fester Prozentsatz- Nicht-versandte Mahnungen (Status ≤ ERSTELLT) werden beim card.php-Aufruf automatisch neu berechnet
- Setup-Seite zeigt Placeholder mit Standard-Zinssatz + Hilfetext
Versand & Bonität (Phase 6)
- Versand-Felder:
date_versand,versandweg,tracking_nr,tracking_provideranllx_mahnung_mahnung - Tracking-URLs aus DB (
llx_mahnung_trackingpattern) viaMahnungTrackingPattern::urlFor(), Fallback:Mahnung::trackingUrl()(hardcoded) - Beleg-Upload:
formfile->showdocuments('mahnung', $ref, $filedir, ...)—$conf->mahnung->dir_outputwird von Dolibarr automatisch gesetzt (KB #605), kein Custom-Setup nötig - Beleg-Scan:
pdftotext+ocrmypdf(OCR-Fallback für Bild-PDFs) im90-Dolibarr-Prod-Custom-Container; Pattern-Match viaMahnungTrackingPattern::detectFromText() pdftotextgibt\x0C(Form-Feed) bei Bild-PDFs zurück —trim()mit expliziter Zeichenliste" \t\n\r\0\x0B\x0C"nötig- "Übernehmen" setzt
tracking_nr+tracking_provider+date_versand+versandwegautomatisch (kein extra Speichern) - Uneinbringlich-Klassifikation:
Facture::setCanceled($user, CommonInvoice::CLOSECODE_BADDEBT, $note)→ setztfk_statut=3+close_code='badcustomer'(KB #606) - Steuer-Modul kompatibel: EÜR ignoriert (liest nur
llx_paiement), UStVA filtertfk_statut IN (1,2)automatisch (KB #607)
Dolibarr-Versionshinweise
f.fk_statutstattf.statut(seit Dolibarr 22.x)verifCsrf()existiert nicht — CSRF vianewToken()+ GETPOST('token')dol_mkdir()gibt 0 zurück wenn Verzeichnis bereits existiert (nicht false)dol_dir_list()gibtfullnamezurück (nichtfullpath)$form->formconfirm()unterstützt textarea-Feld via$formquestion-Array (KB #609)