Swathi6 commited on
Commit
f1e3572
·
verified ·
1 Parent(s): 5cd0c37

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +61 -48
app.py CHANGED
@@ -10,23 +10,24 @@ from fastapi.responses import HTMLResponse
10
  from simple_salesforce import Salesforce
11
  import json
12
 
13
- # Set up logging to capture errors and debug information
14
  logging.basicConfig(level=logging.INFO)
15
  logger = logging.getLogger(__name__)
16
 
17
  app = FastAPI()
18
 
19
- # Salesforce credentials
20
- SF_USERNAME = os.getenv("SF_USERNAME", "[email protected]")
21
- SF_PASSWORD = os.getenv("SF_PASSWORD", "Internal@1")
22
- SF_SECURITY_TOKEN = os.getenv("SF_SECURITY_TOKEN", "NbUKcTx45azba5HEdntE9YAh")
23
  SF_DOMAIN = os.getenv("SF_DOMAIN", "login")
24
 
25
- # Verify API key is set
26
- API_KEY = os.getenv("HUGGINGFACE_API_KEY")
27
- if not API_KEY:
28
- logger.error("HUGGINGFACE_API_KEY environment variable not set")
29
- raise ValueError("HUGGINGFACE_API_KEY environment variable not set")
 
30
 
31
  # Connect to Salesforce
32
  try:
@@ -61,9 +62,9 @@ vendor_logs = []
61
  def fetch_vendor_logs_from_salesforce():
62
  try:
63
  query = """
64
- SELECT Id, Name, Vendor__c, Work_Completion_Percentage__c, Quality_Percentage__c, Incident_Severity__c,
65
- Work_Completion_Date__c, Actual_Completion_Date__c, Delay_Days__c,Project__c
66
-
67
  FROM Vendor_Log__c
68
  """
69
  result = sf.query_all(query)
@@ -83,13 +84,14 @@ def fetch_vendor_logs_from_salesforce():
83
  actualCompletionDate=record['Actual_Completion_Date__c'] or "N/A",
84
  vendorLogName=record['Name'] or "Unknown",
85
  delayDays=int(record['Delay_Days__c'] or 0),
86
- project=record['Project__c'] or "Unknown"
87
  )
88
  logs.append(log)
 
89
  return logs
90
  except Exception as e:
91
  logger.error(f"Error fetching vendor logs from Salesforce: {str(e)}")
92
- raise
93
 
94
  def calculate_scores(log: VendorLog):
95
  try:
@@ -109,7 +111,6 @@ def calculate_scores(log: VendorLog):
109
  # Communication Score: Weighted average of other scores
110
  communication_score = (quality_score * 0.33 + timeliness_score * 0.33 + safety_score * 0.33)
111
 
112
- # Removed finalScore calculation since Final_Score__c is a Formula field
113
  return {
114
  'qualityScore': round(quality_score, 2),
115
  'timelinessScore': round(timeliness_score, 2),
@@ -118,7 +119,7 @@ def calculate_scores(log: VendorLog):
118
  }
119
  except Exception as e:
120
  logger.error(f"Error calculating scores: {str(e)}")
121
- raise
122
 
123
  def get_feedback(score: float, metric: str) -> str:
124
  try:
@@ -146,7 +147,7 @@ def get_feedback(score: float, metric: str) -> str:
146
  return "Poor: Communication issues detected"
147
  except Exception as e:
148
  logger.error(f"Error generating feedback: {str(e)}")
149
- raise
150
 
151
  def generate_pdf(vendor_id: str, vendor_log_name: str, scores: dict):
152
  try:
@@ -160,7 +161,6 @@ def generate_pdf(vendor_id: str, vendor_log_name: str, scores: dict):
160
  c.drawString(100, 670, f'Timeliness Score: {scores["timelinessScore"]}% ({get_feedback(scores["timelinessScore"], "Timeliness")})')
161
  c.drawString(100, 650, f'Safety Score: {scores["safetyScore"]}% ({get_feedback(scores["safetyScore"], "Safety")})')
