RathodHarish commited on
Commit
140273b
·
verified ·
1 Parent(s): db570c6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -12
app.py CHANGED
@@ -11,10 +11,21 @@ import io
11
  import time
12
  import asyncio
13
  from simple_salesforce import Salesforce
 
 
14
 
15
  # Configure logging
16
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
17
 
 
 
 
 
 
 
 
 
 
18
  # Salesforce configuration
19
  try:
20
  sf = Salesforce(
@@ -75,7 +86,8 @@ picklist_mapping = {
75
  'maintenance': 'Smart Log',
76
  'cell': 'Cell Analysis',
77
  'uv': 'UV Verification',
78
- 'weight log': 'Smart Log'
 
79
  }
80
  }
81
 
@@ -164,7 +176,7 @@ def save_to_salesforce(df, reminders_df):
164
  amc_date_str = None
165
  if pd.notna(row['amc_date']):
166
  try:
167
- amc_date = pd.to_datetime(row['amc_date']).strftime('%Y-%m-%d')
168
  amc_date_str = amc_date
169
  amc_date_dt = datetime.strptime(amc_date, '%Y-%m-%d')
170
  if status_mapped == "Active" and current_date.date() <= amc_date_dt.date() <= next_30_days.date():
@@ -200,6 +212,22 @@ def save_to_salesforce(df, reminders_df):
200
  except Exception as e:
201
  logging.error(f"Failed to save to Salesforce: {str(e)}")
202
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
  # Summarize logs
204
  def summarize_logs(df):
205
  try:
@@ -223,7 +251,9 @@ def detect_anomalies(df):
223
  anomalies = df[df["anomaly"] == -1][["device_id", "usage_hours", "downtime", "timestamp"]]
224
  if anomalies.empty:
225
  return "No anomalies detected.", anomalies
226
- return "\n".join([f"- Device ID: {row['device_id']}, Usage: {row['usage_hours']}, Downtime: {row['downtime']}, Timestamp: {row['timestamp']}" for _, row in anomalies.head(5).iterrows()]), anomalies
 
 
227
  except Exception as e:
228
  logging.error(f"Anomaly detection failed: {str(e)}")
229
  return f"Anomaly detection failed: {str(e)}", pd.DataFrame()
@@ -233,13 +263,19 @@ def check_amc_reminders(df, current_date):
233
  try:
234
  if "device_id" not in df.columns or "amc_date" not in df.columns:
235
  return "AMC reminders require 'device_id' and 'amc_date' columns.", pd.DataFrame()
236
- df["amc_date"] = pd.to_datetime(df["amc_date"], errors='coerce')
237
- current_date = pd.to_datetime(current_date)
 
 
 
238
  df["days_to_amc"] = (df["amc_date"] - current_date).dt.days
239
- reminders = df[(df["days_to_amc"] >= 0) & (df["days_to_amc"] <= 30)][["device_id", "log_type", "status", "timestamp", "usage_hours", "downtime", "amc_date"]]
 
240
  if reminders.empty:
241
  return "No AMC reminders due within the next 30 days.", reminders
242
- return "\n".join([f"- Device ID: {row['device_id']}, AMC Date: {row['amc_date']}" for _, row in reminders.head(5).iterrows()]), reminders
 
 
243
  except Exception as e:
244
  logging.error(f"AMC reminder generation failed: {str(e)}")
245
  return f"AMC reminder generation failed: {str(e)}", pd.DataFrame()
