|
|
""" |
|
|
Jeu de tests pour vérifier le parsing de messages SWIFT. |
|
|
|
|
|
Teste différents formats et cas limites pour s'assurer que l'extraction |
|
|
fonctionne correctement avec validation Pydantic. |
|
|
""" |
|
|
|
|
|
import sys |
|
|
from pathlib import Path |
|
|
|
|
|
|
|
|
sys.path.insert(0, str(Path(__file__).parent)) |
|
|
|
|
|
from swift_extractor import ( |
|
|
parse_swift_mt103_advanced, |
|
|
SwiftMT103Parsed, |
|
|
extract_iban_from_text, |
|
|
extract_bic_from_text, |
|
|
parse_swift_field_32a, |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TEST_MESSAGE_1_SIMPLE = """ |
|
|
:20:NONREF |
|
|
:23B:CRED |
|
|
:32A:241215EUR15000.00 |
|
|
:50K:/FR76300040000100000000000123 |
|
|
ORDRE DUPONT JEAN |
|
|
:59:/FR1420041010050500013M02606 |
|
|
BENEFICIAIRE MARTIN PIERRE |
|
|
:70:Paiement facture décembre 2024 |
|
|
:71A:OUR |
|
|
""" |
|
|
|
|
|
TEST_MESSAGE_2_FULL_DATE = """ |
|
|
:20:INVOICE-2024-001 |
|
|
:23B:CRED |
|
|
:32A:20241215EUR25000.50 |
|
|
:50K:/FR76300040000100000000000123 |
|
|
ORDRE DUPONT JEAN |
|
|
RUE DE LA REPUBLIQUE 123 |
|
|
75001 PARIS FRANCE |
|
|
:52A:BNPAFRPPXXX |
|
|
:56A:SOGEFRPPXXX |
|
|
:57A:CRLYFRPPXXX |
|
|
:59:/FR1420041010050500013M02606 |
|
|
BENEFICIAIRE MARTIN PIERRE |
|
|
AVENUE DES CHAMPS ELYSEES 456 |
|
|
75008 PARIS FRANCE |
|
|
:70:Paiement facture décembre 2024 |
|
|
Référence: INV-001 |
|
|
:71A:SHA |
|
|
:72:/INS/BANQUE INTERMEDIAIRE |
|
|
""" |
|
|
|
|
|
TEST_MESSAGE_3_MULTILINE = """ |
|
|
:20:TXN-2025-001 |
|
|
:23B:CRED |
|
|
:32A:250120USD50000.00 |
|
|
:50K:/US64SVBKUS6SXXX123456789 |
|
|
COMPANY ABC INC |
|
|
123 MAIN STREET |
|
|
NEW YORK NY 10001 |
|
|
UNITED STATES |
|
|
:52A:ABCDUS33XXX |
|
|
:59:/GB82WEST12345698765432 |
|
|
BENEFICIARY XYZ LTD |
|
|
456 HIGH STREET |
|
|
LONDON EC1A 1BB |
|
|
UNITED KINGDOM |
|
|
:70:Payment for services Q1 2025 |
|
|
Contract reference: CONTRACT-2025-001 |
|
|
Invoice: INV-2025-042 |
|
|
:71A:BEN |
|
|
:72:/INS/Urgent payment requested |
|
|
""" |
|
|
|
|
|
TEST_MESSAGE_4_EUROPEAN = """ |
|
|
:20:PAY-2024-042 |
|
|
:23B:CRED |
|
|
:32A:241231CHF125000.00 |
|
|
:50K:/CH9300762011623852957 |
|
|
SWISS COMPANY AG |
|
|
BAHNHOFSTRASSE 1 |
|
|
8001 ZURICH |
|
|
SWITZERLAND |
|
|
:52A:UBSWCHZH80A |
|
|
:57A:DEUTDEFFXXX |
|
|
:59:/DE89370400440532013000 |
|
|
GERMAN BENEFICIARY GMBH |
|
|
FRIEDRICHSTRASSE 100 |
|
|
10117 BERLIN |
|
|
GERMANY |
|
|
:70:Year-end payment 2024 |
|
|
:71A:OUR |
|
|
:72:/INS/Final payment of the year |
|
|
""" |
|
|
|
|
|
TEST_MESSAGE_5_MINIMAL = """ |
|
|
:20:MIN-REF-001 |
|
|
:23B:CRED |
|
|
:32A:250101EUR100.00 |
|
|
:50K:/FR76300040000100000000000123 |
|
|
CUSTOMER NAME |
|
|
:59:/FR1420041010050500013M02606 |
|
|
BENEFICIARY NAME |
|
|
:71A:OUR |
|
|
""" |
|
|
|
|
|
TEST_MESSAGE_6_WITH_COMMA_ENGLISH = """ |
|
|
:20:REF-COMMA-ENG |
|
|
:23B:CRED |
|
|
:32A:250101EUR1,234.56 |
|
|
:50K:/FR76300040000100000000000123 |
|
|
ORDERING CUSTOMER |
|
|
:59:/FR1420041010050500013M02606 |
|
|
BENEFICIARY CUSTOMER |
|
|
:70:Test with comma as thousands separator (English format) |
|
|
:71A:OUR |
|
|
""" |
|
|
|
|
|
TEST_MESSAGE_6_WITH_COMMA_EUROPEAN = """ |
|
|
:20:REF-COMMA-EUR |
|
|
:23B:CRED |
|
|
:32A:250101EUR1.234,56 |
|
|
:50K:/FR76300040000100000000000123 |
|
|
ORDERING CUSTOMER |
|
|
:59:/FR1420041010050500013M02606 |
|
|
BENEFICIARY CUSTOMER |
|
|
:70:Test with dot for thousands and comma for decimals (European format) |
|
|
:71A:OUR |
|
|
""" |
|
|
|
|
|
TEST_MESSAGE_7_INTERNATIONAL = """ |
|
|
:20:INTL-TXN-001 |
|
|
:23B:CRED |
|
|
:32A:250215JPY1000000.00 |
|
|
:50K:/JP9123456789012345678901 |
|
|
JAPANESE COMPANY CO LTD |
|
|
TOKYO 100-0001 |
|
|
JAPAN |
|
|
:52A:MHCBJPJTXXX |
|
|
:56A:CHASUS33XXX |
|
|
:57A:HSBCGB2LXXX |
|
|
:59:/GB29NWBK60161331926819 |
|
|
UK BENEFICIARY LTD |
|
|
LONDON |
|
|
:70:International transfer |
|
|
:71A:SHA |
|
|
:72:/INS/Correspondent bank details |
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_field_32a_parsing(): |
|
|
"""Test le parsing du champ :32A: avec différents formats.""" |
|
|
print("\n" + "=" * 60) |
|
|
print("TEST: Parsing champ :32A:") |
|
|
print("=" * 60) |
|
|
|
|
|
test_cases = [ |
|
|
("241215EUR15000.00", "2024-12-15", "EUR", 15000.0), |
|
|
("20241215EUR15000.00", "2024-12-15", "EUR", 15000.0), |
|
|
("250101USD100.50", "2025-01-01", "USD", 100.5), |
|
|
("991231GBP5000.00", "1999-12-31", "GBP", 5000.0), |
|
|
] |
|
|
|
|
|
for value, expected_date, expected_currency, expected_amount in test_cases: |
|
|
try: |
|
|
parsed = parse_swift_field_32a(value) |
|
|
assert parsed.value_date == expected_date.replace("-", ""), \ |
|
|
f"Date mismatch: {parsed.value_date} != {expected_date}" |
|
|
assert parsed.currency == expected_currency, \ |
|
|
f"Currency mismatch: {parsed.currency} != {expected_currency}" |
|
|
assert parsed.amount == expected_amount, \ |
|
|
f"Amount mismatch: {parsed.amount} != {expected_amount}" |
|
|
print(f"✅ {value} → {parsed.value_date} {parsed.currency} {parsed.amount}") |
|
|
except Exception as e: |
|
|
print(f"❌ {value} → ERREUR: {e}") |
|
|
|
|
|
|
|
|
def test_iban_extraction(): |
|
|
"""Test l'extraction d'IBAN depuis du texte.""" |
|
|
print("\n" + "=" * 60) |
|
|
print("TEST: Extraction IBAN") |
|
|
print("=" * 60) |
|
|
|
|
|
test_cases = [ |
|
|
("/FR76 3000 4000 0100 0000 0000 123", "FR76300040000100000000000123"), |
|
|
("FR1420041010050500013M02606", "FR1420041010050500013M02606"), |
|
|
("Compte: GB82WEST12345698765432", "GB82WEST12345698765432"), |
|
|
("IBAN: CH9300762011623852957 dans le texte", "CH9300762011623852957"), |
|
|
] |
|
|
|
|
|
for text, expected in test_cases: |
|
|
iban = extract_iban_from_text(text) |
|
|
if iban == expected: |
|
|
print(f"✅ '{text[:40]}...' → {iban}") |
|
|
else: |
|
|
print(f"❌ '{text[:40]}...' → {iban} (attendu: {expected})") |
|
|
|
|
|
|
|
|
def test_bic_extraction(): |
|
|
"""Test l'extraction de BIC depuis du texte.""" |
|
|
print("\n" + "=" * 60) |
|
|
print("TEST: Extraction BIC") |
|
|
print("=" * 60) |
|
|
|
|
|
test_cases = [ |
|
|
("BNPAFRPPXXX", "BNPAFRPPXXX"), |
|
|
("BIC: SOGEFRPPXXX", "SOGEFRPPXXX"), |
|
|
("Bank: ABCDUS33", "ABCDUS33"), |
|
|
("BIC ABCDUS33XXX in text", "ABCDUS33XXX"), |
|
|
] |
|
|
|
|
|
for text, expected in test_cases: |
|
|
bic = extract_bic_from_text(text) |
|
|
if bic == expected: |
|
|
print(f"✅ '{text}' → {bic}") |
|
|
else: |
|
|
print(f"❌ '{text}' → {bic} (attendu: {expected})") |
|
|
|
|
|
|
|
|
def test_swift_parsing(message_name: str, message: str, description: str = ""): |
|
|
"""Test le parsing d'un message SWIFT complet.""" |
|
|
print(f"\n{'=' * 60}") |
|
|
print(f"TEST: {message_name}") |
|
|
if description: |
|
|
print(f"Description: {description}") |
|
|
print("=" * 60) |
|
|
|
|
|
try: |
|
|
parsed = parse_swift_mt103_advanced(message) |
|
|
|
|
|
print(f"✅ Parsing réussi!") |
|
|
print(f" Référence: {parsed.field_20}") |
|
|
print(f" Date: {parsed.field_32A.value_date}") |
|
|
print(f" Devise: {parsed.field_32A.currency}") |
|
|
print(f" Montant: {parsed.field_32A.amount:,.2f} {parsed.field_32A.currency}") |
|
|
|
|
|
if parsed.ordering_customer_account: |
|
|
print(f" IBAN ordonnateur: {parsed.ordering_customer_account}") |
|
|
if parsed.beneficiary_account: |
|
|
print(f" IBAN bénéficiaire: {parsed.beneficiary_account}") |
|
|
if parsed.field_52A: |
|
|
print(f" BIC banque ordonnateur: {parsed.field_52A}") |
|
|
if parsed.field_56A: |
|
|
print(f" BIC banque intermédiaire: {parsed.field_56A}") |
|
|
if parsed.field_57A: |
|
|
print(f" BIC banque bénéficiaire: {parsed.field_57A}") |
|
|
if parsed.field_70: |
|
|
print(f" Motif: {parsed.field_70[:50]}...") |
|
|
print(f" Frais: {parsed.field_71A}") |
|
|
|
|
|
return True |
|
|
|
|
|
except Exception as e: |
|
|
print(f"❌ ERREUR: {e}") |
|
|
import traceback |
|
|
traceback.print_exc() |
|
|
return False |
|
|
|
|
|
|
|
|
def run_all_tests(): |
|
|
"""Exécute tous les tests.""" |
|
|
print("\n" + "=" * 60) |
|
|
print("SUITE DE TESTS - PARSING SWIFT") |
|
|
print("=" * 60) |
|
|
|
|
|
results = [] |
|
|
|
|
|
|
|
|
test_field_32a_parsing() |
|
|
test_iban_extraction() |
|
|
test_bic_extraction() |
|
|
|
|
|
|
|
|
results.append(("Message simple", test_swift_parsing( |
|
|
"Message simple (YYMMDD)", |
|
|
TEST_MESSAGE_1_SIMPLE, |
|
|
"Format basique avec date YYMMDD" |
|
|
))) |
|
|
|
|
|
results.append(("Message complet", test_swift_parsing( |
|
|
"Message complet (YYYYMMDD)", |
|
|
TEST_MESSAGE_2_FULL_DATE, |
|
|
"Tous les champs avec banques intermédiaires" |
|
|
))) |
|
|
|
|
|
results.append(("Multi-lignes", test_swift_parsing( |
|
|
"Message multi-lignes", |
|
|
TEST_MESSAGE_3_MULTILINE, |
|
|
"Adresses complètes sur plusieurs lignes" |
|
|
))) |
|
|
|
|
|
results.append(("Européen", test_swift_parsing( |
|
|
"Message européen", |
|
|
TEST_MESSAGE_4_EUROPEAN, |
|
|
"IBAN suisse et allemand" |
|
|
))) |
|
|
|
|
|
results.append(("Minimal", test_swift_parsing( |
|
|
"Message minimal", |
|
|
TEST_MESSAGE_5_MINIMAL, |
|
|
"Uniquement les champs obligatoires" |
|
|
))) |
|
|
|
|
|
results.append(("Format anglais", test_swift_parsing( |
|
|
"Message avec virgule (format anglais)", |
|
|
TEST_MESSAGE_6_WITH_COMMA_ENGLISH, |
|
|
"Montant 1,234.56 (virgule = milliers, point = décimales)" |
|
|
))) |
|
|
|
|
|
results.append(("Format européen", test_swift_parsing( |
|
|
"Message avec virgule (format européen)", |
|
|
TEST_MESSAGE_6_WITH_COMMA_EUROPEAN, |
|
|
"Montant 1.234,56 (point = milliers, virgule = décimales)" |
|
|
))) |
|
|
|
|
|
results.append(("International", test_swift_parsing( |
|
|
"Message international", |
|
|
TEST_MESSAGE_7_INTERNATIONAL, |
|
|
"Transfert intercontinental avec JPY" |
|
|
))) |
|
|
|
|
|
|
|
|
print("\n" + "=" * 60) |
|
|
print("RÉSUMÉ DES TESTS") |
|
|
print("=" * 60) |
|
|
|
|
|
passed = sum(1 for _, result in results if result) |
|
|
total = len(results) |
|
|
|
|
|
for name, result in results: |
|
|
status = "✅ PASSÉ" if result else "❌ ÉCHOUÉ" |
|
|
print(f"{status}: {name}") |
|
|
|
|
|
print(f"\nTotal: {passed}/{total} tests réussis") |
|
|
|
|
|
if passed == total: |
|
|
print("\n🎉 Tous les tests sont passés!") |
|
|
else: |
|
|
print(f"\n⚠️ {total - passed} test(s) ont échoué") |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
run_all_tests() |
|
|
|
|
|
|