lokeshloki143 commited on
Commit
cfeafa3
·
verified ·
1 Parent(s): 7dfb5e3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +360 -314
app.py CHANGED
@@ -1,396 +1,442 @@
 
 
1
  import os
2
- import logging
3
- import requests
4
  from datetime import datetime
5
- from flask import Flask, render_template, request, redirect, url_for, session, jsonify, send_file
6
- from simple_salesforce import Salesforce
7
  from dotenv import load_dotenv
 
8
  from reportlab.lib.pagesizes import letter
9
  from reportlab.pdfgen import canvas
10
- from io import BytesIO
 
11
 
12
  # Load environment variables
13
  load_dotenv()
14
 
15
  # Configure logging
16
  logging.basicConfig(
17
- filename='app.log',
18
  level=logging.INFO,
19
- format='%(asctime)s - %(levelname)s - %(message)s'
 
 
 
 
20
  )
 
21
 
22
  app = Flask(__name__)
23
- app.secret_key = os.getenv('FLASK_SECRET_KEY', 'default-secret-key')
24
-
25
- # Salesforce connection
26
- sf = None
27
- try:
28
- sf = Salesforce(
29
- username=os.getenv('SALESFORCE_USERNAME'),
30
- password=os.getenv('SALESFORCE_PASSWORD'),
31
- security_token=os.getenv('SALESFORCE_SECURITY_TOKEN'),
32
- domain=os.getenv('SALESFORCE_DOMAIN', 'login')
33
- )
34
- # Verify connection by querying Salesforce metadata
35
- user_info = sf.query("SELECT Id, Name FROM User WHERE Username = '{}'".format(os.getenv('SALESFORCE_USERNAME')))
36
- if user_info['totalSize'] > 0:
37
- logging.info(f"Successfully connected to Salesforce org. User: {user_info['records'][0]['Name']}")
38
- else:
39
- logging.error("Salesforce connection established, but user not found in org")
40
- except Exception as e:
41
- logging.error(f"Failed to connect to Salesforce: {str(e)}")
42
- sf = None
43
-
44
- # Hugging Face API configuration
45
- HUGGING_FACE_API_TOKEN = os.getenv('HUGGING_FACE_API_TOKEN')
46
- HUGGING_FACE_API_URL = os.getenv('HUGGING_FACE_API_URL')
47
- HUGGING_FACE_HEADERS = {
48
- 'Authorization': f'Bearer {HUGGING_FACE_API_TOKEN}',
49
- 'Content-Type': 'application/json'
50
  }
51
 
52
- def generate_coaching_output_with_hf(data):
 
53
  try:
54
- prompt = (
55
- f"Generate a daily checklist and focus tips for a supervisor with the following details:\n"
56
- f"Project ID: {data.get('project_id', 'N/A')}\n"
57
- f"Engagement Score: {data.get('engagement_score', 0)}%\n"
58
- f"KPI Flag: {'Active' if data.get('kpi_flag', False) else 'Inactive'}\n"
59
- f"Reflection Log: {data.get('reflection_log', 'No reflections yet.')}\n\n"
60
- "Provide a checklist (3 items) and focus tips (3 items) in a concise format."
61
  )
62
- payload = {
63
- "inputs": prompt,
64
- "parameters": {"max_length": 150, "num_return_sequences": 1}
65
- }
66
- response = requests.post(HUGGING_FACE_API_URL, headers=HUGGING_FACE_HEADERS, json=payload)
67
- response.raise_for_status()
68
- result = response.json()
69
- generated_text = result[0]['generated_text'].split('\n')
70
-
71
- checklist = []
72
- tips = []
73
- is_checklist = True
74
- for line in generated_text:
75
- line = line.strip()
76
- if not line:
77
- continue
78
- if "focus tips" in line.lower():
79
- is_checklist = False
80
- continue
81
- if is_checklist and len(checklist) < 3:
82
- checklist.append(line.replace('- ', '').strip())
83
- elif not is_checklist and len(tips) < 3:
84
- tips.append(line.replace('- ', '').strip())
85
-
86
- # Fallback if model output is incomplete
87
- while len(checklist) < 3:
88
- checklist.append(f"Placeholder Task {len(checklist) + 1}")
89
- while len(tips) < 3:
90
- tips.append(f"Placeholder Tip {len(tips) + 1}")
91
-
92
- return {'checklist': checklist, 'tips': tips}
93
  except Exception as e:
94
- logging.error(f"Error generating coaching output with Hugging Face API: {str(e)}")
95
- return {
96
- 'checklist': ['Review project milestones', 'Conduct team check-in', 'Update resource allocation'],
97
- 'tips': ['Set clear deadlines', 'Encourage team feedback', 'Monitor progress daily']
98
- }
99
 
100
  @app.route('/')
101
- def home():
102
  if 'supervisor_name' not in session:
103
- logging.info("User not logged in, redirecting to login page")
104
- return redirect(url_for('login'))
105
- logging.info(f"User {session['supervisor_name']} accessed the dashboard")
106
  return render_template('index.html')
