Fix: Bank-Import-Duplikate durch Transaktion, UNIQUE-Constraint und Dateiname-Prüfung verhindern

This commit is contained in:
fds2610-bot 2026-05-15 16:51:38 +02:00
parent d27911b707
commit d26bbfc37b
5 changed files with 62 additions and 4 deletions

View file

@ -2,6 +2,21 @@
---
## 2026-05-15 – Fix: Bank-Import-Duplikate verhindern
- Migration 051: UNIQUE-Constraint `(buchungstag, wertstellung, wert, buchungstext(200))` auf `bank_transactions`; bestehende Duplikate wurden dabei bereinigt
- `BankController::upload()`: Import läuft jetzt in einer DB-Transaktion – bei Fehler wird alles zurückgerollt statt einen unvollständigen Batch zu hinterlassen
- `BankController::upload()`: Dateiname-Prüfung vor dem Import – erneuter Upload derselben Datei wird mit Fehlermeldung abgelehnt
- `BankTransaction::filenameExists()`: neue Hilfsmethode zur Duplikat-Prüfung anhand Dateiname
---
## 2026-05-15 – Fix: Netto-Neuberechnung bei Kategorie-Wechsel in Bank-Buchungsmaske
- IIFE-Wrapper für `updateAutoUst` in einen `DOMContentLoaded`-Listener verschoben, damit er erst nach der Funktionsdefinition (späteres `<script>`-Tag) gesetzt wird und nicht sofort von ihr überschrieben wird.
---
## 2026-05-14 – Feature: Bank buchen
- Navigation: neuer Eintrag „Bank buchen" unter Belege & Buchungen

View file

@ -0,0 +1,22 @@
-- Duplikate entfernen: pro Gruppe (buchungstag, wertstellung, wert, buchungstext) die niedrigste id behalten
DELETE bt
FROM bank_transactions bt
INNER JOIN (
SELECT MIN(id) AS keep_id, buchungstag, wertstellung, wert, buchungstext
FROM bank_transactions
GROUP BY buchungstag, wertstellung, wert, buchungstext
HAVING COUNT(*) > 1
) dup ON bt.buchungstag = dup.buchungstag
AND bt.wertstellung = dup.wertstellung
AND bt.wert = dup.wert
AND bt.buchungstext = dup.buchungstext
AND bt.id > dup.keep_id;
-- Unvollständige Batches entfernen (row_count stimmt nicht mit tatsächlichen Zeilen überein)
DELETE FROM bank_import_batches
WHERE id NOT IN (SELECT DISTINCT batch_id FROM bank_transactions)
AND row_count > 0;
-- UNIQUE-Constraint gegen Doppel-Importe
ALTER TABLE bank_transactions
ADD CONSTRAINT uq_bank_tx UNIQUE (buchungstag, wertstellung, wert, buchungstext(200));

View file

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Steuerkram\Controllers;
use Steuerkram\Database;
use Steuerkram\Models\BankImportFormat;
use Steuerkram\Models\BankTransaction;
use Steuerkram\Models\Beleg;
@ -83,10 +84,21 @@ class BankController
View::redirect('/bank/upload', 'Keine Buchungszeilen in der Datei gefunden.', 'error');
}
if (BankTransaction::filenameExists($origName)) {
View::redirect('/bank/upload', 'Diese Datei wurde bereits importiert (' . $origName . ').', 'error');
}
Database::beginTransaction();
try {
$batchId = BankTransaction::createBatch($formatId, $origName, count($rows));
foreach ($rows as $row) {
BankTransaction::insertRow($batchId, $row);
}
Database::commit();
} catch (\Throwable $e) {
Database::rollBack();
View::redirect('/bank/upload', 'Import fehlgeschlagen: ' . $e->getMessage(), 'error');
}
View::redirect('/bank', count($rows) . ' Buchungen importiert.');
}

View file

@ -96,6 +96,15 @@ class BankTransaction
);
}
public static function filenameExists(string $filename): bool
{
$row = Database::fetchOne(
'SELECT id FROM bank_import_batches WHERE filename = ? LIMIT 1',
[$filename]
);
return $row !== null;
}
public static function createBatch(int $formatId, string $filename, int $rowCount): int
{
Database::execute(

View file

@ -1 +1 @@
1-260514
1-260515