lokesh341 commited on
Commit
8d1d1a4
·
verified ·
1 Parent(s): dd99f96

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -28
app.py CHANGED
@@ -1,4 +1,4 @@
1
- from fastapi import FastAPI, HTTPException, Header
2
  from pydantic import BaseModel
3
  from reportlab.lib.pagesizes import letter
4
  from reportlab.pdfgen import canvas
@@ -8,14 +8,13 @@ import logging
8
  import traceback
9
  import html # For escaping special characters
10
  from datetime import datetime
11
- from fastapi.responses import HTMLResponse
12
  from simple_salesforce import Salesforce
13
 
14
  # Set up logging to capture errors and debug information
15
  logging.basicConfig(level=logging.INFO)
16
  logger = logging.getLogger(__name__)
17
 
18
- app = FastAPI()
19
 
20
  # Salesforce credentials
21
  SF_USERNAME = "scores@app.com"
@@ -148,13 +147,26 @@ def determine_alert_flag(final_score: float, all_logs: list):
148
  logger.error(f"Error determining alert flag: {str(e)}")
149
  raise
150
 
151
- @app.post('/score')
152
- async def score_vendor(log: VendorLog, authorization: str = Header(...)):
153
  try:
 
 
 
 
 
 
 
 
 
 
 
 
154
  logger.info(f"Received Vendor Log: {log}")
155
- # Validate Salesforce session or token (optional, depending on your setup)
 
156
  if not sf.session_id:
157
- raise HTTPException(status_code=401, detail='Salesforce session invalid')
158
 
159
  # Calculate scores
160
  scores = calculate_scores(log)
@@ -182,7 +194,7 @@ async def score_vendor(log: VendorLog, authorization: str = Header(...)):
182
  'extracted': True
183
  })
184
 
185
- # Optionally, save scores back to Salesforce (example mapping to a custom object)
186
  try:
187
  sf.Vendor_Log__c.create({
188
  'Vendor_Log_Id__c': log.vendorLogId,
@@ -194,15 +206,15 @@ async def score_vendor(log: VendorLog, authorization: str = Header(...)):
194
  'Communication_Score__c': scores['communicationScore'],
195
  'Final_Score__c': scores['finalScore'],
196
  'Alert_Flag__c': alert_flag,
197
- 'PDF_Content__c': pdf_base64 # Assuming a text field for base64 PDF
198
  })
199
  logger.info(f"Successfully saved scores to Salesforce for Vendor Log: {log.vendorLogId}")
200
  except Exception as e:
201
  logger.error(f"Error saving to Salesforce: {str(e)}")
202
- # Continue even if Salesforce save fails to ensure response is returned
203
 
204
- # Return the response to the caller
205
- return {
206
  'vendorLogId': log.vendorLogId,
207
  'vendorId': log.vendorId,
208
  'vendorLogName': log.vendorLogName,
@@ -213,19 +225,19 @@ async def score_vendor(log: VendorLog, authorization: str = Header(...)):
213
  'finalScore': scores['finalScore'],
214
  'pdfContent': pdf_base64,
215
  'alert': alert_flag
216
- }
217
  except Exception as e:
218
  logger.error(f"Error in /score endpoint: {str(e)}")
219
- raise HTTPException(status_code=500, detail=f"Error processing vendor log: {str(e)}")
220
 
221
- @app.get('/', response_class=HTMLResponse)
222
- async def get_dashboard():
223
  try:
224
  # Calculate summary metrics
225
  total_vendors = len(vendor_logs)
226
  performance_alerts = sum(1 for log in vendor_logs if determine_alert_flag(log['scores']['finalScore'], vendor_logs))
227
  top_performers = sum(1 for log in vendor_logs if log['scores']['finalScore'] >= 90)
228
- improving_vendors = sum(1 for log in vendor_logs if log['scores']['finalScore'] >= 70) # Simplified logic for "improving"
229
 
230
  # Sort vendor logs by final score for leaderboard
231
  sorted_logs = sorted(vendor_logs, key=lambda x: x['scores']['finalScore'], reverse=True)
@@ -235,6 +247,7 @@ async def get_dashboard():
235
 
236
  # HTML content for the dashboard
