74 lines
2.3 KiB
Python
74 lines
2.3 KiB
Python
"""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
|