sonuprasad23 commited on
Commit
f03221e
·
1 Parent(s): f8af8c1
Files changed (2) hide show
  1. config/emails.conf +1 -2
  2. server.py +156 -125
config/emails.conf CHANGED
@@ -1,5 +1,4 @@
1
  derinpatel@hillsidemedicalgroup.com
2
  bruno.carvalho@iglobalservices.net
3
  arajendra@hillsidemedicalgroup.com
4
- smahato@hillsidemedicalgroup.com
5
- example@hillsidemedicalgroup.com
 
1
  derinpatel@hillsidemedicalgroup.com
2
  bruno.carvalho@iglobalservices.net
3
  arajendra@hillsidemedicalgroup.com
4
+ smahato@hillsidemedicalgroup.com
 
server.py CHANGED
@@ -1,4 +1,3 @@
1
- # server.py - Gmail API with Professional Email Reports
2
  import eventlet
3
  eventlet.monkey_patch()
4
 
@@ -57,15 +56,15 @@ class GmailApiService:
57
  credentials = credentials.with_subject(self.sender_email)
58
 
59
  self.service = build('gmail', 'v1', credentials=credentials)
60
- print("[Gmail API] Service initialized successfully using existing credentials")
61
 
62
  except Exception as e:
63
  print(f"[Gmail API] Error: {e}")
64
 
65
  def create_professional_email_template(self, subject, status_text, stats, custom_name):
66
- """Create a professional HTML email template"""
67
 
68
- status_color = "#28a745" if "successfully" in status_text else "#dc3545" if "error" in status_text else "#ffc107"
69
  current_date = datetime.now().strftime("%B %d, %Y at %I:%M %p")
70
 
