Skip to content

A full-stack FastAPI application for creating, saving, and analyzing loan scenarios with amortization previews.

License

Notifications You must be signed in to change notification settings

samueltuffour/LoanFlow

Repository files navigation

LoanFlow - Loan Scenario Calculator

A full-stack loan scenario calculator application that allows users to calculate loan payments, save multiple scenarios, and view detailed amortization schedules. Built with FastAPI backend and vanilla HTML/CSS/JavaScript frontend.

Project Overview

LoanFlow provides an intuitive interface for calculating loan payments and managing multiple loan scenarios. Users can:

  • Calculate loan payments with custom amounts, interest rates, and terms
  • Save multiple loan scenarios with descriptive names
  • View saved scenarios with all calculation details
  • Analyze amortization schedules showing payment breakdown (principal vs interest)

Key Features:

  • ✅ Real-time loan calculations using amortization formula
  • ✅ Persistent scenario storage with SQLite database
  • ✅ Detailed amortization schedules (up to 12 months preview)
  • ✅ RESTful API with comprehensive error handling
  • ✅ Responsive web interface
  • ✅ Comprehensive test suite (40 tests)

Tech Stack

Backend

  • Framework: FastAPI 0.104.1 (Python async web framework)
  • Server: Uvicorn 0.24.0 (ASGI server)
  • ORM: SQLAlchemy 2.0.45 (Object-relational mapping)
  • Database: SQLite (file-based, no external setup required)
  • Validation: Pydantic 2.x (data validation and serialization)
  • Environment: Python 3.14

Frontend

  • HTML5: Semantic markup for loan calculator form
  • CSS3: Modern gradient design with responsive layout
  • JavaScript: Vanilla ES6+ (no build tools required)
  • HTTP: Fetch API for backend communication

Testing

  • Framework: pytest 9.0.2
  • HTTP Client: httpx 0.28.1
  • Test Coverage: 40 tests (unit + integration)

Setup Instructions

Prerequisites

  • Python 3.10+
  • Git
  • A web browser

Clone Repository

git clone https://github.com/samueltuffour/LoanFlow.git
cd LoanFlow

Install Backend Dependencies

cd backend
pip install -r requirements.txt

Dependencies include:

  • fastapi - Web framework
  • uvicorn - ASGI server
  • sqlalchemy - Database ORM
  • pydantic-settings - Configuration management
  • pytest - Testing framework
  • httpx - HTTP client for testing

No Frontend Setup Required

Frontend files are static HTML/CSS/JavaScript served directly by Python's http.server.

Running the Application

Start Backend Server

cd backend
python -m uvicorn app.main:app --reload --host 127.0.0.1 --port 8000

Output:

INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started server process
INFO:     Waiting for application startup.
INFO:     Application startup complete.

Start Frontend Server

In a new terminal:

cd frontend
python -m http.server 8080 --bind 127.0.0.1

Output:

