VaneshDev commited on
Commit
b02145f
Β·
verified Β·
1 Parent(s): f680f41

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +51 -55
app.py CHANGED
@@ -67,11 +67,11 @@ ai_suggestion_choices = ["Move", "Pause Rent", "Repair", "Replace"]
67
  # AI suggestion logic
68
  def call_ai_model(usage, idle, freq, cost, last):
69
  try:
70
- # Ensure inputs are valid numbers
71
- usage = float(usage) if usage is not None else 0.0
72
- idle = float(idle) if idle is not None else 0.0
73
- freq = float(freq) if freq is not None else 0.0
74
- cost = float(cost) if cost is not None else 0.0
75
 
76
  total = usage + idle
77
  ratio = usage / total if total > 0 else 0
@@ -126,7 +126,7 @@ def process_equipment_utilization(equip, proj, use_h, idle_h, move_f, cost_h, la
126
  record_data = {
127
  "Equipment_Name__c": equip,
128
  "Project_Name__c": proj,
129
- "Usage_Hours__c": float(use_h), # Ensure float
130
  "Idle_Hours__c": float(idle_h),
131
  "AI_Suggestion__c": ai_sug,
132
  "Suggestion_Confidence__c": float(conf * 100),
@@ -137,6 +137,11 @@ def process_equipment_utilization(equip, proj, use_h, idle_h, move_f, cost_h, la
137
  "Dashboard_Flag__c": False
138
  }
139
 
 
 
 
 
 
140
  # Log the record data for debugging
141
  logger.info(f"Sending record data to Salesforce: {record_data}")
142
 
@@ -211,7 +216,6 @@ def process_equipment_utilization(equip, proj, use_h, idle_h, move_f, cost_h, la
211
  # Format output
212
  def format_output(result):
213
  summary = result.get("Summary", {})
214
- # Cost formatting
215
  cost_val = summary.get("Cost per Hour", 0)
216
  try:
217
  cost_str = locale.currency(cost_val, grouping=True)
@@ -231,7 +235,9 @@ def format_output(result):
231
  f" β€’ Project: {summary.get('Project', 'N/A')}",
232
  f" β€’ Usage Hours: {summary.get('Usage Hours', 0):.2f}",
233
  f" β€’ Idle Hours: {summary.get('Idle Hours', 0):.2f}",
234
- f" β€’ Cost per Hour: {cost_str}",
 
 
235
  f" β€’ Last Maintenance: {summary.get('Last Maintenance', 'N/A')}"
236
  ]
237
  return "\n".join(lines)
@@ -239,61 +245,49 @@ def format_output(result):
239
  # Gradio callbacks
240
  def manual_input(equipment, project, usage, idle, freq, cost, last, ai_suggestion):
241
  try:
242
- # Validate inputs
243
  if not equipment or equipment not in equipment_choices:
244
  raise ValueError("Please select a valid Equipment Name.")
245
  if not project or project not in project_choices:
246
  raise ValueError("Please select a valid Project Name.")
247
- if usage is None or usage < 0:
248
  raise ValueError("Usage Hours must be a non-negative number.")
249
- if idle is None or idle < 0:
250
  raise ValueError("Idle Hours must be a non-negative number.")
251
- if freq is None or freq < 0:
252
- raise ValueError("Movement Frequency must be a non-negative number.")
253
- if cost is None or cost < 0:
254
- raise ValueError("Cost per Hour must be a non-negative number.")
255
-
256
- last_val = last or "N/A"
257
- res = process_equipment_utilization(equipment, project, usage, idle, freq, cost, last_val, ai_suggestion)
258
- formatted = format_output(res)
259
- return formatted, res.get("Report_File_Path")
260
- except Exception as e:
261
- logger.error(f"Error in manual_input: {e}")
262
- return f"Error: {str(e)}", None
263
-
264
- def batch_upload(csv_file):
265
- try:
266
- if not csv_file:
267
- raise ValueError("Please upload a CSV file.")
268
- df = pd.read_csv(csv_file.name)
269
- required_columns = ['equipment_name', 'project_name', 'usage_hours', 'idle_hours', 'movement_frequency', 'cost_per_hour']
270
- missing_columns = [col for col in required_columns if col not in df.columns]
271
- if missing_columns:
272
- raise ValueError(f"CSV file is missing required columns: {', '.join(missing_columns)}")
273
-
274
- # Validate numeric columns for NaN or invalid values
275
- numeric_columns = ['usage_hours', 'idle_hours', 'movement_frequency', 'cost_per_hour']
276
- for col in numeric_columns:
277
  if df[col].isna().any():
278
- raise ValueError(f"Column '{col}' contains missing or invalid values (e.g., NaN). Please ensure all values are valid numbers.")
279
- try:
280
- df[col] = df[col].astype(float)
281
- except ValueError as e:
282
- raise ValueError(f"Column '{col}' contains non-numeric values: {str(e)}")
 
283
 
284
- ids = []
285
- for _, row in df.iterrows():
286
- rec = process_equipment_utilization(
287
- row['equipment_name'], row['project_name'],
288
- row['usage_hours'], row['idle_hours'],
289
- row['movement_frequency'], row['cost_per_hour'],
290
- row.get('last_maintenance', 'N/A'), row.get('ai_suggestion', '')
291
  )
292
- ids.append(rec['Salesforce_Record_Id'])
293
- return {"records": ids}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
294
  except Exception as e:
295
  logger.error(f"Error in batch_upload: {e}")
296
- return {"error": str(e)}
297
 
298
  # Interface
299
  with gr.Blocks() as app:
@@ -316,17 +310,19 @@ with gr.Blocks() as app:
316
  clear_btn = gr.Button("🧹 Clear")
317
  result_txt = gr.Markdown(elem_id="result-box")
318
  report_file = gr.File(label="πŸ“ƒ Download PDF Report")
 
319
  submit_btn.click(
320
  fn=manual_input,
321
  inputs=[equipment_dropdown, project_dropdown, usage, idle, freq, cost, last, ai_dropdown],
322
- outputs=[result_txt, report_file]
323
  )
324
- clear_btn.click(lambda: ("", None), None, [result_txt, report_file])
325
  with gr.TabItem("CSV Upload"):
326
  with gr.Group():
327
  csv_file = gr.File(label="πŸ“‚ Upload CSV file", file_types=[".csv"])
328
  csv_output = gr.JSON(label="πŸ“„ Batch Upload Results")
329
- csv_file.change(fn=batch_upload, inputs=csv_file, outputs=csv_output)
 
330
  app.css = """
331
  .gradio-container { background-color: #ffffff !important; }
332
  #app-title { text-align: center !important; }
 
67
  # AI suggestion logic
68
  def call_ai_model(usage, idle, freq, cost, last):
69
  try:
70
+ # Ensure inputs are valid numbers and not NaN
71
+ usage = float(usage) if usage is not None and not np.isnan(usage) else 0.0
72
+ idle = float(idle) if idle is not None and not np.isnan(idle) else 0.0
73
+ freq = float(freq) if freq is not None and not np.isnan(freq) else 0.0
74
+ cost = float(cost) if cost is not None and not np.isnan(cost) else 0.0
75
 
76
  total = usage + idle
77
  ratio = usage / total if total > 0 else 0
 
126
  record_data = {
127
  "Equipment_Name__c": equip,
128
  "Project_Name__c": proj,
129
+ "Usage_Hours__c": float(use_h),
130
  "Idle_Hours__c": float(idle_h),
131
  "AI_Suggestion__c": ai_sug,
132
  "Suggestion_Confidence__c": float(conf * 100),
 
137
  "Dashboard_Flag__c": False
138
  }
139
 
140
+ # Final check for NaN in record_data
141
+ for key, value in record_data.items():
142
+ if isinstance(value, float) and np.isnan(value):
143
+ raise ValueError(f"Field {key} contains NaN, which is not allowed in Salesforce requests.")
144
+
145
  # Log the record data for debugging
146
  logger.info(f"Sending record data to Salesforce: {record_data}")
147
 
 
216
  # Format output
217
  def format_output(result):
218
  summary = result.get("Summary", {})
 
219
  cost_val = summary.get("Cost per Hour", 0)
220
  try:
221
  cost_str = locale.currency(cost_val, grouping=True)
 
235
  f" β€’ Project: {summary.get('Project', 'N/A')}",
236
  f" β€’ Usage Hours: {summary.get('Usage Hours', 0):.2f}",
237
  f" β€’ Idle Hours: {summary.get('Idle Hours', 0):.2f}",
238
+ f" β€’ Cost per
239
+
240
+ Hour: {cost_str}",
241
  f" β€’ Last Maintenance: {summary.get('Last Maintenance', 'N/A')}"
242
  ]
243
  return "\n".join(lines)
 
245
  # Gradio callbacks
246
  def manual_input(equipment, project, usage, idle, freq, cost, last, ai_suggestion):
247
  try:
 
248
  if not equipment or equipment not in equipment_choices:
249
  raise ValueError("Please select a valid Equipment Name.")
250
  if not project or project not in project_choices:
251
  raise ValueError("Please select a valid Project Name.")
252
+ if usage is None or usage < 0 or np.isnan(usage):
253
  raise ValueError("Usage Hours must be a non-negative number.")
254
+ if idle is None or idle < 0 or np.isnan(idle):
255
  raise ValueError("Idle Hours must be a non-negative number.")
256
+ if freq is None or freqNUMERIC_FIELDS = ['usage_hours', 'idle_hours', 'movement_frequency', 'cost_per_hour']
257
+ for col in NUMERIC_FIELDS:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  if df[col].isna().any():
259
+ raise ValueError(f"ColumnACHINERY_FIELDS = ['equipment_name', 'project_name']
260
+ for col in MACHINERY_FIELDS:
261
+ if col not in df.columns:
262
+ raise ValueError(f"Missing required column: {col}")
263
+ if df[col].isna().any():
264
+ raise ValueError(f"Column '{col}' contains missing values. Please ensure all rows have valid equipment and project names.")
265
 
266
+ # Validate ai_suggestion if provided
267
+ if 'ai_suggestion' in df.columns:
268
+ df['ai_suggestion'] = df['ai_suggestion'].apply(
269
+ lambda x: x if x in ai_suggestion_choices or pd.isna(x) or x == '' else None
 
 
 
270
  )
271
+
272
+ ids = []
273
+ csv_files = []
274
+ for idx, row in df.iterrows():
275
+ try:
276
+ rec = process_equipment_utilization(
277
+ row['equipment_name'], row['project_name'],
278
+ row['usage_hours'], row['idle_hours'],
279
+ row['movement_frequency'], row['cost_per_hour'],
280
+ row.get('last_maintenance', 'N/A'), row.get('ai_suggestion', '')
281
+ )
282
+ ids.append(rec['Salesforce_Record_Id'])
283
+ csv_files.append(rec['CSV_Report_Link'])
284
+ except Exception as e:
285
+ logger.error(f"Error processing row {idx + 2}: {e}")
286
+ raise ValueError(f"Error processing row {idx + 2}: {str(e)}")
287
+ return {"records": ids}, csv_files
288
  except Exception as e:
289
  logger.error(f"Error in batch_upload: {e}")
290
+ return {"error": str(e)}, None
291
 
292
  # Interface
293
  with gr.Blocks() as app:
 
310
  clear_btn = gr.Button("🧹 Clear")
311
  result_txt = gr.Markdown(elem_id="result-box")
312
  report_file = gr.File(label="πŸ“ƒ Download PDF Report")
313
+ csv_file = gr.File(label="πŸ“„ Download CSV Report")
314
  submit_btn.click(
315
  fn=manual_input,
316
  inputs=[equipment_dropdown, project_dropdown, usage, idle, freq, cost, last, ai_dropdown],
317
+ outputs=[result_txt, report_file, csv_file]
318
  )
319
+ clear_btn.click(lambda: ("", None, None), None, [result_txt, report_file, csv_file])
320
  with gr.TabItem("CSV Upload"):
321
  with gr.Group():
322
  csv_file = gr.File(label="πŸ“‚ Upload CSV file", file_types=[".csv"])
323
  csv_output = gr.JSON(label="πŸ“„ Batch Upload Results")
324
+ csv_downloads = gr.File(label="πŸ“₯ Download Generated CSV Reports")
325
+ csv_file.change(fn=batch_upload, inputs=csv_file, outputs=[csv_output, csv_downloads])
326
  app.css = """
327
  .gradio-container { background-color: #ffffff !important; }
328
  #app-title { text-align: center !important; }