71
  html_template = f"""
@@ -83,65 +82,89 @@ class GmailApiService:
83
  }}
84
 
85
  body {{
86
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
87
  line-height: 1.6;
88
- color: #333333;
89
- background-color: #f8f9fa;
90
  }}
91
 
92
  .email-container {{
93
  max-width: 700px;
94
- margin: 0 auto;
95
  background-color: #ffffff;
96
- box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
 
 
97
  }}
98
 
99
  .header {{
100
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
101
  color: white;
102
  padding: 40px 30px;
103
  text-align: center;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  }}
105
 
106
  .header h1 {{
107
- font-size: 28px;
108
- font-weight: 600;
109
  margin-bottom: 8px;
 
110
  }}
111
 
112
  .header p {{
113
- font-size: 16px;
114
- opacity: 0.9;
115
  font-weight: 300;
 
116
  }}
117
 
118
  .status-banner {{
119
- background-color: {status_color};
120
  color: white;
121
  text-align: center;
122
- padding: 15px;
123
  font-size: 16px;
124
- font-weight: 500;
125
  text-transform: uppercase;
126
- letter-spacing: 0.5px;
 
127
  }}
128
 
129
  .content {{
130
- padding: 30px;
131
  }}
132
 
133
  .report-info {{
134
- background-color: #f8f9fa;
135
- border-left: 4px solid #667eea;
136
- padding: 20px;
137
- margin-bottom: 30px;
138
- border-radius: 0 6px 6px 0;
 
139
  }}
140
 
141
  .report-info h3 {{
142
- color: #495057;
143
- margin-bottom: 15px;
144
- font-size: 18px;
 
145
  }}
146
 
147
  .info-grid {{
@@ -155,85 +178,98 @@ class GmailApiService:
155
  display: flex;
156
  justify-content: space-between;
157
  align-items: center;
158
- padding: 12px 0;
159
- border-bottom: 1px solid #e9ecef;
160
  }}
161
 
162
  .info-label {{
163
- font-weight: 500;
164
- color: #495057;
 
165
  }}
166
 
167
  .info-value {{
168
- font-weight: 600;
169
- color: #212529;
 
170
  }}
171
 
172
  .stats-section {{
173
- margin: 30px 0;
174
  }}
175
 
176
  .stats-section h3 {{
177
- color: #495057;
178
- margin-bottom: 20px;
179
- font-size: 18px;
180
- border-bottom: 2px solid #e9ecef;
 
181
  padding-bottom: 10px;
182
  }}
183
 
184
  .stats-grid {{
185
  display: grid;
186
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
187
  gap: 20px;
188
- margin-bottom: 20px;
189
  }}
190
 
191
  .stat-card {{
192
- background-color: white;
193
- border: 1px solid #e9ecef;
194
- border-radius: 8px;
195
- padding: 20px;
196
  text-align: center;
197
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
 
 
 
 
 
 
198
  }}
199
 
200
  .stat-number {{
201
- font-size: 32px;
202
- font-weight: 700;
203
- color: #667eea;
204
- margin-bottom: 8px;
 
205
  }}
206
 
207
  .stat-label {{
208
- font-size: 14px;
209
- color: #6c757d;
210
  text-transform: uppercase;
211
- letter-spacing: 0.5px;
212
- font-weight: 500;
213
  }}
214
 
215
- .success .stat-number {{ color: #28a745; }}
216
- .warning .stat-number {{ color: #ffc107; }}
217
- .danger .stat-number {{ color: #dc3545; }}
218
 
219
  .attachments-section {{
220
- background-color: #f8f9fa;
221
- border-radius: 8px;
222
- padding: 20px;
223
- margin: 30px 0;
 
 
224
  }}
225
 
226
  .attachments-section h3 {{
227
- color: #495057;
228
- margin-bottom: 15px;
229
- font-size: 16px;
 
230
  }}
231
 
232
  .attachment-item {{
233
  display: flex;
234
  align-items: center;
235
- padding: 10px 0;
236
- border-bottom: 1px solid #dee2e6;
237
  }}
238
 
239
  .attachment-item:last-child {{
@@ -241,28 +277,30 @@ class GmailApiService:
241
  }}
242
 
243
  .attachment-icon {{
244
- width: 24px;
245
- height: 24px;
246
- background-color: #667eea;
247
- border-radius: 4px;
248
- margin-right: 12px;
249
  display: flex;
250
  align-items: center;
251
  justify-content: center;
252
  color: white;
253
  font-size: 12px;
254
  font-weight: bold;
 
255
  }}
256
 
257
  .attachment-name {{
258
  font-weight: 500;
259
- color: #495057;
 
260
  }}
261
 
262
  .footer {{
263
- background-color: #495057;
264
- color: #ffffff;
265
- padding: 30px;
266
  text-align: center;
267
  }}
268
 
@@ -273,28 +311,28 @@ class GmailApiService:
273
 
274
  .footer h4 {{
275
  margin-bottom: 15px;
276
- font-size: 16px;
277
- font-weight: 600;
278
  }}
279
 
280
  .footer p {{
281
  font-size: 14px;
282
- opacity: 0.8;
283
- line-height: 1.5;
284
  }}
285
 
286
  .footer .timestamp {{
287
- margin-top: 20px;
288
  padding-top: 20px;
289
- border-top: 1px solid rgba(255, 255, 255, 0.2);
290
  font-size: 12px;
291
- opacity: 0.7;
292
  }}
293
 
294
  @media only screen and (max-width: 600px) {{
295
  .email-container {{
296
- margin: 0;
297
- box-shadow: none;
298
  }}
299
 
300
  .header {{
@@ -302,20 +340,24 @@ class GmailApiService:
302
  }}
303
 
304
  .content {{
305
- padding: 20px;
306
  }}
307
 
308
  .info-grid {{
309
  grid-template-columns: 1fr;
310
- gap: 10px;
311
  }}
312
 
313
  .stats-grid {{
314
- grid-template-columns: 1fr;
315
  }}
316
 
317
  .header h1 {{
318
- font-size: 24px;
 
 
 
 
319
  }}
320
  }}
321
  </style>
@@ -323,8 +365,10 @@ class GmailApiService:
323
  <body>
324
  <div class="email-container">
325
  <div class="header">
326
- <h1>Hillside Medical Group</h1>
327
- <p>Automation Processing Report</p>
 
 
328
  </div>
329
 
330
  <div class="status-banner">
@@ -333,29 +377,29 @@ class GmailApiService:
333
 
334
  <div class="content">
335
  <div class="report-info">
336
- <h3>Report Information</h3>
337
  <div class="info-grid">
338
  <div class="info-item">
339
- <span class="info-label">Report Name:</span>
340
  <span class="info-value">{custom_name}</span>
341
  </div>
342
  <div class="info-item">
343
- <span class="info-label">Generated:</span>
344
  <span class="info-value">{current_date}</span>
345
  </div>
346
  <div class="info-item">
347
- <span class="info-label">Process Status:</span>
348
  <span class="info-value" style="color: {status_color};">{status_text.title()}</span>
349
  </div>
350
  <div class="info-item">
351
- <span class="info-label">Email Method:</span>
352
- <span class="info-value">Gmail API</span>
353
  </div>
354
  </div>
355
  </div>
356
 
357
  <div class="stats-section">
358
- <h3>Processing Statistics</h3>
359
  <div class="stats-grid">
360
  <div class="stat-card">
361
  <div class="stat-number">{stats['total']}</div>
@@ -367,11 +411,11 @@ class GmailApiService:
367
  </div>
368
  <div class="stat-card success">
369
  <div class="stat-number">{stats['successful']}</div>
370
- <div class="stat-label">Successful</div>
371
  </div>
372
  <div class="stat-card danger">
373
  <div class="stat-number">{stats['failed']}</div>
374
- <div class="stat-label">Issues Found</div>
375
  </div>
376
  </div>
377
  </div>
@@ -380,36 +424,24 @@ class GmailApiService:
380
  <h3>Report Files</h3>
381
  <div class="attachment-item">
382
  <div class="attachment-icon">CSV</div>
383
- <div class="attachment-name">{custom_name}_Full.csv - Complete processing report with all patient records</div>
384
  </div>
385
  <div class="attachment-item">
386
  <div class="attachment-icon">CSV</div>
387
- <div class="attachment-name">{custom_name}_Bad.csv - Records that encountered processing issues</div>
388
  </div>
389
  </div>
390
-
391
- <div style="background-color: #e3f2fd; border-radius: 8px; padding: 20px; margin: 30px 0;">
392
- <h4 style="color: #1565c0; margin-bottom: 10px;">Important Information</h4>
393
- <p style="color: #1976d2; margin: 0;">
394
- This automated report contains sensitive patient processing information.
395
- Please ensure proper handling and storage according to your organization's data protection policies.
396
- The attached files contain detailed processing results for review and record-keeping.
397
- </p>
398
- </div>
399
  </div>
400
 
401
  <div class="footer">
402
  <div class="footer-content">
403
  <h4>Hillside Medical Group</h4>
404
  <p>
405
- This automated report was generated by the Hillside Quantum Automation System.
406
- The system processes patient records efficiently while maintaining the highest standards
407
- of data security and accuracy.
408
  </p>
409
  <div class="timestamp">
410
- Report generated on {current_date}
411
- <br>
412
- System: HuggingFace Spaces | Version: 2.0
413
  </div>
414
  </div>
415
  </div>
@@ -432,7 +464,7 @@ class GmailApiService:
432
  try:
433
  from googleapiclient.errors import HttpError
434
 
435
- print(f"[Gmail API] Sending professional report to: {recipients}")
436
 
437
  message = MIMEMultipart()
438
  message['From'] = self.sender_email
@@ -457,7 +489,7 @@ class GmailApiService:
457
  body=gmail_message
458
  ).execute()
459
 
460
- print(f"[Gmail API] Professional email sent successfully! Message ID: {sent_message['id']}")
461
  return True
462
 
463
  except HttpError as error:
@@ -482,9 +514,9 @@ class GoogleDriveService:
482
  creds_dict = json.loads(creds_json)
483
  self.creds = service_account.Credentials.from_service_account_info(creds_dict, scopes=['https://www.googleapis.com/auth/drive'])
484
  self.service = build('drive', 'v3', credentials=self.creds)
485
- print("[G-Drive] Service initialized securely from environment variables.")
486
  except Exception as e:
487
- print(f"[G-Drive] CRITICAL ERROR: Could not initialize Google Drive service: {e}")
488
 
489
  def upload_file(self, filename, file_content):
490
  if not self.service:
@@ -572,7 +604,7 @@ def generate_and_send_reports(session_id, results, is_crash_report=False, is_ter
572
  'failed': len([r for r in results if r['Status'] == 'Bad'])
573
  }
574
 
575
- subject = f"Hillside Automation Report - {status_text.title()}: {custom_name}"
576
 
577
  professional_body = email_service.create_professional_email_template(
578
  subject, status_text, stats, custom_name
@@ -581,13 +613,13 @@ def generate_and_send_reports(session_id, results, is_crash_report=False, is_ter
581
  email_success = email_service.send_report(data.get('emails'), subject, professional_body, attachments)
582
 
583
  if email_success:
584
- socketio.emit('process_complete', {'message': f'Process {status_text}. Professional report sent successfully via Gmail API.'})
585
  else:
586
  socketio.emit('process_complete', {'message': f'Process {status_text}. Email sending failed.'})
587
 
588
  @app.route('/')
589
  def status_page():
590
- APP_STATUS_HTML = """<!DOCTYPE html><html lang="en"><head><title>Hillside Automation - Gmail API</title><style>body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;display:flex;justify-content:center;align-items:center;height:100vh;margin:0;background:linear-gradient(135deg, #667eea 0%, #764ba2 100%);color:white;}.status-box{text-align:center;padding:40px 60px;background:rgba(255,255,255,0.1);border-radius:12px;box-shadow:0 8px 30px rgba(0,0,0,0.3);backdrop-filter:blur(10px);}h1{font-size:28px;margin-bottom:10px;} .indicator{font-size:18px;font-weight:600;padding:12px 20px;border-radius:25px;background:rgba(40,167,69,0.2);border:2px solid #28a745;color:#28a745;margin:15px 0;}.info{margin-top:20px;opacity:0.9;}</style></head><body><div class="status-box"><h1>Hillside Automation</h1><div class="indicator">Gmail API Mode - Professional Reports</div><div class="info">Chrome: Ready<br>Email: Gmail API (HTTP)<br>Drive: Integrated<br>Platform: HuggingFace<br><br><a href="https://quantbot.netlify.app" style="color:#60a5fa;">quantbot.netlify.app</a></div></div></body></html>"""
591
  return Response(APP_STATUS_HTML)
592
 
593
  @socketio.on('connect')
@@ -640,9 +672,8 @@ def handle_terminate():
640
 
641
  if __name__ == '__main__':
642
  print("====================================================================")
643
- print(" Hillside Automation - Professional Gmail API Edition")
644
- print(" Email: Gmail API with Professional Reports")
645
- print(" SMTP: Completely bypassed")
646
  print(f" Frontend: {FRONTEND_ORIGIN}")
647
  print("====================================================================")
648
  socketio.run(app, host='0.0.0.0', port=int(os.getenv('PORT', 7860)))
 
 
1
  import eventlet
2
  eventlet.monkey_patch()
3
 
 
56
  credentials = credentials.with_subject(self.sender_email)
57
 
58
  self.service = build('gmail', 'v1', credentials=credentials)
59
+ print("[Gmail API] Service initialized successfully")
60
 
61
  except Exception as e:
62
  print(f"[Gmail API] Error: {e}")
63
 
64
  def create_professional_email_template(self, subject, status_text, stats, custom_name):
65
+ """Create a professional blood red, white & violet themed email template"""
66
 
67
+ status_color = "#8B0000" if "successfully" in status_text else "#DC143C" if "error" in status_text else "#8A2BE2"
68
  current_date = datetime.now().strftime("%B %d, %Y at %I:%M %p")
69
 
70
  html_template = f"""
 
82
  }}
83
 
84
  body {{
85
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
86
  line-height: 1.6;
87
+ color: #2c2c2c;
88
+ background-color: #f8f8f8;
89
  }}
90
 
91
  .email-container {{
92
  max-width: 700px;
93
+ margin: 20px auto;
94
  background-color: #ffffff;
95
+ box-shadow: 0 8px 32px rgba(139, 0, 0, 0.15);
96
+ border-radius: 12px;
97
+ overflow: hidden;
98
  }}
99
 
100
  .header {{
101
+ background: linear-gradient(135deg, #8B0000 0%, #DC143C 50%, #8A2BE2 100%);
102
  color: white;
103
  padding: 40px 30px;
104
  text-align: center;
105
+ position: relative;
106
+ }}
107
+
108
+ .header::before {{
109
+ content: '';
110
+ position: absolute;
111
+ top: 0;
112
+ left: 0;
113
+ right: 0;
114
+ bottom: 0;
115
+ background: rgba(255, 255, 255, 0.1);
116
+ backdrop-filter: blur(10px);
117
+ }}
118
+
119
+ .header-content {{
120
+ position: relative;
121
+ z-index: 2;
122
  }}
123
 
124
  .header h1 {{
125
+ font-size: 32px;
126
+ font-weight: 700;
127
  margin-bottom: 8px;
128
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
129
  }}
130
 
131
  .header p {{
132
+ font-size: 18px;
133
+ opacity: 0.95;
134
  font-weight: 300;
135
+ letter-spacing: 1px;
136
  }}
137
 
138
  .status-banner {{
139
+ background: {status_color};
140
  color: white;
141
  text-align: center;
142
+ padding: 18px;
143
  font-size: 16px;
144
+ font-weight: 600;
145
  text-transform: uppercase;
146
+ letter-spacing: 1.5px;
147
+ box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2);
148
  }}
149
 
150
  .content {{
151
+ padding: 40px 30px;
152
  }}
153
 
154
  .report-info {{
155
+ background: linear-gradient(135deg, #f8f8f8 0%, #ffffff 100%);
156
+ border-left: 6px solid #8A2BE2;
157
+ padding: 25px;
158
+ margin-bottom: 35px;
159
+ border-radius: 8px;
160
+ box-shadow: 0 4px 12px rgba(138, 43, 226, 0.1);
161
  }}
162
 
163
  .report-info h3 {{
164
+ color: #8B0000;
165
+ margin-bottom: 20px;
166
+ font-size: 20px;
167
+ font-weight: 600;
168
  }}
169
 
170
  .info-grid {{
 
178
  display: flex;
179
  justify-content: space-between;
180
  align-items: center;
181
+ padding: 15px 0;
182
+ border-bottom: 2px solid #f0f0f0;
183
  }}
184
 
185
  .info-label {{
186
+ font-weight: 600;
187
+ color: #8B0000;
188
+ font-size: 14px;
189
  }}
190
 
191
  .info-value {{
192
+ font-weight: 700;
193
+ color: #2c2c2c;
194
+ font-size: 14px;
195
  }}
196
 
197
  .stats-section {{
198
+ margin: 35px 0;
199
  }}
200
 
201
  .stats-section h3 {{
202
+ color: #8B0000;
203
+ margin-bottom: 25px;
204
+ font-size: 20px;
205
+ font-weight: 600;
206
+ border-bottom: 3px solid #8A2BE2;
207
  padding-bottom: 10px;
208
  }}
209
 
210
  .stats-grid {{
211
  display: grid;
212
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
213
  gap: 20px;
214
+ margin-bottom: 25px;
215
  }}
216
 
217
  .stat-card {{
218
+ background: linear-gradient(135deg, #ffffff 0%, #f8f8f8 100%);
219
+ border: 2px solid #e0e0e0;
220
+ border-radius: 12px;
221
+ padding: 25px 15px;
222
  text-align: center;
223
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08);
224
+ transition: all 0.3s ease;
225
+ }}
226
+
227
+ .stat-card:hover {{
228
+ transform: translateY(-2px);
229
+ box-shadow: 0 8px 25px rgba(139, 0, 0, 0.15);
230
  }}
231
 
232
  .stat-number {{
233
+ font-size: 36px;
234
+ font-weight: 800;
235
+ color: #8A2BE2;
236
+ margin-bottom: 10px;
237
+ text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
238
  }}
239
 
240
  .stat-label {{
241
+ font-size: 12px;
242
+ color: #666;
243
  text-transform: uppercase;
244
+ letter-spacing: 1px;
245
+ font-weight: 600;
246
  }}
247
 
248
+ .success .stat-number {{ color: #8B0000; }}
249
+ .warning .stat-number {{ color: #DC143C; }}
250
+ .danger .stat-number {{ color: #8A2BE2; }}
251
 
252
  .attachments-section {{
253
+ background: linear-gradient(135deg, #8A2BE2 0%, #9370DB 100%);
254
+ color: white;
255
+ border-radius: 12px;
256
+ padding: 25px;
257
+ margin: 35px 0;
258
+ box-shadow: 0 6px 20px rgba(138, 43, 226, 0.3);
259
  }}
260
 
261
  .attachments-section h3 {{
262
+ color: white;
263
+ margin-bottom: 20px;
264
+ font-size: 18px;
265
+ font-weight: 600;
266
  }}
267
 
268
  .attachment-item {{
269
  display: flex;
270
  align-items: center;
271
+ padding: 15px 0;
272
+ border-bottom: 1px solid rgba(255, 255, 255, 0.2);
273
  }}
274
 
275
  .attachment-item:last-child {{
 
277
  }}
278
 
279
  .attachment-icon {{
280
+ width: 28px;
281
+ height: 28px;
282
+ background-color: #8B0000;
283
+ border-radius: 6px;
284
+ margin-right: 15px;
285
  display: flex;
286
  align-items: center;
287
  justify-content: center;
288
  color: white;
289
  font-size: 12px;
290
  font-weight: bold;
291
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
292
  }}
293
 
294
  .attachment-name {{
295
  font-weight: 500;
296
+ color: white;
297
+ font-size: 14px;
298
  }}
299
 
300
  .footer {{
301
+ background: linear-gradient(135deg, #2c2c2c 0%, #8B0000 100%);
302
+ color: white;
303
+ padding: 35px 30px;
304
  text-align: center;
305
  }}
306
 
 
311
 
312
  .footer h4 {{
313
  margin-bottom: 15px;
314
+ font-size: 18px;
315
+ font-weight: 700;
316
  }}
317
 
318
  .footer p {{
319
  font-size: 14px;
320
+ opacity: 0.9;
321
+ line-height: 1.6;
322
  }}
323
 
324
  .footer .timestamp {{
325
+ margin-top: 25px;
326
  padding-top: 20px;
327
+ border-top: 1px solid rgba(255, 255, 255, 0.3);
328
  font-size: 12px;
329
+ opacity: 0.8;
330
  }}
331
 
332
  @media only screen and (max-width: 600px) {{
333
  .email-container {{
334
+ margin: 10px;
335
+ border-radius: 8px;
336
  }}
337
 
338
  .header {{
 
340
  }}
341
 
342
  .content {{
343
+ padding: 25px 20px;
344
  }}
345
 
346
  .info-grid {{
347
  grid-template-columns: 1fr;
348
+ gap: 15px;
349
  }}
350
 
351
  .stats-grid {{
352
+ grid-template-columns: repeat(2, 1fr);
353
  }}
354
 
355
  .header h1 {{
356
+ font-size: 26px;
357
+ }}
358
+
359
+ .stat-number {{
360
+ font-size: 28px;
361
  }}
362
  }}
363
  </style>
 
365
  <body>
366
  <div class="email-container">
367
  <div class="header">
368
+ <div class="header-content">
369
+ <h1>Hillside Medical Group</h1>
370
+ <p>Patient Processing Report</p>
371
+ </div>
372
  </div>
373
 
374
  <div class="status-banner">
 
377
 
378
  <div class="content">
379
  <div class="report-info">
380
+ <h3>Report Summary</h3>
381
  <div class="info-grid">
382
  <div class="info-item">
383
+ <span class="info-label">Report Name</span>
384
  <span class="info-value">{custom_name}</span>
385
  </div>
386
  <div class="info-item">
387
+ <span class="info-label">Generated</span>
388
  <span class="info-value">{current_date}</span>
389
  </div>
390
  <div class="info-item">
391
+ <span class="info-label">Status</span>
392
  <span class="info-value" style="color: {status_color};">{status_text.title()}</span>
393
  </div>
394
  <div class="info-item">
395
+ <span class="info-label">Processing Type</span>
396
+ <span class="info-value">Automated</span>
397
  </div>
398
  </div>
399
  </div>
400
 
401
  <div class="stats-section">
402
+ <h3>Processing Results</h3>
403
  <div class="stats-grid">
404
  <div class="stat-card">
405
  <div class="stat-number">{stats['total']}</div>
 
411
  </div>
412
  <div class="stat-card success">
413
  <div class="stat-number">{stats['successful']}</div>
414
+ <div class="stat-label">Completed</div>
415
  </div>
416
  <div class="stat-card danger">
417
  <div class="stat-number">{stats['failed']}</div>
418
+ <div class="stat-label">Requires Review</div>
419
  </div>
420
  </div>
421
  </div>
 
424
  <h3>Report Files</h3>
425
  <div class="attachment-item">
426
  <div class="attachment-icon">CSV</div>
427
+ <div class="attachment-name">{custom_name}_Full.csv - Complete patient processing report</div>
428
  </div>
429
  <div class="attachment-item">
430
  <div class="attachment-icon">CSV</div>
431
+ <div class="attachment-name">{custom_name}_Bad.csv - Records requiring manual review</div>
432
  </div>
433
  </div>
 
 
 
 
 
 
 
 
 
434
  </div>
435
 
436
  <div class="footer">
437
  <div class="footer-content">
438
  <h4>Hillside Medical Group</h4>
439
  <p>
440
+ Automated patient processing system ensuring accurate and efficient
441
+ record management while maintaining compliance with healthcare data standards.
 
442
  </p>
443
  <div class="timestamp">
444
+ Report generated {current_date}
 
 
445
  </div>
446
  </div>
447
  </div>
 
464
  try:
465
  from googleapiclient.errors import HttpError
466
 
467
+ print(f"[Gmail API] Sending report to: {recipients}")
468
 
469
  message = MIMEMultipart()
470
  message['From'] = self.sender_email
 
489
  body=gmail_message
490
  ).execute()
491
 
492
+ print(f"[Gmail API] Email sent successfully! Message ID: {sent_message['id']}")
493
  return True
494
 
495
  except HttpError as error:
 
514
  creds_dict = json.loads(creds_json)
515
  self.creds = service_account.Credentials.from_service_account_info(creds_dict, scopes=['https://www.googleapis.com/auth/drive'])
516
  self.service = build('drive', 'v3', credentials=self.creds)
517
+ print("[G-Drive] Service initialized successfully.")
518
  except Exception as e:
519
+ print(f"[G-Drive] ERROR: Could not initialize Google Drive service: {e}")
520
 
521
  def upload_file(self, filename, file_content):
522
  if not self.service:
 
604
  'failed': len([r for r in results if r['Status'] == 'Bad'])
605
  }
606
 
607
+ subject = f"Patient Processing Report - {status_text.title()}: {custom_name}"
608
 
609
  professional_body = email_service.create_professional_email_template(
610
  subject, status_text, stats, custom_name
 
613
  email_success = email_service.send_report(data.get('emails'), subject, professional_body, attachments)
614
 
615
  if email_success:
616
+ socketio.emit('process_complete', {'message': f'Process {status_text}. Report sent successfully.'})
617
  else:
618
  socketio.emit('process_complete', {'message': f'Process {status_text}. Email sending failed.'})
619
 
620
  @app.route('/')
621
  def status_page():
622
+ APP_STATUS_HTML = """<!DOCTYPE html><html lang="en"><head><title>Hillside Automation</title><style>body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;display:flex;justify-content:center;align-items:center;height:100vh;margin:0;background:linear-gradient(135deg, #8B0000 0%, #DC143C 50%, #8A2BE2 100%);color:white;}.status-box{text-align:center;padding:40px 60px;background:rgba(255,255,255,0.15);border-radius:12px;box-shadow:0 8px 30px rgba(0,0,0,0.3);backdrop-filter:blur(10px);}h1{font-size:28px;margin-bottom:10px;} .indicator{font-size:18px;font-weight:600;padding:12px 20px;border-radius:25px;background:rgba(255,255,255,0.2);border:2px solid white;color:white;margin:15px 0;}.info{margin-top:20px;opacity:0.9;}</style></head><body><div class="status-box"><h1>Hillside Automation</h1><div class="indicator">Patient Processing System</div><div class="info">Chrome: Ready<br>Email: Gmail API<br>Drive: Integrated<br><br><a href="https://quantbot.netlify.app" style="color:#fff;">quantbot.netlify.app</a></div></div></body></html>"""
623
  return Response(APP_STATUS_HTML)
624
 
625
  @socketio.on('connect')
 
672
 
673
  if __name__ == '__main__':
674
  print("====================================================================")
675
+ print(" Hillside Medical Group - Patient Processing System")
676
+ print(" Email: Professional Reports via Gmail API")
 
677
  print(f" Frontend: {FRONTEND_ORIGIN}")
678
  print("====================================================================")
679
  socketio.run(app, host='0.0.0.0', port=int(os.getenv('PORT', 7860)))