107
 
108
- @app.route('/login', methods=['GET', 'POST'])
109
- def login():
110
- if request.method == 'POST':
111
- username = request.form['username']
112
- password = request.form['password']
113
- logging.info(f"Login attempt for username: {username}")
114
-
115
- if username == 'GUEST':
116
- session['supervisor_name'] = 'GUEST'
117
- logging.info("Guest login successful")
118
- return redirect(url_for('home'))
119
-
120
- if not sf:
121
- logging.error("Salesforce connection not available during login")
122
- return render_template('login.html', error="Salesforce connection unavailable")
123
-
124
- try:
125
- query = f"SELECT Id, Name, Password__c FROM Supervisor_AI_Coaching__c WHERE Name = '{username}'"
126
- result = sf.query(query)
127
- logging.info(f"Queried Salesforce for user: {username}")
128
-
129
- if result['totalSize'] == 0:
130
- logging.warning(f"User {username} not found in Salesforce")
131
- return render_template('login.html', error="Invalid username or password")
132
-
133
- user = result['records'][0]
134
- if user['Password__c'] == password:
135
- session['supervisor_name'] = user['Name']
136
- sf.Supervisor_AI_Coaching__c.update(user['Id'], {'Last_Login__c': datetime.utcnow().isoformat()})
137
- logging.info(f"User {username} logged in successfully")
138
- return redirect(url_for('home'))
139
- else:
140
- logging.warning(f"Invalid password for user {username}")
141
- return render_template('login.html', error="Invalid username or password")
142
- except Exception as e:
143
- logging.error(f"Error during login for {username}: {str(e)}")
144
- return render_template('login.html', error="An error occurred during login")
145
  return render_template('login.html')
146
 
147
- @app.route('/signup', methods=['GET', 'POST'])
148
- def signup():
149
- if request.method == 'POST':
150
- username = request.form['username']
151
- password = request.form['password']
152
- project_id = request.form['project_id']
153
- engagement_score = float(request.form['engagement_score'])
154
- kpi_flag = request.form.get('kpi_flag') == 'on'
155
- logging.info(f"Signup attempt for username: {username}")
156
-
157
- if not sf:
158
- logging.error("Salesforce connection not available during signup")
159
- return render_template('signup.html', error="Salesforce connection unavailable")
160
-
161
- try:
162
- existing_user = sf.query(f"SELECT Id FROM Supervisor_AI_Coaching__c WHERE Name = '{username}'")
163
- if existing_user['totalSize'] > 0:
164
- logging.warning(f"Signup failed: Username {username} already exists")
165
- return render_template('signup.html', error="Username already exists")
166
-
167
- sf.Supervisor_AI_Coaching__c.create({
168
- 'Name': username,
169
- 'Password__c': password,
170
- 'Project_ID__c': project_id,
171
- 'Engagement_Score__c': engagement_score,
172
- 'KPI_Flag__c': kpi_flag
173
- })
174
- logging.info(f"User {username} signed up successfully")
175
- return redirect(url_for('login'))
176
- except Exception as e:
177
- logging.error(f"Error during signup for {username}: {str(e)}")
178
- return render_template('signup.html', error="An error occurred during signup")
179
  return render_template('signup.html')
180
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  @app.route('/logout', methods=['POST'])
182
  def logout():
183
- username = session.get('supervisor_name', 'Unknown')
184
  session.pop('supervisor_name', None)
185
- logging.info(f"User {username} logged out")
186
- return jsonify({'status': 'success', 'message': 'Logged out successfully'})
187
 
188
  @app.route('/get_supervisor_data')
189
  def get_supervisor_data():
190
  supervisor_name = session.get('supervisor_name', 'GUEST')
191
- logging.info(f"Fetching supervisor data for: {supervisor_name}")
192
-
193
  if supervisor_name == 'GUEST':
194
- logging.info("Returning default data for GUEST user")
195
- return jsonify({
196
- 'status': 'success',
197
- 'data': {
198
- 'supervisor_name': 'GUEST',
199
- 'daily_checklist': 'Sample Task 1\nSample Task 2',
200
- 'suggested_tips': 'Tip 1\nTip 2\nTip 3',
201
- 'reflection_log': '',
202
- 'engagement_score': 50,
203
- 'kpi_flag': False,
204
- 'download_link': ''
205
- }
206
- })
207
-
208
- if not sf:
209
- logging.error("Salesforce connection not available for get_supervisor_data")
210
- return jsonify({'status': 'error', 'message': 'Salesforce connection unavailable'}), 500
211
 
212
  try:
 
213
  query = f"""
214
- SELECT Name, Project_ID__c, Daily_Checklist__c, Suggested_Tips__c,
215
- Reflection_Log__c, Engagement_Score__c, KPI_Flag__c,
216
- Download_Link__c, Last_Login__c
217
- FROM Supervisor_AI_Coaching__c
218
  WHERE Name = '{supervisor_name}'
 
219
  """
