# Backend Specification

## 1. System Summary

**System Name:** Simple Loan Calculator

**Description:** A single-page web application that calculates loan payments, total interest, and generates amortization schedules for anonymous users. The system provides comprehensive loan calculation capabilities including monthly payment computation, total interest calculation, and detailed period-by-period amortization schedules with export functionality.

**Primary Users:** Anonymous users (no authentication required)

**Core Capabilities:**
- Calculate monthly loan payments using standard amortization formula
- Generate complete amortization schedules with payment breakdowns
- Export calculation results in CSV and PDF formats
- Track user sessions for analytics purposes
- Support loan amounts up to $1 billion with terms up to 50 years

## 2. Source Input Summary

This backend specification is derived from the following source materials:

- **DDL Schema:** `/home/ubuntu/dpg/pipeline/step-02-prd-generation/output/20260514_021925/schema.sql`
  - Defines three tables: `loan_calculations`, `amortization_schedule_entries`, `calculation_sessions`
  - Includes comprehensive field definitions with appropriate data types and constraints
  
- **PRD Document:** `/home/ubuntu/dpg/pipeline/step-02-prd-generation/output/20260514_021925/full_prd.md`
  - Contains detailed workflows for loan calculation, amortization schedule viewing, reset, and export
  - Specifies business rules, validation requirements, and calculation formulas
  
- **Domain:** `freemeal.dev.dalfin.ai`

- **Additional Inputs:** Prompt provided; no images provided

## 3. Generation Mode

**Mode:** `strict`

In strict mode, the backend implementation must:
- Adhere precisely to the entity definitions, field types, and relationships specified in the DDL schema
- Implement all business rules and validation rules exactly as documented
- Generate only the API endpoints explicitly listed or implied by the PRD workflows
- Use the exact calculation formulas specified in the business rules
- Maintain data integrity constraints as defined in the schema
- Not deviate from the specified architecture patterns

## 4. Backend Scope

The backend system encompasses two primary modules:

### Module 1: loan_calculation
**Entities:** `Loancalculation`, `Amortizationscheduleentry`

**Responsibilities:**
- Execute loan payment calculations using standard amortization formula
- Generate complete amortization schedules with period-by-period breakdowns
- Compute total interest and total amount paid over loan term
- Handle payment breakdown into principal and interest portions
- Manage cumulative totals for interest and principal
- Adjust final payment for rounding differences
- Support export functionality for calculation results

### Module 2: session_tracking
**Entities:** `Calculationsession`

**Responsibilities:**
- Track anonymous user sessions for analytics
- Maintain calculation count per session
- Record user agent information for device/browser analytics
- Update last activity timestamps
- Support session-based calculation history (optional)

## 5. Roles

### AnonymousUser
**Description:** Unauthenticated users who access the loan calculator

**Permissions:**
- Create new loan calculations
- View calculation results and amortization schedules
- Export calculation results in CSV and PDF formats
- Reset calculator to perform new calculations
- No data persistence or account management required

**Access Level:** Full access to all calculation and export features without authentication

## 6. Entities and Fields

### Entity: Loancalculation

**Table Name:** `loan_calculations`

**Description:** Represents a single loan calculation instance with input parameters and computed results

| Field Name | Type | Required | Description |
|------------|------|----------|-------------|
| id | str | Yes | Unique identifier (UUID) |
| principal | Decimal | Yes | The loan amount borrowed |
| annual_interest_rate | Decimal | Yes | Annual interest rate as a percentage |
| loan_term_months | int | Yes | Duration of the loan in months |
| monthly_payment | Decimal | Yes | Calculated monthly payment amount |
| total_interest | Decimal | Yes | Total interest paid over loan term |
| total_amount | Decimal | Yes | Total amount paid (principal + interest) |
| calculation_method | str | Yes | Method used for calculation (e.g., "standard-amortization") |
| session_id | Optional[str] | No | Reference to calculation session |
| created_at | datetime | Yes | Creation timestamp |
| updated_at | datetime | Yes | Last update timestamp |

**Status Field:** None (entity does not have status tracking)

**Indexes:**
- Primary key on `id`
- Index on `session_id` for session-based queries
- Index on `created_at` for temporal queries

---

### Entity: Amortizationscheduleentry

**Table Name:** `amortization_schedule_entries`

**Description:** Represents a single payment period in the loan amortization schedule

