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

Construyamos 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 cuenta y validación para garantizar 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 del constructor para type (string: "deposit", "withdrawal" o "transfer"), amount (float) y timestamp (string). Todas las propiedades deben ser públicas y de solo lectura. Añade un método getDescription(): string que devuelva "[type]: $[amount]" (formatea amount con 2 decimales).
  • BankAccount.php: Incluye el archivo Transaction. Crea una clase abstracta BankAccount con:
    • Promoción del constructor para accountNumber (string, público y de solo lectura) y holderName (string, público y de solo lectura)
    • Una propiedad $balance protegida, inicializada en 0.0
    • Un array privado para almacenar el historial de transacciones
    • getBalance(): float: devuelve el saldo actual
    • deposit(float $amount): string: suma al saldo, registra la transacción y 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 BankAccount con:
    • Una constante de clase INTEREST_RATE establecida en 0.02 (2 %)
    • withdraw(float $amount): string: si amount supera el saldo, devuelve "Insufficient funds"; de lo contrario, descuenta el importe, registra la transacción y devuelve "Withdrew: $[amount]"
    • applyInterest(): string: calcula los intereses sobre el saldo actual, los añade como un depósito y devuelve "Interest applied: $[interest]"
  • CheckingAccount.php: Incluye el archivo BankAccount. Crea una clase CheckingAccount que extienda BankAccount con:
    • Una propiedad privada $overdraftLimit establecida mediante el constructor (añade un tercer parámetro con valor predeterminado 100.0)
    • withdraw(float $amount): string: permite el retiro si amount no supera el saldo + el límite de sobregiro; devuelve "Insufficient funds (overdraft limit: $[limit])" en caso de error o "Withdrew: $[amount]" si se realiza correctamente
    • getOverdraftLimit(): float: devuelve el límite de sobregiro
  • Bank.php: Incluye ambos archivos de cuentas. 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. Si se realiza correctamente, deposita el dinero en la cuenta de 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 del JSON de cuentas:

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

    Formato del 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 importes 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]" (con 2 decimales)

    Imprime cada resultado en una línea nueva. Formatea todos los importes monetarios con 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 permanece oculta para el código externo, demostrando una encapsulación adecuada en un contexto financiero.

Pruébalo tú mismo

<?php

require_once 'Bank.php';

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

// Analizar 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 cuenta al banco
//   - Depositar cantidad inicial

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

?>

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de PHP online