220
  result = sf.query(query)
221
- logging.info(f"Queried Salesforce for supervisor data: {supervisor_name}")
222
-
223
- if result['totalSize'] == 0:
224
- logging.warning(f"No data found for user {supervisor_name}")
225
- return jsonify({'status': 'error', 'message': 'User not found'})
226
 
227
- record = result['records'][0]
228
- data = {
229
- 'supervisor_name': record['Name'],
230
- 'project_id': record['Project_ID__c'],
231
- 'daily_checklist': record['Daily_Checklist__c'] or '',
232
- 'suggested_tips': record['Suggested_Tips__c'] or '',
233
- 'reflection_log': record['Reflection_Log__c'] or '',
234
- 'engagement_score': record['Engagement_Score__c'] or 0,
235
- 'kpi_flag': record['KPI_Flag__c'] or False,
236
- 'download_link': record['Download_Link__c'] or '',
237
- 'last_login': record['Last_Login__c']
238
- }
239
- logging.info(f"Successfully fetched supervisor data for {supervisor_name}")
240
- return jsonify({'status': 'success', 'data': data})
 
 
 
 
 
 
 
241
  except Exception as e:
242
- logging.error(f"Error fetching supervisor data for {supervisor_name}: {str(e)}")
243
- return jsonify({'status': 'error', 'message': 'Error fetching data'})
244
 
245
  @app.route('/submit_reflection', methods=['POST'])
246
  def submit_reflection():
247
  supervisor_name = session.get('supervisor_name', 'GUEST')
248
- logging.info(f"Submitting reflection for user: {supervisor_name}")
249
-
250
  if supervisor_name == 'GUEST':
251
- logging.warning("Reflection submission not allowed for GUEST user")
252
- return jsonify({'status': 'error', 'message': 'Guest users cannot submit reflections'})
 
253
 
254
- if not sf:
255
- logging.error("Salesforce connection not available for submit_reflection")
256
- return jsonify({'status': 'error', 'message': 'Salesforce connection unavailable'}), 500
257
-
258
- reflection = request.json.get('reflection')
259
- if not reflection:
260
- logging.warning(f"Empty reflection submitted by {supervisor_name}")
261
- return jsonify({'status': 'error', 'message': 'Reflection cannot be empty'})
262
 
263
  try:
264
- query = f"SELECT Id FROM Supervisor_AI_Coaching__c WHERE Name = '{supervisor_name}'"
 
265
  result = sf.query(query)
266
- if result['totalSize'] == 0:
267
- logging.warning(f"User {supervisor_name} not found for reflection submission")
268
- return jsonify({'status': 'error', 'message': 'User not found'})
269
 
270
  record_id = result['records'][0]['Id']
271
  sf.Supervisor_AI_Coaching__c.update(record_id, {'Reflection_Log__c': reflection})
272
- logging.info(f"Reflection submitted successfully for {supervisor_name}")
273
- return jsonify({'status': 'success', 'message': 'Reflection submitted successfully'})
 
 
 
274
  except Exception as e:
275
- logging.error(f"Error submitting reflection for {supervisor_name}: {str(e)}")
276
- return jsonify({'status': 'error', 'message': 'Error submitting reflection'})
277
 
278
  @app.route('/generate', methods=['POST'])
279
- def generate_coaching():
280
  supervisor_name = session.get('supervisor_name', 'GUEST')
281
- logging.info(f"Generating coaching output for user: {supervisor_name}")
 
 
 
 
 
 
 
 
 
 
 
 
282
 
283
- if not sf:
284
- logging.error("Salesforce connection not available for generate_coaching")
285
- return jsonify({'status': 'error', 'message': 'Salesforce connection unavailable'}), 500
 
 
 
 
 
 
 
 
286
 
287
  try:
288
- # Fetch supervisor data to pass to Hugging Face API
289
- data = request.json
290
- output = generate_coaching_output_with_hf(data)
291
-
292
- if supervisor_name != 'GUEST':
293
- query = f"SELECT Id FROM Supervisor_AI_Coaching__c WHERE Name = '{supervisor_name}'"
294
- result = sf.query(query)
295
- if result['totalSize'] == 0:
296
- logging.warning(f"User {supervisor_name} not found for coaching generation")
297
- return jsonify({'status': 'error', 'message': 'User not found'})
298
-
299
- record_id = result['records'][0]['Id']
300
- sf.Supervisor_AI_Coaching__c.update(record_id, {
301
- 'Daily_Checklist__c': '\n'.join(output['checklist']),
302
- 'Suggested_Tips__c': '\n'.join(output['tips'])
303
- })
304
- logging.info(f"Coaching output updated in Salesforce for {supervisor_name}")
305
-
306
- logging.info(f"Coaching output generated for {supervisor_name}")
307
- return jsonify({'status': 'success', 'output': output})
 
 
 
308
  except Exception as e:
