mahnung/sql/llx_mahnung_stufe.sql
Eduard Wisch 0244a5b07e feat(mahnung): Mailversand ueber FormMail, Versandprotokoll, HTML-Mails
Phase 13/14 abgeschlossen. Der Mailversand war zuvor KAPUTT: ajax/sendmail.php
war bereits zur Funktionsbibliothek umgebaut, card.php postete aber weiterhin
per JS dagegen.

Mailformular (FormMail)
- card.php nutzt jetzt Dolibarrs Standard-Mailformular (action=presend/send):
  Empfaenger (Firma + alle Ansprechpartner), Betreff, Text und Anhang sichtbar
  und aenderbar. Gesendet wird ausschliesslich ueber mahnungSendeErinnerungsMail().
- Anhang = unveraenderte Original-Rechnungs-PDF, wird bei Bedarf nacherzeugt.
  Eigener Parameter mailinit statt mode=init, weil get_form() bei mode=init die
  Anhangsliste selbst leert.
- HTML-Mails: DolEditor im Setup + withfckeditor=-1 im Formular (folgt
  FCKEDITOR_ENABLE_MAIL wie Dolibarrs eigene Mailvorlagen).
- Klartext bleibt Klartext: GETPOST('restricthtml') jagt jeden Nicht-HTML-Text
  durch dol_nl2br() — mahnungBodyEntkleiden() nimmt nur dieses Artefakt zurueck
  und laesst echte Formatierung unangetastet.
- Platzhalter jetzt auch in Dolibarr-Schreibweise (__REF__, __DATE_YMD__,
  __AMOUNT_FORMATED__, __DATE_DUE_YMD__, __FRIST_TAGE__ ...), Liste sichtbar im Setup.
- Absender-Adresse und -Name konfigurierbar (MAHNUNG_EMAIL_SENDER[_NAME]).
- Erneuter Versand moeglich (force aus dem Status abgeleitet, nicht aus dem
  Request — Doppelversand-Schutz bleibt wirksam).

Versandprotokoll (neue Tabelle llx_mahnung_mailprotokoll)
- Jede versendete Erinnerung wird mit Empfaenger, Kopie, Betreff, Text und
  Anhangsnamen festgehalten, einsehbar unter Versandstatus. Historie statt
  Spalten am Vorgang, weil erneut gesendet werden kann.
- Lazy-Migration legt die Tabelle an (DB_VERSION 0.4.0), kein Reaktivieren noetig.

Haertung nach Code-Review (21 bestaetigte Funde)
- Anhang liess sich nicht abwaehlen (wurde sofort wieder eingehaengt)
- Upload/Entfernen ohne Rechtepruefung; Temp-Verzeichnis pro Vorgang getrennt
- Teilzahlung zwischen Oeffnen und Senden fuehrt zurueck ins Formular
- Empfaenger: Semikolon-Trenner, keine stillen Verwerfungen, Dubletten, CR/LF
- CSRF: presend + Core-Dateiaktionen (confirm_deletefile, renamefile, sendit,
  linkit) token-pflichtig
- Externe Benutzer sehen nur eigene Vorgaenge; Abschreiben verlangt facture.creer

UI
- Mahnstufe nur noch EINE Darstellung (Badge), Farbskala zentral in
  lib/mahnung_ui.lib.php statt doppelt gepflegt
- Zahnrad oben rechts in die Einstellungen (nur mit Recht mahnung.setup)
- Original-Rechnung unter Verknuepfte Dokumente mit Vorschau, Groesse in KB
- PDF-Einleitungstext nur noch, wo ueberhaupt ein PDF entsteht

Sprachdateien de_DE/en_US deckungsgleich, 9 tote Keys entfernt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 21:31:25 +02:00

50 lines
3 KiB
SQL

-- Copyright (C) 2026 Eduard Wisch <data@data-it-solution.de>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
-- Mahnstufen-Konfiguration (frei konfigurierbar, Basis BGB §288)
-- Stufe 0 = kostenlose Zahlungserinnerung (ist_erinnerung = 1)
CREATE TABLE llx_mahnung_stufe (
rowid INTEGER AUTO_INCREMENT PRIMARY KEY,
entity INTEGER DEFAULT 1 NOT NULL,
stufe TINYINT NOT NULL,
label VARCHAR(60) NOT NULL,
frist_tage INTEGER DEFAULT 0 NOT NULL,
neue_frist_tage INTEGER DEFAULT 7 NOT NULL,
mahngebuehr_b2c DOUBLE(10,2) DEFAULT 0,
mahngebuehr_b2b DOUBLE(10,2) DEFAULT 0,
pauschale_b2b_einmalig TINYINT DEFAULT 0,
-- DECIMAL(6,3): der B2B-Satz (Basiszins + 9 %) liegt ueber 9,9999 und passte
-- nicht mehr in das alte DECIMAL(5,4).
zinssatz_b2c_uebersteuern DECIMAL(6,3),
zinssatz_b2b_uebersteuern DECIMAL(6,3),
versandart_default VARCHAR(20) DEFAULT 'pdf',
email_subject VARCHAR(255),
email_body TEXT,
pdf_intro TEXT,
-- 1 = kostenlose Zahlungserinnerung: keine Mahngebuehr, keine Pauschale,
-- keine Verzugszinsen, Anhang ist die Original-Rechnungs-PDF.
-- Massgeblich ist dieses Flag, NICHT die Stufennummer.
ist_erinnerung TINYINT DEFAULT 0 NOT NULL,
active TINYINT DEFAULT 1 NOT NULL,
datec DATETIME,
tms TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB;
-- Default-Stufen (idempotent: INSERT IGNORE wegen UNIQUE entity+stufe)
-- Die Labels muessen eindeutig sein: 'Zahlungserinnerung' ist ausschliesslich der
-- kostenlosen Stufe 0 vorbehalten, damit im Vorschlag/Sammelbrief/PDF sofort klar
-- ist, ob eine kostenlose Erinnerung oder eine kostenpflichtige Mahnung gemeint ist.
INSERT IGNORE INTO llx_mahnung_stufe (entity, stufe, label, frist_tage, neue_frist_tage, mahngebuehr_b2c, mahngebuehr_b2b, pauschale_b2b_einmalig, versandart_default, datec) VALUES
(1, 1, '1. Mahnung', 7, 14, 0.00, 0.00, 1, 'pdf', NOW()),
(1, 2, '2. Mahnung', 14, 10, 5.00, 5.00, 0, 'pdf', NOW()),
(1, 3, 'Letzte Mahnung', 10, 7, 10.00, 10.00, 0, 'pdf', NOW());
-- Stufe 0: kostenlose Zahlungserinnerung vor der ersten echten Mahnstufe.
-- frist_tage = 0 -> sofort ab Faelligkeit, Versand per E-Mail mit Original-Rechnung.
INSERT IGNORE INTO llx_mahnung_stufe (entity, stufe, label, frist_tage, neue_frist_tage, mahngebuehr_b2c, mahngebuehr_b2b, pauschale_b2b_einmalig, zinssatz_b2c_uebersteuern, zinssatz_b2b_uebersteuern, versandart_default, ist_erinnerung, active, datec) VALUES
(1, 0, 'Zahlungserinnerung', 0, 7, 0.00, 0.00, 0, 0.000, 0.000, 'mail', 1, 1, NOW());