162
  c.drawString(100, 630, f'Communication Score: {scores["communicationScore"]}% ({get_feedback(scores["communicationScore"], "Communication")})')
163
- # Removed Final Score from PDF since it's a Formula field
164
  c.save()
165
 
166
  with open(filename, 'rb') as f:
@@ -169,40 +169,40 @@ def generate_pdf(vendor_id: str, vendor_log_name: str, scores: dict):
169
  return pdf_content
170
  except Exception as e:
171
  logger.error(f"Error generating PDF: {str(e)}")
172
- raise
173
 
174
  def determine_alert_flag(scores: dict, all_logs: list):
175
  try:
176
  if not all_logs:
177
  return False
178
- # Since finalScore is a Formula field, we'll need to fetch it from Salesforce or adjust logic
179
- # For now, we'll base the alert on the average of other scores
180
- avg_score = (scores['qualityScore'] + scores['timelinessScore'] + scores['safetyScore'] + scores['communicationScore']) / 4
181
  if avg_score < 50:
182
  return True
183
- lowest_avg = min([(log['scores']['qualityScore'] + log['scores']['timelinessScore'] + log['scores']['safetyScore'] + log['scores']['communicationScore']) / 4 for log in all_logs])
 
 
184
  return avg_score == lowest_avg
185
  except Exception as e:
186
  logger.error(f"Error determining alert flag: {str(e)}")
187
- raise
188
 
189
  def store_scores_in_salesforce(log: VendorLog, scores: dict, pdf_content: bytes, alert_flag: bool):
190
  try:
191
- # Step 1: Create the Subcontractor_Performance_Score__c record without Final_Score__c
192
  score_record = sf.Subcontractor_Performance_Score__c.create({
193
- 'Vendor_Log__c': log.vendorLogId,
194
  'Vendor__c': log.vendorRecordId,
 
195
  'Quality_Score__c': scores['qualityScore'],
196
  'Timeliness_Score__c': scores['timelinessScore'],
197
  'Safety_Score__c': scores['safetyScore'],
198
  'Communication_Score__c': scores['communicationScore'],
199
  'Alert_Flag__c': alert_flag
200
- # Removed Final_Score__c since it's a Formula field
201
  })
202
  score_record_id = score_record['id']
203
- logger.info(f"Successfully created Subcontractor_Performance_Score__c record with ID: {score_record_id}")
204
 
205
- # Step 2: Upload the PDF as a ContentVersion
206
  pdf_base64 = base64.b64encode(pdf_content).decode('utf-8')
207
  content_version = sf.ContentVersion.create({
208
  'Title': f'Performance_Report_{log.vendorId}',
@@ -210,32 +210,34 @@ def store_scores_in_salesforce(log: VendorLog, scores: dict, pdf_content: bytes,
210
  'VersionData': pdf_base64,
211
  'FirstPublishLocationId': score_record_id
212
  })
213
- logger.info(f"Successfully uploaded PDF as ContentVersion for Vendor Log ID: {log.vendorLogId}")
214
 
215
- # Step 3: Get the ContentDocumentId and construct a URL to the file
216
  content_version_id = content_version['id']
217
  content_version_record = sf.query(f"SELECT ContentDocumentId FROM ContentVersion WHERE Id = '{content_version_id}'")
 
 
 
218
  content_document_id = content_version_record['records'][0]['ContentDocumentId']
219
-
220
- # Construct the URL to the file
221
  pdf_url = f"https://{sf.sf_instance}/sfc/servlet.shepherd/document/download/{content_document_id}"
222
 
223
- # Step 4: Update the Subcontractor_Performance_Score__c record with the PDF URL
 
224
  sf.Subcontractor_Performance_Score__c.update(score_record_id, {
225
- 'PDF_Link__c': pdf_url
226
  })
227
- logger.info(f"Successfully updated Subcontractor_Performance_Score__c record with PDF URL: {pdf_url}")
228
-
229
  except Exception as e:
230
  logger.error(f"Error storing scores in Salesforce: {str(e)}")
231
- raise
232
 
233
  @app.post('/score')
234
- async def score_vendor(log: VendorLog, authorization: str = Header(...)):
235
  try:
236
  logger.info(f"Received Vendor Log: {log}")
237
- if authorization != f'Bearer {API_KEY}':
238
- raise HTTPException(status_code=401, detail='Invalid API key')
 
239
 
240
  scores = calculate_scores(log)
241
  pdf_content = generate_pdf(log.vendorId, log.vendorLogName, scores)
@@ -269,6 +271,8 @@ async def score_vendor(log: VendorLog, authorization: str = Header(...)):
269
  'pdfContent': pdf_base64,
270
  'alert': alert_flag
271
  }
 
 