| Field Name | Type | Required | Description |
|------------|------|----------|-------------|
| id | str | Yes | Unique identifier (UUID) |
| loan_calculation_id | str | Yes | Reference to parent loan calculation |
| payment_number | int | Yes | Sequential payment number (1 to N) |
| payment_date | Optional[date] | No | Scheduled payment date |
| beginning_balance | Decimal | Yes | Loan balance at start of period |
| payment_amount | Decimal | Yes | Total payment for the period |
| principal_portion | Decimal | Yes | Amount applied to principal |
| interest_portion | Decimal | Yes | Amount applied to interest |
| ending_balance | Decimal | Yes | Loan balance at end of period |
| cumulative_interest | Decimal | Yes | Total interest paid to date |
| cumulative_principal | Decimal | Yes | Total principal paid to date |
| created_at | datetime | Yes | Creation timestamp |
| updated_at | datetime | Yes | Last update timestamp |

**Status Field:** None

**Indexes:**
- Primary key on `id`
- Foreign key index on `loan_calculation_id`
- Composite index on `(loan_calculation_id, payment_number)` for ordered retrieval

---

### Entity: Calculationsession

**Table Name:** `calculation_sessions`

**Description:** Tracks user session for analytics and temporary storage

| Field Name | Type | Required | Description |
|------------|------|----------|-------------|
| id | str | Yes | Unique identifier (UUID) |
| session_id | str | Yes | Unique session identifier |
| calculation_count | int | Yes | Number of calculations performed in session |
| user_agent | Optional[str] | No | Browser/device information |
| last_activity_at | datetime | Yes | Last interaction time |
| created_at | datetime | Yes | Creation timestamp |
| updated_at | datetime | Yes | Last update timestamp |

**Status Field:** None

**Indexes:**
- Primary key on `id`
- Unique index on `session_id`
- Index on `last_activity_at` for session cleanup queries

## 7. Enumerations

No enumerations are defined in this system. The `calculation_method` field uses string values (e.g., "standard-amortization") but is not constrained to a predefined enum set to allow for future calculation method extensions.

## 8. Relationships

### Relationship 1: AmortizationScheduleEntry → LoanCalculation

**Type:** Many-to-One (required)

**Description:** Each amortization schedule entry belongs to exactly one loan calculation

**Foreign Key:** `amortization_schedule_entries.loan_calculation_id` → `loan_calculations.id`

**Navigation Required:** Yes

**Cascade Behavior:** DELETE CASCADE (when a loan calculation is deleted, all associated schedule entries are deleted)

**Usage:** Required for retrieving complete amortization schedules and ensuring data integrity

---

### Relationship 2: LoanCalculation → CalculationSession

**Type:** Many-to-One (optional)

**Description:** A loan calculation may optionally belong to a calculation session for analytics tracking

**Foreign Key:** `loan_calculations.session_id` → `calculation_sessions.session_id`

**Navigation Required:** No

**Cascade Behavior:** SET NULL (when a session is deleted, loan calculations remain but session_id is nulled)

**Usage:** Optional relationship for analytics and session-based calculation history

## 9. API Endpoints

### Loan Calculation Endpoints

#### POST /loan-calculations/calculate
**Description:** Performs a complete loan calculation including amortization schedule generation

**Request Body:**
```json
{
  "principal": "decimal",
  "annual_interest_rate": "decimal",
  "loan_term_months": "integer",
  "session_id": "string (optional)"
}
```

**Response:** Complete loan calculation with embedded amortization schedule

**Business Logic:** Validates inputs, calculates monthly payment, generates amortization schedule, creates LoanCalculation and AmortizationScheduleEntry records in a transaction

---

#### GET /loan-calculations/{id}
**Description:** Retrieves a specific loan calculation by ID

**Path Parameters:** `id` (string, UUID)

**Response:** LoanCalculation entity with all fields

---

#### GET /loan-calculations/{id}/details
**Description:** Retrieves loan calculation with complete amortization schedule (detail endpoint)

**Path Parameters:** `id` (string, UUID)

**Response:** LoanCalculation with eager-loaded amortization_schedule_entries array

**Eager Load Paths:** `LoanCalculation.amortization_schedule_entries`

**Response Includes:**
- All LoanCalculation fields
- `amortization_schedule_entries[]` array containing:
  - payment_number
  - payment_date
  - beginning_balance
  - payment_amount
  - principal_portion
  - interest_portion
  - ending_balance
  - cumulative_interest
  - cumulative_principal

---

#### GET /loan-calculations/{id}/amortization-schedule
**Description:** Retrieves only the amortization schedule for a specific loan calculation

