Steuerkram/migrations/068_bank_sources.sql
fds2610-bot 995b52fbd3 Feature: FinTS-Direktverbindung und vereinheitlichte Importquellen
- FinTS-Abruf für Comdirect/DKB/Sparkassen via nemiah/php-fints (4.1)
  inkl. photoTAN-Eingabe-Modal und Multi-Konto-Auswahl
- Neue Tabelle bank_sources (CSV/API/FinTS) ersetzt bank_import_formats
  und bank_connections, Backfill in Migration 068
- Symmetrische Verschlüsselung sensibler Felder (PayPal-Signature,
  FinTS-PIN) mit AES-256-GCM, APP_KEY in .env
- Routes /bank/fints* → /bank/direkt*; "+ Neue Bank…"-Dialog erlaubt
  freie API/FinTS-Anbieter
- Scripts/encrypt_bank_secrets.php als idempotenter Migrations-Helfer
- Neue Tests 36 (Crypto) und 37 (BankSource)
2026-05-22 07:17:00 +02:00

115 lines
4.6 KiB
SQL

-- Einheitliche Tabelle für alle Bank-Importquellen (CSV-Formate + Direktverbindungen).
-- bank_import_formats und bank_connections bleiben vorerst bestehen, werden aber
-- nicht mehr vom Code gelesen. Drop in späterer Migration.
CREATE TABLE IF NOT EXISTS bank_sources (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
type ENUM('csv','api','fints') NOT NULL,
provider_id INT UNSIGNED NULL,
bezeichnung VARCHAR(150) NOT NULL,
kuerzel VARCHAR(10) NULL,
farbe VARCHAR(7) NULL DEFAULT '#6366f1',
-- CSV-Konfiguration (NULL bei api/fints)
skip_rows INT NULL,
has_header_row TINYINT NULL,
`delimiter` CHAR(1) NULL,
enclosure CHAR(1) NULL,
col_buchungstag INT NULL,
col_wertstellung INT NULL,
col_vorgang INT NULL,
col_buchungstext INT NULL,
col_wert INT NULL,
col_zahlungspflichtiger INT NULL,
col_zahlungsempfaenger INT NULL,
col_verwendungszweck INT NULL,
date_format VARCHAR(20) NULL,
decimal_separator CHAR(1) NULL,
thousands_separator CHAR(1) NULL,
buchungstext_template_debit VARCHAR(500) NULL,
buchungstext_template_credit VARCHAR(500) NULL,
-- API/FinTS gemeinsam
sandbox TINYINT(1) NOT NULL DEFAULT 0,
last_fetched_at TIMESTAMP NULL DEFAULT NULL,
-- API-spezifisch (PayPal-NVP)
app_name VARCHAR(150) NULL,
client_id_enc TEXT NULL,
secret_enc TEXT NULL,
-- FinTS-spezifisch
blz VARCHAR(11) NULL,
fints_url VARCHAR(255) NULL,
benutzerkennung VARCHAR(100) NULL,
pin_enc TEXT NULL,
iban_filter VARCHAR(34) NULL,
-- Backfill-Tracking (wird am Ende dieser Migration entfernt)
legacy_format_id INT UNSIGNED NULL,
legacy_connection_id INT UNSIGNED NULL,
created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
INDEX idx_bs_type (type),
INDEX idx_bs_legacy_format (legacy_format_id),
INDEX idx_bs_legacy_connection (legacy_connection_id),
FOREIGN KEY (provider_id) REFERENCES bank_providers(id) ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Backfill: CSV-Formate übernehmen
INSERT INTO bank_sources (
type, bezeichnung, kuerzel, farbe,
skip_rows, has_header_row, `delimiter`, enclosure,
col_buchungstag, col_wertstellung, col_vorgang, col_buchungstext, col_wert,
col_zahlungspflichtiger, col_zahlungsempfaenger, col_verwendungszweck,
date_format, decimal_separator, thousands_separator,
buchungstext_template_debit, buchungstext_template_credit,
legacy_format_id
)
SELECT 'csv', name, kuerzel, farbe,
skip_rows, has_header_row, `delimiter`, enclosure,
col_buchungstag, col_wertstellung, col_vorgang, col_buchungstext, col_wert,
col_zahlungspflichtiger, col_zahlungsempfaenger, col_verwendungszweck,
date_format, decimal_separator, thousands_separator,
buchungstext_template_debit, buchungstext_template_credit,
id
FROM bank_import_formats;
-- Backfill: Direktverbindungen übernehmen (Klartext-Credentials in *_enc-Spalten;
-- werden im Anschluss durch scripts/encrypt_bank_secrets.php verschlüsselt).
INSERT INTO bank_sources (
type, provider_id, bezeichnung, kuerzel, farbe, sandbox, last_fetched_at,
app_name, client_id_enc, secret_enc,
legacy_connection_id
)
SELECT
CASE bp.verbindungstyp WHEN 'API' THEN 'api' ELSE 'fints' END,
bc.provider_id, bc.bezeichnung, bc.kuerzel, bc.farbe, bc.sandbox, bc.last_fetched_at,
bc.app_name, bc.client_id, bc.secret,
bc.id
FROM bank_connections bc
JOIN bank_providers bp ON bp.id = bc.provider_id;
-- source_id-Spalte auf bank_import_batches
ALTER TABLE bank_import_batches
ADD COLUMN IF NOT EXISTS source_id INT UNSIGNED NULL,
ADD INDEX IF NOT EXISTS idx_bib_source (source_id);
-- Backfill: source_id aus format_id (CSV-Batches)
UPDATE bank_import_batches bib
JOIN bank_sources bs ON bs.legacy_format_id = bib.format_id AND bs.type = 'csv'
SET bib.source_id = bs.id
WHERE bib.format_id IS NOT NULL AND bib.source_id IS NULL;
-- Backfill: source_id aus connection_id (API/FinTS-Batches)
UPDATE bank_import_batches bib
JOIN bank_sources bs ON bs.legacy_connection_id = bib.connection_id AND bs.type IN ('api','fints')
SET bib.source_id = bs.id
WHERE bib.connection_id IS NOT NULL AND bib.source_id IS NULL;
-- Backfill-Tracking-Spalten wieder entfernen
ALTER TABLE bank_sources
DROP INDEX idx_bs_legacy_format,
DROP INDEX idx_bs_legacy_connection,
DROP COLUMN legacy_format_id,
DROP COLUMN legacy_connection_id;