Menu
Coddy logo textTech

Système bancaire

Fait partie de la section Object Oriented Programming du Journey Python de Coddy — leçon 62 sur 64.

challenge icon

Défi

Difficile

Dans ce défi, vous allez construire un système bancaire avec plusieurs types de comptes, des transactions et un gestionnaire de banque centrale.

Implémentez le système bancaire en complétant les éléments TODO dans ces fichiers :

  • transaction.py - Classe Transaction pour l'enregistrement des activités financières
  • account.py - Classe de base abstraite Account avec les fonctionnalités communes
  • savingsaccount.py - Implémentation de SavingsAccount avec intérêts et solde minimum
  • checkingaccount.py - Implémentation de CheckingAccount avec des capacités de découvert
  • bank.py - Classe Bank pour gérer les comptes et les transferts

Aide-mémoire

Ce défi consiste à construire un système bancaire avec des concepts de programmation orientée objet, notamment :

  • Classe Transaction - Enregistre les activités financières
  • Classe abstraite Account - Classe de base avec des fonctionnalités de compte communes
  • SavingsAccount - Type de compte avec calcul d'intérêts et exigences de solde minimum
  • CheckingAccount - Type de compte avec des capacités de protection contre les découverts
  • Classe Bank - Gestionnaire central pour les comptes et les transferts d'argent

Les concepts clés incluent l'héritage, l'abstraction, l'encapsulation et le polymorphisme pour créer une architecture de système bancaire modulaire.

Essayez vous-même

from transaction import Transaction
from account import Account
from savingsaccount import SavingsAccount
from checkingaccount import CheckingAccount
from bank import Bank

# Gestionnaire de cas de test complet couvrant tous les scénarios et cas limites
test_case = input()

if test_case == "transaction_class":
    # Tester la classe Transaction
    transaction = Transaction("deposit", 100.50, None)
    print(str(transaction))
    
    transaction = Transaction("withdrawal", 75.25, None)
    print(str(transaction))

elif test_case == "account_deposit":
    # Tester la fonctionnalité de dépôt
    savings = SavingsAccount("S123", "John Doe", 500)
    
    # Montant positif
    success, message = savings.deposit(200)
    print(f"Success: {success}")
    print(f"Message: {message}")
    print(f"Balance: ${savings.get_balance():.2f}")
    
    # Montant négatif (devrait échouer)
    success, message = savings.deposit(-50)
    print(f"Success: {success}")
    print(f"Message: {message}")

elif test_case == "savings_withdraw":
    # Tester le retrait d'un compte d'épargne
    savings = SavingsAccount("S123", "John Doe", 500, min_balance=200)
    
    # Retrait valide
    success, message = savings.withdraw(100)
    print(f"Success: {success}")
    print(f"Message: {message}")
    
    # Invalide (en dessous du solde minimum)
    success, message = savings.withdraw(300)
    print(f"Success: {success}")
    print(f"Message: {message}")
    
    # Montant négatif
    success, message = savings.withdraw(-50)
    print(f"Success: {success}")
    print(f"Message: {message}")

elif test_case == "checking_withdraw":
    # Tester le retrait d'un compte courant
    checking = CheckingAccount("C123", "Jane Smith", 300, overdraft_limit=200)
    
    # Retrait normal
    success, message = checking.withdraw(100)
    print(f"Success: {success}")
    print(f"Message: {message}")
    
    # Retrait avec découvert
    success, message = checking.withdraw(300)
    print(f"Success: {success}")
    print(f"Message: {message}")
    
    # Dépassement de la limite de découvert
    success, message = checking.withdraw(200)
    print(f"Success: {success}")
    print(f"Message: {message}")

elif test_case == "interest_application":
    # Tester l'application des intérêts
    savings = SavingsAccount("S123", "John Doe", 1000, interest_rate=0.05)
    success, message = savings.apply_interest()
    print(f"Success: {success}")
    print(f"Message: {message}")
    print(f"New Balance: ${savings.get_balance():.2f}")
    
    # Vérifier l'historique des transactions
    transactions = savings.get_transaction_history()
    print(f"Transaction count: {len(transactions)}")
    print(f"Last transaction: {transactions[-1]}")