**Path Parameters:** `id` (string, UUID)

**Response:** Array of AmortizationScheduleEntry entities ordered by payment_number

---

#### GET /loan-calculations/{id}/export-csv
**Description:** Exports loan calculation and amortization schedule as CSV file

**Path Parameters:** `id` (string, UUID)

**Response:** CSV file download with headers and complete schedule data

**Content-Type:** `text/csv`

---

#### GET /loan-calculations/{id}/export-pdf
**Description:** Exports loan calculation and amortization schedule as PDF file

**Path Parameters:** `id` (string, UUID)

**Response:** PDF file download with formatted calculation results and schedule

**Content-Type:** `application/pdf`

---

#### POST /loan-calculations
**Description:** Creates a new loan calculation (standard CRUD)

**Request Body:** LoanCalculation fields (excluding computed fields)

**Response:** Created LoanCalculation entity

---

#### GET /loan-calculations
**Description:** Lists loan calculations with optional filtering

**Query Parameters:**
- `session_id` (optional): Filter by session
- `limit` (optional): Pagination limit
- `offset` (optional): Pagination offset

**Response:** Array of LoanCalculation entities

---

#### PUT /loan-calculations/{id}
**Description:** Updates an existing loan calculation

**Path Parameters:** `id` (string, UUID)

**Request Body:** Partial LoanCalculation fields

**Response:** Updated LoanCalculation entity

---

#### DELETE /loan-calculations/{id}
**Description:** Deletes a loan calculation and associated schedule entries

**Path Parameters:** `id` (string, UUID)

**Response:** 204 No Content

---

### Amortization Schedule Entry Endpoints

#### POST /amortization-schedule-entries
**Description:** Creates a new amortization schedule entry (standard CRUD)

**Request Body:** AmortizationScheduleEntry fields

**Response:** Created AmortizationScheduleEntry entity

---

#### GET /amortization-schedule-entries/{id}
**Description:** Retrieves a specific amortization schedule entry

**Path Parameters:** `id` (string, UUID)

**Response:** AmortizationScheduleEntry entity

---

#### GET /amortization-schedule-entries
**Description:** Lists amortization schedule entries with filtering

**Query Parameters:**
- `loan_calculation_id` (optional): Filter by loan calculation
- `limit` (optional): Pagination limit
- `offset` (optional): Pagination offset

**Response:** Array of AmortizationScheduleEntry entities

---

#### PUT /amortization-schedule-entries/{id}
**Description:** Updates an existing amortization schedule entry

**Path Parameters:** `id` (string, UUID)

**Request Body:** Partial AmortizationScheduleEntry fields

**Response:** Updated AmortizationScheduleEntry entity

---

#### DELETE /amortization-schedule-entries/{id}
**Description:** Deletes a specific amortization schedule entry

**Path Parameters:** `id` (string, UUID)

**Response:** 204 No Content

---

### Calculation Session Endpoints

#### POST /calculation-sessions
**Description:** Creates a new calculation session

**Request Body:** CalculationSession fields

**Response:** Created CalculationSession entity

---

#### GET /calculation-sessions/{id}
**Description:** Retrieves a specific calculation session

**Path Parameters:** `id` (string, UUID)

**Response:** CalculationSession entity

---

#### GET /calculation-sessions
**Description:** Lists calculation sessions

**Query Parameters:**
- `limit` (optional): Pagination limit
- `offset` (optional): Pagination offset

**Response:** Array of CalculationSession entities

---

#### PUT /calculation-sessions/{id}
**Description:** Updates an existing calculation session

**Path Parameters:** `id` (string, UUID)

**Request Body:** Partial CalculationSession fields

**Response:** Updated CalculationSession entity

---

#### DELETE /calculation-sessions/{id}
**Description:** Deletes a calculation session

**Path Parameters:** `id` (string, UUID)

**Response:** 204 No Content

## 10. Workflow Logic

### Workflow 1: Perform Loan Calculation

**Trigger:** User submits loan calculation form with principal, interest rate, and term

**Steps:**

1. **Input Reception**
   - Receive POST request to `/loan-calculations/calculate`
   - Extract principal, annual_interest_rate, loan_term_months, and optional session_id

2. **Input Validation**
   - Validate principal > 0 and ≤ 1,000,000,000
   - Validate annual_interest_rate ≥ 0 and < 100
   - Validate loan_term_months > 0 and ≤ 600
   - Return 400 Bad Request with validation errors if any check fails