309
- logging.error(f"Error generating coaching output for {supervisor_name}: {str(e)}")
310
- return jsonify({'status': 'error', 'message': 'Error generating coaching output'})
311
 
312
- @app.route('/download_pdf')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
  def download_pdf():
314
  supervisor_name = session.get('supervisor_name', 'GUEST')
315
- logging.info(f"Generating PDF for user: {supervisor_name}")
316
-
317
- if not sf:
318
- logging.error("Salesforce connection not available for download_pdf")
319
- return jsonify({'status': 'error', 'message': 'Salesforce connection unavailable'}), 500
320
 
321
  try:
 
322
  query = f"""
323
- SELECT Name, Project_ID__c, Daily_Checklist__c, Suggested_Tips__c,
324
- Reflection_Log__c, Engagement_Score__c, KPI_Flag__c
325
- FROM Supervisor_AI_Coaching__c
326
  WHERE Name = '{supervisor_name}'
 
327
  """
328
  result = sf.query(query)
329
- if result['totalSize'] == 0:
330
- logging.warning(f"User {supervisor_name} not found for PDF generation")
331
- return jsonify({'status': 'error', 'message': 'User not found'})
332
 
333
  record = result['records'][0]
 
 
 
 
 
 
 
 
 
 
 
 
334
 
335
- buffer = BytesIO()
336
- c = canvas.Canvas(buffer, pagesize=letter)
337
- c.setFont("Helvetica", 12)
338
-
339
- y = 750
340
- c.drawString(100, y, f"Supervisor Report for {record['Name']}")
341
- y -= 30
342
- c.drawString(100, y, f"Project ID: {record['Project_ID__c'] or 'N/A'}")
343
- y -= 20
344
- c.drawString(100, y, f"Engagement Score: {record['Engagement_Score__c'] or 0}%")
345
- y -= 20
346
- c.drawString(100, y, f"KPI Flag: {'Active' if record['KPI_Flag__c'] else 'Inactive'}")
347
- y -= 30
348
-
349
- c.drawString(100, y, "Daily Checklist:")
350
- y -= 20
351
- checklist = (record['Daily_Checklist__c'] or '').split('\n')
352
- for item in checklist:
353
- if item.strip():
354
- c.drawString(120, y, f"- {item}")
355
- y -= 15
356
-
357
- y -= 20
358
- c.drawString(100, y, "Suggested Tips:")
359
- y -= 20
360
- tips = (record['Suggested_Tips__c'] or '').split('\n')
361
- for tip in tips:
362
- if tip.strip():
363
- c.drawString(120, y, f"- {tip}")
364
- y -= 15
365
-
366
- y -= 20
367
- c.drawString(100, y, "Reflection Log:")
368
- y -= 20
369
- reflection = record['Reflection_Log__c'] or 'No reflections yet.'
370
- c.drawString(120, y, reflection[:80])
371
- y -= 15
372
- if len(reflection) > 80:
373
- c.drawString(120, y, reflection[80:160])
374
- y -= 15
375
-
376
- c.showPage()
377
- c.save()
378
- buffer.seek(0)
379
-
380
- if supervisor_name != 'GUEST':
381
- record_id = result['records'][0]['Id']
382
- sf.Supervisor_AI_Coaching__c.update(record_id, {
383
- 'Download_Link__c': 'https://example.com/report.pdf'
384
- })
385
- logging.info(f"Updated Download_Link__c for {supervisor_name}")
386
-
387
- logging.info(f"PDF generated successfully for {supervisor_name}")
388
- return send_file(buffer, as_attachment=True, download_name=f'supervisor_report_{supervisor_name}.pdf', mimetype='application/pdf')
389
  except Exception as e:
390
- logging.error(f"Error generating PDF for {supervisor_name}: {str(e)}")
391
- return jsonify({'status': 'error', 'message': 'Error generating PDF'})
 
 
 
 
 
 
 
392
 
393
  if __name__ == '__main__':
394
  port = int(os.getenv('PORT', 5000))
395
- logging.info(f"Starting Flask app on port {port}")
396
  app.run(host='0.0.0.0', port=port, debug=True)
 
1
+ from flask import Flask, request, jsonify, session, redirect, url_for, render_template, send_file
2
+ from simple_salesforce import Salesforce, SalesforceAuthenticationFailed, SalesforceError
3
  import os
 
 
4
  from datetime import datetime
 
 
5
  from dotenv import load_dotenv
6
+ import logging
7
  from reportlab.lib.pagesizes import letter
8
  from reportlab.pdfgen import canvas
9
+ import io
10
+ import tempfile
11
 
12
  # Load environment variables
13
  load_dotenv()
14
 
15
  # Configure logging
16
  logging.basicConfig(
 
17
  level=logging.INFO,
18
+ format='%(asctime)s - %(levelname)s - %(message)s',
19
+ handlers=[
20
+ logging.FileHandler('app.log'),
21
+ logging.StreamHandler()
22
+ ]
23
  )