237
  html_content = """
 
238
  <html>
239
  <head>
240
  <title>Subcontractor Performance Score App</title>
@@ -278,17 +291,17 @@ async def get_dashboard():
278
  <div class="card">
279
  <h3>Performance Alerts</h3>
280
  <p>{performance_alerts}</p>
281
- <small>{round(performance_alerts/total_vendors*100, 1) if total_vendors else 0}% of vendors</small>
282
  </div>
283
  <div class="card">
284
  <h3>Top Performers</h3>
285
  <p>{top_performers}</p>
286
- <small>{round(top_performers/total_vendors*100, 1) if total_vendors else 0}% of vendors</small>
287
  </div>
288
  <div class="card">
289
  <h3>Improving Vendors</h3>
290
  <p>{improving_vendors}</p>
291
- <small>{round(improving_vendors/total_vendors*100, 1) if total_vendors else 0}% of vendors</small>
292
  </div>
293
  </div>
294
 
@@ -304,7 +317,15 @@ async def get_dashboard():
304
  <th>Trend</th>
305
  <th>Status</th>
306
  </tr>
307
- """.format(total_vendors=total_vendors, performance_alerts=performance_alerts, top_performers=top_performers, improving_vendors=improving_vendors)
 
 
 
 
 
 
 
 
308
 
309
  for idx, log in enumerate(top_logs, 1):
310
  scores = log['scores']
@@ -312,7 +333,6 @@ async def get_dashboard():
312
  trend = "trend-up" if scores['finalScore'] >= 90 else "trend-down" if scores['finalScore'] < 70 else "trend-flat"
313
  status_class = "status-good" if not alert_flag else "status-alert"
314
  status_text = "Good" if not alert_flag else "Alert"
315
- # Escape dynamic data to prevent HTML injection
316
  vendor_name = html.escape(log['vendorLogName'])
317
  html_content += f"""
318
  <tr>
@@ -440,14 +460,12 @@ async def get_dashboard():
440
  </body>
441
  </html>
442
  """
443
- # Ensure the HTML content is properly encoded
444
- return HTMLResponse(content=html_content.encode('utf-8'), media_type="text/html; charset=utf-8")
445
  except Exception as e:
446
- # Log the full stack trace for better debugging
447
  error_trace = traceback.format_exc()
448
  logger.error(f"Error in / endpoint: {str(e)}\nStack trace:\n{error_trace}")
449
- raise HTTPException(status_code=500, detail=f"Error generating dashboard: {str(e)}")
450
 
451
  if __name__ == "__main__":
452
- import uvicorn
453
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
1
+ from flask import Flask, request, Response, jsonify, render_template_string
2
  from pydantic import BaseModel
3
  from reportlab.lib.pagesizes import letter
4
  from reportlab.pdfgen import canvas
 
8
  import traceback
9
  import html # For escaping special characters
10
  from datetime import datetime
 
11
  from simple_salesforce import Salesforce
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 = Flask(__name__)
18
 
19
  # Salesforce credentials
20
  SF_USERNAME = "scores@app.com"
 
147
  logger.error(f"Error determining alert flag: {str(e)}")
148
  raise
149
 
150
+ @app.route('/score', methods=['POST'])
151
+ def score_vendor():
152
  try:
153
+ # Validate the Authorization header
154
+ authorization = request.headers.get('Authorization')
155
+ if not authorization:
156
+ return jsonify({'error': 'Authorization header missing'}), 401
157
+
158
+ # Parse the request data
159
+ data = request.get_json()
160
+ if not data:
161
+ return jsonify({'error': 'Invalid request data'}), 400
162
+
163
+ # Validate and create VendorLog instance
164
+ log = VendorLog(**data)
165
  logger.info(f"Received Vendor Log: {log}")
166
+
167
+ # Validate Salesforce session
168
  if not sf.session_id:
169
+ return jsonify({'error': 'Salesforce session invalid'}), 401
170
 
171
  # Calculate scores
172
  scores = calculate_scores(log)
 
194
  'extracted': True
195
  })
196
 
197
+ # Optionally, save scores back to Salesforce
198
  try:
