Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -11,21 +11,10 @@ import io
|
|
| 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,8 +75,7 @@ picklist_mapping = {
|
|
| 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,7 +164,7 @@ def save_to_salesforce(df, reminders_df):
|
|
| 176 |
amc_date_str = None
|
| 177 |
if pd.notna(row['amc_date']):
|
| 178 |
try:
|
| 179 |
-
amc_date = pd.to_datetime(row['amc_date']
|
| 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,22 +200,6 @@ def save_to_salesforce(df, reminders_df):
|
|
| 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,9 +223,7 @@ def detect_anomalies(df):
|
|
| 251 |
anomalies = df[df["anomaly"] == -1][["device_id", "usage_hours", "downtime", "timestamp"]]
|
| 252 |
if anomalies.empty:
|
| 253 |
return "No anomalies detected.", anomalies
|
| 254 |
-
|
| 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,19 +233,13 @@ def check_amc_reminders(df, current_date):
|
|
| 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 |
-
|
| 267 |
-
|
| 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 |
-
|
| 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 |
-
|
| 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,11 +518,10 @@ async def process_logs(file_obj, lab_site_filter, equipment_type_filter, date_ra
|
|
| 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 |
-
|
| 558 |
-
df["
|
| 559 |
-
|
| 560 |
-
|
| 561 |
-
df["amc_date"] = pd.to_datetime(df["amc_date"], format='%m/%d/%Y', errors='coerce').dt.tz_localize('UTC').dt.tz_convert('Asia/Kolkata')
|
| 562 |
if df.empty:
|
| 563 |
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
|
| 564 |
else:
|
|
@@ -602,7 +565,7 @@ async def process_logs(file_obj, lab_site_filter, equipment_type_filter, date_ra
|
|
| 602 |
# Run critical tasks concurrently
|
| 603 |
with ThreadPoolExecutor(max_workers=2) as executor:
|
| 604 |
future_anomalies = executor.submit(detect_anomalies, filtered_df)
|
| 605 |
-
future_amc = executor.submit(check_amc_reminders,
|
| 606 |
|
| 607 |
summary = f"Step 1: Summary Report\n{summarize_logs(filtered_df)}"
|
| 608 |
anomalies, anomalies_df = future_anomalies.result()
|
|
|
|
| 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 |
'maintenance': 'Smart Log',
|
| 76 |
'cell': 'Cell Analysis',
|
| 77 |
'uv': 'UV Verification',
|
| 78 |
+
'weight log': 'Smart Log'
|
|
|
|
| 79 |
}
|
| 80 |
}
|
| 81 |
|
|
|
|
| 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 |
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 |
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 |
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 |
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 |
# 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()
|