24
+ logger = logging.getLogger(__name__)
25
 
26
  app = Flask(__name__)
27
+ app.secret_key = os.getenv('FLASK_SECRET_KEY', 'your-secret-key')
28
+
29
+ # Salesforce mock data for guest users
30
+ MOCK_DATA = {
31
+ "supervisor_name": "GUEST",
32
+ "project_id": "PROJ_001",
33
+ "daily_checklist": "Inspect safety equipment\nReview team assignments\nCheck project timeline",
34
+ "suggested_tips": "Prioritize safety checks\nCommunicate clearly with the team\nMonitor resource usage",
35
+ "reflection_log": "",
36
+ "engagement_score": 85,
37
+ "kpi_flag": False,
38
+ "download_link": "",
39
+ "last_login": str(datetime.now())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  }
41
 
42
+ def get_salesforce_connection():
43
+ """Establish a Salesforce connection with error handling."""
44
  try:
45
+ sf = Salesforce(
46
+ username=os.getenv('SALESFORCE_USERNAME'),
47
+ password=os.getenv('SALESFORCE_PASSWORD'),
48
+ security_token=os.getenv('SALESFORCE_SECURITY_TOKEN'),
49
+ domain=os.getenv('SALESFORCE_DOMAIN', 'test') # 'login' for production
 
 
50
  )