elif test_case == "bank_create_account":
    # Tester la création de compte bancaire
    bank = Bank("Test Bank")
    
    # Créer un compte d'épargne
    success, message = bank.create_account("savings", "S123", "John Doe", 1000, interest_rate=0.03)
    print(f"Success: {success}")
    print(f"Message: {message}")
    
    # Créer un compte courant
    success, message = bank.create_account("checking", "C456", "Jane Smith", 500, overdraft_limit=300)
    print(f"Success: {success}")
    print(f"Message: {message}")
    
    # Créer avec un numéro de compte en double
    success, message = bank.create_account("savings", "S123", "Another Person", 200)
    print(f"Success: {success}")
    print(f"Message: {message}")
    
    # Créer avec un type invalide
    success, message = bank.create_account("invalid", "I789", "Test Person", 100)
    print(f"Success: {success}")
    print(f"Message: {message}")

elif test_case == "bank_transfer":
    # Tester la fonctionnalité de transfert bancaire
    bank = Bank("Transfer Test Bank")
    
    # Créer deux comptes
    bank.create_account("savings", "S123", "John Doe", 1000, min_balance=100)
    bank.create_account("checking", "C456", "Jane Smith", 500)
    
    # Transfert valide
    success, message = bank.transfer("S123", "C456", 300)
    print(f"Success: {success}")
    print(f"Message: {message}")
    print(f"Source balance: ${bank.get_account('S123').get_balance():.2f}")
    print(f"Destination balance: ${bank.get_account('C456').get_balance():.2f}")
    
    # Transfert invalide (dépasse le solde minimum)
    success, message = bank.transfer("S123", "C456", 700)
    print(f"Success: {success}")
    print(f"Message: {message}")
    
    # Compte invalide
    success, message = bank.transfer("NONEXISTENT", "C456", 100)
    print(f"Success: {success}")
    print(f"Message: {message}")

elif test_case == "full_banking_workflow":
    # Tester un flux de travail complet
    bank = Bank("Full Workflow Bank")
    
    # Créer des comptes
    bank.create_account("savings", "S123", "John Doe", 1000, interest_rate=0.05, min_balance=200)
    bank.create_account("checking", "C456", "Jane Smith", 500, overdraft_limit=250)
    
    # Effectuer des dépôts
    savings = bank.get_account("S123")
    checking = bank.get_account("C456")
    
    savings.deposit(300)
    checking.deposit(200)
    
    # Effectuer un transfert
    bank.transfer("S123", "C456", 400)
    
    # Appliquer les intérêts à l'épargne
    savings.apply_interest()
    
    # Effectuer un retrait du compte courant avec découvert
    checking.withdraw(900)
    
    # Afficher l'état final
    print("Final Account States:")
    print(f"Savings (S123): ${savings.get_balance():.2f}")
    print(f"Checking (C456): ${checking.get_balance():.2f}")
    
    print("\nTransaction History (Savings):")
    for transaction in savings.get_transaction_history():
        print(f"- {transaction}")
    
    print("\nTransaction History (Checking):")
    for transaction in checking.get_transaction_history():
        print(f"- {transaction}")

elif test_case == "inheritance_validation_test":
    # Validation complète de l'héritage
    objects = []
    if 'Transaction' in locals():
        objects.append(Transaction('test_param', 100, None))
    if 'SavingsAccount' in locals():
        objects.append(SavingsAccount('test_param', 'Test User'))  
    if 'CheckingAccount' in locals():
        objects.append(CheckingAccount('test_param', 'Test User'))
    if 'Bank' in locals():
        objects.append(Bank('test_param'))
    
    for obj in objects:
        print(f'{type(obj).__name__}:')
        print(f'  MRO: {[cls.__name__ for cls in type(obj).__mro__]}')
        print()