@@ -518,10 +554,8 @@ async def process_logs(file_obj, lab_site_filter, equipment_type_filter, date_ra
518
  if missing_columns:
519
  return f"Missing columns: {missing_columns}", "<p>Missing required columns.</p>", None, '<p>No device cards available.</p>', None, None, None, None, "", "", "", None, cached_df_state, last_modified_state
520
 
521
- df["timestamp"] = pd.to_datetime(df["timestamp"], errors='coerce')
522
- df["amc_date"] = pd.to_datetime(df["amc_date"], errors='coerce')
523
- if df["timestamp"].dt.tz is None:
524
- df["timestamp"] = df["timestamp"].dt.tz_localize('UTC').dt.tz_convert('Asia/Kolkata')
525
  if df.empty:
526
  return "No data available.", "<p>No data available.</p>", None, '<p>No device cards available.</p>', None, None, None, None, "", "", "", None, df, current_modified_time
527
  else:
@@ -565,7 +599,7 @@ async def process_logs(file_obj, lab_site_filter, equipment_type_filter, date_ra
565
  # Run critical tasks concurrently
566
  with ThreadPoolExecutor(max_workers=2) as executor:
567
  future_anomalies = executor.submit(detect_anomalies, filtered_df)
568
- future_amc = executor.submit(check_amc_reminders, filtered_df, datetime.now())
569
 
570
  summary = f"Step 1: Summary Report\n{summarize_logs(filtered_df)}"
571
  anomalies, anomalies_df = future_anomalies.result()
 
11
  import time
12
  import asyncio
13
  from simple_salesforce import Salesforce
14
+ import smtplib
15
+ from email.mime.text import MIMEText
16
 
17
  # Configure logging
18
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
19
 
20
+ # Email configuration
21
+ EMAIL_CONFIG = {
22
+ 'sender_email': 'your-email@gmail.com', # Replace with your Gmail address
23
+ 'app_password': 'your-app-password', # Replace with your Gmail App Password
24
+ 'recipient_email': 'recipient@example.com', # Replace with recipient email
25
+ 'smtp_server': 'smtp.gmail.com',
26
+ 'smtp_port': 587
27
+ }
28
+
29
  # Salesforce configuration
30
  try:
31
  sf = Salesforce(
 
86
  'maintenance': 'Smart Log',
87
  'cell': 'Cell Analysis',
88
  'uv': 'UV Verification',
89
+ 'weight log': 'Smart Log',
90
+ 'wegit log': 'Smart Log' # Added mapping for 'Wegit Log'
91
  }
92
  }
93
 
 
176
  amc_date_str = None
177
  if pd.notna(row['amc_date']):
178
  try:
179
+ amc_date = pd.to_datetime(row['amc_date'], format='%m/%d/%Y').strftime('%Y-%m-%d')
180
  amc_date_str = amc_date
181
  amc_date_dt = datetime.strptime(amc_date, '%Y-%m-%d')
182
  if status_mapped == "Active" and current_date.date() <= amc_date_dt.date() <= next_30_days.date():
 
212
  except Exception as e:
213
  logging.error(f"Failed to save to Salesforce: {str(e)}")
214
 
215
+ # Send email alert
216
+ def send_email_alert(subject, body):
217
+ try:
218
+ msg = MIMEText(body)
219
+ msg['Subject'] = subject
220
+ msg['From'] = EMAIL_CONFIG['sender_email']
221
+ msg['To'] = EMAIL_CONFIG['recipient_email']
222
+
223
+ with smtplib.SMTP(EMAIL_CONFIG['smtp_server'], EMAIL_CONFIG['smtp_port']) as server:
224
+ server.starttls()
225
+ server.login(EMAIL_CONFIG['sender_email'], EMAIL_CONFIG['app_password'])
226
+ server.send_message(msg)
227
+ logging.info(f"Email alert sent successfully to {EMAIL_CONFIG['recipient_email']}")
228
+ except Exception as e:
229
+ logging.error(f"Failed to send email alert: {str(e)}")
230
+
231
  # Summarize logs
232
  def summarize_logs(df):
233
  try:
 
251
  anomalies = df[df["anomaly"] == -1][["device_id", "usage_hours", "downtime", "timestamp"]]
252
  if anomalies.empty:
253
  return "No anomalies detected.", anomalies
254
+ anomaly_summary = "\n".join([f"- Device ID: {row['device_id']}, Usage: {row['usage_hours']}, Downtime: {row['downtime']}, Timestamp: {row['timestamp']}" for _, row in anomalies.head(5).iterrows()])
255
+ send_email_alert("Anomaly Detection Alert", f"Anomalies detected:\n{anomaly_summary}")
256
+ return anomaly_summary, anomalies
257
  except Exception as e:
258
  logging.error(f"Anomaly detection failed: {str(e)}")
259
  return f"Anomaly detection failed: {str(e)}", pd.DataFrame()
 
263
  try:
264
  if "device_id" not in df.columns or "amc_date" not in df.columns:
265
  return "AMC reminders require 'device_id' and 'amc_date' columns.", pd.DataFrame()
266
+ # Parse amc_date with explicit format and handle timezone
267
+ df["amc_date"] = pd.to_datetime(df["amc_date"], format='%m/%d/%Y', errors='coerce').dt.tz_localize('UTC').dt.tz_convert('Asia/Kolkata')
268
+ current_date = pd.to_datetime(current_date).tz_localize('Asia/Kolkata')
269
+ logging.info(f"Current date for AMC: {current_date}")
270
+ logging.info(f"AMC dates parsed: {df['amc_date'].dropna().tolist()}")
271
  df["days_to_amc"] = (df["amc_date"] - current_date).dt.days
272
+ logging.info(f"Days to AMC: {df['days_to_amc'].dropna().tolist()}")
273
+ reminders = df[(df["days_to_amc"] >= 0) & (df["days_to_amc"] <= 30) & (df["status"] == "Active")][["device_id", "log_type", "status", "timestamp", "usage_hours", "downtime", "amc_date"]]
274
  if reminders.empty:
275
  return "No AMC reminders due within the next 30 days.", reminders
276
+ reminder_summary = "\n".join([f"- Device ID: {row['device_id']}, AMC Date: {row['amc_date'].date()}" for _, row in reminders.head(5).iterrows()])
277
+ send_email_alert("AMC Reminder Alert", f"AMC reminders due within 30 days:\n{reminder_summary}")
278
+ return reminder_summary, reminders
279
  except Exception as e:
280
  logging.error(f"AMC reminder generation failed: {str(e)}")
281
  return f"AMC reminder generation failed: {str(e)}", pd.DataFrame()
 
554
  if missing_columns:
555
  return f"Missing columns: {missing_columns}", "<p>Missing required columns.</p>", None, '<p>No device cards available.</p>', None, None, None, None, "", "", "", None, cached_df_state, last_modified_state
556
 
557
+ df["timestamp"] = pd.to_datetime(df["timestamp"], utc=True).dt.tz_convert('Asia/Kolkata')
558
+ df["amc_date"] = pd.to_datetime(df["amc_date"], format='%m/%d/%Y', errors='coerce').dt.tz_localize('UTC').dt.tz_convert('Asia/Kolkata')
 
 
559
  if df.empty:
560
  return "No data available.", "<p>No data available.</p>", None, '<p>No device cards available.</p>', None, None, None, None, "", "", "", None, df, current_modified_time
561
  else:
 
599
  # Run critical tasks concurrently
600
  with ThreadPoolExecutor(max_workers=2) as executor:
601
  future_anomalies = executor.submit(detect_anomalies, filtered_df)
602
+ future_amc = executor.submit(check_amc_reminders, df) # Use full df for AMC
603
 
604
  summary = f"Step 1: Summary Report\n{summarize_logs(filtered_df)}"
605
  anomalies, anomalies_df = future_anomalies.result()