272
  except Exception as e:
273
  logger.error(f"Error in /score endpoint: {str(e)}")
274
  raise HTTPException(status_code=500, detail=f"Error processing vendor log: {str(e)}")
@@ -325,11 +329,15 @@ async def get_dashboard():
325
  </style>
326
  <script>
327
  async function generateScores() {
328
- const response = await fetch('/generate', { method: 'POST' });
329
- if (response.ok) {
330
- window.location.reload();
331
- } else {
332
- alert('Error generating scores');
 
 
 
 
333
  }
334
  }
335
  </script>
@@ -419,6 +427,8 @@ async def get_dashboard():
419
  </html>
420
  """
421
  return HTMLResponse(content=html_content)
 
 
422
  except Exception as e:
423
  logger.error(f"Error in / endpoint: {str(e)}")
424
  raise HTTPException(status_code=500, detail=f"Error generating dashboard: {str(e)}")
@@ -427,8 +437,8 @@ async def get_dashboard():
427
  async def generate_scores():
428
  try:
429
  global vendor_logs
430
- fetched_logs = fetch_vendor_logs_from_salesforce()
431
  vendor_logs = []
 
432
  for log in fetched_logs:
433
  scores = calculate_scores(log)
434
  pdf_content = generate_pdf(log.vendorId, log.vendorLogName, scores)
@@ -449,7 +459,10 @@ async def generate_scores():
449
  'scores': scores,
450
  'extracted': True
451
  })
 
452
  return {"status": "success"}
 
 
453
  except Exception as e:
454
  logger.error(f"Error in /generate endpoint: {str(e)}")
455
  raise HTTPException(status_code=500, detail=f"Error generating scores: {str(e)}")
 
10
  from simple_salesforce import Salesforce
11
  import json
12
 
13
+ # Set up logging
14
  logging.basicConfig(level=logging.INFO)
15
  logger = logging.getLogger(__name__)
16
 
17
  app = FastAPI()
18
 
19
+ # Environment variables for Salesforce
20
+ SF_USERNAME = os.getenv("SF_USERNAME")
21
+ SF_PASSWORD = os.getenv("SF_PASSWORD")
22
+ SF_SECURITY_TOKEN = os.getenv("SF_SECURITY_TOKEN")
23
  SF_DOMAIN = os.getenv("SF_DOMAIN", "login")
24
 
25
+ # Validate environment variables
26
+ required_env_vars = ["SF_USERNAME", "SF_PASSWORD", "SF_SECURITY_TOKEN"]
27
+ for var in required_env_vars:
28
+ if not os.getenv(var):
29
+ logger.error(f"Environment variable {var} is not set")
30
+ raise ValueError(f"Environment variable {var} is not set")
31
 
32
  # Connect to Salesforce
33
  try:
 
62
  def fetch_vendor_logs_from_salesforce():
63
  try:
64
  query = """
65
+ SELECT Id, Name, Vendor__c, Work_Completion_Percentage__c, Quality_Percentage__c,
66
+ Incident_Severity__c, Work_Completion_Date__c, Actual_Completion_Date__c,
67
+ Delay_Days__c, Project__c
68
  FROM Vendor_Log__c