3. **Monthly Payment Calculation**
   - Convert annual interest rate to monthly rate: `r = annual_interest_rate / 100 / 12`
   - If interest rate = 0: `monthly_payment = principal / loan_term_months`
   - Else: Apply standard amortization formula: `M = P × [r(1 + r)^n] / [(1 + r)^n - 1]`
   - Round to 2 decimal places for display

4. **Total Calculations**
   - Calculate `total_amount = monthly_payment × loan_term_months`
   - Calculate `total_interest = total_amount - principal`

5. **Amortization Schedule Generation**
   - Initialize `beginning_balance = principal`
   - Initialize `cumulative_interest = 0`, `cumulative_principal = 0`
   - For each payment period (1 to loan_term_months):
     - Calculate `interest_portion = beginning_balance × monthly_rate`
     - Calculate `principal_portion = monthly_payment - interest_portion`
     - Calculate `ending_balance = beginning_balance - principal_portion`
     - Update `cumulative_interest += interest_portion`
     - Update `cumulative_principal += principal_portion`
     - Create AmortizationScheduleEntry record
     - Set `beginning_balance = ending_balance` for next iteration
   - Adjust final payment if ending_balance ≠ 0 (within $0.01 tolerance)

6. **Database Transaction**
   - Begin transaction
   - Create LoanCalculation record with all computed values
   - Batch insert all AmortizationScheduleEntry records
   - If session_id provided, update CalculationSession.calculation_count and last_activity_at
   - Commit transaction

7. **Response**
   - Return 201 Created with complete LoanCalculation and embedded amortization_schedule_entries

**Error Handling:**
- Validation errors: 400 Bad Request
- Database errors: 500 Internal Server Error with rollback
- Invalid session_id: Continue without session tracking (log warning)

---

### Workflow 2: View Amortization Schedule

**Trigger:** User requests to view detailed amortization schedule for a calculation

**Steps:**

1. **Request Reception**
   - Receive GET request to `/loan-calculations/{id}/details` or `/loan-calculations/{id}/amortization-schedule`

2. **Data Retrieval**
   - Query LoanCalculation by ID
   - If not found, return 404 Not Found
   - Eager load associated AmortizationScheduleEntry records
   - Order entries by payment_number ascending

3. **Response Formatting**
   - Format all decimal values to 2 decimal places
   - Include currency symbols and thousand separators
   - Return complete schedule with all fields

4. **Response**
   - Return 200 OK with formatted data

---

### Workflow 3: Reset Calculator

**Trigger:** User clicks reset button (client-side action, no backend endpoint required)

**Steps:**

1. Client-side JavaScript clears all form inputs
2. Client-side JavaScript clears displayed results
3. Client-side JavaScript hides amortization schedule section
4. No backend API call required

**Note:** This is a pure client-side workflow with no backend interaction.

---

### Workflow 4: Export/Download Results

**Trigger:** User clicks download button and selects format (CSV or PDF)

**Steps:**

1. **Request Reception**
   - Receive GET request to `/loan-calculations/{id}/export-csv` or `/loan-calculations/{id}/export-pdf`

2. **Data Retrieval**
   - Query LoanCalculation by ID with eager-loaded amortization schedule
   - If not found, return 404 Not Found

3. **CSV Export (if CSV format selected)**
   - Generate CSV with headers: Payment Number, Payment Date, Beginning Balance, Payment Amount, Principal, Interest, Ending Balance, Cumulative Interest, Cumulative Principal
   - Include summary section with input parameters and totals
   - Format all monetary values with 2 decimal places
   - Set Content-Type: text/csv
   - Set Content-Disposition: attachment; filename="loan-calculation-{id}.csv"

4. **PDF Export (if PDF format selected)**
   - Generate PDF document with formatted layout
   - Include header with calculation summary (principal, rate, term)
   - Include results summary (monthly payment, total interest, total amount)
   - Include formatted amortization schedule table
   - Set Content-Type: application/pdf
   - Set Content-Disposition: attachment; filename="loan-calculation-{id}.pdf"

5. **Response**
   - Return 200 OK with file content and appropriate headers for download

**Error Handling:**
- Calculation not found: 404 Not Found
- File generation error: 500 Internal Server Error

## 11. Business Logic

### Loan Calculation Rules

1. **Principal Constraints**
   - Must be greater than 0
   - Must be less than or equal to 1,000,000,000
   - Stored and calculated as Decimal with minimum 4 decimal places internally
   - Displayed with 2 decimal places