elif test_case == "method_overriding_test":
    # Tester le comportement de la redéfinition de méthode
    print('Testing method overriding...')
    # Créer des instances et tester les méthodes redéfinies
    if 'SavingsAccount' in locals():
        obj = SavingsAccount('test', 'Test User')
        print(f'SavingsAccount methods work correctly')
    if 'CheckingAccount' in locals():
        obj = CheckingAccount('test', 'Test User')
        print(f'CheckingAccount methods work correctly')

elif test_case == "attribute_access_test":
    # Tester l'accès aux attributs
    print('Testing attribute access...')
    if 'Transaction' in locals():
        obj = Transaction('test', 100, None)
        print(f'Transaction attributes accessible')
    if 'SavingsAccount' in locals():
        obj = SavingsAccount('test', 'Test User')
        print(f'SavingsAccount attributes accessible')
    if 'CheckingAccount' in locals():
        obj = CheckingAccount('test', 'Test User')
        print(f'CheckingAccount attributes accessible')
    if 'Bank' in locals():
        obj = Bank('test')
        print(f'Bank attributes accessible')

elif test_case == "boundary_conditions_test":
    # Tester les conditions aux limites et les valeurs critiques
    print('Running boundary_conditions_test test...')
    print('Test completed successfully')

elif test_case == "error_handling_test":
    # Tester la gestion des erreurs et les scénarios d'exception
    print('Running error_handling_test test...')
    print('Test completed successfully')

elif test_case == "polymorphic_behavior_test":
    # Tester le comportement polymorphe avec des objets mixtes
    print('Running polymorphic_behavior_test test...')
    print('Test completed successfully')

elif test_case == "stress_test":
    # Test de charge avec plusieurs objets
    import time
    start_time = time.time()
    
    objects = []
    for i in range(50):
        try:
            objects.append(Transaction(f'test_{i}', 100, None))
        except:
            pass  # Gérer les erreurs de création avec élégance
        try:
            objects.append(SavingsAccount(f'test_{i}', f'User_{i}'))
        except:
            pass  # Gérer les erreurs de création avec élégance
        try:
            objects.append(CheckingAccount(f'test_{i}', f'User_{i}'))
        except:
            pass  # Gérer les erreurs de création avec élégance
        try:
            objects.append(Bank(f'test_{i}'))
        except:
            pass  # Gérer les erreurs de création avec élégance
    
    end_time = time.time()
    print(f'Created {len(objects)} objects')
    print(f'Time taken: {end_time - start_time:.4f} seconds')
    print('Stress test completed')

elif test_case == "comprehensive_validation":
    # Test de validation complet
    print('=== Comprehensive Validation Test ===')
    
    # Test 1 : Création d'objets de base
    print('1. Basic Object Creation:')
    success_count = 0
    classes = ['Transaction', 'SavingsAccount', 'CheckingAccount', 'Bank']
    
    try:
        obj = Transaction('test', 100, None)
        success_count += 1
        print(f'   Transaction: Created successfully')
    except Exception as e:
        print(f'   Transaction: Creation failed - {e}')
    try:
        obj = SavingsAccount('test', 'Test User')
        success_count += 1
        print(f'   SavingsAccount: Created successfully')
    except Exception as e:
        print(f'   SavingsAccount: Creation failed - {e}')
    try:
        obj = CheckingAccount('test', 'Test User')
        success_count += 1
        print(f'   CheckingAccount: Created successfully')
    except Exception as e:
        print(f'   CheckingAccount: Creation failed - {e}')
    try:
        obj = Bank('test')
        success_count += 1
        print(f'   Bank: Created successfully')
    except Exception as e:
        print(f'   Bank: Creation failed - {e}')
    
    print(f'   Successfully created {success_count}/{len(classes)} classes')
    
    print('=== Validation Complete ===')

Toutes les leçons de Object Oriented Programming