varshakolanu commited on
Commit
09c69ec
·
verified ·
1 Parent(s): b9012d2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +109 -31
app.py CHANGED
@@ -1,40 +1,118 @@
1
- from fastapi import FastAPI
2
- from pydantic import BaseModel
 
 
3
  import uvicorn
 
4
 
5
- app = FastAPI()
 
 
 
6
 
7
  # Define the request body structure
8
  class VendorLog(BaseModel):
9
- work_logs: int
10
- delay_logs: int
11
- quality_logs: int
12
- incident_logs: int
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
- # Scoring logic
15
- @app.post("/score")
 
 
 
 
 
 
 
16
  async def calculate_score(logs: VendorLog):
17
- # Simple scoring logic (you can customize this)
18
- quality_score = (logs.quality_logs / (logs.work_logs + 1)) * 100
19
- timeliness_score = (1 - logs.delay_logs / (logs.work_logs + 1)) * 100
20
- safety_score = (1 - logs.incident_logs / (logs.work_logs + 1)) * 100
21
- communication_score = 50 # Placeholder, adjust based on your logic
22
-
23
- # Final score (average of individual scores)
24
- final_score = (quality_score + timeliness_score + safety_score + communication_score) / 4
25
-
26
- # Alert flag logic (example: flag if final score < 50)
27
- alert_flag = final_score < 50
28
-
29
- return {
30
- "final_score": round(final_score, 2),
31
- "alert_flag": alert_flag,
32
- "quality_score": round(quality_score, 2),
33
- "timeliness_score": round(timeliness_score, 2),
34
- "safety_score": round(safety_score, 2),
35
- "communication_score": round(communication_score, 2)
36
- }
37
-
38
- # Run the server
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  if __name__ == "__main__":
40
  uvicorn.run(app, host="0.0.0.0", port=8000)
 
1
+ from fastapi import FastAPI, HTTPException
2
+ from pydantic import BaseModel, Field
3
+ from typing import List, Optional
4
+ from datetime import datetime
5
  import uvicorn
6
+ import numpy as np
7
 
8
+ app = FastAPI(title="Vendor Performance Scoring API", description="API for calculating vendor performance scores with trend detection")
9
+
10
+ # In-memory store for historical scores (replace with database for production)
11
+ historical_scores = []
12
 
13
  # Define the request body structure
14
  class VendorLog(BaseModel):
15
+ vendor_id: str = Field(..., description="Unique identifier for the vendor")
16
+ delay_logs: int = Field(..., ge=0, description="Number of delay incidents")
17
+ qa_incidents: int = Field(..., ge=0, description="Number of quality assurance incidents")
18
+ safety_compliance: int = Field(..., ge=0, description="Number of safety compliance issues")
19
+ feedback_logs: int = Field(..., ge=0, description="Number of feedback logs")
20
+ work_logs: int = Field(..., ge=1, description="Total number of work logs")
21
+ month: str = Field(..., description="Month of the score (YYYY-MM format)")
22
+
23
+ # Define the response structure
24
+ class ScoreResponse(BaseModel):
25
+ vendor_id: str
26
+ month: str
27
+ final_score: float
28
+ quality_score: float
29
+ timeliness_score: float
30
+ safety_score: float
31
+ communication_score: float
32
+ alert_flag: bool
33
+ trend_deviation: Optional[float]
34
+ certification_url: Optional[str]
35
 
36
+ # Scoring weights (configurable)
37
+ WEIGHTS = {
38
+ "quality": 0.3,
39
+ "timeliness": 0.3,
40
+ "safety": 0.2,
41
+ "communication": 0.2
42
+ }
43
+
44
+ @app.post("/score", response_model=ScoreResponse)
45
  async def calculate_score(logs: VendorLog):
46
+ try:
47
+ # Validate month format
48
+ datetime.strptime(logs.month, "%Y-%m")
49
+
50
+ # Calculate individual scores
51
+ quality_score = (1 - logs.qa_incidents / logs.work_logs) * 100
52
+ timeliness_score = (1 - logs.delay_logs / logs.work_logs) * 100
53
+ safety_score = (1 - logs.safety_compliance / logs.work_logs) * 100
54
+ communication_score = (logs.feedback_logs / logs.work_logs) * 50 # Adjusted logic
55
+
56
+ # Ensure scores are within 0-100
57
+ quality_score = max(0, min(100, quality_score))
58
+ timeliness_score = max(0, min(100, timeliness_score))
59
+ safety_score = max(0, min(100, safety_score))
60
+ communication_score = max(0, min(100, communication_score))
61
+
62
+ # Calculate weighted final score
63
+ final_score = (
64
+ WEIGHTS["quality"] * quality_score +
65
+ WEIGHTS["timeliness"] * timeliness_score +
66
+ WEIGHTS["safety"] * safety_score +
67
+ WEIGHTS["communication"] * communication_score
68
+ )
69
+
70
+ # Alert flag logic
71
+ alert_flag = final_score < 50
72
+
73
+ # Trend detection (compare with historical scores for this vendor)
74
+ vendor_history = [score for score in historical_scores if score["vendor_id"] == logs.vendor_id]
75
+ trend_deviation = None
76
+ if len(vendor_history) >= 2:
77
+ previous_scores = [score["final_score"] for score in vendor_history[-2:]]
78
+ trend_deviation = final_score - np.mean(previous_scores)
79
+
80
+ # Store the current score
81
+ historical_scores.append({
82
+ "vendor_id": logs.vendor_id,
83
+ "month": logs.month,
84
+ "final_score": final_score,
85
+ "quality_score": quality_score,
86
+ "timeliness_score": timeliness_score,
87
+ "safety_score": safety_score,
88
+ "communication_score": communication_score
89
+ })
90
+
91
+ # Mock certification URL (replace with actual logic)
92
+ certification_url = f"https://example.com/cert/{logs.vendor_id}"
93
+
94
+ return {
95
+ "vendor_id": logs.vendor_id,
96
+ "month": logs.month,
97
+ "final_score": round(final_score, 2),
98
+ "quality_score": round(quality_score, 2),
99
+ "timeliness_score": round(timeliness_score, 2),
100
+ "safety_score": round(safety_score, 2),
101
+ "communication_score": round(communication_score, 2),
102
+ "alert_flag": alert_flag,
103
+ "trend_deviation": round(trend_deviation, 2) if trend_deviation is not None else None,
104
+ "certification_url": certification_url
105
+ }
106
+
107
+ except ValueError as e:
108
+ raise HTTPException(status_code=400, detail=f"Invalid month format: {str(e)}")
109
+ except Exception as e:
110
+ raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
111
+
112
+ # Health check endpoint
113
+ @app.get("/health")
114
+ async def health_check():
115
+ return {"status": "healthy"}
116
+
117
  if __name__ == "__main__":
118
  uvicorn.run(app, host="0.0.0.0", port=8000)