2. **Interest Rate Constraints**
   - Must be greater than or equal to 0
   - Must be less than 100 (exclusive)
   - Stored as annual percentage rate
   - Converted to monthly rate for calculations: `monthly_rate = annual_rate / 100 / 12`

3. **Loan Term Constraints**
   - Must be greater than 0
   - Must be less than or equal to 600 months (50 years)
   - Stored as integer number of months

4. **Monthly Payment Calculation**
   - **Standard Formula (interest rate > 0):**
     ```
     M = P × [r(1 + r)^n] / [(1 + r)^n - 1]
     where:
     M = monthly payment
     P = principal
     r = monthly interest rate (annual_rate / 100 / 12)
     n = loan term in months
     ```
   - **Zero Interest Formula (interest rate = 0):**
     ```
     M = P / n
     ```
   - Result rounded to 2 decimal places for display

5. **Total Interest Calculation**
   - `total_interest = (monthly_payment × loan_term_months) - principal`
   - Must be non-negative

6. **Total Amount Calculation**
   - `total_amount = principal + total_interest`
   - Equals `monthly_payment × loan_term_months` (subject to rounding adjustment)

### Amortization Schedule Rules

7. **Schedule Entry Count**
   - Must contain exactly N entries where N = loan_term_months
   - Entries numbered sequentially from 1 to N

8. **Beginning Balance Rules**
   - First payment beginning_balance must equal loan principal
   - Each subsequent beginning_balance must equal previous ending_balance
   - Validated during generation to ensure continuity

9. **Interest Portion Calculation**
   - `interest_portion = beginning_balance × monthly_interest_rate`
   - Calculated with minimum 4 decimal places internally
   - Rounded to 2 decimal places for storage and display

10. **Principal Portion Calculation**
    - `principal_portion = payment_amount - interest_portion`
    - Must be non-negative (except potentially final payment adjustment)

11. **Ending Balance Calculation**
    - `ending_balance = beginning_balance - principal_portion`
    - Must be non-negative (except final payment which should be 0)
    - Last payment ending_balance must equal 0 (or within $0.01 tolerance)

12. **Final Payment Adjustment**
    - If ending_balance of final payment ≠ 0 due to rounding:
      - Adjust final payment's principal_portion to zero out ending_balance
      - Adjust final payment_amount accordingly
      - Ensure ending_balance = 0.00

13. **Cumulative Totals**
    - `cumulative_interest` = sum of all interest_portion values up to current payment
    - `cumulative_principal` = sum of all principal_portion values up to current payment
    - Final cumulative_interest must equal total_interest (within rounding tolerance)
    - Final cumulative_principal must equal original principal

14. **Validation Checks**
    - Sum of all principal_portion values must equal original loan amount
    - Sum of all interest_portion values must equal total_interest calculated
    - Each period's ending_balance must equal next period's beginning_balance
    - All monetary values must be non-negative (except as noted for adjustments)

### Session Tracking Rules

15. **Session Creation**
    - Create new CalculationSession on first calculation if session_id not provided
    - Generate unique session_id (UUID)
    - Initialize calculation_count = 0
    - Capture user_agent from request headers

16. **Session Updates**
    - Increment calculation_count on each new calculation
    - Update last_activity_at timestamp on each interaction
    - Update updated_at timestamp

17. **Session Association**
    - LoanCalculation.session_id is optional
    - If provided, must reference valid CalculationSession.session_id
    - Session deletion does not delete associated calculations (SET NULL)

### Calculation Method

18. **Calculation Method Field**
    - Default value: "standard-amortization"
    - Stored as string to allow future calculation method extensions
    - Current implementation supports only standard amortization

### Decimal Precision

19. **Internal Precision**
    - All monetary calculations use Decimal type with minimum 4 decimal places
    - Prevents floating-point arithmetic errors
    - Ensures accurate cumulative calculations

20. **Display Precision**
    - All displayed monetary values rounded to 2 decimal places
    - Currency formatting with thousand separators
    - Default currency symbol: $ (USD)

## 12. Validation Rules

### Input Validation

1. **Principal Validation**
   - Must be a valid numeric value (Decimal)
   - Must be positive (> 0)
   - Must not exceed 1,000,000,000
   - Reject non-numeric characters except decimal point
   - Error message: "Principal must be between $0.01 and $1,000,000,000.00"

2. **Annual Interest Rate Validation**
   - Must be a valid numeric value (Decimal)
   - Must be non-negative (≥ 0)
   - Must be less than 100
   - Reject non-numeric characters except decimal point
   - Error message: "Interest rate must be between 0% and 99.99%"

