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>
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>
Umlaute in allen lang-Dateien korrigiert. Alle hardcodierten deutschen Strings
in 22 PHP-Dateien durch $langs->trans('Key') ersetzt. Neue Schlüssel für
Cron-Meldungen, Dokument-Aktionen, Bonität, Vorschlag-Status, Template-Vars u.a.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bonitaets-Anzeige:
- Hook tabContentViewThirdparty rendert prominente rote Warnbox auf der
Kundenkarte wenn fk_statut=3 + close_code=badcustomer existiert. Zeigt
Anzahl, Gesamtsumme, Datum letzter Abschreibung + Link zur Detail-Liste.
- Hook formObjectOptions zeigt kompakte Warn-Zeile auf ordercard und
invoicecard wenn der Kunde Forderungsausfaelle hat.
- ordercard zum module_parts.hooks.data ergaenzt.
Uneinbringlich-Button:
- Auf Mahnung-Karten der Stufe 3, Status >= ERSTELLT, nicht storniert,
Rechnung noch nicht abandoned.
- Bestaetigungs-Dialog mit Begruendungs-Textfeld (Default-Text setzt
das aktuelle Datum ein).
- Ruft Facture::setCanceled mit CommonInvoice::CLOSECODE_BADDEBT.
- Mahnung wird storniert + Begruendung in note_private festgehalten.
Steuer-Modul kompatibel: EÜR liest nur llx_paiement (keine Zahlung =
keine Einnahme), UStVA filtert fk_statut IN (1,2) — abandoned Rechnungen
werden automatisch korrekt ausgeschlossen. Bei Ist-Versteuerung damit
buchhalterisch sauber, kein manueller Eingriff noetig.
Lang-Keys: 16 neu (de_DE + en_US) fuer Bonitaets-Box + Uneinbringlich-Workflow.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Neuer Cron-Job MahnungCronVersandReminder (taeglich):
- Sucht in llx_mahnung_mahnung Status=ERSTELLT (1) + date_versand IS NULL
+ datec < NOW() - INTERVAL N DAY.
- N steht in der Konstante MAHNUNG_VERSAND_REMINDER_DAYS (Default 2).
- Bei Treffern: Ntfy-Push (Topic MAHNUNG_NTFY_TOPIC) mit Titel + Liste
der bis zu 8 Mahnungen ("MAHN2026-0042 (Stufe 2, 3 Tage alt) — Kunde").
- Optional GlobalNotify-Badge "mahnung_versand" wenn GlobalNotify aktiv.
Modul-Descriptor:
- Cronjobs-Array um Reminder ergaenzt (frequency 1d, priority 55, status 1).
Lang-Keys: 2x (de_DE + en_US) fuer Cron-Label + Description.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Rechnungen ohne Mahnung: "—" als Zeichen
- Rechnungen mit Mahnung: farbiger Badge verlinkt auf card.php der Mahnung
- Mahnung-ID per Subquery geholt
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Widget basiert jetzt 1:1 auf box_factures_imp.php:
- Alle offenen Rechnungen (nicht nur ueberfaellige)
- Status-Icon wie Original (LibStatut)
- Summenzeile ueber alle offenen (separate Query)
- Link zur Rechnungsliste im Header
Plus: Extra-Spalte Mahnstufe mit farbigem Badge (wenn vorhanden)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- box_mahnung_offen.php: require_once mahnung.class.php nach oben verschoben,
da Mahnung::STATUS_STORNIERT in der SQL-Query vor dem bisherigen Include benutzt wurde
- setup.php: actions_setmoduleoptions.inc.php vor llxHeader() verschoben
(sonst scheitert der ODT-Upload wegen "headers already sent"), Duplikat entfernt
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>