ipns-poc-eval / src /controllers /_proposal_evaluation_controller.py
Aryan Jain
decimal upto 2 places
90dfc4a
from fastapi import APIRouter, HTTPException, Query, Path
from pydantic import BaseModel, field_validator
from typing import List, Optional
from uuid import UUID
from datetime import datetime
from src.config import logger
from src.models import EvaluationType
from src.services import ProposalEvaluationService
class Evaluation(BaseModel):
id: UUID
proposal_id: UUID
evaluation_type: EvaluationType
ai_score: Optional[float] = None
adjusted_score: Optional[float] = None
created_at: datetime
updated_at: datetime
@field_validator("ai_score", "adjusted_score")
@classmethod
def round_to_two_decimals(cls, v):
if v is not None:
return round(v, 2)
return v
class Response(BaseModel):
status: str
data: Optional[List[Evaluation]] = None
class RequestEvaluation(BaseModel):
evaluation_type: Optional[EvaluationType] = None
ai_score: Optional[float] = None
adjusted_score: Optional[float] = None
class DeleteResponse(BaseModel):
status: str
class CreateEvaluation(BaseModel):
evaluation_type: EvaluationType
ai_score: Optional[float] = None
adjusted_score: Optional[float] = None
class CreateEvaluationRequest(BaseModel):
data: List[CreateEvaluation]
class UpdateEvaluation(BaseModel):
evaluation_type: Optional[EvaluationType] = None
ai_score: Optional[float] = None
adjusted_score: Optional[float] = None
class ProposalEvaluationController:
def __init__(self):
self.service = ProposalEvaluationService
self.router = APIRouter()
self.router.add_api_route(
"/rfps/{rfp_id}/proposals/{proposal_id}/evaluations",
self.get_evaluation_by_proposal_and_rfp_id,
methods=["GET"],
response_model=Response,
tags=["Evaluations by Proposal and RFP ID"],
)
self.router.add_api_route(
"/rfps/{rfp_id}/proposals/{proposal_id}/evaluations/{id}",
self.get_evaluation_by_proposal_and_rfp_id_and_id,
methods=["GET"],
response_model=Response,
tags=["Evaluations by Proposal and RFP ID and ID"],
)
self.router.add_api_route(
"/rfps/{rfp_id}/proposals/{proposal_id}/evaluations",
self.create_evaluation_by_proposal_and_rfp_id,
methods=["POST"],
response_model=Response,
tags=["Evaluations by Proposal and RFP ID"],
)
self.router.add_api_route(
"/rfps/{rfp_id}/proposals/{proposal_id}/evaluations/{id}",
self.update_evaluation_by_proposal_and_rfp_id_and_id,
methods=["PUT"],
response_model=Response,
tags=["Evaluations by Proposal and RFP ID and ID"],
)
self.router.add_api_route(
"/rfps/{rfp_id}/proposals/{proposal_id}/evaluations",
self.delete_evaluation_by_proposal_and_rfp_id,
methods=["DELETE"],
response_model=DeleteResponse,
tags=["Evaluations by Proposal and RFP ID"],
)
self.router.add_api_route(
"/rfps/{rfp_id}/proposals/{proposal_id}/evaluations/{id}",
self.delete_evaluation_by_proposal_and_rfp_id_and_id,
methods=["DELETE"],
response_model=DeleteResponse,
tags=["Evaluations by Proposal and RFP ID and ID"],
)
async def get_evaluation_by_proposal_and_rfp_id(
self,
rfp_id: str = Path(...),
proposal_id: str = Path(...),
evaluation_type: Optional[EvaluationType] = Query(None),
):
try:
async with self.service() as service:
results = await service.get_evaluations(
proposal_id=proposal_id, evaluation_type=evaluation_type
)
return Response(
status="success",
data=[Evaluation(**result) for result in results],
)
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail="Failed to retrieve proposals.")
async def get_evaluation_by_proposal_and_rfp_id_and_id(
self, rfp_id: str = Path(...), proposal_id: str = Path(...), id: str = Path(...)
):
try:
async with self.service() as service:
result = await service.get_evaluations(proposal_id=proposal_id, id=id)
return Response(
status="success",
data=[Evaluation(**result) for result in result],
)
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail="Failed to retrieve proposals.")
async def create_evaluation_by_proposal_and_rfp_id(
self,
evaluation: CreateEvaluationRequest,
rfp_id: str = Path(...),
proposal_id: str = Path(...),
):
try:
async with self.service() as service:
result = await service.create_evaluations(
proposal_id=proposal_id,
evaluations=evaluation.model_dump(mode="json", exclude_unset=True)[
"data"
],
)
return Response(
status="success",
data=[Evaluation(**result) for result in result],
)
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail="Failed to retrieve proposals.")
async def update_evaluation_by_proposal_and_rfp_id_and_id(
self,
evaluation: UpdateEvaluation,
rfp_id: str = Path(...),
proposal_id: str = Path(...),
id: str = Path(...),
):
try:
async with self.service() as service:
result = await service.update_evaluations(
proposal_id=proposal_id,
id=id,
evaluations=evaluation.model_dump(mode="json", exclude_unset=True),
)
return Response(
status="success",
data=[Evaluation(**result) for result in result],
)
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail="Failed to retrieve proposals.")
async def delete_evaluation_by_proposal_and_rfp_id(
self, rfp_id: str = Path(...), proposal_id: str = Path(...)
):
try:
async with self.service() as service:
result = await service.delete_evaluations(proposal_id=proposal_id)
return DeleteResponse(status="success")
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail="Failed to retrieve proposals.")
async def delete_evaluation_by_proposal_and_rfp_id_and_id(
self, rfp_id: str = Path(...), proposal_id: str = Path(...), id: str = Path(...)
):
try:
async with self.service() as service:
result = await service.delete_evaluations(
proposal_id=proposal_id, id=id
)
return DeleteResponse(status="success")
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail="Failed to retrieve proposals.")