3. **Loan Term Validation**
   - Must be a valid integer
   - Must be positive (> 0)
   - Must not exceed 600 months
   - Reject non-integer values
   - Error message: "Loan term must be between 1 and 600 months"

### Field-Level Validation

4. **UUID Validation**
   - All `id` fields must be valid UUID format
   - Generated automatically on creation
   - Immutable after creation

5. **Foreign Key Validation**
   - `loan_calculation_id` must reference existing LoanCalculation
   - `session_id` (when provided) must reference existing CalculationSession
   - Return 400 Bad Request if foreign key constraint violated

6. **Payment Number Validation**
   - Must be positive integer
   - Must be within range [1, loan_term_months]
   - Must be unique within loan_calculation_id scope

7. **Date Validation**
   - `payment_date` must be valid date format (YYYY-MM-DD)
   - Optional field, can be null
   - If provided, should be chronologically ordered

8. **Decimal Field Validation**
   - All monetary fields must be valid Decimal values
   - Must be non-negative (≥ 0)
   - Precision: up to 4 decimal places internally, 2 for display
   - Reject values that exceed Decimal precision limits

9. **Timestamp Validation**
   - `created_at` set automatically on creation, immutable
   - `updated_at` set automatically on creation and updates
   - Must be valid datetime format (ISO 8601)

### Business Logic Validation

10. **Calculation Result Validation**
    - `monthly_payment` must be positive
    - `total_interest` must be non-negative
    - `total_amount` must equal `principal + total_interest`
    - Validate before persisting to database

11. **Amortization Schedule Validation**
    - Number of entries must equal `loan_term_months`
    - First entry `beginning_balance` must equal `principal`
    - Last entry `ending_balance` must be 0 (within $0.01 tolerance)
    - Each entry's `ending_balance` must equal next entry's `beginning_balance`
    - Sum of all `principal_portion` values must equal `principal`
    - Sum of all `interest_portion` values must equal `total_interest`

12. **Session Validation**
    - `calculation_count` must be non-negative integer
    - `last_activity_at` must not be in the future
    - `session_id` must be unique across all sessions

### Response Validation

13. **Export Validation**
    - Calculation must exist before export
    - Amortization schedule must be complete
    - File generation must succeed before returning response

14. **Negative Value Prevention**
    - No negative values permitted in calculation results
    - No negative values permitted in amortization schedule entries
    - Validation enforced at service layer before database persistence

15. **Required Field Validation**
    - All required fields must be present in create/update requests
    - Return 400 Bad Request with specific field errors
    - Use Pydantic models for automatic validation

## 13. Implementation Notes

### Technology Stack

**Framework:** FastAPI (Python 3.11+)
- Leverages async/await for high-performance I/O operations
- Automatic OpenAPI (Swagger) documentation generation at `/docs`
- Automatic ReDoc documentation at `/redoc`
- Built-in request/response validation using Pydantic v2

**ORM:** SQLAlchemy 2.0+
- Declarative models for all entities
- Async engine support for non-blocking database operations
- Relationship loading with eager/lazy loading strategies
- Transaction management with context managers

**Database:** SQLite (development/demo)
- File-based database for simplicity and portability
- Suitable for single-instance deployments
- No separate database server required
- Easy backup and migration

**Validation:** Pydantic v2
- Schema definitions for all request/response models
- Automatic validation with detailed error messages
- Type coercion and serialization
- Custom validators for business logic

**Package Management:** uv
- Fast Python package installer and resolver
- Dependency management with lock files
- Virtual environment management

### Architecture Patterns

**Service Layer Pattern:**
- Separate service classes for business logic
- Controllers (route handlers) delegate to services
- Services orchestrate repository/ORM operations
- Clear separation of concerns

**Dependency Injection:**
- Use FastAPI's `Depends()` for database session injection
- `get_db()` dependency provides SQLAlchemy session
- Automatic session cleanup and transaction management
- Example:
  ```python
  def get_db():
      db = SessionLocal()
      try:
          yield db
      finally:
          db.close()
  ```

**Repository Pattern (Optional):**
- Consider repository layer for complex queries
- Encapsulates data access logic
- Improves testability and maintainability

### Project Structure

