Menu
Coddy logo textTech

System bankowy

Część sekcji Programowanie obiektowe ścieżki PHP w Coddy. Lekcja 89 z 91.

challenge icon

Wyzwanie

Łatwy

Zbudujmy system bankowy, który obsługuje konta, transakcje i przelewy między kontami. Stworzysz system z odpowiednią enkapsulacją, aby chronić dane finansowe, dziedziczeniem dla różnych typów kont oraz walidacją zapewniającą integralność danych.

Rozmieścisz kod w sześciu plikach:

  • Transaction.php: Utwórz klasę Transaction do rejestrowania operacji finansowych. Użyj promocji konstruktora dla type (string: "deposit", "withdrawal" lub "transfer"), amount (float) i timestamp (string). Wszystkie właściwości powinny być publiczne i tylko do odczytu. Dodaj metodę getDescription(): string, która zwraca "[type]: $[amount]" (sformatuj kwotę do 2 miejsc po przecinku).
  • BankAccount.php: Dołącz plik Transaction. Utwórz abstrakcyjną klasę BankAccount zawierającą:
    • Promocję konstruktora dla accountNumber (string, public readonly) i holderName (string, public readonly)
    • Chronioną właściwość $balance zainicjalizowaną wartością 0.0
    • Prywatną tablicę do przechowywania historii transakcji
    • getBalance(): float: zwraca bieżące saldo
    • deposit(float $amount): string: dodaje kwotę do salda, rejestruje transakcję i zwraca "Deposited: $[amount]"
    • abstract withdraw(float $amount): string: klasy potomne implementują zasady wypłat
    • addTransaction(Transaction $t): void: chroniona metoda dodająca transakcje do historii
    • getTransactionCount(): int: zwraca liczbę transakcji
  • SavingsAccount.php: Dołącz plik BankAccount. Utwórz klasę SavingsAccount rozszerzającą BankAccount, która zawiera:
    • Stałą klasową INTEREST_RATE ustawioną na 0.02 (2%)
    • withdraw(float $amount): string: jeśli kwota przekracza saldo, zwróć "Insufficient funds"; w przeciwnym razie odejmij kwotę, zarejestruj transakcję i zwróć "Withdrew: $[amount]"
    • applyInterest(): string: oblicza odsetki od bieżącego salda, dodaje je jako wpłatę i zwraca "Interest applied: $[interest]"
  • CheckingAccount.php: Dołącz plik BankAccount. Utwórz klasę CheckingAccount rozszerzającą BankAccount, która zawiera:
    • Prywatną właściwość $overdraftLimit ustawianą przez konstruktor (dodaj trzeci parametr o domyślnej wartości 100.0)
    • withdraw(float $amount): string: pozwala na wypłatę, jeśli kwota nie przekracza sumy salda i limitu kredytu w rachunku; w przypadku niepowodzenia zwraca "Insufficient funds (overdraft limit: $[limit])", a w przypadku powodzenia "Withdrew: $[amount]"
    • getOverdraftLimit(): float: zwraca limit kredytu w rachunku
  • Bank.php: Dołącz oba pliki kont. Utwórz klasę Bank do zarządzania kontami:
    • Prywatna tablica do przechowywania kont indeksowanych numerem konta
    • addAccount(BankAccount $account): void: dodaje konto
    • findAccount(string $accountNumber): ?BankAccount: zwraca konto albo null
    • transfer(string $fromAccount, string $toAccount, float $amount): string: przelewa pieniądze między kontami. Zwraca "Source account not found", "Destination account not found" albo wynik wypłaty, jeśli się nie powiedzie. W przypadku powodzenia wpłaca środki na konto docelowe i zwraca "Transferred $[amount] from [from] to [to]"
  • main.php: Dołącz plik Bank. Otrzymasz dwa wejścia: dane kont (JSON) i operacje (JSON).

    Format JSON kont:

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

    Format JSON operacji:

    [{"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"}]

    Utwórz bank i wszystkie konta (wpłacając kwoty początkowe). Przetwórz każdą operację:

    • "deposit": wypisz wynik deposit()
    • "withdraw": wypisz wynik withdraw()
    • "transfer": wypisz wynik transfer()
    • "interest": wypisz wynik applyInterest() (tylko dla kont oszczędnościowych)
    • "balance": wypisz "[holder] balance: $[balance]" (2 miejsca po przecinku)

    Wypisz każdy wynik w nowej linii. Formatuj wszystkie kwoty pieniężne do 2 miejsc po przecinku.

Pamiętaj, że przelewy powinny być atomowe: jeśli wypłata się nie powiedzie, wpłata nie powinna nastąpić. Chroniona właściwość $balance pozwala klasom potomnym ją modyfikować, jednocześnie ukrywając ją przed kodem zewnętrznym, co pokazuje prawidłową enkapsulację w kontekście finansowym.

Spróbuj swoich sił

<?php

require_once 'Bank.php';

// Odczytaj dane wejściowe
$accountsJson = trim(fgets(STDIN));
$operationsJson = trim(fgets(STDIN));

// Przetwórz dane wejściowe w formacie JSON
$accounts = (array)json_decode($accountsJson, true);
$operations = (array)json_decode($operationsJson, true);

// TODO: Utwórz instancję Bank

// TODO: Utwórz konta na podstawie danych kont
// Dla każdego konta w $accounts:
//   - Jeśli typ to "savings", utwórz SavingsAccount
//   - Jeśli typ to "checking", utwórz CheckingAccount (z limitem debetowym, jeśli podano)
//   - Dodaj konto do banku
//   - Wpłać kwotę początkową

// TODO: Przetwórz każdą operację
// Dla każdej operacji w $operations:
//   - "deposit": Wypisz wynik deposit()
//   - "withdraw": Wypisz wynik withdraw()
//   - "transfer": Wypisz wynik transfer()
//   - "interest": Wypisz wynik applyInterest() (tylko dla kont oszczędnościowych)
//   - "balance": Wypisz "[holder] balance: $[balance]" (2 miejsca po przecinku)

?>

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator PHP online