199
  sf.Vendor_Log__c.create({
200
  'Vendor_Log_Id__c': log.vendorLogId,
 
206
  'Communication_Score__c': scores['communicationScore'],
207
  'Final_Score__c': scores['finalScore'],
208
  'Alert_Flag__c': alert_flag,
209
+ 'PDF_Content__c': pdf_base64
210
  })
211
  logger.info(f"Successfully saved scores to Salesforce for Vendor Log: {log.vendorLogId}")
212
  except Exception as e:
213
  logger.error(f"Error saving to Salesforce: {str(e)}")
214
+ # Continue even if Salesforce save fails
215
 
216
+ # Return the response
217
+ return jsonify({
218
  'vendorLogId': log.vendorLogId,
219
  'vendorId': log.vendorId,
220
  'vendorLogName': log.vendorLogName,
 
225
  'finalScore': scores['finalScore'],
226
  'pdfContent': pdf_base64,
227
  'alert': alert_flag
228
+ }), 200
229
  except Exception as e:
230
  logger.error(f"Error in /score endpoint: {str(e)}")
231
+ return jsonify({'error': f"Error processing vendor log: {str(e)}"}), 500
232
 
233
+ @app.route('/', methods=['GET'])
234
+ def get_dashboard():
235
  try:
236
  # Calculate summary metrics
237
  total_vendors = len(vendor_logs)
238
  performance_alerts = sum(1 for log in vendor_logs if determine_alert_flag(log['scores']['finalScore'], vendor_logs))
239
  top_performers = sum(1 for log in vendor_logs if log['scores']['finalScore'] >= 90)
240
+ improving_vendors = sum(1 for log in vendor_logs if log['scores']['finalScore'] >= 70)
241
 
242
  # Sort vendor logs by final score for leaderboard
243
  sorted_logs = sorted(vendor_logs, key=lambda x: x['scores']['finalScore'], reverse=True)
 
247
 
248
  # HTML content for the dashboard
249
  html_content = """
250
+ <!DOCTYPE html>
251
  <html>
252
  <head>
253
  <title>Subcontractor Performance Score App</title>
 
291
  <div class="card">
292
  <h3>Performance Alerts</h3>
293
  <p>{performance_alerts}</p>
294
+ <small>{percent_alerts}% of vendors</small>
295
  </div>
296
  <div class="card">
297
  <h3>Top Performers</h3>
298
  <p>{top_performers}</p>
299
+ <small>{percent_top}% of vendors</small>
300
  </div>
301
  <div class="card">
302
  <h3>Improving Vendors</h3>
303
  <p>{improving_vendors}</p>
304
+ <small>{percent_improving}% of vendors</small>
305
  </div>
306
  </div>
307
 
 
317
  <th>Trend</th>
318
  <th>Status</th>
319
  </tr>
320
+ """.format(
321
+ total_vendors=total_vendors,
322
+ performance_alerts=performance_alerts,
323
+ percent_alerts=round(performance_alerts/total_vendors*100, 1) if total_vendors else 0,
324
+ top_performers=top_performers,
325
+ percent_top=round(top_performers/total_vendors*100, 1) if total_vendors else 0,
326
+ improving_vendors=improving_vendors,
327
+ percent_improving=round(improving_vendors/total_vendors*100, 1) if total_vendors else 0
328
+ )
329
 
330
  for idx, log in enumerate(top_logs, 1):
331
  scores = log['scores']
 
333
  trend = "trend-up" if scores['finalScore'] >= 90 else "trend-down" if scores['finalScore'] < 70 else "trend-flat"
334
  status_class = "status-good" if not alert_flag else "status-alert"
335
  status_text = "Good" if not alert_flag else "Alert"
 
336
  vendor_name = html.escape(log['vendorLogName'])
337
  html_content += f"""
338
  <tr>
 
460
  </body>
461
  </html>
462
  """
463
+ # Return the HTML response with proper encoding
464
+ return Response(html_content, mimetype='text/html; charset=utf-8')
465
  except Exception as e:
 
466
  error_trace = traceback.format_exc()
467
  logger.error(f"Error in / endpoint: {str(e)}\nStack trace:\n{error_trace}")
468
+ return jsonify({'error': f"Error generating dashboard: {str(e)}"}), 500
469
 
470
  if __name__ == "__main__":
471
+ app.run(host="0.0.0.0", port=7860, debug=True)