lavanya121 commited on
Commit
625cf67
·
verified ·
1 Parent(s): cdfbc0c

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +188 -0
app.py ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify
2
+ import requests
3
+ import pandas as pd
4
+ import numpy as np
5
+ from sklearn.ensemble import IsolationForest
6
+ from datetime import datetime, timedelta
7
+ import smtplib
8
+ from email.mime.text import MIMEText
9
+ from reportlab.lib.pagesizes import letter
10
+ from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
11
+ from reportlab.lib.styles import getSampleStyleSheet
12
+ import io
13
+ import base64
14
+ import os
15
+
16
+ app = Flask(__name__)
17
+
18
+ # Salesforce credentials (use environment variables in production)
19
+ SF_CLIENT_ID = os.getenv('SF_CLIENT_ID', 'YOUR_CLIENT_ID')
20
+ SF_CLIENT_SECRET = os.getenv('SF_CLIENT_SECRET', 'YOUR_CLIENT_SECRET')
21
+ SF_USERNAME = os.getenv('SF_USERNAME', 'YOUR_USERNAME')
22
+ SF_PASSWORD = os.getenv('SF_PASSWORD', 'YOUR_PASSWORD+SECURITY_TOKEN')
23
+ SF_AUTH_URL = 'https://login.salesforce.com/services/oauth2/token'
24
+
25
+ # Email configuration
26
+ EMAIL_ADDRESS = os.getenv('EMAIL_ADDRESS', 'your_email@example.com')
27
+ EMAIL_PASSWORD = os.getenv('EMAIL_PASSWORD', 'your_password')
28
+ SMTP_SERVER = 'smtp.gmail.com'
29
+ SMTP_PORT = 587
30
+
31
+ # Get Salesforce access token
32
+ def get_sf_access_token():
33
+ try:
34
+ response = requests.post(SF_AUTH_URL, data={
35
+ 'grant_type': 'password',
36
+ 'client_id': SF_CLIENT_ID,
37
+ 'client_secret': SF_CLIENT_SECRET,
38
+ 'username': SF_USERNAME,
39
+ 'password': SF_PASSWORD
40
+ })
41
+ response.raise_for_status()
42
+ return response.json()['access_token'], response.json()['instance_url']
43
+ except Exception as e:
44
+ print(f"Error getting Salesforce token: {e}")
45
+ return None, None
46
+
47
+ # Anomaly detection using Isolation Forest
48
+ def detect_anomalies(log_data):
49
+ try:
50
+ df = pd.DataFrame(log_data)
51
+ if df.empty:
52
+ return []
53
+ df['Timestamp__c'] = pd.to_datetime(df['Timestamp__c'])
54
+ df['Timestamp_numeric'] = df['Timestamp__c'].apply(lambda x: x.timestamp())
55
+ features = df[['Usage__c', 'Timestamp_numeric']]
56
+ model = IsolationForest(contamination=0.1, random_state=42)
57
+ model.fit(features)
58
+ df['is_anomaly'] = model.predict(features) == -1
59
+ return df[['Id', 'is_anomaly']].to_dict('records')
60
+ except Exception as e:
61
+ print(f"Error in anomaly detection: {e}")
62
+ return []
63
+
64
+ # Dashboard data endpoint
65
+ @app.route('/api/dashboard', methods=['GET'])
66
+ def get_dashboard_data():
67
+ lab = request.args.get('lab', '')
68
+ equipment_type = request.args.get('equipmentType', '')
69
+ date_range = request.args.get('dateRange', '7')
70
+
71
+ access_token, instance_url = get_sf_access_token()
72
+ if not access_token:
73
+ return jsonify({'error': 'Failed to authenticate with Salesforce'}), 500
74
+
75
+ # Fetch devices
76
+ soql = 'SELECT Id, Name, Status__c, Usage__c, Last_Log_Timestamp__c, Lab__c, Type FROM Equipment__c WHERE '
77
+ if lab:
78
+ soql += f"Lab__c = '{lab}' AND "
79
+ if equipment_type:
80
+ soql += f"Type = '{equipment_type}' AND "
81
+ soql += f"Last_Log_Timestamp__c = LAST_N_DAYS:{date_range} LIMIT 100"
82
+
83
+ try:
84
+ response = requests.get(f'{instance_url}/services/data/v52.0/query?q={soql}', headers={'Authorization': f'Bearer {access_token}'})
85
+ response.raise_for_status()
86
+ devices = response.json()['records']
87
+
88
+ # Fetch logs for anomaly detection
89
+ log_soql = 'SELECT Id, Usage__c, Timestamp__c, Equipment__c FROM SmartLog__c WHERE '
90
+ if lab:
91
+ log_soql += f"Equipment__r.Lab__c = '{lab}' AND "
92
+ if equipment_type:
93
+ log_soql += f"Equipment__r.Type = '{equipment_type}' AND "
94
+ log_soql += f"Timestamp__c = LAST_N_DAYS:{date_range}"
95
+
96
+ log_response = requests.get(f'{instance_url}/services/data/v52.0/query?q={log_soql}', headers={'Authorization': f'Bearer {access_token}'})
97
+ log_response.raise_for_status()
98
+ logs = log_response.json()['records']
99
+
100
+ # Detect anomalies
101
+ anomalies = detect_anomalies(logs)
102
+ anomaly_map = {a['Id']: a['is_anomaly'] for a in anomalies}
103
+ devices_with_anomalies = [
104
+ {**d, 'isAnomaly': any(l['Equipment__c'] == d['Id'] and anomaly_map.get(l['Id'], False) for l in logs)}
105
+ for d in devices
106
+ ]
107
+
108
+ # Fetch chart data (daily log trends)
109
+ chart_soql = f"SELECT CALENDAR_DATE(Timestamp__c) logDate, COUNT(Id) logCount FROM SmartLog__c WHERE Timestamp__c = LAST_N_DAYS:{date_range} GROUP BY CALENDAR_DATE(Timestamp__c)"
110
+ chart_response = requests.get(f'{instance_url}/services/data/v52.0/query?q={chart_soql}', headers={'Authorization': f'Bearer {access_token}'})
111
+ chart_response.raise_for_status()
112
+ chart_data = chart_response.json()['records']
113
+ labels = [str(r['logDate']) for r in chart_data]
114
+ data = [r['logCount'] for r in chart_data]
115
+
116
+ # Calculate weekly uptime %
117
+ uptime_soql = f"SELECT Equipment__c, COUNT(Id) upCount FROM SmartLog__c WHERE Status__c = 'Active' AND Timestamp__c = LAST_N_DAYS:{date_range} GROUP BY Equipment__c"
118
+ uptime_response = requests.get(f'{instance_url}/services/data/v52.0/query?q={uptime_soql}', headers={'Authorization': f'Bearer {access_token}'})
119
+ uptime_response.raise_for_status()
120
+ uptime_data = uptime_response.json()['records']
121
+ total_logs = sum(r['logCount'] for r in chart_data)
122
+ uptime = sum(r['upCount'] for r in uptime_data) / total_logs * 100 if total_logs > 0 else 0
123
+
124
+ return jsonify({
125
+ 'devices': devices_with_anomalies,
126
+ 'chartData': {
127
+ 'dailyTrends': {'labels': labels, 'data': data},
128
+ 'weeklyUptime': round(uptime, 2)
129
+ }
130
+ })
131
+ except Exception as e:
132
+ print(f"Error fetching dashboard data: {e}")
133
+ return jsonify({'error': 'Failed to fetch data'}), 500
134
+
135
+ # PDF generation endpoint
136
+ @app.route('/api/generate-pdf', methods=['POST'])
137
+ def generate_pdf():
138
+ dashboard_data = request.json.get('dashboardData', [])
139
+ try:
140
+ output = io.BytesIO()
141
+ doc = SimpleDocTemplate(output, pagesize=letter)
142
+ styles = getSampleStyleSheet()
143
+ elements = [Paragraph("LabOps Monthly Report", styles['Title']), Spacer(1, 12)]
144
+
145
+ for device in dashboard_data:
146
+ text = f"Device: {device['Name']}<br/>Health: {device['Status__c']}<br/>Usage: {device['Usage__c']}<br/>Last Log: {device['Last_Log_Timestamp__c']}<br/>Anomaly: {'Yes' if device['isAnomaly'] else 'No'}"
147
+ elements.append(Paragraph(text, styles['Normal']))
148
+ elements.append(Spacer(1, 12))
149
+
150
+ doc.build(elements)
151
+ pdf_base64 = base64.b64encode(output.getvalue()).decode('utf-8')
152
+ output.close()
153
+ return jsonify({'pdf': pdf_base64})
154
+ except Exception as e:
155
+ print(f"Error generating PDF: {e}")
156
+ return jsonify({'error': 'Failed to generate PDF'}), 500
157
+
158
+ # AMC expiry checker
159
+ @app.route('/api/check-amc', methods=['POST'])
160
+ def check_amc_expiry():
161
+ access_token, instance_url = get_sf_access_token()
162
+ if not access_token:
163
+ return jsonify({'error': 'Failed to authenticate with Salesforce'}), 500
164
+
165
+ try:
166
+ expiry_date = (datetime.now() + timedelta(days=14)).strftime('%Y-%m-%d')
167
+ soql = f"SELECT Id, Name, AMC_Expiry_Date__c, Lab__c FROM Equipment__c WHERE AMC_Expiry_Date__c <= {expiry_date}"
168
+ response = requests.get(f'{instance_url}/services/data/v52.0/query?q={soql}', headers={'Authorization': f'Bearer {access_token}'})
169
+ response.raise_for_status()
170
+ equipment = response.json()['records']
171
+
172
+ for equip in equipment:
173
+ msg = MIMEText(f"AMC for {equip['Name']} (Lab: {equip['Lab__c']}) expires on {equip['AMC_Expiry_Date__c']}")
174
+ msg['Subject'] = 'AMC Expiry Reminder'
175
+ msg['From'] = EMAIL_ADDRESS
176
+ msg['To'] = 'lab_manager@example.com'
177
+ with smtplib.SMTP(SMTP_SERVER, SMTP_PORT) as server:
178
+ server.starttls()
179
+ server.login(EMAIL_ADDRESS, EMAIL_PASSWORD)
180
+ server.send_message(msg)
181
+
182
+ return jsonify({'status': 'Notifications sent', 'count': len(equipment)})
183
+ except Exception as e:
184
+ print(f"Error checking AMC: {e}")
185
+ return jsonify({'error': 'Failed to check AMC expiries'}), 500
186
+
187
+ if __name__ == '__main__':
188
+ app.run(host='0.0.0.0', port=8080)