VaneshDev commited on
Commit
d4a3eb9
·
verified ·
1 Parent(s): acf2327

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +147 -77
app.py CHANGED
@@ -46,7 +46,11 @@ def connect_to_salesforce():
46
  logger.error(f"Salesforce connection failed: {e}")
47
  raise
48
 
49
- sf = connect_to_salesforce()
 
 
 
 
50
 
51
  # Choices
52
  equipment_choices = [
@@ -77,66 +81,104 @@ def call_ai_model(usage, idle, freq, cost, last):
77
 
78
  # Core processing
79
  def process_equipment_utilization(equip, proj, use_h, idle_h, move_f, cost_h, last_maint, ai_sug):
80
- if not ai_sug:
81
- ai_sug, conf, score = call_ai_model(use_h, idle_h, move_f, cost_h, last_maint)
82
- else:
83
- conf, score = 0.9, 85.0
84
- summary = {
85
- "Equipment Name": equip,
86
- "Project": proj,
87
- "Usage Hours": use_h,
88
- "Idle Hours": idle_h,
89
- "Suggestion": ai_sug,
90
- "Confidence": conf,
91
- "Utilization Score": score,
92
- "Cost per Hour": cost_h,
93
- "Last Maintenance": last_maint or "N/A"
94
- }
95
- record_data = {
96
- "Equipment_Name__c": equip,
97
- "Project_Name__c": proj,
98
- "Usage_Hours__c": use_h,
99
- "Idle_Hours__c": idle_h,
100
- "AI_Suggestion__c": ai_sug,
101
- "Suggestion_Confidence__c": conf * 100,
102
- "Utilization_Score__c": score,
103
- "Cost_per_Hour__c": cost_h,
104
- "Report_Link__c": "Pending",
105
- "Last_Maintenance__c": last_maint if last_maint != "N/A" else None,
106
- "Dashboard_Flag__c": False
107
- }
108
- resp = sf.Equipment_Utilization_Record__c.create(record_data)
109
- rec_id = resp.get("id")
110
- # Prepare paths
111
- uid = uuid.uuid4().hex[:8]
112
- pdf_path = Path(f"static/reports/report_{uid}.pdf")
113
- csv_path = Path(f"static/reports/report_{uid}.csv")
114
- pdf_path.parent.mkdir(parents=True, exist_ok=True)
115
- # Generate PDF
116
- c = canvas.Canvas(str(pdf_path), pagesize=letter)
117
- c.setFont("Helvetica", 12)
118
- c.drawString(100, 750, "Equipment Utilization Report")
119
- c.drawString(100, 735, f"Record ID: {rec_id}")
120
- y = 710
121
- for k, v in summary.items(): c.drawString(100, y, f"{k}: {v}"); y -= 20
122
- c.save()
123
- # Generate CSV
124
- with open(csv_path, "w", newline="") as f:
125
- w = csv.writer(f)
126
- w.writerow(["Field", "Value"])
127
- w.writerow(["Record ID", rec_id])
128
- [w.writerow([k, v]) for k, v in summary.items()]
129
- # Upload PDF
130
- encoded = base64.b64encode(pdf_path.read_bytes()).decode()
131
- cv = sf.ContentVersion.create({
132
- "Title": "UtilReport",
133
- "PathOnClient": os.path.basename(str(pdf_path)),
134
- "VersionData": encoded,
135
- "FirstPublishLocationId": Report_File_Path
136
- })
137
- pdf_url = f"https://{sf.sf_instance}/sfc/servlet.shepherd/version/download/{cv['id']}"
138
- sf.Equipment_Utilization_Record__c.update(rec_id, {"Report_Link__c": pdf_url})
139
- return {"Salesforce_Record_Id": rec_id, "Summary": summary, "Report_Link": pdf_url, "CSV_Report_Link": str(csv_path), "Report_File_Path": str(pdf_path)}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
 
141
  # Format output
142
  def format_output(result):
@@ -172,24 +214,52 @@ def format_output(result):
172
 
173
  # Gradio callbacks
174
  def manual_input(equipment, project, usage, idle, freq, cost, last, ai_suggestion):
175
- last_val = last or "N/A"
176
- res = process_equipment_utilization(equipment, project, usage, idle, freq, cost, last_val, ai_suggestion)
177
- formatted = format_output(res)
178
- return formatted, res.get("Report_File_Path")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
 
180
  def batch_upload(csv_file):
181
- if not csv_file: return {}
182
- df = pd.read_csv(csv_file.name)
183
- ids = []
184
- for _, row in df.iterrows():
185
- rec = process_equipment_utilization(
186
- row['equipment_name'], row['project_name'],
187
- float(row['usage_hours']), float(row['idle_hours']),
188
- float(row['movement_frequency']), float(row['cost_per_hour']),
189
- row.get('last_maintenance','N/A'), row.get('ai_suggestion','')
190
- )
191
- ids.append(rec['Salesforce_Record_Id'])
192
- return {"records": ids}
 
 
 
 
 
 
 
 
 
 
193
 
194
  # Interface
195
  with gr.Blocks() as app:
 
46
  logger.error(f"Salesforce connection failed: {e}")
47
  raise
48
 
49
+ try:
50
+ sf = connect_to_salesforce()
51
+ except Exception as e:
52
+ logger.error(f"Failed to initialize Salesforce connection: {e}")
53
+ sf = None
54
 
55
  # Choices
56
  equipment_choices = [
 
81
 
82
  # Core processing
83
  def process_equipment_utilization(equip, proj, use_h, idle_h, move_f, cost_h, last_maint, ai_sug):
84
+ try:
85
+ if not sf:
86
+ raise ValueError("Salesforce connection is not initialized. Please check credentials and try again.")
87
+
88
+ if not ai_sug:
89
+ ai_sug, conf, score = call_ai_model(use_h, idle_h, move_f, cost_h, last_maint)
90
+ else:
91
+ conf, score = 0.9, 85.0
92
+ summary = {
93
+ "Equipment Name": equip,
94
+ "Project": proj,
95
+ "Usage Hours": use_h,
96
+ "Idle Hours": idle_h,
97
+ "Suggestion": ai_sug,
98
+ "Confidence": conf,
99
+ "Utilization Score": score,
100
+ "Cost per Hour": cost_h,
101
+ "Last Maintenance": last_maint or "N/A"
102
+ }
103
+ record_data = {
104
+ "Equipment_Name__c": equip,
105
+ "Project_Name__c": proj,
106
+ "Usage_Hours__c": use_h,
107
+ "Idle_Hours__c": idle_h,
108
+ "AI_Suggestion__c": ai_sug,
109
+ "Suggestion_Confidence__c": conf * 100,
110
+ "Utilization_Score__c": score,
111
+ "Cost_per_Hour__c": cost_h,
112
+ "Report_Link__c": "Pending",
113
+ "Last_Maintenance__c": last_maint if last_maint != "N/A" else None,
114
+ "Dashboard_Flag__c": False
115
+ }
116
+ resp = sf.Equipment_Utilization_Record__c.create(record_data)
117
+ if not resp.get("success"):
118
+ raise ValueError(f"Failed to create Salesforce record: {resp}")
119
+ rec_id = resp.get("id")
120
+ if not rec_id:
121
+ raise ValueError("Salesforce record creation succeeded, but no record ID was returned.")
122
+
123
+ # Prepare paths
124
+ uid = uuid.uuid4().hex[:8]
125
+ pdf_path = Path(f"static/reports/report_{uid}.pdf")
126
+ csv_path = Path(f"static/reports/report_{uid}.csv")
127
+ try:
128
+ pdf_path.parent.mkdir(parents=True, exist_ok=True)
129
+ except Exception as e:
130
+ raise ValueError(f"Failed to create directory {pdf_path.parent}: {e}")
131
+
132
+ # Generate PDF
133
+ try:
134
+ c = canvas.Canvas(str(pdf_path), pagesize=letter)
135
+ c.setFont("Helvetica", 12)
136
+ c.drawString(100, 750, "Equipment Utilization Report")
137
+ c.drawString(100, 735, f"Record ID: {rec_id}")
138
+ y = 710
139
+ for k, v in summary.items():
140
+ c.drawString(100, y, f"{k}: {v}")
141
+ y -= 20
142
+ c.save()
143
+ except Exception as e:
144
+ raise ValueError(f"Failed to generate PDF: {e}")
145
+
146
+ # Generate CSV
147
+ try:
148
+ with open(csv_path, "w", newline="") as f:
149
+ w = csv.writer(f)
150
+ w.writerow(["Field", "Value"])
151
+ w.writerow(["Record ID", rec_id])
152
+ [w.writerow([k, v]) for k, v in summary.items()]
153
+ except Exception as e:
154
+ raise ValueError(f"Failed to generate CSV: {e}")
155
+
156
+ # Upload PDF to Salesforce
157
+ try:
158
+ encoded = base64.b64encode(pdf_path.read_bytes()).decode()
159
+ cv = sf.ContentVersion.create({
160
+ "Title": "UtilReport",
161
+ "PathOnClient": os.path.basename(str(pdf_path)),
162
+ "VersionData": encoded,
163
+ "FirstPublishLocationId": rec_id
164
+ })
165
+ if not cv.get("success"):
166
+ raise ValueError(f"Failed to upload PDF to Salesforce: {cv}")
167
+ pdf_url = f"https://{sf.sf_instance}/sfc/servlet.shepherd/version/download/{cv['id']}"
168
+ sf.Equipment_Utilization_Record__c.update(rec_id, {"Report_Link__c": pdf_url})
169
+ except Exception as e:
170
+ raise ValueError(f"Failed to upload PDF to Salesforce: {e}")
171
+
172
+ return {
173
+ "Salesforce_Record_Id": rec_id,
174
+ "Summary": summary,
175
+ "Report_Link": pdf_url,
176
+ "CSV_Report_Link": str(csv_path),
177
+ "Report_File_Path": str(pdf_path)
178
+ }
179
+ except Exception as e:
180
+ logger.error(f"Error in process_equipment_utilization: {e}")
181
+ raise ValueError(f"Processing failed: {str(e)}")
182
 
183
  # Format output
184
  def format_output(result):
 
214
 
215
  # Gradio callbacks
216
  def manual_input(equipment, project, usage, idle, freq, cost, last, ai_suggestion):
217
+ try:
218
+ # Validate inputs
219
+ if not equipment or equipment not in equipment_choices:
220
+ raise ValueError("Please select a valid Equipment Name.")
221
+ if not project or project not in project_choices:
222
+ raise ValueError("Please select a valid Project Name.")
223
+ if usage is None or usage < 0:
224
+ raise ValueError("Usage Hours must be a non-negative number.")
225
+ if idle is None or idle < 0:
226
+ raise ValueError("Idle Hours must be a non-negative number.")
227
+ if freq is None or freq < 0:
228
+ raise ValueError("Movement Frequency must be a non-negative number.")
229
+ if cost is None or cost < 0:
230
+ raise ValueError("Cost per Hour must be a non-negative number.")
231
+
232
+ last_val = last or "N/A"
233
+ res = process_equipment_utilization(equipment, project, usage, idle, freq, cost, last_val, ai_suggestion)
234
+ formatted = format_output(res)
235
+ return formatted, res.get("Report_File_Path")
236
+ except Exception as e:
237
+ logger.error(f"Error in manual_input: {e}")
238
+ return f"Error: {str(e)}", None
239
 
240
  def batch_upload(csv_file):
241
+ try:
242
+ if not csv_file:
243
+ raise ValueError("Please upload a CSV file.")
244
+ df = pd.read_csv(csv_file.name)
245
+ required_columns = ['equipment_name', 'project_name', 'usage_hours', 'idle_hours', 'movement_frequency', 'cost_per_hour']
246
+ missing_columns = [col for col in required_columns if col not in df.columns]
247
+ if missing_columns:
248
+ raise ValueError(f"CSV file is missing required columns: {', '.join(missing_columns)}")
249
+
250
+ ids = []
251
+ for _, row in df.iterrows():
252
+ rec = process_equipment_utilization(
253
+ row['equipment_name'], row['project_name'],
254
+ float(row['usage_hours']), float(row['idle_hours']),
255
+ float(row['movement_frequency']), float(row['cost_per_hour']),
256
+ row.get('last_maintenance', 'N/A'), row.get('ai_suggestion', '')
257
+ )
258
+ ids.append(rec['Salesforce_Record_Id'])
259
+ return {"records": ids}
260
+ except Exception as e:
261
+ logger.error(f"Error in batch_upload: {e}")
262
+ return {"error": str(e)}
263
 
264
  # Interface
265
  with gr.Blocks() as app: