Menu
Coddy logo textTech

Sistema bancario

Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy — lección 104 de 104.

challenge icon

Desafío

Fácil

Vamos a construir un Sistema Bancario que demuestre el patrón State, la herencia y la gestión de punteros inteligentes. Crearás un sistema donde las cuentas pueden estar en diferentes estados (Active, Frozen, Closed), cada uno con comportamientos distintos para manejar transacciones.

Organizarás tu código en seis archivos:

  • AccountState.h: Define la infraestructura del patrón State para los estados de la cuenta.

    Crea una clase base abstracta AccountState con métodos virtuales puros:

    • deposit(double amount) — devuelve true si el depósito está permitido, false en caso contrario
    • withdraw(double amount) — devuelve true si el retiro está permitido, false en caso contrario
    • getStateName() — devuelve el nombre del estado como un string

    Implementa tres estados concretos:

    • ActiveState: Permite tanto depósitos como retiros, devuelve "Active"
    • FrozenState: Permite depósitos pero rechaza retiros, devuelve "Frozen"
    • ClosedState: Rechaza tanto depósitos como retiros, devuelve "Closed"
  • Account.h: Construye una jerarquía de cuentas con gestión de estados.

    Crea una clase base Account con:

    • Número de cuenta (string), nombre del propietario y saldo
    • Un std::unique_ptr<AccountState> para gestionar el estado actual
    • deposit(double amount) — consulta primero al estado; si está permitido, lo suma al saldo e imprime "Deposited [amount] to [accountNumber]", de lo contrario imprime "Deposit rejected: account is [stateName]"
    • withdraw(double amount) — consulta al estado; si está permitido y hay fondos suficientes, deduce e imprime "Withdrew [amount] from [accountNumber]". Si el estado lo rechaza, imprime "Withdrawal rejected: account is [stateName]". Si no hay fondos suficientes, imprime "Insufficient funds"
    • freeze(), activate() y close() — cambian el estado de la cuenta
    • getInfo() — devuelve "[accountNumber] ([ownerName]): $[balance] - [stateName]"
    • getAccountType() virtual que devuelve "Basic"

    Crea dos tipos de cuenta derivados:

    • SavingsAccount: Tiene un requisito de saldo mínimo (pasado al constructor). Sobrescribe withdraw para verificar también si el retiro caería por debajo del mínimo; si es así, imprime "Cannot go below minimum balance of [minimum]". Devuelve "Savings" como tipo de cuenta.
    • CheckingAccount: Tiene un límite de sobregiro (pasado al constructor). Permite retiros hasta (balance + overdraftLimit). Devuelve "Checking" como tipo de cuenta.
  • Transaction.h: Modela las transacciones como objetos.

    Crea una clase Transaction que registre:

    • Tipo de transacción (string: "Deposit", "Withdrawal", "Transfer")
    • Monto
    • Número de cuenta involucrado
    • Estado de éxito (bool)

    Añade un método getDescription() que devuelva "[type]: $[amount] on [accountNumber] - [Success/Failed]"

  • Customer.h: Crea un cliente que posee múltiples cuentas.

    Un Customer tiene un nombre, ID y un vector de std::shared_ptr<Account>. Implementa:

    • addAccount(std::shared_ptr<Account> account)
    • getAccount(const std::string& accountNumber) — devuelve la cuenta coincidente o nullptr
    • getTotalBalance() — suma los saldos de todas las cuentas
    • listAccounts() — imprime la información de cada cuenta
  • Bank.h: Coordina las operaciones bancarias.

    La clase Bank almacena clientes y mantiene un historial de transacciones. Implementa:

    • addCustomer(std::shared_ptr<Customer> customer)
    • findAccount(const std::string& accountNumber) — busca la cuenta en todos los clientes
    • processDeposit(const std::string& accountNumber, double amount) — busca la cuenta, realiza el depósito, registra la transacción
    • processWithdrawal(const std::string& accountNumber, double amount) — busca la cuenta, realiza el retiro, registra la transacción
    • getTransactionCount() — devuelve el total de transacciones procesadas
  • main.cpp: Demuestra tu sistema bancario.

    Lee cuatro entradas:

    1. Detalles del cliente (formato: name,customerId)
    2. Detalles de la cuenta de ahorros (formato: accountNumber,minBalance)
    3. Operación 1 (formato: action,accountNumber,amount donde action es deposit o withdraw)
    4. Operación 2 (formato: action,accountNumber,amount o freeze,accountNumber)

    Crea el banco y el cliente. Crea una cuenta de ahorros con el cliente como propietario y añádela al cliente. Añade el cliente al banco. Procesa ambas operaciones (si es un comando freeze, congela la cuenta y luego intenta un pequeño retiro de $10 para demostrar el estado). Finalmente, imprime la lista de cuentas del cliente y el recuento total de transacciones como "Transactions: [count]".

Por ejemplo, con las entradas Alice,C001, SAV001,100, deposit,SAV001,500, y withdraw,SAV001,200:

Deposited 500 to SAV001
Withdrew 200 from SAV001
SAV001 (Alice): $300 - Active
Transactions: 2

Con las entradas Bob,C002, SAV002,50, deposit,SAV002,100, y freeze,SAV002:

Deposited 100 to SAV002
Withdrawal rejected: account is Frozen
SAV002 (Bob): $100 - Frozen
Transactions: 2

Con las entradas Carol,C003, SAV003,200, deposit,SAV003,250, y withdraw,SAV003,100:

Deposited 250 to SAV003
Cannot go below minimum balance of 200
SAV003 (Carol): $250 - Active
Transactions: 2

Este desafío reúne el patrón State para gestionar los comportamientos de las cuentas, la herencia para diferentes tipos de cuentas, los punteros inteligentes para las relaciones de propiedad y el seguimiento de transacciones; todos conceptos básicos que has dominado a lo largo de este curso.

Pruébalo tú mismo

#include <iostream>
#include <string>
#include <sstream>
#include <memory>
#include "Bank.h"

int main() {
    // Leer entrada 1: Detalles del cliente (formato: name,customerId)
    std::string customerInput;
    std::getline(std::cin, customerInput);
    
    // Leer entrada 2: Detalles de la cuenta de ahorros (formato: accountNumber,minBalance)
    std::string accountInput;
    std::getline(std::cin, accountInput);
    
    // Leer entrada 3: Operación 1 (formato: action,accountNumber,amount)
    std::string op1Input;
    std::getline(std::cin, op1Input);
    
    // Leer entrada 4: Operación 2 (formato: action,accountNumber,amount o freeze,accountNumber)
    std::string op2Input;
    std::getline(std::cin, op2Input);
    
    // TODO: Analizar los detalles del cliente desde customerInput
    // Sugerencia: Usa find(',') para dividir la cadena
    
    // TODO: Analizar los detalles de la cuenta desde accountInput
    
    // TODO: Crear el banco
    
    // TODO: Crear el cliente
    
    // TODO: Crear una cuenta de ahorros con el cliente como propietario
    
    // TODO: Añadir la cuenta al cliente
    
    // TODO: Añadir el cliente al banco
    
    // TODO: Analizar y procesar la operación 1
    // Formato: action,accountNumber,amount (action es "deposit" o "withdraw")
    
    // TODO: Analizar y procesar la operación 2
    // Puede ser: action,accountNumber,amount O freeze,accountNumber
    // Si es freeze, congelar la cuenta e intentar un retiro de $10
    
    // TODO: Imprimir la lista de cuentas del cliente
    
    // TODO: Imprimir el recuento de transacciones como "Transactions: [count]"
    
    return 0;
}

Todas las lecciones de Programación Orientada a Objetos