```
backend/
├── app/
│   ├── __init__.py
│   ├── main.py                 # FastAPI application entry point
│   ├── config.py               # Configuration settings
│   ├── database.py             # Database connection and session
│   ├── models/                 # SQLAlchemy ORM models
│   │   ├── __init__.py
│   │   ├── loan_calculation.py
│   │   ├── amortization_schedule_entry.py
│   │   └── calculation_session.py
│   ├── schemas/                # Pydantic models
│   │   ├── __init__.py
│   │   ├── loan_calculation.py
│   │   ├── amortization_schedule_entry.py
│   │   └── calculation_session.py
│   ├── services/               # Business logic layer
│   │   ├── __init__.py
│   │   ├── loan_calculation_service.py
│   │   ├── amortization_service.py
│   │   └── session_service.py
│   ├── routers/                # API route handlers
│   │   ├── __init__.py
│   │   ├── loan_calculations.py
│   │   ├── amortization_schedule.py
│   │   └── sessions.py
│   └── utils/                  # Utility functions
│       ├── __init__.py
│       ├── calculations.py     # Loan calculation formulas
│       ├── export.py           # CSV/PDF export utilities
│       └── validators.py       # Custom validation functions
├── pyproject.toml              # uv project configuration
├── uv.lock                     # Dependency lock file
└── README.md
```

### Key Implementation Details

**Database Session Management:**
- Use FastAPI dependency injection for session lifecycle
- Automatic commit on success, rollback on exception
- Context manager pattern for explicit transaction control

**Decimal Precision:**
- Use Python's `decimal.Decimal` for all monetary calculations
- Set precision context: `getcontext().prec = 28`
- Round to 2 decimal places only for display/storage

**Batch Operations:**
- Use SQLAlchemy's `bulk_insert_mappings()` for amortization schedule entries
- Improves performance for large schedules (up to 600 entries)
- Wrap in transaction for atomicity

**Error Handling:**
- Custom exception classes for business logic errors
- Global exception handler for consistent error responses
- Detailed validation error messages from Pydantic

**CORS Configuration:**
- Enable CORS for frontend integration
- Configure allowed origins for domain `freemeal.dev.dalfin.ai`
- Allow credentials for session tracking

**Logging:**
- Structured logging with JSON format
- Log all calculation requests and results
- Log errors with stack traces
- Separate log levels for development/production

**API Documentation:**
- Automatic OpenAPI schema generation
- Comprehensive endpoint descriptions
- Request/response examples
- Available at `/docs` (Swagger UI) and `/redoc`

### Performance Considerations

**Eager Loading:**
- Use `selectinload()` for amortization schedule entries
- Prevents N+1 query problem
- Single query for calculation + schedule

**Caching:**
- Consider caching calculation results (optional)
- Cache key: hash of input parameters
- TTL: configurable (e.g., 1 hour)

**Pagination:**
- Implement limit/offset pagination for list endpoints
- Default limit: 50, max limit: 1000
- Return total count in response headers

**Database Indexes:**
- Index on `loan_calculations.session_id`
- Composite index on `(loan_calculation_id, payment_number)`
- Index on `calculation_sessions.session_id` (unique)

## 14. Assumptions

1. **No Authentication Required:**
   - System is designed for anonymous users
   - No user accounts, login, or authentication mechanisms
   - All calculations are publicly accessible by ID

2. **Stateless Architecture:**
   - Each request is independent
   - No server-side session state (except optional session tracking)
   - Supports horizontal scaling and load balancing

3. **Session Tracking Optional:**
   - Session tracking is for analytics only
   - System functions fully without session tracking
   - No personally identifiable information (PII) collected

4. **Currency Assumptions:**
   - Default currency is USD ($)
   - Currency symbol and formatting are hardcoded
   - Future support for multiple currencies is planned but not implemented

5. **Calculation Method:**
   - Only standard amortization method is implemented
   - `calculation_method` field allows for future extensions
   - No support for alternative payment schedules (bi-weekly, weekly) in current version

6. **Payment Date Calculation:**
   - Payment dates in amortization schedule are optional
   - If generated, assume monthly intervals from assumed start date
   - No calendar-aware date calculations (e.g., business days)

7. **Data Persistence:**
   - Calculations are persisted to database for retrieval and export
   - No automatic cleanup or expiration of old calculations
   - Manual cleanup or scheduled jobs required for data management

8. **Export Formats:**
   - CSV export uses standard comma-separated format
   - PDF export uses basic formatting (no advanced styling)
   - Print functionality handled by browser (no server-side print endpoint)

