VaneshDev commited on
Commit
a1edc7c
Β·
verified Β·
1 Parent(s): 39a4d82

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +181 -116
app.py CHANGED
@@ -2,15 +2,15 @@ import datetime
2
  import logging
3
  import sys
4
  import uuid
5
- import base64
6
  from pathlib import Path
7
  import csv
 
8
  import gradio as gr
9
  from reportlab.lib.pagesizes import letter
10
  from reportlab.pdfgen import canvas
11
  from simple_salesforce import Salesforce
12
 
13
- # Logging setup
14
  logging.basicConfig(
15
  level=logging.INFO,
16
  format='%(asctime)s - %(levelname)s - %(message)s',
@@ -23,28 +23,26 @@ SALESFORCE_USERNAME = "vaneshdevarapalli866@agentforce.com"
23
  SALESFORCE_PASSWORD = "vanesh@331"
24
  SALESFORCE_SECURITY_TOKEN = "VRUVbBOdG0s9Q4xy0W6DB1Y6b"
25
 
26
- # Your exact Salesforce instance URL (from your org URL)
27
- SALESFORCE_INSTANCE_URL = "https://orgfarm-ef617b5a6b-dev-ed.develop.lightning.force.com"
28
-
29
  def connect_to_salesforce():
30
  try:
31
- sf = Salesforce(
32
  username=SALESFORCE_USERNAME,
33
  password=SALESFORCE_PASSWORD,
34
  security_token=SALESFORCE_SECURITY_TOKEN,
35
- domain="login" # initial login domain
36
  )
37
- # Override instance URL explicitly with your org URL
38
- sf.instance_url = SALESFORCE_INSTANCE_URL
39
- sf.base_url = f"{sf.instance_url}/services/data/v{sf.sf_version}"
40
- logger.info(f"Connected to Salesforce instance at {sf.instance_url}")
41
- return sf
42
  except Exception as e:
43
  logger.error(f"Salesforce connection failed: {e}")
44
  raise
45
 
46
  sf = connect_to_salesforce()
47
 
 
48
  equipment_choices = [
49
  "Bulldozer", "Crane", "Excavator", "Loader", "Forklift",
50
  "Backhoe", "Grader", "Scraper", "Dump Truck", "Roller"
@@ -57,6 +55,7 @@ project_choices = [
57
 
58
  ai_suggestion_choices = ["Move", "Pause Rent", "Repair", "Replace"]
59
 
 
60
  def generate_pdf_report(record_id, data_dict):
61
  report_id = str(uuid.uuid4())[:8]
62
  report_filename = f"report_{report_id}.pdf"
@@ -74,9 +73,12 @@ def generate_pdf_report(record_id, data_dict):
74
  y -= 20
75
 
76
  c.save()
77
- logger.info(f"Generated PDF report at {report_path}")
78
- return str(report_path)
79
 
 
 
 
 
 
80
  def generate_csv_report(record_id, data_dict):
81
  report_id = str(uuid.uuid4())[:8]
82
  csv_filename = f"report_{report_id}.csv"
@@ -89,8 +91,10 @@ def generate_csv_report(record_id, data_dict):
89
  writer.writerow(["Salesforce Record ID", record_id])
90
  for k, v in data_dict.items():
91
  writer.writerow([k, v])
92
- logger.info(f"Generated CSV report at {csv_path}")
93
- return str(csv_path)
 
 
94
 
95
  def upload_file_to_salesforce(sf, file_path, file_name, parent_record_id):
96
  with open(file_path, "rb") as f:
@@ -128,79 +132,98 @@ def upload_file_to_salesforce(sf, file_path, file_name, parent_record_id):
128
  logger.info(f"Uploaded file {file_name} to Salesforce with public URL: {public_url}")
129
  return public_url
130
 
131
- def call_ai_model(usage_hours, idle_hours):
132
- total = usage_hours + idle_hours
133
- ratio = usage_hours / total if total > 0 else 0
134
- if ratio < 0.3:
135
- return "Pause Rent", 0.7, ratio * 100
136
- elif ratio < 0.6:
137
- return "Move", 0.8, ratio * 100
138
- elif ratio < 0.8:
139
- return "Repair", 0.9, ratio * 100
140
- else:
141
- return "Replace", 0.95, ratio * 100
 
 
 
 
 
 
 
 
 
 
 
 
 
142
 
143
  def process_equipment_utilization(equipment_name, project_name, usage_hours, idle_hours,
144
  movement_frequency, cost_per_hour, last_maintenance, ai_suggestion):
 
145
  if not ai_suggestion:
146
- ai_suggestion, confidence, utilization_score = call_ai_model(usage_hours, idle_hours)
 
 
 
147
  else:
148
- confidence = 0.9
149
- utilization_score = 85.0
150
 
151
  summary_data = {
152
  "Equipment Name": equipment_name,
153
  "Project": project_name,
154
  "Usage Hours": usage_hours,
155
  "Idle Hours": idle_hours,
156
- "Movement Frequency": movement_frequency,
 
 
157
  "Cost per Hour": cost_per_hour,
158
- "Last Maintenance": last_maintenance if last_maintenance else "N/A",
159
- "AI Suggestion": ai_suggestion,
160
- "Suggestion Confidence": confidence,
161
- "Utilization Score": utilization_score
162
- }
163
-
164
- record_data = {
165
- "Equipment_Name__c": equipment_name,
166
- "Project_Name__c": project_name,
167
- "Usage_Hours__c": usage_hours,
168
- "Idle_Hours__c": idle_hours,
169
- "Movement_Frequency__c": movement_frequency,
170
- "Cost_per_Hour__c": cost_per_hour,
171
- "AI_Suggestion__c": ai_suggestion,
172
- "Suggestion_Confidence__c": confidence * 100,
173
- "Utilization_Score__c": utilization_score,
174
- "Last_Maintenance__c": last_maintenance,
175
- "Report_Link__c": "Pending",
176
- "CSV_Report_Link__c": "Pending"
177
  }
178
 
179
- response = sf.Equipment_Utilization_Record__c.create(record_data)
180
- record_id = response.get("id")
181
- logger.info(f"Created Equipment Record with ID: {record_id}")
182
-
183
- pdf_path = generate_pdf_report(record_id, summary_data)
184
- csv_path = generate_csv_report(record_id, summary_data)
185
-
186
- pdf_file_name = f"EquipmentReport_{record_id}.pdf"
187
- csv_file_name = f"EquipmentReport_{record_id}.csv"
188
-
189
- public_pdf_url = upload_file_to_salesforce(sf, pdf_path, pdf_file_name, record_id)
190
- public_csv_url = upload_file_to_salesforce(sf, csv_path, csv_file_name, record_id)
191
-
192
- sf.Equipment_Utilization_Record__c.update(record_id, {
193
- "Report_Link__c": public_pdf_url,
194
- "CSV_Report_Link__c": public_csv_url
195
- })
196
- logger.info(f"Updated Equipment Record {record_id} with report links")
197
-
198
- return {
199
- "Salesforce_Record_Id": record_id,
200
- "PDF_Report_Link": public_pdf_url,
201
- "CSV_Report_Link": public_csv_url,
202
- "Summary": summary_data
203
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
 
205
  def gradio_upload_process(equipment_name, project_name, usage_hours, idle_hours,
206
  movement_frequency, cost_per_hour, last_maintenance, ai_suggestion):
@@ -210,12 +233,12 @@ def gradio_upload_process(equipment_name, project_name, usage_hours, idle_hours,
210
  movement_frequency = float(movement_frequency)
211
  cost_per_hour = float(cost_per_hour)
212
  except Exception as e:
213
- return {"error": f"Invalid numeric input: {str(e)}"}
214
 
215
  try:
216
- last_maintenance_val = last_maintenance if last_maintenance else None
217
  except Exception as e:
218
- return {"error": f"Invalid date format for Last Maintenance (expected YYYY-MM-DD): {str(e)}"}
219
 
220
  result = process_equipment_utilization(
221
  equipment_name,
@@ -224,48 +247,90 @@ def gradio_upload_process(equipment_name, project_name, usage_hours, idle_hours,
224
  idle_hours,
225
  movement_frequency,
226
  cost_per_hour,
227
- last_maintenance_val,
228
  ai_suggestion
229
  )
230
- return result
231
 
232
  with gr.Blocks() as app:
233
- gr.Markdown("## πŸ“‹ Equipment Utilization Record Creator")
234
- gr.Markdown("Fill in the details below and submit to generate AI suggestions and save data to Salesforce.")
235
-
236
- with gr.Row():
237
- equipment_dropdown = gr.Dropdown(choices=equipment_choices, label="Equipment Name")
238
- project_dropdown = gr.Dropdown(choices=project_choices, label="Project Name")
239
- ai_suggestion_dropdown = gr.Dropdown(choices=[""] + ai_suggestion_choices, label="AI Suggestion (optional)")
240
-
241
- with gr.Row():
242
- usage_hours = gr.Number(label="Usage Hours", value=0, minimum=0)
243
- idle_hours = gr.Number(label="Idle Hours", value=0, minimum=0)
244
-
245
- with gr.Row():
246
- movement_frequency = gr.Number(label="Movement Frequency", value=0, minimum=0)
247
- cost_per_hour = gr.Number(label="Cost per Hour", value=0, minimum=0)
248
-
249
- last_maintenance = gr.Textbox(label="Last Maintenance Date (YYYY-MM-DD)", placeholder="Optional")
250
-
251
- submit_button = gr.Button("Submit")
252
-
253
- output = gr.JSON(label="Salesforce Record Creation Result")
254
-
255
- submit_button.click(
256
- fn=gradio_upload_process,
257
- inputs=[
258
- equipment_dropdown,
259
- project_dropdown,
260
- usage_hours,
261
- idle_hours,
262
- movement_frequency,
263
- cost_per_hour,
264
- last_maintenance,
265
- ai_suggestion_dropdown
266
- ],
267
- outputs=[output]
268
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
 
270
  if __name__ == "__main__":
271
  app.launch()
 
2
  import logging
3
  import sys
4
  import uuid
 
5
  from pathlib import Path
6
  import csv
7
+ import pandas as pd
8
  import gradio as gr
9
  from reportlab.lib.pagesizes import letter
10
  from reportlab.pdfgen import canvas
11
  from simple_salesforce import Salesforce
12
 
13
+ # Configure logging
14
  logging.basicConfig(
15
  level=logging.INFO,
16
  format='%(asctime)s - %(levelname)s - %(message)s',
 
23
  SALESFORCE_PASSWORD = "vanesh@331"
24
  SALESFORCE_SECURITY_TOKEN = "VRUVbBOdG0s9Q4xy0W6DB1Y6b"
25
 
26
+ # Connect to Salesforce
 
 
27
  def connect_to_salesforce():
28
  try:
29
+ sf_instance = Salesforce(
30
  username=SALESFORCE_USERNAME,
31
  password=SALESFORCE_PASSWORD,
32
  security_token=SALESFORCE_SECURITY_TOKEN,
33
+ domain="login"
34
  )
35
+ # Set your Salesforce instance URL here
36
+ sf_instance.instance_url = "https://yourinstance.salesforce.com" # <-- Replace with your actual Salesforce instance URL
37
+ logger.info("Connected to Salesforce successfully.")
38
+ return sf_instance
 
39
  except Exception as e:
40
  logger.error(f"Salesforce connection failed: {e}")
41
  raise
42
 
43
  sf = connect_to_salesforce()
44
 
45
+ # Choices
46
  equipment_choices = [
47
  "Bulldozer", "Crane", "Excavator", "Loader", "Forklift",
48
  "Backhoe", "Grader", "Scraper", "Dump Truck", "Roller"
 
55
 
56
  ai_suggestion_choices = ["Move", "Pause Rent", "Repair", "Replace"]
57
 
58
+ # Generate PDF report
59
  def generate_pdf_report(record_id, data_dict):
60
  report_id = str(uuid.uuid4())[:8]
61
  report_filename = f"report_{report_id}.pdf"
 
73
  y -= 20
74
 
75
  c.save()
 
 
76
 
77
+ # Upload to Salesforce and generate public URL for download
78
+ public_url = upload_file_to_salesforce(sf, str(report_path), report_filename, record_id)
79
+ return public_url
80
+
81
+ # Generate CSV report
82
  def generate_csv_report(record_id, data_dict):
83
  report_id = str(uuid.uuid4())[:8]
84
  csv_filename = f"report_{report_id}.csv"
 
91
  writer.writerow(["Salesforce Record ID", record_id])
92
  for k, v in data_dict.items():
93
  writer.writerow([k, v])
94
+
95
+ # Upload to Salesforce and generate public URL for download
96
+ public_url = upload_file_to_salesforce(sf, str(csv_path), csv_filename, record_id)
97
+ return public_url
98
 
99
  def upload_file_to_salesforce(sf, file_path, file_name, parent_record_id):
100
  with open(file_path, "rb") as f:
 
132
  logger.info(f"Uploaded file {file_name} to Salesforce with public URL: {public_url}")
133
  return public_url
134
 
135
+ def call_ai_model(usage_hours, idle_hours, movement_frequency, cost_per_hour, last_maintenance_str):
136
+ try:
137
+ total_time = usage_hours + idle_hours
138
+ utilization_ratio = usage_hours / total_time if total_time > 0 else 0
139
+
140
+ if utilization_ratio < 0.3:
141
+ suggestion = "Pause Rent"
142
+ elif utilization_ratio < 0.6:
143
+ suggestion = "Move"
144
+ elif utilization_ratio < 0.8:
145
+ suggestion = "Repair"
146
+ else:
147
+ suggestion = "Replace"
148
+
149
+ confidence = min(1.0, utilization_ratio + 0.1)
150
+ utilization_score = utilization_ratio * 100
151
+
152
+ logger.info(f"AI Model Prediction: suggestion={suggestion}, confidence={confidence:.2f}, utilization_score={utilization_score:.2f}")
153
+
154
+ return suggestion, confidence, utilization_score
155
+
156
+ except Exception as e:
157
+ logger.error(f"Error in AI model prediction: {e}")
158
+ return "No Action", 0.0, 0.0
159
 
160
  def process_equipment_utilization(equipment_name, project_name, usage_hours, idle_hours,
161
  movement_frequency, cost_per_hour, last_maintenance, ai_suggestion):
162
+
163
  if not ai_suggestion:
164
+ last_maintenance_str = last_maintenance.strftime('%Y-%m-%d') if last_maintenance else ""
165
+ ai_suggestion, suggestion_confidence, utilization_score = call_ai_model(
166
+ usage_hours, idle_hours, movement_frequency, cost_per_hour, last_maintenance_str
167
+ )
168
  else:
169
+ suggestion_confidence = 0.9
170
+ utilization_score = 0.85
171
 
172
  summary_data = {
173
  "Equipment Name": equipment_name,
174
  "Project": project_name,
175
  "Usage Hours": usage_hours,
176
  "Idle Hours": idle_hours,
177
+ "Suggestion": ai_suggestion,
178
+ "Confidence": suggestion_confidence,
179
+ "Utilization Score": utilization_score,
180
  "Cost per Hour": cost_per_hour,
181
+ "Last Maintenance": last_maintenance.strftime('%Y-%m-%d') if last_maintenance else "N/A"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  }
183
 
184
+ try:
185
+ record_data = {
186
+ "Equipment_Name__c": equipment_name,
187
+ "Project_Name__c": project_name,
188
+ "Usage_Hours__c": usage_hours,
189
+ "Idle_Hours__c": idle_hours,
190
+ "AI_Suggestion__c": ai_suggestion,
191
+ "Suggestion_Confidence__c": suggestion_confidence * 100,
192
+ "Utilization_Score__c": utilization_score * 100,
193
+ "Cost_per_Hour__c": cost_per_hour,
194
+ "Report_Link__c": "Pending",
195
+ "Last_Maintenance__c": last_maintenance.strftime('%Y-%m-%d') if last_maintenance else None,
196
+ "Dashboard_Flag__c": False
197
+ }
198
+ logger.info(f"Creating Salesforce record with data: {record_data}")
199
+
200
+ response = sf.Equipment_Utilization_Record__c.create(record_data)
201
+ record_id = response.get("id")
202
+ logger.info(f"Successfully created Salesforce record with ID: {record_id}")
203
+
204
+ # Generate CSV and PDF and get URLs
205
+ pdf_url = generate_pdf_report(record_id, summary_data)
206
+ csv_url = generate_csv_report(record_id, summary_data)
207
+
208
+ sf.Equipment_Utilization_Record__c.update(record_id, {"Report_Link__c": pdf_url})
209
+ logger.info(f"Updated Salesforce record {record_id} with Report_Link__c: {pdf_url}")
210
+
211
+ # Convert datetime to string here to avoid JSON serialization error
212
+ summary_data["Last Maintenance"] = summary_data["Last Maintenance"] if isinstance(summary_data["Last Maintenance"], str) else summary_data["Last Maintenance"].strftime('%Y-%m-%d')
213
+
214
+ return {
215
+ "Salesforce_Record_Id": record_id,
216
+ "status": "Success",
217
+ "AI_Suggestion": ai_suggestion,
218
+ "Suggestion_Confidence": suggestion_confidence,
219
+ "Utilization_Score": utilization_score,
220
+ "Report_Link": pdf_url,
221
+ "CSV_Report_Link": csv_url,
222
+ "Summary": summary_data
223
+ }
224
+ except Exception as e:
225
+ logger.error(f"Error creating or updating Salesforce record: {e}")
226
+ return {"error": str(e)}
227
 
228
  def gradio_upload_process(equipment_name, project_name, usage_hours, idle_hours,
229
  movement_frequency, cost_per_hour, last_maintenance, ai_suggestion):
 
233
  movement_frequency = float(movement_frequency)
234
  cost_per_hour = float(cost_per_hour)
235
  except Exception as e:
236
+ return {"error": f"Invalid numeric input: {str(e)}"}, None
237
 
238
  try:
239
+ last_maintenance_dt = datetime.datetime.strptime(last_maintenance, "%Y-%m-%d") if last_maintenance else None
240
  except Exception as e:
241
+ return {"error": f"Invalid date format for Last Maintenance (expected YYYY-MM-DD): {str(e)}"}, None
242
 
243
  result = process_equipment_utilization(
244
  equipment_name,
 
247
  idle_hours,
248
  movement_frequency,
249
  cost_per_hour,
250
+ last_maintenance_dt,
251
  ai_suggestion
252
  )
253
+ return result, result.get("report_file_path")
254
 
255
  with gr.Blocks() as app:
256
+ gr.Markdown("## πŸ“‹ Equipment Utilization Record Uploader")
257
+ gr.Markdown("Fill in the details below to generate AI suggestions and save them to Salesforce.")
258
+
259
+ with gr.Group():
260
+ with gr.Row():
261
+ equipment_dropdown = gr.Dropdown(choices=equipment_choices, label="πŸ”§ Equipment Name", interactive=True)
262
+ project_dropdown = gr.Dropdown(choices=project_choices, label="🏍️ Project Name", interactive=True)
263
+ ai_suggestion_dropdown = gr.Dropdown(choices=[""] + ai_suggestion_choices, label="🧐 AI Suggestion (optional)", interactive=True)
264
+
265
+ gr.Markdown("---")
266
+
267
+ with gr.Row():
268
+ usage_hours = gr.Number(label="⏱️ Usage Hours", value=0, minimum=0)
269
+ idle_hours = gr.Number(label="πŸ•’ Idle Hours", value=0, minimum=0)
270
+
271
+ with gr.Row():
272
+ movement_frequency = gr.Number(label="πŸ“ˆ Movement Frequency", value=0, minimum=0)
273
+ cost_per_hour = gr.Number(label="πŸ’° Cost per Hour", value=0, minimum=0)
274
+
275
+ with gr.Row():
276
+ last_maintenance = gr.Textbox(label="πŸ› οΈ Last Maintenance Date (YYYY-MM-DD)", placeholder="Optional")
277
+
278
+ gr.Markdown("---")
279
+
280
+ with gr.Row():
281
+ submit_button = gr.Button("πŸš€ Submit", variant="primary")
282
+ output = gr.JSON(label="πŸ“„ Salesforce Record Creation Result")
283
+ report_file_output = gr.File(label="πŸ“ƒ Download PDF Report")
284
+
285
+ submit_button.click(
286
+ fn=gradio_upload_process,
287
+ inputs=[
288
+ equipment_dropdown, project_dropdown,
289
+ usage_hours, idle_hours,
290
+ movement_frequency, cost_per_hour,
291
+ last_maintenance, ai_suggestion_dropdown
292
+ ],
293
+ outputs=[output, report_file_output]
294
+ )
295
+
296
+ # CSV Upload
297
+ csv_upload = gr.File(label="πŸ“‚ Upload CSV file", file_types=[".csv"])
298
+ csv_output = gr.JSON(label="πŸ“„ Batch Upload Results")
299
+
300
+ csv_upload.change(
301
+ fn=lambda file: process_csv_upload(file.name) if file else {},
302
+ inputs=csv_upload,
303
+ outputs=csv_output
304
+ )
305
+
306
+ app.css = """
307
+ .gradio-container {
308
+ background-color: #000000 !important;
309
+ padding: 20px;
310
+ color: #ffffff !important;
311
+ }
312
+ .gr-button-primary {
313
+ background-color: #1e90ff !important;
314
+ color: white !important;
315
+ }
316
+ .gr-button-primary:hover {
317
+ background-color: #0d6efd !important;
318
+ }
319
+ .gr-markdown {
320
+ font-size: 18px;
321
+ font-weight: 600;
322
+ color: #ffffff !important;
323
+ }
324
+ label {
325
+ font-weight: 500;
326
+ color: #ffffff !important;
327
+ }
328
+ input, textarea, select {
329
+ background-color: #1c1c1c !important;
330
+ color: #ffffff !important;
331
+ border: 1px solid #444 !important;
332
+ }
333
+ """
334
 
335
  if __name__ == "__main__":
336
  app.launch()