|
|
""" |
|
|
Modèles Pydantic pour messages SWIFT. |
|
|
|
|
|
Ces modèles peuvent être utilisés avec output_type pour valider |
|
|
automatiquement la structure des messages SWIFT générés. |
|
|
""" |
|
|
|
|
|
from pydantic import BaseModel, Field, field_validator |
|
|
from datetime import datetime |
|
|
|
|
|
|
|
|
class SWIFTFielBase(BaseModel): |
|
|
"""Classe de base pour les champs SWIFT.""" |
|
|
pass |
|
|
|
|
|
|
|
|
class MT103Field32A(BaseModel): |
|
|
"""Champ :32A: Date de valeur, devise, montant.""" |
|
|
value_date: str = Field(description="Date de valeur YYYYMMDD") |
|
|
currency: str = Field(description="Code devise ISO 3 lettres") |
|
|
amount: float = Field(description="Montant", gt=0) |
|
|
|
|
|
@field_validator("value_date") |
|
|
def validate_date(cls, v): |
|
|
if len(v) != 8 or not v.isdigit(): |
|
|
raise ValueError("Date must be YYYYMMDD format") |
|
|
try: |
|
|
datetime.strptime(v, "%Y%m%d") |
|
|
except ValueError: |
|
|
raise ValueError("Invalid date") |
|
|
return v |
|
|
|
|
|
@field_validator("currency") |
|
|
def validate_currency(cls, v): |
|
|
if len(v) != 3 or not v.isalpha(): |
|
|
raise ValueError("Currency must be 3 letter ISO code") |
|
|
return v.upper() |
|
|
|
|
|
|
|
|
class SWIFTMT103Structured(BaseModel): |
|
|
"""Message SWIFT MT103 avec validation complète.""" |
|
|
|
|
|
field_20: str = Field(description=":20: Référence du transfert") |
|
|
field_23B: str = Field(default="CRED", description=":23B: Code instruction") |
|
|
field_32A: MT103Field32A = Field(description=":32A: Date, devise, montant") |
|
|
field_50K: str = Field(description=":50K: Ordre donneur") |
|
|
field_59: str = Field(description=":59: Bénéficiaire") |
|
|
field_70: str | None = Field(default=None, description=":70: Information pour bénéficiaire") |
|
|
field_71A: str = Field(default="OUR", description=":71A: Frais (OUR/SHA/BEN)") |
|
|
|
|
|
@field_validator("field_71A") |
|
|
def validate_charges(cls, v): |
|
|
valid = ["OUR", "SHA", "BEN"] |
|
|
if v not in valid: |
|
|
raise ValueError(f"Charges must be one of {valid}") |
|
|
return v |
|
|
|
|
|
def to_swift_format(self) -> str: |
|
|
"""Convertit en format SWIFT standard.""" |
|
|
lines = [ |
|
|
f":20:{self.field_20}", |
|
|
f":23B:{self.field_23B}", |
|
|
f":32A:{self.field_32A.value_date}{self.field_32A.currency}{self.field_32A.amount:.2f}", |
|
|
f":50K:/{self.field_50K}", |
|
|
f":59:/{self.field_59}", |
|
|
] |
|
|
|
|
|
if self.field_70: |
|
|
lines.append(f":70:{self.field_70}") |
|
|
|
|
|
lines.append(f":71A:{self.field_71A}") |
|
|
|
|
|
return "\n".join(lines) |
|
|
|
|
|
|
|
|
|
|
|
def example_with_validation(): |
|
|
"""Exemple d'utilisation avec validation Pydantic.""" |
|
|
try: |
|
|
mt103 = SWIFTMT103Structured( |
|
|
field_20="TXN-2025-001", |
|
|
field_32A=MT103Field32A( |
|
|
value_date="20250120", |
|
|
currency="EUR", |
|
|
amount=15000.00 |
|
|
), |
|
|
field_50K="FR76300040000100000000000123\nORDRE DUPONT", |
|
|
field_59="FR1420041010050500013M02606\nBENEFICIAIRE MARTIN", |
|
|
field_70="Paiement facture", |
|
|
field_71A="OUR" |
|
|
) |
|
|
|
|
|
print("✅ Message SWIFT validé:") |
|
|
print(mt103.to_swift_format()) |
|
|
|
|
|
except Exception as e: |
|
|
print(f"❌ Erreur de validation: {e}") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|