9. **Rounding and Precision:**
   - All rounding uses standard "round half up" method
   - Final payment adjustment ensures ending balance = 0
   - Tolerance for rounding errors: $0.01

10. **Scalability:**
    - SQLite suitable for development and small-scale deployments
    - Production deployments should migrate to PostgreSQL
    - Application designed to be stateless for horizontal scaling

11. **Error Handling:**
    - All validation errors return 400 Bad Request
    - Database errors return 500 Internal Server Error
    - Not found errors return 404 Not Found
    - No retry logic for failed operations

12. **API Versioning:**
    - No API versioning in initial implementation
    - Future versions may introduce `/v1/` prefix
    - Breaking changes will require version increment

## 15. Future Improvements

### Infrastructure and DevOps

1. **Database Migration Management:**
   - Implement Alembic for database schema migrations
   - Version-controlled migration scripts
   - Support for rollback and forward migrations
   - Automated migration execution in deployment pipeline

2. **PostgreSQL Migration:**
   - Migrate from SQLite to PostgreSQL for production
   - Improved concurrency and performance
   - Better support for large datasets
   - Advanced indexing and query optimization

3. **Containerization:**
   - Docker containerization for consistent deployments
   - Docker Compose for local development environment
   - Multi-stage builds for optimized image size
   - Kubernetes manifests for orchestration

### Security and Authentication

4. **JWT Authentication:**
   - Implement JWT-based authentication for user accounts
   - Support for registered users to save calculation history
   - Token refresh mechanism
   - Secure token storage and validation

5. **Role-Based Access Control (RBAC):**
   - Define roles: Anonymous, RegisteredUser, Admin
   - Implement permission checks for sensitive operations
   - Admin endpoints for system management
   - Audit logging for privileged actions

6. **API Rate Limiting:**
   - Implement rate limiting to prevent abuse
   - Different limits for anonymous vs. authenticated users
   - Redis-backed rate limiting for distributed systems

### Testing and Quality Assurance

7. **Comprehensive Test Suite:**
   - Unit tests for all service layer functions
   - Integration tests for API endpoints
   - Test coverage target: 90%+
   - Automated test execution in CI/CD pipeline

8. **End-to-End Testing:**
   - Automated E2E tests for critical workflows
   - Test data fixtures and factories
   - Performance testing for calculation-heavy operations

9. **Code Quality Tools:**
   - Linting with Ruff or Pylint
   - Type checking with mypy
   - Code formatting with Black
   - Pre-commit hooks for quality checks

### Monitoring and Observability

10. **Application Monitoring:**
    - Integrate with monitoring tools (Prometheus, Grafana)
    - Track API response times and error rates
    - Database query performance monitoring
    - Alert configuration for critical issues

11. **Structured Logging:**
    - Enhanced logging with correlation IDs
    - Log aggregation with ELK stack or similar
    - Distributed tracing for request flows
    - Performance profiling and bottleneck identification

### Feature Enhancements

12. **Advanced Calculation Features:**
    - Support for bi-weekly and weekly payment schedules
    - Extra payment calculator for early payoff scenarios
    - Refinancing calculator to compare loan options
    - Mortgage-specific features (property tax, insurance, PMI)

13. **Comparison Mode:**
    - Side-by-side comparison of multiple loan scenarios
    - Visual charts for payment breakdown over time
    - Sensitivity analysis for rate and term variations

14. **Multi-Currency Support:**
    - Support for EUR, GBP, and other major currencies
    - Locale-specific formatting and symbols
    - Currency conversion (optional)

15. **Internationalization (i18n):**
    - Multi-language support for global users
    - Translated error messages and documentation
    - Locale-aware date and number formatting

16. **Data Export Enhancements:**
    - Excel export format (.xlsx)
    - Enhanced PDF formatting with charts
    - Email delivery of calculation results
    - Shareable calculation links with URL parameters

17. **Calculation History:**
    - Save calculation history for registered users
    - Compare past calculations
    - Favorite/bookmark calculations
    - Notes and annotations on calculations

18. **API Enhancements:**
    - GraphQL API for flexible data querying
    - Webhook support for calculation events
    - Batch calculation API for multiple scenarios
    - API versioning strategy

### Performance Optimization

19. **Caching Strategy:**
    - Redis caching for frequently accessed calculations
    - Cache invalidation policies
    - CDN integration for static assets

20. **Database Optimization:**
    - Query optimization and indexing strategy
    - Database connection pooling
    - Read replicas for scaling read operations
    - Partitioning for large datasets

---

**End of Backend Specification**
