Implements the Sprint 10 Phase 1 foundation for the Smart Payment Import feature:
Domain layer:
- 3 new enums: BankFormat (MT940, CAMT053, CSV), ImportSessionStatus, MatchStatus
- StaffPermission.FINANCE_IMPORT
- AuditEventType: BANK_IMPORT_STARTED/COMPLETED/FAILED + BANK_PAYMENT_CONFIRMED
- NotificationType.BANK_IMPORT_COMPLETED
- ConsentType.BANK_DATA (DSGVO consent for IBAN storage)
- 3 new entities: BankImportSession, BankTransaction, CsvColumnMapping
- Member: + iban (VARCHAR 34) + ibanConsentDate
- MemberStatus.LEFT (semantic alias for RESIGNED, referenced by Sprint 9 RetentionService)
Persistence:
- V30__bank_import_sessions.sql
- V31__bank_transactions.sql
- V32__csv_column_mappings.sql (also adds iban + iban_consent_date to members)
- 3 Spring Data repositories
Parser infrastructure (cannamanage-service/src/main/java/de/cannamanage/service/bankimport):
- BankStatementParser interface (Strategy pattern, Spring-injected list)
- ParsedTransaction + ParseResult records
- BankStatementParseException (parse errors)
- Mt940Parser: custom state machine, CENTURY_BOUNDARY=70 for YY→YYYY, proprietary
header tolerance (skips lines before first :20: for StarMoney/WISO/Hibiscus wrappers)
- Camt053Parser: StAX streaming with XXE hardening (IS_SUPPORTING_EXTERNAL_ENTITIES,
SUPPORT_DTD, IS_REPLACING_ENTITY_REFERENCES all false); supports camt.053.001.02
and camt.053.001.08 namespaces
- CsvBankParser: Apache Commons CSV with configurable columns per club; German number
format ("1.234,56"); ISO-8859-1 default encoding
- BankStatementParserService: filename-extension hint + content probe; throws
UnrecognizedFormatException when no parser claims the file
Build verified via Docker (cannamanage-api:sprint10-phase1).
Sprint 9 fix (incidental, required to compile):
- Added MemberStatus.LEFT (Sprint 9 RetentionService referenced it but the enum
value was missing)
- MemberListRegistryGenerator: added LEFT to formatStatus() switch (mapped to
"Ausgetreten", same as RESIGNED)
Sprint 10 docs: analysis, plan, plan-review, testplan.
Co-Authored-By: Lumen <lumen@cannamanage.de>
24 KiB
Sprint 10 Test Plan — Smart Payment Import
Date: 2026-06-15 Author: Patrick Plate / Lumen (Architect) Status: Draft v1 Basis: cannamanage-sprint10-plan.md Sprint Goal: Bank statement import with auto-matching for member payment reconciliation
Test Overview
| ID | Description | Type | Class/Component | Status |
|---|---|---|---|---|
| T-01 | MT940 parsing — standard Sparkasse file | Unit | Mt940ParserTest | ⬜ |
| T-02 | MT940 parsing — multi-line Verwendungszweck | Unit | Mt940ParserTest | ⬜ |
| T-03 | MT940 parsing — debit/credit identification | Unit | Mt940ParserTest | ⬜ |
| T-04 | MT940 parsing — German amount format (comma decimal) | Unit | Mt940ParserTest | ⬜ |
| T-05 | MT940 parsing — multi-statement file (multiple accounts) | Unit | Mt940ParserTest | ⬜ |
| T-06 | MT940 parsing — malformed input (graceful error) | Unit | Mt940ParserTest | ⬜ |
| T-07 | CAMT.053 parsing — standard XML file | Unit | Camt053ParserTest | ⬜ |
| T-08 | CAMT.053 parsing — multiple entries extraction | Unit | Camt053ParserTest | ⬜ |
| T-09 | CAMT.053 parsing — namespace v2 and v8 support | Unit | Camt053ParserTest | ⬜ |
| T-10 | CAMT.053 parsing — counterparty IBAN + name extraction | Unit | Camt053ParserTest | ⬜ |
| T-11 | CAMT.053 parsing — invalid XML (error handling) | Unit | Camt053ParserTest | ⬜ |
| T-12 | CSV parsing — semicolon delimiter, ISO-8859-1 | Unit | CsvBankParserTest | ⬜ |
| T-13 | CSV parsing — German number format (1.234,56) | Unit | CsvBankParserTest | ⬜ |
| T-14 | CSV parsing — configurable column mapping | Unit | CsvBankParserTest | ⬜ |
| T-15 | CSV parsing — skip header rows | Unit | CsvBankParserTest | ⬜ |
| T-16 | CSV parsing — UTF-8 encoding variant | Unit | CsvBankParserTest | ⬜ |
| T-17 | CSV parsing — empty/malformed rows skipped | Unit | CsvBankParserTest | ⬜ |
| T-18 | Format detection — MT940 by content signature | Unit | BankStatementParserServiceTest | ⬜ |
| T-19 | Format detection — CAMT.053 by XML namespace | Unit | BankStatementParserServiceTest | ⬜ |
| T-20 | Format detection — CSV by file extension | Unit | BankStatementParserServiceTest | ⬜ |
| T-21 | Format detection — unrecognized format throws exception | Unit | BankStatementParserServiceTest | ⬜ |
| T-22 | Matching — exact amount match scores 100 | Unit | PaymentMatchingServiceTest | ⬜ |
| T-23 | Matching — amount within 5% scores 80 | Unit | PaymentMatchingServiceTest | ⬜ |
| T-24 | Matching — member number in Verwendungszweck (M-0042) | Unit | PaymentMatchingServiceTest | ⬜ |
| T-25 | Matching — full member name in reference text | Unit | PaymentMatchingServiceTest | ⬜ |
| T-26 | Matching — last name only (partial name match) | Unit | PaymentMatchingServiceTest | ⬜ |
| T-27 | Matching — IBAN exact match | Unit | PaymentMatchingServiceTest | ⬜ |
| T-28 | Matching — confidence ≥90% → MATCHED status | Unit | PaymentMatchingServiceTest | ⬜ |
| T-29 | Matching — confidence 60-89% → SUGGESTED status | Unit | PaymentMatchingServiceTest | ⬜ |
| T-30 | Matching — confidence <60% → UNMATCHED status | Unit | PaymentMatchingServiceTest | ⬜ |
| T-31 | Matching — conflict: multiple members match → SUGGESTED | Unit | PaymentMatchingServiceTest | ⬜ |
| T-32 | Matching — negative amount (debit) skipped from matching | Unit | PaymentMatchingServiceTest | ⬜ |
| T-33 | Matching — no active fee assignment → no match | Unit | PaymentMatchingServiceTest | ⬜ |
| T-34 | Import service — upload and parse creates session | Integration | BankImportServiceTest | ⬜ |
| T-35 | Import service — run matching updates transactions | Integration | BankImportServiceTest | ⬜ |
| T-36 | Import service — confirm match creates Payment + LedgerEntry | Integration | BankImportServiceTest | ⬜ |
| T-37 | Import service — bulk confirm all matched | Integration | BankImportServiceTest | ⬜ |
| T-38 | Import service — skip transaction sets status | Integration | BankImportServiceTest | ⬜ |
| T-39 | Import service — manual assign with explicit member | Integration | BankImportServiceTest | ⬜ |
| T-40 | Import service — categorize as expense creates LedgerEntry | Integration | BankImportServiceTest | ⬜ |
| T-41 | Import service — complete session updates status | Integration | BankImportServiceTest | ⬜ |
| T-42 | Tier enforcement — Starter: CSV only | Unit | TierLimitServiceTest | ⬜ |
| T-43 | Tier enforcement — Starter: max 1 import/month | Unit | TierLimitServiceTest | ⬜ |
| T-44 | Tier enforcement — Pro: all formats allowed | Unit | TierLimitServiceTest | ⬜ |
| T-45 | Tier enforcement — Pro: max 3 CSV templates | Unit | TierLimitServiceTest | ⬜ |
| T-46 | Tier enforcement — Enterprise: auto-confirm enabled | Unit | TierLimitServiceTest | ⬜ |
| T-47 | IBAN validation — valid German IBAN (DE) | Unit | IbanValidatorTest | ⬜ |
| T-48 | IBAN validation — invalid checksum rejected | Unit | IbanValidatorTest | ⬜ |
| T-49 | IBAN validation — wrong length rejected | Unit | IbanValidatorTest | ⬜ |
| T-50 | IBAN validation — international IBAN formats | Unit | IbanValidatorTest | ⬜ |
| T-51 | REST API — upload file returns session | Integration | BankImportControllerTest | ⬜ |
| T-52 | REST API — upload exceeds 10MB → 413 error | Integration | BankImportControllerTest | ⬜ |
| T-53 | REST API — unauthorized user → 403 | Integration | BankImportControllerTest | ⬜ |
| T-54 | REST API — confirm match endpoint | Integration | BankImportControllerTest | ⬜ |
| T-55 | REST API — list sessions paginated | Integration | BankImportControllerTest | ⬜ |
| T-56 | REST API — CSV mapping CRUD | Integration | BankImportControllerTest | ⬜ |
| T-57 | REST API — tenant isolation (club A cannot see club B sessions) | Integration | BankImportControllerTest | ⬜ |
| T-58 | Member IBAN — store with consent verification | Integration | MemberControllerTest | ⬜ |
| T-59 | Member IBAN — reject without consent | Integration | MemberControllerTest | ⬜ |
| T-60 | Flyway migration — V30 applies cleanly | Integration | FlywayMigrationTest | ⬜ |
| T-61 | Flyway migration — V31 applies cleanly | Integration | FlywayMigrationTest | ⬜ |
| T-62 | Flyway migration — V32 applies cleanly | Integration | FlywayMigrationTest | ⬜ |
| T-63 | End-to-end — MT940 upload → match → confirm → payment created | E2E | BankImportE2ETest | ⬜ |
| T-64 | End-to-end — CSV with custom mapping → successful import | E2E | BankImportE2ETest | ⬜ |
| T-65 | End-to-end — mixed matches (auto + manual + skip) | E2E | BankImportE2ETest | ⬜ |
| T-66 | Frontend — upload wizard renders all 4 steps | E2E | Playwright | ⬜ |
| T-67 | Frontend — CSV column mapping interaction | E2E | Playwright | ⬜ |
| T-68 | Frontend — match review table filtering | E2E | Playwright | ⬜ |
| T-69 | Frontend — bulk confirm action | E2E | Playwright | ⬜ |
| T-70 | Frontend — import history table | E2E | Playwright | ⬜ |
Status: ⬜ Pending | ✅ Passed | ❌ Failed | ⏭️ Skipped
Test Cases — Detailed
T-01: MT940 parsing — standard Sparkasse file
Type: Unit
Class: cannamanage-service/src/test/java/de/cannamanage/service/bankimport/Mt940ParserTest.java
Method: testParseSparkasseFile()
Preconditions:
- MT940 test fixture file in
src/test/resources/fixtures/mt940/sparkasse-standard.sta
Scenarios:
| # | Input | Expected Result |
|---|---|---|
| a | Standard Sparkasse MT940 with 5 transactions | ParseResult with 5 transactions, correct amounts/dates |
| b | Opening balance :60F:C260601EUR1234,56 |
openingBalanceCents = 123456 |
| c | Credit transaction :61:2506150615CR50,00 |
amountCents = 5000, bookingDate = 2025-06-15 |
| d | Account IBAN from :25: field |
accountIban extracted correctly |
Postconditions:
- All transactions have non-null bookingDate and amountCents
T-02: MT940 parsing — multi-line Verwendungszweck
Type: Unit
Class: Mt940ParserTest.java
Method: testMultiLineReference()
Scenarios:
| # | Input | Expected Result |
|---|---|---|
| a | :86: spanning 3 lines with SVWZ+ |
referenceText contains full concatenated text |
| b | :86: with EREF+, KREF+, MREF+ sub-fields |
Sub-fields parsed, SVWZ extracted as reference |
| c | :86: with DEBT+DE89370400440532013000 |
counterpartyIban = "DE89370400440532013000" |
T-03: MT940 parsing — debit/credit identification
Type: Unit
Class: Mt940ParserTest.java
Method: testDebitCreditIdentification()
Scenarios:
| # | Input | Expected Result |
|---|---|---|
| a | :61: with CR indicator |
amountCents > 0 (positive/incoming) |
| b | :61: with D indicator |
amountCents < 0 (negative/outgoing) |
| c | :61: with RC (reversal credit) |
amountCents > 0 |
| d | :61: with RD (reversal debit) |
amountCents < 0 |
T-04: MT940 parsing — German amount format
Type: Unit
Class: Mt940ParserTest.java
Method: testGermanAmountParsing()
Scenarios:
| # | Input | Expected Result |
|---|---|---|
| a | 50,00 |
5000 cents |
| b | 1234,56 |
123456 cents |
| c | 0,01 |
1 cent |
| d | 99999,99 |
9999999 cents |
T-05: MT940 parsing — multi-statement file
Type: Unit
Class: Mt940ParserTest.java
Method: testMultiStatementFile()
Scenarios:
| # | Input | Expected Result |
|---|---|---|
| a | File with 2 statements (2 different accounts) | Parse both, return transactions from all |
| b | Filter by specific account IBAN | Only matching account's transactions returned |
T-06: MT940 parsing — malformed input
Type: Unit
Class: Mt940ParserTest.java
Method: testMalformedInput()
Scenarios:
| # | Input | Expected Result |
|---|---|---|
| a | Empty file | ParseResult with empty list + warning |
| b | Missing :60F: (no opening balance) |
Parse continues, openingBalanceCents = null |
| c | Corrupted amount field | Transaction skipped, warning added |
| d | Binary file (not text) | Exception or empty result with error warning |
T-07: CAMT.053 parsing — standard XML file
Type: Unit
Class: cannamanage-service/src/test/java/de/cannamanage/service/bankimport/Camt053ParserTest.java
Method: testParseStandardCamt053()
Preconditions:
- CAMT.053 test fixture in
src/test/resources/fixtures/camt053/standard.xml
Scenarios:
| # | Input | Expected Result |
|---|---|---|
| a | Standard CAMT.053 with 3 entries | ParseResult with 3 transactions |
| b | <Amt Ccy="EUR">50.00</Amt> |
amountCents = 5000 |
| c | <CdtDbtInd>CRDT</CdtDbtInd> |
amountCents positive |
| d | <BookgDt><Dt>2025-06-15</Dt></BookgDt> |
bookingDate = 2025-06-15 |
T-08: CAMT.053 parsing — multiple entries
Type: Unit
Class: Camt053ParserTest.java
Method: testMultipleEntries()
Scenarios:
| # | Input | Expected Result |
|---|---|---|
| a | 10 <Ntry> elements |
10 ParsedTransaction objects |
| b | Mix of CRDT and DBIT | Correct positive/negative amounts |
T-09: CAMT.053 parsing — namespace versions
Type: Unit
Class: Camt053ParserTest.java
Method: testNamespaceVersions()
Scenarios:
| # | Input | Expected Result |
|---|---|---|
| a | Namespace camt.053.001.02 |
Parsed successfully |
| b | Namespace camt.053.001.08 |
Parsed successfully |
| c | Unknown namespace camt.054.001.02 |
canParse returns false or warning |
T-10: CAMT.053 parsing — counterparty extraction
Type: Unit
Class: Camt053ParserTest.java
Method: testCounterpartyExtraction()
Scenarios:
| # | Input | Expected Result |
|---|---|---|
| a | <Dbtr><Nm>Max Mustermann</Nm></Dbtr> |
counterpartyName = "Max Mustermann" |
| b | <DbtrAcct><Id><IBAN>DE12...</IBAN></Id></DbtrAcct> |
counterpartyIban = "DE12..." |
| c | <Ustrd>M-0042 Beitrag</Ustrd> |
referenceText = "M-0042 Beitrag" |
T-11: CAMT.053 parsing — invalid XML
Type: Unit
Class: Camt053ParserTest.java
Method: testInvalidXml()
Scenarios:
| # | Input | Expected Result |
|---|---|---|
| a | Malformed XML (unclosed tag) | Exception with descriptive message |
| b | Valid XML but wrong schema (not CAMT) | Empty result or format detection rejects |
T-12 through T-17: CSV parsing tests
Type: Unit
Class: cannamanage-service/src/test/java/de/cannamanage/service/bankimport/CsvBankParserTest.java
Test fixtures:
src/test/resources/fixtures/csv/sparkasse.csv(semicolon, ISO-8859-1, dd.MM.yyyy)src/test/resources/fixtures/csv/ing-diba.csv(semicolon, ISO-8859-1, different columns)src/test/resources/fixtures/csv/commerzbank.csv(semicolon, UTF-8)src/test/resources/fixtures/csv/malformed.csv(bad rows)
Key scenarios:
- Semicolon delimiter parsing
- German number format:
"1.234,56"→ 123456 cents - Configurable column positions via CsvColumnMapping
- Header row skipping (1 or 2 rows)
- UTF-8 encoding support
- Empty/malformed rows produce warnings, don't abort
T-22 through T-33: Matching algorithm tests
Type: Unit
Class: cannamanage-service/src/test/java/de/cannamanage/service/bankimport/PaymentMatchingServiceTest.java
Test data setup:
// Members:
// - Member "M-0042" (Max Mustermann, IBAN DE89370400440532013000, fee 50€/month)
// - Member "M-0043" (Anna Schmidt, no IBAN, fee 75€/quarter)
// - Member "M-0044" (Peter Müller, IBAN DE12345678901234567890, fee 50€/month)
Key test scenarios:
| Test | Transaction | Expected Match | Confidence | Rationale |
|---|---|---|---|---|
| T-22 | 50.00€, ref "M-0042 Beitrag" | M-0042 | ≥95% | Exact amount + member number |
| T-23 | 51.00€, ref "M-0042 Beitrag" | M-0042 | ~85% | Amount within 5% + member number |
| T-24 | 50.00€, ref "M-0042 Juni" | M-0042 | ≥90% | Exact amount + member number |
| T-25 | 50.00€, ref "Max Mustermann Beitrag" | M-0042 | ≥80% | Amount + full name |
| T-26 | 50.00€, ref "Mustermann Mitgliedsbeitrag" | M-0042 | ~75% | Amount + last name |
| T-27 | 50.00€, ref "Überweisung", IBAN DE89... | M-0042 | ≥85% | Amount + IBAN |
| T-28 | 50.00€, ref "M-0042", IBAN DE89... | M-0042 | ≥95% (MATCHED) | All criteria hit |
| T-29 | 50.00€, ref "Beitrag", no IBAN | M-0042 or M-0044 | 60-89% (SUGGESTED) | Amount matches two members |
| T-30 | 123.45€, ref "random text" | None | <60% (UNMATCHED) | No criteria match |
| T-31 | 50.00€, ref "Beitrag", no IBAN match | Conflict | SUGGESTED | Two 50€ members, can't distinguish |
| T-32 | -50.00€ (debit) | Skipped | N/A | Negative = outgoing, not a payment |
| T-33 | 50.00€ from member with no fee assignment | None | <60% | No expected payment to match against |
T-34 through T-41: Import service integration tests
Type: Integration (Spring Boot Test with H2)
Class: cannamanage-service/src/test/java/de/cannamanage/service/bankimport/BankImportServiceTest.java
Setup: @SpringBootTest with @Transactional, test fixtures loaded via Flyway
| Test | Scenario | Verification |
|---|---|---|
| T-34 | Upload MT940 file | Session created, status=PENDING, transactions persisted |
| T-35 | Run matching on session | Transactions updated with matchStatus + confidence |
| T-36 | Confirm a MATCHED transaction | Payment entity created, LedgerEntry(INCOME) created, tx status=CONFIRMED |
| T-37 | Bulk confirm 5 MATCHED transactions | 5 Payments created, session.confirmedCount = 5 |
| T-38 | Skip a transaction | tx status=SKIPPED, skipReason set |
| T-39 | Manual assign to different member | Payment created with specified memberId |
| T-40 | Categorize debit as RENT expense | LedgerEntry(EXPENSE, RENT) created |
| T-41 | Complete session | status=COMPLETED, completedAt set |
Postconditions for T-36:
Paymentexists with correct memberId, amountCents, paymentMethod=BANK_TRANSFERLedgerEntryexists with transactionType=INCOME, relatedPaymentId setBankTransaction.matchedPaymentIdset to new Payment ID- Audit event BANK_PAYMENT_CONFIRMED logged
T-42 through T-46: Tier enforcement tests
Type: Unit
Class: cannamanage-service/src/test/java/de/cannamanage/service/TierLimitServiceTest.java
| Test | Tier | Action | Expected |
|---|---|---|---|
| T-42 | STARTER | Import MT940 | TierLimitExceededException |
| T-43 | STARTER | 2nd import in same month | TierLimitExceededException |
| T-44 | PRO | Import MT940 | Allowed |
| T-45 | PRO | Create 4th CSV mapping | TierLimitExceededException |
| T-46 | ENTERPRISE | Check autoConfirmAllowed | returns true |
T-47 through T-50: IBAN validation tests
Type: Unit
Class: cannamanage-service/src/test/java/de/cannamanage/service/bankimport/IbanValidatorTest.java
| Test | Input | Expected |
|---|---|---|
| T-47 | DE89370400440532013000 |
valid = true |
| T-48 | DE00370400440532013000 (bad checksum) |
valid = false |
| T-49 | DE893704004 (too short) |
valid = false |
| T-50 | GB29NWBK60161331926819 (UK IBAN) |
valid = true |
T-51 through T-57: REST API integration tests
Type: Integration (MockMvc)
Class: cannamanage-api/src/test/java/de/cannamanage/api/controller/BankImportControllerTest.java
| Test | Request | Expected Response |
|---|---|---|
| T-51 | POST /api/finance/import/upload (multipart) | 201, session JSON with transaction count |
| T-52 | POST /api/finance/import/upload (15MB file) | 413 Payload Too Large |
| T-53 | POST /api/finance/import/upload (no FINANCE_IMPORT permission) | 403 Forbidden |
| T-54 | POST /api/finance/import/transactions/{id}/confirm | 200, updated transaction JSON |
| T-55 | GET /api/finance/import/sessions?page=0&size=10 | 200, paginated session list |
| T-56 | POST + GET + PUT + DELETE /api/finance/import/csv-mappings | Full CRUD cycle |
| T-57 | GET /api/finance/import/sessions (as different club) | 200, empty list (tenant isolation) |
T-58 through T-59: Member IBAN consent tests
Type: Integration
Class: cannamanage-api/src/test/java/de/cannamanage/api/controller/MemberControllerTest.java
| Test | Precondition | Request | Expected |
|---|---|---|---|
| T-58 | BANK_DATA consent granted | PATCH /api/members/{id}/iban | 200, IBAN stored |
| T-59 | No BANK_DATA consent | PATCH /api/members/{id}/iban | 400, "Consent required" |
T-60 through T-62: Flyway migration tests
Type: Integration
Class: cannamanage-api/src/test/java/de/cannamanage/api/FlywayMigrationTest.java
Verify all migrations V30-V32 apply cleanly on a fresh H2 database without errors.
T-63 through T-65: End-to-end backend tests
Type: E2E (Spring Boot integration with full context)
Class: cannamanage-api/src/test/java/de/cannamanage/api/BankImportE2ETest.java
| Test | Flow | Verification |
|---|---|---|
| T-63 | Upload MT940 → detect → parse → match → confirm all → complete | Payments + LedgerEntries created, session COMPLETED |
| T-64 | Upload CSV → create mapping → parse with mapping → match → confirm | Custom mapping applied, correct column extraction |
| T-65 | Upload → match (3 auto, 2 suggested, 1 unmatched) → confirm 3 → assign 2 → skip 1 → complete | All statuses correct, counts accurate |
T-66 through T-70: Frontend E2E tests (Playwright)
Type: E2E (Playwright)
File: cannamanage-frontend/e2e/bank-import.spec.ts
| Test | Scenario | Verification |
|---|---|---|
| T-66 | Navigate to /finance/import, verify 4-step wizard structure | Steps visible, upload zone rendered |
| T-67 | Upload CSV → column mapping dropdowns → assign columns → proceed | Mapping applied, preview table shown |
| T-68 | Match review table → filter by status → verify correct rows | Filter tabs work, row counts match |
| T-69 | Click "Alle bestätigen" → success toast → counts update | Confirmed count increases, green rows disappear |
| T-70 | Navigate to import history → past sessions listed | Table with filename, date, status columns |
Test Data (Fixtures)
MT940 Test File (sparkasse-standard.sta)
:20:STARTUMSE
:25:20050550/7654321
:28C:00000/001
:60F:C260601EUR1234,56
:61:2506150615CR50,00NMSCNONREF
:86:SVWZ+M-0042 Mitgliedsbeitrag Juni 2025
EREF+NOTPROVIDED
DEBT+DE89370400440532013000
:61:2506150615CR75,00NMSCNONREF
:86:SVWZ+Anna Schmidt Quartalsbeitrag
DEBT+DE55500105175898765432
:61:2506150615DR120,00NMSCNONREF
:86:SVWZ+Miete Vereinsraum Juni
CRED+DE44100800000123456789
:61:2506150615CR50,00NMSCNONREF
:86:SVWZ+Beitrag
DEBT+DE12345678901234567890
:61:2506150615CR25,00NMSCNONREF
:86:SVWZ+Spende Vereinsfest
DEBT+DE99876543210987654321
:62F:C260615EUR1239,56
CAMT.053 Test File (standard.xml)
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.02">
<BkToCstmrStmt>
<Stmt>
<Id>2025-06-15-001</Id>
<Acct><Id><IBAN>DE20050550007654321</IBAN></Id></Acct>
<Bal><!-- balances --></Bal>
<Ntry>
<Amt Ccy="EUR">50.00</Amt>
<CdtDbtInd>CRDT</CdtDbtInd>
<BookgDt><Dt>2025-06-15</Dt></BookgDt>
<ValDt><Dt>2025-06-15</Dt></ValDt>
<NtryDtls><TxDtls>
<RmtInf><Ustrd>M-0042 Mitgliedsbeitrag Juni 2025</Ustrd></RmtInf>
<RltdPties>
<Dbtr><Nm>Max Mustermann</Nm></Dbtr>
<DbtrAcct><Id><IBAN>DE89370400440532013000</IBAN></Id></DbtrAcct>
</RltdPties>
</TxDtls></NtryDtls>
</Ntry>
<!-- more entries... -->
</Stmt>
</BkToCstmrStmt>
</Document>
CSV Test File (sparkasse.csv)
"Auftragskonto";"Buchungstag";"Valutadatum";"Buchungstext";"Verwendungszweck";"Beguenstigter/Zahlungspflichtiger";"Kontonummer";"BLZ";"Betrag";"Waehrung"
"DE20050550007654321";"15.06.2025";"15.06.2025";"GUTSCHR";"M-0042 Mitgliedsbeitrag Juni 2025";"Max Mustermann";"DE89370400440532013000";"37040044";"50,00";"EUR"
"DE20050550007654321";"15.06.2025";"15.06.2025";"GUTSCHR";"Anna Schmidt Quartalsbeitrag";"Anna Schmidt";"DE55500105175898765432";"50010517";"75,00";"EUR"
Test Coverage Matrix
| Component | Unit | Integration | E2E | Total |
|---|---|---|---|---|
| Mt940Parser | 6 | 0 | 1 | 7 |
| Camt053Parser | 5 | 0 | 0 | 5 |
| CsvBankParser | 6 | 0 | 1 | 7 |
| BankStatementParserService | 4 | 0 | 0 | 4 |
| PaymentMatchingService | 12 | 0 | 0 | 12 |
| BankImportService | 0 | 8 | 3 | 11 |
| TierLimitService | 5 | 0 | 0 | 5 |
| IbanValidator | 4 | 0 | 0 | 4 |
| BankImportController | 0 | 7 | 0 | 7 |
| MemberController (IBAN) | 0 | 2 | 0 | 2 |
| Flyway Migrations | 0 | 3 | 0 | 3 |
| Frontend (Playwright) | 0 | 0 | 5 | 5 |
| Total | 42 | 20 | 10 | 70 |
Traceability Matrix
| Requirement | Plan Step | Test Case(s) |
|---|---|---|
| MT940 format parsing | Phase 2, Step 2.2 | T-01 through T-06 |
| CAMT.053 format parsing | Phase 2, Step 2.3 | T-07 through T-11 |
| CSV format parsing with configurable columns | Phase 2, Step 2.4 | T-12 through T-17 |
| Auto-format detection | Phase 2, Step 2.5 | T-18 through T-21 |
| Weighted matching algorithm | Phase 3, Step 3.1 | T-22 through T-33 |
| Import session lifecycle | Phase 3, Step 3.2 | T-34 through T-41 |
| Tier-based restrictions | Phase 3, Step 3.3 | T-42 through T-46 |
| IBAN validation + consent | Phase 4, Step 4.4 | T-47 through T-50, T-58, T-59 |
| REST API endpoints | Phase 4, Step 4.1 | T-51 through T-57 |
| Database migrations | Phase 1, Step 1.1 | T-60 through T-62 |
| Full import flow | All phases | T-63 through T-65 |
| Frontend wizard UX | Phase 5 | T-66 through T-70 |
| Tenant isolation | Phase 4, Step 4.3 | T-57 |
| GDPR consent for IBAN | Phase 1, Step 1.2 (ConsentType) | T-58, T-59 |
| File size limit (10MB) | Phase 4, Step 4.3 | T-52 |
| Permission enforcement | Phase 4, Step 4.3 | T-53 |