From af83ae8592b5360ab4c043be944ed83758c15d39 Mon Sep 17 00:00:00 2001 From: fds2610-bot Date: Sat, 30 May 2026 14:22:57 +0200 Subject: [PATCH] Feature: E-Mail-Betreff und -Text pro Kunde statt global - Felder mail_subject_template / mail_body_template in customers-Tabelle - Kundenformular um E-Mail-Vorlage-Abschnitt erweitert - EmailService verwendet Kundenvorlage mit Fallback auf Standardtext - Globale E-Mail-Text-Einstellung in Einstellungen entfernt - Migration 082: neue Spalten in customers --- migrations/082_customer_mail_templates.sql | 6 ++ public/index.php | 1 - src/Controllers/InvoiceController.php | 5 +- src/Controllers/SettingsController.php | 19 ------ src/Models/Customer.php | 11 +++- src/Services/EmailService.php | 9 +-- src/Views/customers/form.php | 26 ++++++++ src/Views/settings/form.php | 74 ---------------------- 8 files changed, 49 insertions(+), 102 deletions(-) create mode 100644 migrations/082_customer_mail_templates.sql diff --git a/migrations/082_customer_mail_templates.sql b/migrations/082_customer_mail_templates.sql new file mode 100644 index 0000000..d8f0b2a --- /dev/null +++ b/migrations/082_customer_mail_templates.sql @@ -0,0 +1,6 @@ +-- 082_customer_mail_templates.sql +-- E-Mail-Betreff und -Text pro Kunde statt global in company_settings. + +ALTER TABLE customers + ADD COLUMN IF NOT EXISTS mail_subject_template VARCHAR(255) NULL DEFAULT NULL AFTER notes, + ADD COLUMN IF NOT EXISTS mail_body_template TEXT NULL DEFAULT NULL AFTER mail_subject_template; diff --git a/public/index.php b/public/index.php index 4502560..1efd2cb 100644 --- a/public/index.php +++ b/public/index.php @@ -161,7 +161,6 @@ $router->get('/tax/euer/{year}/anlageliste/pdf', fn($p) => (new EuerController() // ── Einstellungen ──────────────────────────────────────────── $router->get('/settings', fn($p) => (new SettingsController())->show($p)); $router->post('/settings', fn($p) => (new SettingsController())->update($p)); -$router->post('/settings/mail-template', fn($p) => (new SettingsController())->mailTemplate($p)); $router->post('/settings/mail-test', fn($p) => (new SettingsController())->mailTest($p)); $router->post('/settings/logo', fn($p) => (new SettingsController())->uploadLogo($p)); $router->post('/settings/logo/delete', fn($p) => (new SettingsController())->deleteLogo($p)); diff --git a/src/Controllers/InvoiceController.php b/src/Controllers/InvoiceController.php index 4c72fb7..4060542 100644 --- a/src/Controllers/InvoiceController.php +++ b/src/Controllers/InvoiceController.php @@ -258,7 +258,10 @@ class InvoiceController extends BaseController try { $lines = Invoice::lines($id); $settings = Setting::get(); - (new EmailService())->sendInvoice($invoice, $lines, $settings, $recipients); + $customer = !empty($invoice['customer_id']) + ? \Steuerkram\Models\Customer::find((int)$invoice['customer_id']) + : null; + (new EmailService())->sendInvoice($invoice, $lines, $settings, $recipients, $customer ?: null); if ($invoice['status'] === 'Finalisiert') { \Steuerkram\Database::execute( diff --git a/src/Controllers/SettingsController.php b/src/Controllers/SettingsController.php index 5e87042..40503aa 100644 --- a/src/Controllers/SettingsController.php +++ b/src/Controllers/SettingsController.php @@ -95,25 +95,6 @@ class SettingsController extends BaseController View::redirect('/settings', 'Logo hochgeladen.'); } - public function mailTemplate(array $params): void - { - header('Content-Type: application/json'); - $subject = trim($_POST['mail_subject_template'] ?? ''); - $body = trim($_POST['mail_body_template'] ?? ''); - - if ($subject === '') { - echo json_encode(['error' => 'Betreff darf nicht leer sein.']); - return; - } - - \Steuerkram\Database::execute( - 'UPDATE company_settings SET mail_subject_template=?, mail_body_template=? WHERE id=1', - [$subject, $body ?: null] - ); - - echo json_encode(['ok' => true]); - } - public function mailTest(array $params): void { header('Content-Type: application/json'); diff --git a/src/Models/Customer.php b/src/Models/Customer.php index 1d6f027..44695c4 100644 --- a/src/Models/Customer.php +++ b/src/Models/Customer.php @@ -39,8 +39,8 @@ class Customer $nr = self::generateKundennummer(); Database::execute( 'INSERT INTO customers (kundennummer, firma, anrede, vorname, nachname, strasse, plz, ort, land, - email, telefon, ust_id, steuernummer, payment_days, notes) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', + email, telefon, ust_id, steuernummer, payment_days, notes, mail_subject_template, mail_body_template) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [ $data['kundennummer'] ?? $nr, $data['firma'] ?? null, @@ -57,6 +57,8 @@ class Customer $data['steuernummer'] ?? null, (int)($data['payment_days'] ?? 14), $data['notes'] ?? null, + ($data['mail_subject_template'] ?? '') !== '' ? trim($data['mail_subject_template']) : null, + ($data['mail_body_template'] ?? '') !== '' ? trim($data['mail_body_template']) : null, ] ); return (int)Database::lastInsertId(); @@ -66,7 +68,8 @@ class Customer { Database::execute( 'UPDATE customers SET firma=?, anrede=?, vorname=?, nachname=?, strasse=?, plz=?, ort=?, land=?, - email=?, telefon=?, ust_id=?, steuernummer=?, payment_days=?, notes=?, updated_at=NOW() + email=?, telefon=?, ust_id=?, steuernummer=?, payment_days=?, notes=?, + mail_subject_template=?, mail_body_template=?, updated_at=NOW() WHERE id=?', [ $data['firma'] ?? null, @@ -83,6 +86,8 @@ class Customer $data['steuernummer'] ?? null, (int)($data['payment_days'] ?? 14), $data['notes'] ?? null, + ($data['mail_subject_template'] ?? '') !== '' ? trim($data['mail_subject_template']) : null, + ($data['mail_body_template'] ?? '') !== '' ? trim($data['mail_body_template']) : null, $id, ] ); diff --git a/src/Services/EmailService.php b/src/Services/EmailService.php index 7941950..a7610fb 100644 --- a/src/Services/EmailService.php +++ b/src/Services/EmailService.php @@ -9,10 +9,11 @@ class EmailService /** * Sendet eine Rechnung als PDF-Anhang an alle Empfänger. * - * @param string[] $recipients E-Mail-Adressen (1–3) + * @param string[] $recipients E-Mail-Adressen (1–3) + * @param array|null $customer Kundendatensatz (für kundenspezifische E-Mail-Vorlage) * @throws \RuntimeException */ - public function sendInvoice(array $invoice, array $lines, array $settings, array $recipients): void + public function sendInvoice(array $invoice, array $lines, array $settings, array $recipients, ?array $customer = null): void { $mailer = $this->buildMailer($settings); @@ -28,8 +29,8 @@ class EmailService . "Mit freundlichen Grüßen\n" . "%INHABER%"; - $subjectTpl = ($settings['mail_subject_template'] ?? '') ?: 'Rechnung %RNR%'; - $bodyTpl = ($settings['mail_body_template'] ?? '') ?: $defaultBody; + $subjectTpl = ($customer['mail_subject_template'] ?? '') ?: 'Rechnung %RNR%'; + $bodyTpl = ($customer['mail_body_template'] ?? '') ?: $defaultBody; $subject = $this->replacePlaceholders($subjectTpl, $invoice, $settings); $body = $this->replacePlaceholders($bodyTpl, $invoice, $settings); diff --git a/src/Views/customers/form.php b/src/Views/customers/form.php index 634ad6c..b0d664f 100644 --- a/src/Views/customers/form.php +++ b/src/Views/customers/form.php @@ -82,6 +82,32 @@ +
+
+
E-Mail-Vorlage für Rechnungsversand
+
+
+

+ Platzhalter: %RNR% = Rechnungsnummer  ·  + %FNAME% = Firmenname  ·  + %INHABER% = Inhaber. + Leer lassen = Standard-Vorlage verwenden. +

+
+ + +
+
+ + +
+
+
+
Abbrechen diff --git a/src/Views/settings/form.php b/src/Views/settings/form.php index 70a6df9..facb00f 100644 --- a/src/Views/settings/form.php +++ b/src/Views/settings/form.php @@ -1,10 +1,6 @@ View::h($v); ?>
- -
@@ -368,7 +364,6 @@
-
@@ -482,29 +477,6 @@ - - -