Menu
Coddy logo textTech

Sistema Bancário

Parte da seção Object Oriented Programming do Journey de Python da Coddy — lição 62 de 64.

challenge icon

Desafio

Difícil

Neste desafio, você construirá um sistema bancário com múltiplos tipos de conta, transações e um gerente de banco central.

Implemente o sistema bancário completando os itens TODO nestes arquivos:

  • transaction.py - Classe Transaction para registrar atividades financeiras
  • account.py - Classe base abstrata Account com funcionalidades comuns
  • savingsaccount.py - Implementação de SavingsAccount com juros e saldo mínimo
  • checkingaccount.py - Implementação de CheckingAccount com recursos de cheque especial
  • bank.py - Classe Bank para gerenciar contas e transferências

Folha de consulta

Este desafio envolve a construção de um sistema bancário com conceitos de programação orientada a objetos, incluindo:

  • Classe Transaction - Registra atividades financeiras
  • Classe abstrata Account - Classe base com funcionalidades comuns de conta
  • SavingsAccount - Tipo de conta com cálculo de juros e requisitos de saldo mínimo
  • CheckingAccount - Tipo de conta com recursos de proteção contra cheque especial
  • Classe Bank - Gerenciador central para contas e transferências de dinheiro

Os conceitos-chave incluem herança, abstração, encapsulamento e polimorfismo para criar uma arquitetura de sistema bancário modular.

Experimente você mesmo

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

# Manipulador de casos de teste abrangente cobrindo todos os cenários e casos extremos
test_case = input()

if test_case == "transaction_class":
    # Testar a 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":
    # Testar funcionalidade de depósito
    savings = SavingsAccount("S123", "John Doe", 500)
    
    # Valor positivo
    success, message = savings.deposit(200)
    print(f"Success: {success}")
    print(f"Message: {message}")
    print(f"Balance: ${savings.get_balance():.2f}")
    
    # Valor negativo (deve falhar)
    success, message = savings.deposit(-50)
    print(f"Success: {success}")
    print(f"Message: {message}")

elif test_case == "savings_withdraw":
    # Testar saque em conta poupança
    savings = SavingsAccount("S123", "John Doe", 500, min_balance=200)
    
    # Saque válido
    success, message = savings.withdraw(100)
    print(f"Success: {success}")
    print(f"Message: {message}")
    
    # Inválido (abaixo do saldo mínimo)
    success, message = savings.withdraw(300)
    print(f"Success: {success}")
    print(f"Message: {message}")
    
    # Valor negativo
    success, message = savings.withdraw(-50)
    print(f"Success: {success}")
    print(f"Message: {message}")

elif test_case == "checking_withdraw":
    # Testar saque em conta corrente
    checking = CheckingAccount("C123", "Jane Smith", 300, overdraft_limit=200)
    
    # Saque normal
    success, message = checking.withdraw(100)
    print(f"Success: {success}")
    print(f"Message: {message}")
    
    # Saque com cheque especial
    success, message = checking.withdraw(300)
    print(f"Success: {success}")
    print(f"Message: {message}")
    
    # Excedendo o limite do cheque especial
    success, message = checking.withdraw(200)
    print(f"Success: {success}")
    print(f"Message: {message}")

elif test_case == "interest_application":
    # Testar aplicação de juros
    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}")
    
    # Verificar histórico de transações
    transactions = savings.get_transaction_history()
    print(f"Transaction count: {len(transactions)}")
    print(f"Last transaction: {transactions[-1]}")

elif test_case == "bank_create_account":
    # Testar criação de conta bancária
    bank = Bank("Test Bank")
    
    # Criar uma conta poupança
    success, message = bank.create_account("savings", "S123", "John Doe", 1000, interest_rate=0.03)
    print(f"Success: {success}")
    print(f"Message: {message}")
    
    # Criar uma conta corrente
    success, message = bank.create_account("checking", "C456", "Jane Smith", 500, overdraft_limit=300)
    print(f"Success: {success}")
    print(f"Message: {message}")
    
    # Criar com número de conta duplicado
    success, message = bank.create_account("savings", "S123", "Another Person", 200)
    print(f"Success: {success}")
    print(f"Message: {message}")
    
    # Criar com tipo inválido
    success, message = bank.create_account("invalid", "I789", "Test Person", 100)
    print(f"Success: {success}")
    print(f"Message: {message}")

elif test_case == "bank_transfer":
    # Testar funcionalidade de transferência bancária
    bank = Bank("Transfer Test Bank")
    
    # Criar duas contas
    bank.create_account("savings", "S123", "John Doe", 1000, min_balance=100)
    bank.create_account("checking", "C456", "Jane Smith", 500)
    
    # Transferência válida
    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}")
    
    # Transferência inválida (excede o saldo mínimo)
    success, message = bank.transfer("S123", "C456", 700)
    print(f"Success: {success}")
    print(f"Message: {message}")
    
    # Conta inexistente
    success, message = bank.transfer("NONEXISTENT", "C456", 100)
    print(f"Success: {success}")
    print(f"Message: {message}")

elif test_case == "full_banking_workflow":
    # Testar um fluxo de trabalho completo
    bank = Bank("Full Workflow Bank")
    
    # Criar contas
    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)
    
    # Realizar depósitos
    savings = bank.get_account("S123")
    checking = bank.get_account("C456")
    
    savings.deposit(300)
    checking.deposit(200)
    
    # Realizar uma transferência
    bank.transfer("S123", "C456", 400)
    
    # Aplicar juros à poupança
    savings.apply_interest()
    
    # Realizar um saque da conta corrente com cheque especial
    checking.withdraw(900)
    
    # Imprimir estado 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":
    # Validação de herança abrangente
    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":
    # Testar comportamento de sobrescrita de método
    print('Testing method overriding...')
    # Criar instâncias e testar métodos sobrescritos
    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":
    # Testar acesso a atributos
    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":
    # Testar condições de contorno e valores extremos
    print('Running boundary_conditions_test test...')
    print('Test completed successfully')

elif test_case == "error_handling_test":
    # Testar tratamento de erros e cenários de exceção
    print('Running error_handling_test test...')
    print('Test completed successfully')

elif test_case == "polymorphic_behavior_test":
    # Testar comportamento polimórfico com objetos mistos
    print('Running polymorphic_behavior_test test...')
    print('Test completed successfully')

elif test_case == "stress_test":
    # Teste de estresse com múltiplos objetos
    import time
    start_time = time.time()
    
    objects = []
    for i in range(50):
        try:
            objects.append(Transaction(f'test_{i}', 100, None))
        except:
            pass  # Lidar com erros de criação graciosamente
        try:
            objects.append(SavingsAccount(f'test_{i}', f'User_{i}'))
        except:
            pass  # Lidar com erros de criação graciosamente
        try:
            objects.append(CheckingAccount(f'test_{i}', f'User_{i}'))
        except:
            pass  # Lidar com erros de criação graciosamente
        try:
            objects.append(Bank(f'test_{i}'))
        except:
            pass  # Lidar com erros de criação graciosamente
    
    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":
    # Teste de validação abrangente
    print('=== Comprehensive Validation Test ===')
    
    # Teste 1: Criação básica de objetos
    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 ===')

Todas as lições de Object Oriented Programming