gopalswami commited on
Commit
2a79756
·
1 Parent(s): edace29

Implement evaluation status API and enhance RFP service with deficiency check logic

Browse files
src/controllers/_rfp_controller.py CHANGED
@@ -1,14 +1,14 @@
1
  from fastapi import Path
2
  from fastapi import APIRouter, HTTPException, Query
3
  from pydantic import BaseModel, Field, field_validator
4
- from typing import List, Optional
5
  from uuid import UUID
6
 
7
  from src.config import logger
8
  from src.services import RFPService
9
  from datetime import datetime
10
 
11
- from src.models import RFPStatus
12
 
13
 
14
  class RFP(BaseModel):
@@ -65,6 +65,13 @@ class RFPDeleteResponse(BaseModel):
65
  status: str
66
 
67
 
 
 
 
 
 
 
 
68
  class RFPController:
69
  def __init__(self):
70
  self.__rfp_service = RFPService
@@ -104,6 +111,13 @@ class RFPController:
104
  response_model=RFPDeleteResponse,
105
  tags=["RFPs by ID"],
106
  )
 
 
 
 
 
 
 
107
 
108
  async def get_rfps(self, status: Optional[RFPStatus] = Query(None)):
109
  async with self.__rfp_service() as service:
@@ -168,3 +182,15 @@ class RFPController:
168
  except Exception as e:
169
  logger.exception(e)
170
  raise HTTPException(status_code=500, detail="Failed to delete RFP.")
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from fastapi import Path
2
  from fastapi import APIRouter, HTTPException, Query
3
  from pydantic import BaseModel, Field, field_validator
4
+ from typing import List, Optional, Dict, Any
5
  from uuid import UUID
6
 
7
  from src.config import logger
8
  from src.services import RFPService
9
  from datetime import datetime
10
 
11
+ from src.models import RFPStatus, AnalysisType
12
 
13
 
14
  class RFP(BaseModel):
 
65
  status: str
66
 
67
 
68
+ class EvaluationStatusResponse(BaseModel):
69
+ status: bool
70
+
71
+ class EvaluationStatus(BaseModel):
72
+ data: EvaluationStatusResponse
73
+
74
+
75
  class RFPController:
76
  def __init__(self):
77
  self.__rfp_service = RFPService
 
111
  response_model=RFPDeleteResponse,
112
  tags=["RFPs by ID"],
113
  )
114
+ self.router.add_api_route(
115
+ "/rfps/{rfp_id}/evaluation-status",
116
+ self.get_evaluation_status,
117
+ methods=["GET"],
118
+ response_model=EvaluationStatus,
119
+ tags=["RFPs Evaluation Status"],
120
+ )
121
 
122
  async def get_rfps(self, status: Optional[RFPStatus] = Query(None)):
123
  async with self.__rfp_service() as service:
 
182
  except Exception as e:
183
  logger.exception(e)
184
  raise HTTPException(status_code=500, detail="Failed to delete RFP.")
185
+
186
+ async def get_evaluation_status(self, rfp_id: str = Path(...)):
187
+ async with self.__rfp_service() as service:
188
+ try:
189
+ has_deficiencies = await service.check_deficiencies(rfp_id)
190
+ return EvaluationStatus(data=EvaluationStatusResponse(status=has_deficiencies))
191
+ except HTTPException as e:
192
+ logger.warning(e)
193
+ raise e
194
+ except Exception as e:
195
+ logger.exception(e)
196
+ raise HTTPException(status_code=500, detail="Failed to check evaluation status.")
src/services/_rfp_service.py CHANGED
@@ -1,10 +1,13 @@
1
- from src.models import RFP, RFPStatus
2
- from src.repositories import RFPRepository
3
 
4
 
5
  class RFPService:
6
  def __init__(self):
7
  self.rfp_repository = RFPRepository
 
 
 
8
 
9
  async def __aenter__(self):
10
  return self
@@ -27,3 +30,32 @@ class RFPService:
27
  async def delete_rfp(self, rfp_id: str):
28
  async with self.rfp_repository() as repository:
29
  return await repository.delete_rfp(rfp_id)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from src.models import RFP, RFPStatus, AnalysisType
2
+ from src.repositories import RFPRepository, ProposalRepository, ProposalEvaluationRepository, AnalysisRepository
3
 
4
 
5
  class RFPService:
6
  def __init__(self):
7
  self.rfp_repository = RFPRepository
8
+ self.proposal_repository = ProposalRepository
9
+ self.evaluation_repository = ProposalEvaluationRepository
10
+ self.analysis_repository = AnalysisRepository
11
 
12
  async def __aenter__(self):
13
  return self
 
30
  async def delete_rfp(self, rfp_id: str):
31
  async with self.rfp_repository() as repository:
32
  return await repository.delete_rfp(rfp_id)
33
+
34
+ async def check_deficiencies(self, rfp_id: str) -> bool:
35
+ async with self.proposal_repository() as proposal_repo:
36
+ proposals = await proposal_repo.get_proposals(rfp_id=rfp_id)
37
+ if not proposals:
38
+ return False
39
+
40
+ for proposal in proposals:
41
+ proposal_id = proposal["id"]
42
+
43
+ async with self.evaluation_repository() as eval_repo:
44
+ evaluations = await eval_repo.get_evaluations(proposal_id=proposal_id)
45
+
46
+ if not evaluations:
47
+ continue
48
+
49
+ for evaluation in evaluations:
50
+ evaluation_id = evaluation["id"]
51
+
52
+ async with self.analysis_repository() as analysis_repo:
53
+ deficiencies = await analysis_repo.get_analysis(
54
+ evaluation_id=evaluation_id,
55
+ analysis_type=AnalysisType.DEFICIENCIES
56
+ )
57
+
58
+ if deficiencies:
59
+ return True
60
+
61
+ return False