diff --git a/app/resources/payoff.py b/app/resources/payoff.py new file mode 100644 index 0000000..dba5c70 --- /dev/null +++ b/app/resources/payoff.py @@ -0,0 +1,73 @@ +"""Pay-off endpoints.""" +from datetime import date +from decimal import Decimal +from enum import Enum +from typing import Optional + +from fastapi import APIRouter +from pydantic import BaseModel, Field, validator + +from app.logging import get_logger + +router = APIRouter() +logger = get_logger(__name__) + + +class PayoffStatus(str, Enum): + """Enum for payoff status values.""" + PROCESSED = "processed" + PENDING = "pending" + FAILED = "failed" + CANCELLED = "cancelled" + + +class PayoffRequest(BaseModel): + """Request model for loan payoff.""" + loan_id: str = Field(..., description="Loan identifier", min_length=1, max_length=50) + payoff_amount: Decimal = Field(..., description="Payoff amount", gt=0, decimal_places=2) + payoff_date: date = Field(..., description="Payoff date") + borrower_name: Optional[str] = Field(None, description="Borrower name", max_length=100) + payment_method: str = Field(..., description="Payment method", regex="^(check|wire|ach|cash)$") + notes: Optional[str] = Field(None, description="Additional notes", max_length=500) + + @validator('payoff_date') + def validate_payoff_date(cls, v): + """Validate payoff date is not in the future.""" + from datetime import date + if v > date.today(): + raise ValueError('Payoff date cannot be in the future') + return v + + +class PayoffResponse(BaseModel): + """Response model for loan payoff.""" + status: PayoffStatus + loan_id: str + payoff_amount: Decimal + payoff_date: date + transaction_id: str + + +@router.post("/payoff", response_model=PayoffResponse) +async def create_payoff(payoff_request: PayoffRequest) -> PayoffResponse: + """Create a loan payoff record.""" + + logger.info(f"Processing payoff for loan {payoff_request.loan_id}") + + # TODO: Add database logic to process payoff + # For now, return a mock response + + import uuid + transaction_id = str(uuid.uuid4()) + + response = PayoffResponse( + status=PayoffStatus.PROCESSED, + loan_id=payoff_request.loan_id, + payoff_amount=payoff_request.payoff_amount, + payoff_date=payoff_request.payoff_date, + transaction_id=transaction_id + ) + + logger.info(f"Payoff processed successfully for loan {payoff_request.loan_id}, transaction {transaction_id}") + + return response diff --git a/main.py b/main.py index cba66d7..72cfdf1 100644 --- a/main.py +++ b/main.py @@ -9,7 +9,7 @@ from sentry_sdk.integrations.fastapi import FastApiIntegration from app.config import settings from app.logging import configure_logging, get_logger from app.middleware import logging_middleware -from app.resources import health +from app.resources import health, payoff def create_app() -> FastAPI: @@ -43,6 +43,7 @@ def create_app() -> FastAPI: # Include all endpoint routers app.include_router(health.router, tags=["health"]) + app.include_router(payoff.router, tags=["payoff"]) return app