ipns-sow / src /controllers /_rfp_controller.py
Aryan Jain
add apis for rfp
3e28a11
from fastapi import Path
from fastapi import APIRouter, HTTPException, Query
from pydantic import BaseModel, Field, field_validator
from typing import List, Optional
from uuid import UUID
from src.config import logger
from src.services import RFPService
from datetime import datetime
from src.models import RFPStatus
class RFP(BaseModel):
id: UUID
solicitation_no: str
solicitation_title: str
google_drive_id: Optional[str] = None
status: RFPStatus
created_at: datetime
updated_at: datetime
class ResponseRFP(BaseModel):
status: str
data: Optional[List[RFP]]
class REFPSingleResponse(BaseModel):
status: str
data: RFP
class RFPRequest(BaseModel):
solicitation_no: str
solicitation_title: str
google_drive_id: Optional[str] = None
status: Optional[RFPStatus] = None
class RFPUpdateRequest(BaseModel):
solicitation_no: Optional[str] = None
solicitation_title: Optional[str] = None
google_drive_id: Optional[str] = None
status: Optional[RFPStatus] = None
class RFPDeleteResponse(BaseModel):
status: str
class RFPController:
def __init__(self):
self.__rfp_service = RFPService
self.router = APIRouter()
self.router.add_api_route(
"/rfps",
self.get_rfps,
methods=["GET"],
response_model=ResponseRFP,
tags=["RFPs"],
)
self.router.add_api_route(
"/rfps/{rfp_id}",
self.get_rfps_by_id,
methods=["GET"],
response_model=REFPSingleResponse,
tags=["RFPs by ID"],
)
self.router.add_api_route(
"/rfps",
self.create_rfp,
methods=["POST"],
response_model=REFPSingleResponse,
tags=["RFPs"],
)
self.router.add_api_route(
"/rfps/{rfp_id}",
self.update_rfp,
methods=["PATCH"],
response_model=REFPSingleResponse,
tags=["RFPs by ID"],
)
self.router.add_api_route(
"/rfps/{rfp_id}",
self.delete_rfp,
methods=["DELETE"],
response_model=RFPDeleteResponse,
tags=["RFPs by ID"],
)
async def get_rfps(self, status: Optional[RFPStatus] = Query(None)):
async with self.__rfp_service() as service:
try:
rfps = await service.get_rfps(status=status)
return ResponseRFP(status="success", data=[RFP(**rfp) for rfp in rfps])
except HTTPException as e:
logger.warning(e)
raise e
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail="Failed to retrieve RFPs.")
async def get_rfps_by_id(self, rfp_id: UUID = Path(...)):
async with self.__rfp_service() as service:
try:
rfps = await service.get_rfps(rfp_id=rfp_id)
rfp = rfps[0]
return REFPSingleResponse(status="success", data=RFP(**rfp))
except HTTPException as e:
logger.warning(e)
raise e
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail="Failed to retrieve RFPs.")
async def create_rfp(self, rfp: RFPRequest):
async with self.__rfp_service() as service:
try:
rfp = await service.create_rfp(rfp.model_dump(exclude_unset=True))
return REFPSingleResponse(status="success", data=RFP(**rfp))
except HTTPException as e:
logger.warning(e)
raise e
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail="Failed to create RFP.")
async def update_rfp(self, rfp: RFPUpdateRequest, rfp_id: UUID = Path(...)):
async with self.__rfp_service() as service:
try:
rfp = await service.update_rfp(
rfp_id=rfp_id, rfp=rfp.model_dump(exclude_unset=True)
)
return REFPSingleResponse(status="success", data=RFP(**rfp))
except HTTPException as e:
logger.warning(e)
raise e
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail="Failed to update RFP.")
async def delete_rfp(self, rfp_id: UUID = Path(...)):
async with self.__rfp_service() as service:
try:
status = await service.delete_rfp(rfp_id)
if not status:
raise HTTPException(status_code=404, detail="RFP not found.")
return RFPDeleteResponse(status="success")
except HTTPException as e:
logger.warning(e)
raise e
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail="Failed to delete RFP.")