A full-stack bank account management system built in Python, refactored from a procedural CLI script into a modular, object-oriented application with a web-based interface built using Streamlit.
This project started as a single-file procedural script and was rebuilt from the ground up into a properly layered application:
- Object-oriented architecture — separate
Database,Auth,BankSystem, and model classes instead of global state and standalone functions - Secure by design — parameterized SQL queries throughout, salted password and PIN hashing (no plaintext credentials stored)
- SQLite for zero-config, file-based persistence — no external DB server or credentials required
- Streamlit front end — staff and customer login flows, account self-service, and admin-style account management
- Automated tests covering account creation, deposits, withdrawals, transfers, and validation edge cases (insufficient balance, self-transfer, negative amounts, restricted field edits)
- Staff and customer login (separate flows and permissions)
- Customer self-signup with account number issued on creation
- Deposit, withdraw, and transfer funds
- Account detail updates (name, phone, address, email, card status, PIN)
- Staff-only account listing, search, and account deletion
- Input validation for amounts, PINs, phone numbers, and account numbers
- Atomic transfers — a transfer either fully completes or fully rolls back, so a failure mid-transaction can never leave money "lost" between accounts
app.py → Streamlit entry point: login/signup UI, session init
pages/ → Additional Streamlit pages (dashboard, deposit/withdraw,
transfer, account management), sidebar-navigated
database.py → Database class: connection handling, parameterized
query execution, transaction context manager
models.py → Account / Staff dataclasses, mapped from DB rows
auth.py → Auth class: login logic, salted password/PIN hashing
bank.py → BankSystem class: all account business logic
validators.py → Pure validation functions (amount, PIN, phone, etc.)
seed.py → Generates demo staff and customer accounts for testing
test_bank.py → Smoke tests for BankSystem, run against an in-memory DB
requirements.txt → Python dependencies
Each layer has a single responsibility:
Databasenever contains business logic — only connection/query handlingBankSystemnever contains UI or I/O — only banking rules, so the same logic works identically whether called from the CLI, tests, or Streamlit- Validation is pure and side-effect free, so it's independently testable
- Parameterized queries everywhere — no query is ever built with string formatting or concatenation, eliminating SQL injection entirely
- Hashed, salted credentials — staff passwords and customer PINs are hashed with a per-value salt before storage; they're never stored or compared in plaintext
- One
update_field()method with a column allow-list replaces what was previously six nearly-identical "change X" functions, while also guaranteeing a column name can never be built from unvalidated input - Transactions wrap multi-step money operations (like transfers) so a crash or error partway through can't leave one account debited without the other being credited
- Python 3
- SQLite3 (standard library)
- Streamlit
- Pandas (for tabular account displays)
git clone <your-repo-url>
cd bank-management-system
pip install -r requirements.txt
streamlit run app.pyOn first run, the app automatically seeds bank.db with demo staff and
customer accounts so you can log in immediately — or use the Create
Account tab on the customer login page to sign up your own.
python test_bank.pyRuns a set of smoke tests against an in-memory database, covering account creation, deposits, withdrawals, transfers, restricted field edits, and deletion — including verifying that invalid operations (negative amounts, insufficient balance, self-transfers, editing non-editable fields) are correctly rejected.
- Demo deployment uses a shared SQLite file reset on each server restart — not intended for concurrent production use with real financial data
- No transaction history table yet (balances are updated directly); a
transactionslog is a natural next addition - No two-factor authentication or session timeout
- Transaction history table with per-account statements
- Data visualizations (balance trends, deposits vs. withdrawals, accounts per branch)
- Rule-based anomaly flags (e.g. unusually large transactions, high transaction frequency in a short window) as a lightweight, explainable alternative to unsupported "fraud detection ML" claims
- Multi-factor authentication for staff accounts
This project was originally a procedural script using raw string-formatted SQL queries and unhashed credentials, and was rewritten into the object-oriented, security-conscious structure described above.