51
+ logger.info("Successfully connected to Salesforce")
52
+ return sf
53
+ except SalesforceAuthenticationFailed as e:
54
+ logger.error(f"Salesforce authentication failed: {str(e)}")
55
+ raise Exception("Salesforce authentication failed. Check your credentials.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  except Exception as e:
57
+ logger.error(f"Error connecting to Salesforce: {str(e)}")
58
+ raise Exception("Unable to connect to Salesforce. Please try again later.")
 
 
 
59
 
60
  @app.route('/')
61
+ def index():
62
  if 'supervisor_name' not in session:
63
+ logger.info("User not logged in, redirecting to login page")
64
+ return redirect(url_for('login_page'))
 
65
  return render_template('index.html')
66
 
67
+ @app.route('/login', methods=['GET'])
68
+ def login_page():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  return render_template('login.html')
70
 
71
+ @app.route('/signup', methods=['GET'])
72
+ def signup_page():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  return render_template('signup.html')
74
 
75
+ @app.route('/login', methods=['POST'])
76
+ def login():
77
+ data = request.get_json()
78
+ username = data.get('username') # Now using Name field
79
+ password = data.get('password')
80
+
81
+ if username == 'GUEST':
82
+ session['supervisor_name'] = 'GUEST'
83
+ logger.info("Guest login successful")
84
+ return jsonify({"status": "success", "message": "Logged in as guest"})
85
+
86
+ try:
87
+ sf = get_salesforce_connection()
88
+ # Query Supervisor_AI_Coaching__c for Name and Password__c
89
+ query = f"SELECT Id, Name, Password__c FROM Supervisor_AI_Coaching__c WHERE Name = '{username}' LIMIT 1"
90
+ result = sf.query(query)
91
+ if not result['records']:
92
+ logger.warning(f"Invalid username: {username}")
93
+ return jsonify({"status": "error", "message": "Invalid username"}), 401
94
+
95
+ record = result['records'][0]
96
+ stored_password = record['Password__c']
97
+ if stored_password != password:
98
+ logger.warning(f"Invalid password for username: {username}")
99
+ return jsonify({"status": "error", "message": "Invalid password"}), 401
100
+
101
+ session['supervisor_name'] = username
102
+ logger.info(f"Login successful for {username}")
103
+ return jsonify({"status": "success", "message": "Login successful"})
104
+ except Exception as e:
105
+ logger.error(f"Login error: {str(e)}")
106
+ return jsonify({"status": "error", "message": str(e)}), 500
107
+
108
+ @app.route('/signup', methods=['POST'])
109
+ def signup():
110
+ data = request.get_json()
111
+ username = data.get('username') # Name field
112
+ password = data.get('password') # Password__c field
113
+ project_id = data.get('project_id', 'PROJ_001') # Project_ID__c
114
+ engagement_score = float(data.get('engagement_score', 85)) # Engagement_Score__c
115
+ kpi_flag = data.get('kpi_flag', False) # KPI_Flag__c
116
+
117
+ if not username or not password:
118
+ logger.warning("Signup failed: Username and password are required")
119
+ return jsonify({"status": "error", "message": "Username and password are required"}), 400
120
+
121
+ try:
122
+ sf = get_salesforce_connection()
123
+ # Check if username already exists
124
+ query = f"SELECT Id FROM Supervisor_AI_Coaching__c WHERE Name = '{username}' LIMIT 1"
125
+ result = sf.query(query)
126
+ if result['records']:
127
+ logger.warning(f"Signup failed: Username {username} already exists")
128
+ return jsonify({"status": "error", "message": "Username already exists"}), 400
129
+
130
+ # Create new Supervisor_AI_Coaching__c record
131
+ new_record = {
132
+ 'Name': username,
133
+ 'Password__c': password,
134
+ 'Project_ID__c': project_id,
135
+ 'Engagement_Score__c': engagement_score,
136
+ 'KPI_Flag__c': kpi_flag,
137
+ 'Daily_Checklist__c': '',
138
+ 'Suggested_Tips__c': '',
139
+ 'Reflection_Log__c': '',
140
+ 'Download_Link__c': ''
141
+ }
142
+ sf.Supervisor_AI_Coaching__c.create(new_record)
143
+ logger.info(f"Signup successful for {username}")
144
+
145
+ # Automatically log in the user after signup
146
+ session['supervisor_name'] = username
147
+ return jsonify({"status": "success", "message": "Signup successful, you are now logged in"})
148
+ except SalesforceError as e:
149
+ logger.error(f"Salesforce API error during signup: {str(e)}")
150
+ return jsonify({"status": "error", "message": "Salesforce API error. Please try again later."}), 500
151
+ except Exception as e:
152
+ logger.error(f"Signup error: {str(e)}")
153
+ return jsonify({"status": "error", "message": str(e)}), 500
154
+
155
  @app.route('/logout', methods=['POST'])
156
  def logout():
157
+ supervisor_name = session.get('supervisor_name', 'Unknown')
158
  session.pop('supervisor_name', None)
159
+ logger.info(f"User {supervisor_name} logged out")
160
+ return jsonify({"status": "success", "message": "Logged out successfully"})
161
 
162
  @app.route('/get_supervisor_data')
163
  def get_supervisor_data():
164
  supervisor_name = session.get('supervisor_name', 'GUEST')
 
 
165
  if supervisor_name == 'GUEST':
166
+ logger.info("Returning mock data for guest user")
167
+ return jsonify({"status": "success", "data": MOCK_DATA})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
 
169
  try:
170
+ sf = get_salesforce_connection()
171
  query = f"""
172
+ SELECT Name, Project_ID__c, Daily_Checklist__c, Suggested_Tips__c,
173
+ Reflection_Log__c, Engagement_Score__c, KPI_Flag__c, Download_Link__c
174
+ FROM Supervisor_AI_Coaching__c
 
175
  WHERE Name = '{supervisor_name}'
176
+ LIMIT 1
177
  """
178
  result = sf.query(query)
 
 
 
 
 
179
 
180
+ if result['records']:
181
+ record = result['records'][0]
182
+ data = {
183
+ "supervisor_name": record['Name'],
184
+ "project_id": record['Project_ID__c'],
185
+ "daily_checklist": record['Daily_Checklist__c'] or "",
186
+ "suggested_tips": record['Suggested_Tips__c'] or "",
187
+ "reflection_log": record['Reflection_Log__c'] or "",
188
+ "engagement_score": record['Engagement_Score__c'] or 0,
189
+ "kpi_flag": record['KPI_Flag__c'],
190
+ "download_link": record['Download_Link__c'] or "",
191
+ "last_login": str(datetime.now())
192
+ }
193
+ logger.info(f"Fetched data for supervisor {supervisor_name}")
194
+ return jsonify({"status": "success", "data": data})
195
+ else:
196
+ logger.warning(f"No data found for supervisor {supervisor_name}")
197
+ return jsonify({"status": "error", "message": "No data found for this supervisor"})
198
+ except SalesforceError as e:
199
+ logger.error(f"Salesforce API error while fetching data: {str(e)}")
200
+ return jsonify({"status": "error", "message": "Salesforce API error. Please try again later."}), 500
201
  except Exception as e:
202
+ logger.error(f"Error fetching supervisor data: {str(e)}")
203
+ return jsonify({"status": "error", "message": str(e)}), 500
204
 
205
  @app.route('/submit_reflection', methods=['POST'])
206
  def submit_reflection():
207
  supervisor_name = session.get('supervisor_name', 'GUEST')
 
 
208
  if supervisor_name == 'GUEST':
209
+ MOCK_DATA['reflection_log'] = request.get_json().get('reflection')
210
+ logger.info("Reflection submitted for guest user")
211
+ return jsonify({"status": "success", "message": "Reflection submitted successfully (guest mode)"})
212
 
213
+ data = request.get_json()
214
+ reflection = data.get('reflection')
 
 
 
 
 
 
215
 
216
  try:
217
+ sf = get_salesforce_connection()
218
+ query = f"SELECT Id FROM Supervisor_AI_Coaching__c WHERE Name = '{supervisor_name}' LIMIT 1"
219
  result = sf.query(query)
220
+ if not result['records']:
221
+ logger.warning(f"No record found for supervisor {supervisor_name}")
222
+ return jsonify({"status": "error", "message": "No record found for this supervisor"}), 404
223
 
224
  record_id = result['records'][0]['Id']
225
  sf.Supervisor_AI_Coaching__c.update(record_id, {'Reflection_Log__c': reflection})
226
+ logger.info(f"Reflection updated for supervisor {supervisor_name}")
227
+ return jsonify({"status": "success", "message": "Reflection submitted successfully"})
228
+ except SalesforceError as e:
229
+ logger.error(f"Salesforce API error while submitting reflection: {str(e)}")
230
+ return jsonify({"status": "error", "message": "Salesforce API error. Please try again later."}), 500
231
  except Exception as e:
232
+ logger.error(f"Error submitting reflection: {str(e)}")
233
+ return jsonify({"status": "error", "message": str(e)}), 500
234
 
235
  @app.route('/generate', methods=['POST'])
236
+ def generate():
237
  supervisor_name = session.get('supervisor_name', 'GUEST')
238
+ data = request.get_json()
239
+
240
+ # Generate checklist and tips (simplified logic)
241
+ checklist = [
242
+ "Inspect safety equipment",
243
+ "Review team assignments",
244
+ "Check project timeline"
245
+ ]
246
+ tips = [
247
+ "Prioritize safety checks",
248
+ "Communicate clearly with the team",
249
+ "Monitor resource usage"
250
+ ]
251
 
252
+ if supervisor_name == 'GUEST':
253
+ MOCK_DATA['daily_checklist'] = '\n'.join(checklist)
254
+ MOCK_DATA['suggested_tips'] = '\n'.join(tips)
255
+ logger.info("Generated coaching output for guest user")
256
+ return jsonify({
257
+ "status": "success",
258
+ "output": {
259
+ "checklist": checklist,
260
+ "tips": tips
261
+ }
262
+ })
263
 
264
  try:
265
+ sf = get_salesforce_connection()
266
+ query = f"SELECT Id FROM Supervisor_AI_Coaching__c WHERE Name = '{supervisor_name}' LIMIT 1"
267
+ result = sf.query(query)
268
+ if not result['records']:
269
+ logger.warning(f"No record found for supervisor {supervisor_name}")
270
+ return jsonify({"status": "error", "message": "No record found for this supervisor"}), 404
271
+
272
+ record_id = result['records'][0]['Id']
273
+ sf.Supervisor_AI_Coaching__c.update(record_id, {
274
+ 'Daily_Checklist__c': '\n'.join(checklist),
275
+ 'Suggested_Tips__c': '\n'.join(tips)
276
+ })
277
+ logger.info(f"Generated and updated coaching output for supervisor {supervisor_name}")
278
+ return jsonify({
279
+ "status": "success",
280
+ "output": {
281
+ "checklist": checklist,
282
+ "tips": tips
283
+ }
284
+ })
285
+ except SalesforceError as e:
286
+ logger.error(f"Salesforce API error while generating output: {str(e)}")
287
+ return jsonify({"status": "error", "message": "Salesforce API error. Please try again later."}), 500
288
  except Exception as e:
289
+ logger.error(f"Error generating coaching output: {str(e)}")
290
+ return jsonify({"status": "error", "message": str(e)}), 500
291
 
292
+ def generate_pdf_summary(data):
293
+ """Generate a PDF summary and return the file path."""
294
+ try:
295
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf', dir='/tmp') as tmp_file:
296
+ pdf_path = tmp_file.name
297
+ c = canvas.Canvas(pdf_path, pagesize=letter)
298
+ width, height = letter
299
+
300
+ # Title
301
+ c.setFont("Helvetica-Bold", 16)
302
+ c.drawString(50, height - 50, "Supervisor AI Coaching Summary")
303
+
304
+ # Supervisor Data
305
+ c.setFont("Helvetica", 12)
306
+ y_position = height - 100
307
+ c.drawString(50, y_position, f"Supervisor Name: {data.get('supervisor_name', 'N/A')}")
308
+ y_position -= 20
309
+ c.drawString(50, y_position, f"Project ID: {data.get('project_id', 'N/A')}")
310
+ y_position -= 20
311
+ c.drawString(50, y_position, f"Last Login: {data.get('last_login', 'N/A')}")
312
+ y_position -= 40
313
+
314
+ # Daily Checklist
315
+ c.setFont("Helvetica-Bold", 14)
316
+ c.drawString(50, y_position, "Daily Checklist")
317
+ c.setFont("Helvetica", 12)
318
+ y_position -= 20
319
+ checklist = data.get('daily_checklist', '').split('\n')
320
+ for item in checklist:
321
+ if item.strip():
322
+ c.drawString(70, y_position, f"- {item}")
323
+ y_position -= 20
324
+ if y_position < 50:
325
+ c.showPage()
326
+ y_position = height - 50
327
+
328
+ # Suggested Tips
329
+ y_position -= 20
330
+ c.setFont("Helvetica-Bold", 14)
331
+ c.drawString(50, y_position, "Suggested Tips")
332
+ c.setFont("Helvetica", 12)
333
+ y_position -= 20
334
+ tips = data.get('suggested_tips', '').split('\n')
335
+ for tip in tips:
336
+ if tip.strip():
337
+ c.drawString(70, y_position, f"- {tip}")
338
+ y_position -= 20
339
+ if y_position < 50:
340
+ c.showPage()
341
+ y_position = height - 50
342
+
343
+ # Reflection Log
344
+ y_position -= 20
345
+ c.setFont("Helvetica-Bold", 14)
346
+ c.drawString(50, y_position, "Reflection Log")
347
+ c.setFont("Helvetica", 12)
348
+ y_position -= 20
349
+ reflection = data.get('reflection_log', 'No reflection available.')
350
+ lines = reflection.split('\n')
351
+ for line in lines:
352
+ c.drawString(70, y_position, line)
353
+ y_position -= 20
354
+ if y_position < 50:
355
+ c.showPage()
356
+ y_position = height - 50
357
+
358
+ # KPIs
359
+ y_position -= 20
360
+ c.setFont("Helvetica-Bold", 14)
361
+ c.drawString(50, y_position, "KPIs")
362
+ c.setFont("Helvetica", 12)
363
+ y_position -= 20
364
+ c.drawString(70, y_position, f"Engagement Score: {data.get('engagement_score', 0)}%")
365
+ y_position -= 20
366
+ c.drawString(70, y_position, f"KPI Flag: {'Active' if data.get('kpi_flag', False) else 'Inactive'}")
367
+ y_position -= 20
368
+
369
+ c.save()
370
+ logger.info(f"Generated PDF at {pdf_path}")
371
+ return pdf_path
372
+ except Exception as e:
373
+ logger.error(f"Error generating PDF: {str(e)}")
374
+ raise
375
+
376
+ @app.route('/download_pdf', methods=['GET'])
377
  def download_pdf():
378
  supervisor_name = session.get('supervisor_name', 'GUEST')
379
+ if supervisor_name == 'GUEST':
380
+ logger.info("Download not available for guest user")
381
+ return jsonify({"status": "success", "message": "Download not available in guest mode"})
 
 
382
 
383
  try:
384
+ sf = get_salesforce_connection()
385
  query = f"""
386
+ SELECT Id, Name, Project_ID__c, Daily_Checklist__c, Suggested_Tips__c,
387
+ Reflection_Log__c, Engagement_Score__c, KPI_Flag__c, Download_Link__c
388
+ FROM Supervisor_AI_Coaching__c
389
  WHERE Name = '{supervisor_name}'
390
+ LIMIT 1
391
  """
392
  result = sf.query(query)
393
+ if not result['records']:
394
+ logger.warning(f"No record found for supervisor {supervisor_name}")
395
+ return jsonify({"status": "error", "message": "No record found for this supervisor"}), 404
396
 
397
  record = result['records'][0]
398
+ record_id = record['Id']
399
+ data = {
400
+ "supervisor_name": record['Name'],
401
+ "project_id": record['Project_ID__c'],
402
+ "daily_checklist": record['Daily_Checklist__c'] or "",
403
+ "suggested_tips": record['Suggested_Tips__c'] or "",
404
+ "reflection_log": record['Reflection_Log__c'] or "",
405
+ "engagement_score": record['Engagement_Score__c'] or 0,
406
+ "kpi_flag": record['KPI_Flag__c'],
407
+ "download_link": record['Download_Link__c'] or "",
408
+ "last_login": str(datetime.now())
409
+ }
410
 
411
+ # Generate PDF
412
+ pdf_path = generate_pdf_summary(data)
413
+
414
+ # Placeholder for Download_Link__c (requires actual storage solution in production)
415
+ download_link = "https://example.com/report.pdf"
416
+ sf.Supervisor_AI_Coaching__c.update(record_id, {'Download_Link__c': download_link})
417
+ logger.info(f"Updated Download_Link__c for supervisor {supervisor_name}")
418
+
419
+ # Serve the PDF file
420
+ return send_file(
421
+ pdf_path,
422
+ as_attachment=True,
423
+ download_name=f"supervisor_report_{supervisor_name}.pdf",
424
+ mimetype='application/pdf'
425
+ )
426
+ except SalesforceError as e:
427
+ logger.error(f"Salesforce API error while downloading PDF: {str(e)}")
428
+ return jsonify({"status": "error", "message": "Salesforce API error. Please try again later."}), 500
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
429
  except Exception as e:
430
+ logger.error(f"Error downloading PDF: {str(e)}")
431
+ return jsonify({"status": "error", "message": str(e)}), 500
432
+ finally:
433
+ if 'pdf_path' in locals():
434
+ try:
435
+ os.remove(pdf_path)
436
+ logger.info(f"Cleaned up temporary PDF file: {pdf_path}")
437
+ except Exception as e:
438
+ logger.warning(f"Failed to clean up PDF file: {str(e)}")
439
 
440
  if __name__ == '__main__':
441
  port = int(os.getenv('PORT', 5000))
 
442
  app.run(host='0.0.0.0', port=port, debug=True)