diff --git a/CLAUDE.md b/CLAUDE.md index daff55e..cca4fef 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -40,11 +40,18 @@ Dolibarr Custom-Modul: 3-stufiges Mahnwesen nach BGB §288 + Versand-Tracking + - **`${{ github.event.head_commit.message }}` NIE direkt in `run:`-Skript interpolieren** — bei Sonderzeichen (Klammern, Backticks) bricht Bash. Immer via `env:` durchreichen. (KB #603) - `[deploy]`-Tag im Commit nötig, sonst kein Auto-Deploy. +## Verzugszinsen-Override +- `zinssatz_b2c_uebersteuern` / `zinssatz_b2b_uebersteuern` in `llx_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_provider` an `llx_mahnung_mahnung` - Tracking-URLs aus DB (`llx_mahnung_trackingpattern`) via `MahnungTrackingPattern::urlFor()`, Fallback: `Mahnung::trackingUrl()` (hardcoded) - Beleg-Upload: `formfile->showdocuments('mahnung', $ref, $filedir, ...)` — `$conf->mahnung->dir_output` wird von Dolibarr automatisch gesetzt (KB #605), kein Custom-Setup nötig -- Beleg-Scan: `pdftotext` ist im `90-Dolibarr-Prod-Custom`-Container drin (`/usr/bin/pdftotext`); Pattern-Match via `MahnungTrackingPattern::detectFromText()` +- Beleg-Scan: `pdftotext` + `ocrmypdf` (OCR-Fallback für Bild-PDFs) im `90-Dolibarr-Prod-Custom`-Container; Pattern-Match via `MahnungTrackingPattern::detectFromText()` +- `pdftotext` gibt `\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` + `versandweg` automatisch (kein extra Speichern) - Uneinbringlich-Klassifikation: `Facture::setCanceled($user, CommonInvoice::CLOSECODE_BADDEBT, $note)` → setzt `fk_statut=3` + `close_code='badcustomer'` (KB #606) - Steuer-Modul kompatibel: EÜR ignoriert (liest nur `llx_paiement`), UStVA filtert `fk_statut IN (1,2)` automatisch (KB #607) diff --git a/README.md b/README.md index 522533f..763966b 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Version **0.2.0 + Phasen 1-6 (Unreleased)** — UX-Vorschlagsliste, Versand-Erfa | 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 | +| Verzugszinsen | tagesgenau, B2C: Basiszins +5 %, B2B: +9 %; Override pro Stufe möglich; **auto-Neuberechnung** bei noch nicht versandten Mahnungen | | §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 | @@ -33,7 +33,7 @@ Version **0.2.0 + Phasen 1-6 (Unreleased)** — UX-Vorschlagsliste, Versand-Erfa | **Sendebeleg-Upload** pro Mahnung | Dolibarrs `formfile->showdocuments('mahnung', ...)` → `DOL_DATA_ROOT/mahnung//` | | **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` | +| **Beleg-Scan** (pdftotext + ocrmypdf-Fallback + Pattern-Matching → Sendungsnummer-Vorschlag) | Button "Belege scannen" auf `card.php`; "Übernehmen" setzt automatisch Tracking + Versanddatum + Versandweg | | **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) | @@ -46,6 +46,7 @@ Version **0.2.0 + Phasen 1-6 (Unreleased)** — UX-Vorschlagsliste, Versand-Erfa - 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: `pdftotext` + `ocrmypdf` + `tesseract` im Container für OCR-Beleg-Scan - Optional: `GlobalNotify` für In-App-Notification-Badges - Empfohlen: `BankImport` (automatischer Zahlungseingang via FinTS triggert die Mahnungs-Erledigung sauber) diff --git a/core/boxes/box_mahnung_offen.php b/core/boxes/box_mahnung_offen.php index 1ec85d4..595b98d 100644 --- a/core/boxes/box_mahnung_offen.php +++ b/core/boxes/box_mahnung_offen.php @@ -115,6 +115,15 @@ class box_mahnung_offen extends ModeleBoxes $line = 0; $l_due_date = $langs->trans('Late').' ('.strtolower($langs->trans('DateDue')).': %s)'; + // Damit das Widget auch ohne offene Rechnungen sichtbar bleibt: + // leeres info_box_contents würde ModeleBoxes::showBox nichts rendern lassen. + if ($num == 0) { + $this->info_box_contents[0][] = array( + 'td' => 'class="center opacitymedium" colspan="6"', + 'text' => $langs->trans("MahnungBoxKeineOffenenRechnungen"), + ); + } + while ($line < min($num, $this->max)) { $objp = $this->db->fetch_object($result); diff --git a/langs/de_DE/mahnung.lang b/langs/de_DE/mahnung.lang index c943a91..ea54296 100644 --- a/langs/de_DE/mahnung.lang +++ b/langs/de_DE/mahnung.lang @@ -205,6 +205,7 @@ MahnungCronBuildVorschlagDesc = Sucht täglich überfällige Rechnungen und send # Widget # MahnungBoxOffeneRechnungen = Überfällige Rechnungen mit Mahnstufe (%s) +MahnungBoxKeineOffenenRechnungen = Keine offenen Kundenrechnungen # # Dokumentenmodelle diff --git a/langs/en_US/mahnung.lang b/langs/en_US/mahnung.lang index f7d500c..1463a50 100644 --- a/langs/en_US/mahnung.lang +++ b/langs/en_US/mahnung.lang @@ -329,6 +329,8 @@ MahnungSetupTemplateVars = Available template variables MahnungTriggerBeschreibung = Dunning trigger: marks open dunnings as closed on payment receipt. MahnungBoxStufe = Stage %s MahnungBoxStufeVom = Stage %s from %s +MahnungBoxOffeneRechnungen = Overdue customer invoices with dunning stage (%s) +MahnungBoxKeineOffenenRechnungen = No open customer invoices MahnungVorschlagStufeNichtKonfiguriert = Stage 1 not configured MahnungVorschlagFristNichtErreicht = Stage 1 deadline (%s days) not yet reached (overdue %s days) MahnungVorschlagAlleStufenAusgeschoepft = All dunning stages exhausted (last stage %s)