69
  """
70
  result = sf.query_all(query)
 
84
  actualCompletionDate=record['Actual_Completion_Date__c'] or "N/A",
85
  vendorLogName=record['Name'] or "Unknown",
86
  delayDays=int(record['Delay_Days__c'] or 0),
87
+ project=record['Project__c'] or "Unknown"
88
  )
89
  logs.append(log)
90
+ logger.info(f"Fetched {len(logs)} vendor logs from Salesforce")
91
  return logs
92
  except Exception as e:
93
  logger.error(f"Error fetching vendor logs from Salesforce: {str(e)}")
94
+ raise HTTPException(status_code=500, detail=f"Error fetching vendor logs: {str(e)}")
95
 
96
  def calculate_scores(log: VendorLog):
97
  try:
 
111
  # Communication Score: Weighted average of other scores
112
  communication_score = (quality_score * 0.33 + timeliness_score * 0.33 + safety_score * 0.33)
113
 
 
114
  return {
115
  'qualityScore': round(quality_score, 2),
116
  'timelinessScore': round(timeliness_score, 2),
 
119
  }
120
  except Exception as e:
121
  logger.error(f"Error calculating scores: {str(e)}")
122
+ raise HTTPException(status_code=500, detail=f"Error calculating scores: {str(e)}")
123
 
124
  def get_feedback(score: float, metric: str) -> str:
125
  try:
 
147
  return "Poor: Communication issues detected"
148
  except Exception as e:
149
  logger.error(f"Error generating feedback: {str(e)}")
150
+ raise HTTPException(status_code=500, detail=f"Error generating feedback: {str(e)}")
151
 
152
  def generate_pdf(vendor_id: str, vendor_log_name: str, scores: dict):
153
  try:
 
161
  c.drawString(100, 670, f'Timeliness Score: {scores["timelinessScore"]}% ({get_feedback(scores["timelinessScore"], "Timeliness")})')
162
  c.drawString(100, 650, f'Safety Score: {scores["safetyScore"]}% ({get_feedback(scores["safetyScore"], "Safety")})')
163
  c.drawString(100, 630, f'Communication Score: {scores["communicationScore"]}% ({get_feedback(scores["communicationScore"], "Communication")})')
 
164
  c.save()
165
 
166
  with open(filename, 'rb') as f:
 
169
  return pdf_content
170
  except Exception as e:
171
  logger.error(f"Error generating PDF: {str(e)}")
172
+ raise HTTPException(status_code=500, detail=f"Error generating PDF: {str(e)}")
173
 
174
  def determine_alert_flag(scores: dict, all_logs: list):
175
  try:
176
  if not all_logs:
177
  return False
178
+ avg_score = (scores['qualityScore'] + scores['timelinessScore'] +
179
+ scores['safetyScore'] + scores['communicationScore']) / 4
 
180
  if avg_score < 50:
181
  return True
182
+ lowest_avg = min([(log['scores']['qualityScore'] + log['scores']['timelinessScore'] +
183
+ log['scores']['safetyScore'] + log['scores']['communicationScore']) / 4
184
+ for log in all_logs], default=avg_score)
185
  return avg_score == lowest_avg
186
  except Exception as e:
187
  logger.error(f"Error determining alert flag: {str(e)}")
188
+ raise HTTPException(status_code=500, detail=f"Error determining alert flag: {str(e)}")
189
 
190
  def store_scores_in_salesforce(log: VendorLog, scores: dict, pdf_content: bytes, alert_flag: bool):
191
  try:
192
+ # Create Subcontractor_Performance_Score__c record
193
  score_record = sf.Subcontractor_Performance_Score__c.create({
 
194
  'Vendor__c': log.vendorRecordId,
195
+ 'Month__c': datetime.today().replace(day=1).strftime('%Y-%m-%d'),
196
  'Quality_Score__c': scores['qualityScore'],
197
  'Timeliness_Score__c': scores['timelinessScore'],
198
  'Safety_Score__c': scores['safetyScore'],
199
  'Communication_Score__c': scores['communicationScore'],
200
  'Alert_Flag__c': alert_flag
 
201
  })
202
  score_record_id = score_record['id']
203
+ logger.info(f"Created Subcontractor_Performance_Score__c record with ID: {score_record_id}")
204
 
205
+ # Upload PDF as ContentVersion
206
  pdf_base64 = base64.b64encode(pdf_content).decode('utf-8')
207
  content_version = sf.ContentVersion.create({
208
  'Title': f'Performance_Report_{log.vendorId}',
 
210
  'VersionData': pdf_base64,
211
  'FirstPublishLocationId': score_record_id
212
  })
213
+ logger.info(f"Uploaded PDF as ContentVersion for Vendor Log ID: {log.vendorLogId}")
214
 
215
+ # Get ContentDocumentId and construct URL
216
  content_version_id = content_version['id']
217
  content_version_record = sf.query(f"SELECT ContentDocumentId FROM ContentVersion WHERE Id = '{content_version_id}'")
218
+ if content_version_record['totalSize'] == 0:
219
+ logger.error(f"No ContentVersion found for ID: {content_version_id}")
220
+ raise HTTPException(status_code=500, detail="Failed to retrieve ContentDocumentId")
221
  content_document_id = content_version_record['records'][0]['ContentDocumentId']
 
 
222
  pdf_url = f"https://{sf.sf_instance}/sfc/servlet.shepherd/document/download/{content_document_id}"
223
 
224
+ # Update Subcontractor_Performance_Score__c with PDF URL
225
+ # Note: Changed PDF_Link__c to Certification_URL__c to match your previous Salesforce schema
226
  sf.Subcontractor_Performance_Score__c.update(score_record_id, {
227
+ 'Certification_URL__c': pdf_url
228
  })
229
+ logger.info(f"Updated Subcontractor_Performance_Score__c with Certification_URL__c: {pdf_url}")
 
230
  except Exception as e:
231
  logger.error(f"Error storing scores in Salesforce: {str(e)}")
232
+ raise HTTPException(status_code=500, detail=f"Error storing scores: {str(e)}")
233
 
234
  @app.post('/score')
235
+ async def score_vendor(log: VendorLog, authorization: str = Header(None)):
236
  try:
237
  logger.info(f"Received Vendor Log: {log}")
238
+ # Optional: Add API key check if needed
239
+ # if authorization != f'Bearer {API_KEY}':
240
+ # raise HTTPException(status_code=401, detail='Invalid API key')
241
 
242
  scores = calculate_scores(log)
243
  pdf_content = generate_pdf(log.vendorId, log.vendorLogName, scores)
 
271
  'pdfContent': pdf_base64,
272
  'alert': alert_flag
273
  }
274
+ except HTTPException as e:
275
+ raise e
276
  except Exception as e:
277
  logger.error(f"Error in /score endpoint: {str(e)}")
278
  raise HTTPException(status_code=500, detail=f"Error processing vendor log: {str(e)}")
 
329
  </style>
330
  <script>
331
  async function generateScores() {
332
+ try {
333
+ const response = await fetch('/generate', { method: 'POST' });
334
+ if (response.ok) {
335
+ window.location.reload();
336
+ } else {
337
+ alert('Error generating scores');
338
+ }
339
+ } catch (error) {
340
+ alert('Error generating scores: ' + error.message);
341
  }
342
  }
343
  </script>
 
427
  </html>
428
  """
429
  return HTMLResponse(content=html_content)
430
+ except HTTPException as e:
431
+ raise e
432
  except Exception as e:
433
  logger.error(f"Error in / endpoint: {str(e)}")
434
  raise HTTPException(status_code=500, detail=f"Error generating dashboard: {str(e)}")
 
437
  async def generate_scores():
438
  try:
439
  global vendor_logs
 
440
  vendor_logs = []
441
+ fetched_logs = fetch_vendor_logs_from_salesforce()
442
  for log in fetched_logs:
443
  scores = calculate_scores(log)
444
  pdf_content = generate_pdf(log.vendorId, log.vendorLogName, scores)
 
459
  'scores': scores,
460
  'extracted': True
461
  })
462
+ logger.info(f"Generated scores for {len(vendor_logs)} vendor logs")
463
  return {"status": "success"}
464
+ except HTTPException as e:
465
+ raise e
466
  except Exception as e:
467
  logger.error(f"Error in /generate endpoint: {str(e)}")
468
  raise HTTPException(status_code=500, detail=f"Error generating scores: {str(e)}")