Menu
Coddy logo textTech

Sistema bancario

Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy — lección 89 de 91.

challenge icon

Desafío

Fácil

Vamos a construir un Sistema Bancario que gestione cuentas, transacciones y transferencias entre cuentas. Crearás un sistema con una encapsulación adecuada para proteger los datos financieros, herencia para diferentes tipos de cuentas y validación para asegurar la integridad de los datos.

Organizarás tu código en seis archivos:

  • Transaction.php — Crea una clase Transaction para registrar operaciones financieras. Usa la promoción de constructor para type (string — "deposit", "withdrawal", o "transfer"), amount (float) y timestamp (string). Todas las propiedades deben ser public readonly. Añade un método getDescription(): string que devuelva "[type]: $[amount]" (formatea el monto a 2 decimales).
  • BankAccount.php — Incluye el archivo Transaction. Crea una clase abstracta BankAccount con:
    • Promoción de constructor para accountNumber (string, public readonly) y holderName (string, public readonly)
    • Una propiedad protegida $balance inicializada en 0.0
    • Un array privado para almacenar el historial de transacciones
    • getBalance(): float — devuelve el saldo actual
    • deposit(float $amount): string — añade al saldo, registra la transacción, devuelve "Deposited: $[amount]"
    • abstract withdraw(float $amount): string — las clases hijas implementan las reglas de retiro
    • addTransaction(Transaction $t): void — método protegido para añadir transacciones al historial
    • getTransactionCount(): int — devuelve el número de transacciones
  • SavingsAccount.php — Incluye el archivo BankAccount. Crea una clase SavingsAccount que extienda de BankAccount con:
    • Una constante de clase INTEREST_RATE establecida en 0.02 (2%)
    • withdraw(float $amount): string — si el monto excede el saldo, devuelve "Insufficient funds"; de lo contrario, descuenta, registra la transacción y devuelve "Withdrew: $[amount]"
    • applyInterest(): string — calcula el interés sobre el saldo actual, lo añade como un depósito y devuelve "Interest applied: $[interest]"
  • CheckingAccount.php — Incluye el archivo BankAccount. Crea una clase CheckingAccount que extienda de BankAccount con:
    • Una propiedad privada $overdraftLimit establecida a través del constructor (añade un tercer parámetro con un valor predeterminado de 100.0)
    • withdraw(float $amount): string — permite el retiro si el monto no excede el saldo + el límite de sobregiro; devuelve "Insufficient funds (overdraft limit: $[limit])" en caso de fallo, o "Withdrew: $[amount]" en caso de éxito
    • getOverdraftLimit(): float — devuelve el límite de sobregiro
  • Bank.php — Incluye ambos archivos de cuenta. Crea una clase Bank que gestione las cuentas:
    • Un array privado para almacenar las cuentas indexadas por número de cuenta
    • addAccount(BankAccount $account): void — añade una cuenta
    • findAccount(string $accountNumber): ?BankAccount — devuelve la cuenta o null
    • transfer(string $fromAccount, string $toAccount, float $amount): string — transfiere dinero entre cuentas. Devuelve "Source account not found", "Destination account not found", o el resultado del retiro si este falla. En caso de éxito, deposita en el destino y devuelve "Transferred $[amount] from [from] to [to]"
  • main.php — Incluye el archivo Bank. Recibirás dos entradas: datos de cuentas (JSON) y operaciones (JSON).

    Formato JSON de cuentas:

    [{"type": "savings", "number": "SAV001", "holder": "Alice", "initial": 1000}, {"type": "checking", "number": "CHK001", "holder": "Bob", "initial": 500, "overdraft": 200}]

    Formato JSON de operaciones:

    [{"op": "deposit", "account": "SAV001", "amount": 200}, {"op": "withdraw", "account": "CHK001", "amount": 600}, {"op": "transfer", "from": "SAV001", "to": "CHK001", "amount": 300}, {"op": "interest", "account": "SAV001"}, {"op": "balance", "account": "SAV001"}]

    Crea el banco y todas las cuentas (depositando los montos iniciales). Procesa cada operación:

    • "deposit" — Imprime el resultado de deposit()
    • "withdraw" — Imprime el resultado de withdraw()
    • "transfer" — Imprime el resultado de transfer()
    • "interest" — Imprime el resultado de applyInterest() (solo para cuentas de ahorro)
    • "balance" — Imprime "[holder] balance: $[balance]" (2 decimales)

    Imprime cada resultado en una línea nueva. Formatea todos los montos monetarios a 2 decimales.

Recuerda que las transferencias deben ser atómicas: si el retiro falla, el depósito no debe realizarse. La propiedad protegida $balance permite que las clases hijas la modifiquen mientras se mantiene oculta del código externo, demostrando una encapsulación adecuada en un contexto financiero.

Pruébalo tú mismo

<?php

require_once 'Bank.php';

// Leer la entrada
$accountsJson = trim(fgets(STDIN));
$operationsJson = trim(fgets(STDIN));

// Analizar las entradas JSON
$accounts = (array)json_decode($accountsJson, true);
$operations = (array)json_decode($operationsJson, true);

// TODO: Crear una instancia de Bank

// TODO: Crear cuentas a partir de los datos de las cuentas
// Para cada cuenta en $accounts:
//   - Si el tipo es "savings", crear SavingsAccount
//   - Si el tipo es "checking", crear CheckingAccount (con sobregiro si se proporciona)
//   - Añadir la cuenta al banco
//   - Depositar el monto inicial

// TODO: Procesar cada operación
// Para cada operación en $operations:
//   - "deposit": Imprimir el resultado de deposit()
//   - "withdraw": Imprimir el resultado de withdraw()
//   - "transfer": Imprimir el resultado de transfer()
//   - "interest": Imprimir el resultado de applyInterest() (solo para ahorros)
//   - "balance": Imprimir "[holder] balance: $[balance]" (2 decimales)

?>

Todas las lecciones de Programación Orientada a Objetos