Serving HTTP on 127.0.0.1 port 8080 (http://127.0.0.1:8080/) ...

Access Application

Open your browser and navigate to:

http://127.0.0.1:8080

Running Tests

Run All Tests

cd backend
python -m pytest tests/ -v

Run Specific Test File

python -m pytest tests/test_calculations.py -v      # Unit tests
python -m pytest tests/test_api.py -v                # API tests

Run with Coverage Report

python -m pytest tests/ --cov=app --cov-report=html

Expected Output

collected 40 items

tests/test_api.py::TestHealthEndpoints::test_root_endpoint PASSED [ 2%]
tests/test_api.py::TestCalculateEndpoint::test_calculate_basic_loan PASSED [ 7%]
tests/test_calculations.py::TestCalculateMonthlyPayment::test_standard_loan_calculation PASSED [ 55%]
...

======================== 40 passed in 0.92s ========================

API Endpoints

Health Checks

  • GET / - Root endpoint
  • GET /health - Health check

Loan Calculations

  • POST /api/loans/calculate - Calculate loan without saving
  • POST /api/loans/save - Calculate and save scenario
  • GET /api/loans/scenarios - List all saved scenarios
  • GET /api/loans/scenarios/{id} - Get scenario details
  • GET /api/loans/amortization - Get amortization schedule

Loan Calculation Approach

Amortization Formula

LoanFlow uses the standard amortization formula to calculate monthly loan payments:

$$M = P \cdot \frac{r(1+r)^n}{(1+r)^n - 1}$$

Where:

  • M = Monthly payment
  • P = Principal (loan amount)
  • r = Monthly interest rate (annual_rate / 100 / 12)
  • n = Number of payments (years × 12)

Calculation Process

  1. Monthly Payment: Calculated using the amortization formula above
  2. Total Amount Paid: Monthly payment × number of months
  3. Total Interest: Total amount paid - principal
  4. Amortization Schedule: For each payment period:
    • Interest payment = remaining_balance × monthly_rate
    • Principal payment = monthly_payment - interest_payment
    • Remaining balance = previous_balance - principal_payment

Example Calculation

Scenario: $300,000 mortgage at 5% annual interest for 30 years

Monthly Rate (r) = 5 / 100 / 12 = 0.004167
Number of Payments (n) = 30 × 12 = 360

M = 300,000 × [0.004167(1.004167)^360] / [(1.004167)^360 - 1]
M = 300,000 × [0.004167 × 3.8477] / [2.8477]
M = $1,610.06

Total Amount Paid = $1,610.06 × 360 = $579,625
Total Interest = $579,625 - $300,000 = $279,625

Amortization Schedule Progression

The schedule shows how each payment is split between principal and interest:

Period Payment Principal Interest Balance
1 $1,610 $582 $1,028 $299,418
2 $1,610 $585 $1,025 $298,833
... ... ... ... ...
360 $1,610 $1,607 $3 $0

Observation: Early payments are mostly interest; later payments are mostly principal.

Tradeoffs & Assumptions

1. Database Choice: SQLite vs PostgreSQL

Decision: SQLite (file-based database)

Tradeoffs:

Aspect SQLite PostgreSQL
Setup No external setup Requires server
Development Speed ⭐ Faster ⭐⭐ Extra setup
Scalability Single-file Scales to 1000s
Concurrency Limited Excellent

Assumption: Application is for single-user/small-team use during development.

2. Frontend: Vanilla JS vs React/Vue

Decision: Vanilla HTML/CSS/JavaScript (no build tools)

Rationale:

  • Simple calculator interface doesn't require complex state management
  • No build tools = instant setup for students/learners
  • Fast page loads (no bundle overhead)
  • Educational value of understanding HTTP requests

Tradeoff: More manual DOM manipulation vs framework convenience

3. Amortization Formula: Accuracy & Precision

Decision: Standard compound interest formula with rounding

Assumptions:

  • Interest compounds monthly (standard in US mortgages)
  • Payments are fixed (not variable rate)
  • No extra payments or early payoff calculations
  • Rounding to 2 decimal places (standard currency)

Edge Case: Final payment may differ by cents due to rounding accumulation (handled by rounding final balance to zero)

4. Error Handling

Decision: Simplified error responses

Approach:

  • 422 Unprocessable Entity for validation errors (missing/invalid fields)
  • 404 Not Found for nonexistent scenarios
  • 500 Internal Server Error for database/calculation errors

Assumption: Client handles errors appropriately

5. API Design

Decision: RESTful with stateless operations

Reasoning:

  • Each request is independent (stateless)
  • No session management required
  • Easy to test and debug
  • Natural CORS support

Project Structure

LoanFlow/
├── backend/
│   ├── app/
│   │   ├── __init__.py
│   │   ├── main.py                 # FastAPI app setup
│   │   ├── config.py               # Settings/environment
│   │   ├── database/
│   │   │   └── database.py         # SQLAlchemy config
│   │   ├── models/
│   │   │   └── loan.py             # Loan ORM model
│   │   ├── schemas/
│   │   │   └── loan.py             # Pydantic request/response
│   │   ├── routes/
│   │   │   └── loans.py            # API endpoints
│   │   └── utils/
│   │       └── calculations.py     # Amortization logic
│   ├── tests/
│   │   ├── test_calculations.py    # Unit tests
│   │   ├── test_api.py             # Integration tests
│   │   └── conftest.py             # Pytest config
│   ├── requirements.txt            # Python dependencies
│   ├── TESTING.md                  # Testing guide
│   └── run.py                      # Alternative entry point
├── frontend/
│   ├── index.html                  # Main page
│   └── static/
│       ├── css/style.css           # Styling
│       └── js/main.js              # Client logic
├── README.md                       # This file
├── TESTING_SUMMARY.md              # Test documentation
└── DATABASE_ISSUE_RESOLUTION.md    # Debugging guide

Development Workflow

  1. Make changes to backend or frontend files
  2. Backend auto-reloads (uvicorn --reload flag)
  3. Frontend auto-refreshes (browser cache busting with Ctrl+Shift+R)
  4. Run tests to verify changes: pytest tests/ -v
  5. Commit with descriptive message: git commit -m "Feature: ..."
  6. Push to GitHub: git push

Common Issues & Solutions

Issue: "no such table: loans"

Solution: Database tables will auto-create on first startup. Verify backend started without errors.

Issue: Frontend can't reach backend (localhost vs 127.0.0.1)

Solution: Use 127.0.0.1 instead of localhost (Windows networking issue). Both servers run on 127.0.0.1.

Issue: Port already in use (8000 or 8080)

Solution: Change port in startup command:

# Backend on different port
python -m uvicorn app.main:app --host 127.0.0.1 --port 8001

# Frontend on different port
python -m http.server 8081 --bind 127.0.0.1

Testing Summary

  • 40 tests total: 20 unit tests + 20 integration tests
  • 100% endpoint coverage: All 5 API routes tested
  • Calculation validation: All formulas verified
  • Error handling: Edge cases covered

See TESTING_SUMMARY.md for detailed test documentation.

Performance Considerations

  • Calculation Speed: < 1ms for most loans
  • Amortization Schedule: < 10ms even for 30-year loans
  • Database: SQLite sufficient for 1000+ scenarios
  • Frontend Load: HTML/CSS/JS < 100KB total

Future Enhancements

  • Support for different compounding periods (annual, quarterly)
  • Variable rate loans
  • Extra payment calculator
  • Loan comparison tool
  • Export scenarios to PDF
  • User authentication
  • PostgreSQL support for production

License

This project is part of a coding challenge for Summer 2026 internship program.

Author

Samuel Tuffour

Support

For issues or questions, see:

About

A full-stack FastAPI application for creating, saving, and analyzing loan scenarios with amortization previews.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published