Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -96,9 +96,26 @@ def process_equipment_utilization(equip, proj, use_h, idle_h, move_f, cost_h, la
|
|
| 96 |
else:
|
| 97 |
conf, score = 0.9, 85.0
|
| 98 |
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
record_data = {
|
| 103 |
"Equipment_Name__c": equip,
|
| 104 |
"Project_Name__c": proj,
|
|
@@ -108,20 +125,56 @@ def process_equipment_utilization(equip, proj, use_h, idle_h, move_f, cost_h, la
|
|
| 108 |
"Suggestion_Confidence__c": float(conf * 100),
|
| 109 |
"Utilization_Score__c": float(score),
|
| 110 |
"Cost_per_Hour__c": float(cost_h),
|
| 111 |
-
"
|
| 112 |
-
"
|
| 113 |
-
"
|
| 114 |
}
|
| 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 |
-
|
| 120 |
rec_id = resp.get("id")
|
| 121 |
if not rec_id:
|
| 122 |
-
raise ValueError("Salesforce record
|
| 123 |
-
|
| 124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
except Exception as e:
|
| 126 |
logger.error(f"Error in process_equipment_utilization: {e}")
|
| 127 |
raise ValueError(f"Processing failed: {str(e)}")
|
|
@@ -217,31 +270,27 @@ def generate_batch_pdf(records, batch_uid):
|
|
| 217 |
c.save()
|
| 218 |
return str(pdf_path)
|
| 219 |
|
| 220 |
-
def
|
| 221 |
try:
|
| 222 |
if not equipment or equipment not in equipment_choices:
|
| 223 |
-
|
| 224 |
if not project or project not in project_choices:
|
| 225 |
-
|
| 226 |
if usage is None or usage < 0 or np.isnan(usage):
|
| 227 |
-
|
| 228 |
if idle is None or idle < 0 or np.isnan(idle):
|
| 229 |
-
|
| 230 |
if freq is None or freq < 0 or np.isnan(freq):
|
| 231 |
-
|
| 232 |
if cost is None or cost < 0 or np.isnan(cost):
|
| 233 |
-
|
| 234 |
|
| 235 |
last_val = last or "N/A"
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
)
|
| 240 |
-
|
| 241 |
-
# Return immediately with record ID and success message, no PDF generated here
|
| 242 |
-
return f"Record saved successfully! Salesforce ID: {rec_id}", None
|
| 243 |
except Exception as e:
|
| 244 |
-
logger.error(f"Error in
|
| 245 |
return f"Error: {str(e)}", None
|
| 246 |
|
| 247 |
def batch_upload(csv_file):
|
|
@@ -326,7 +375,7 @@ with gr.Blocks() as app:
|
|
| 326 |
result_txt = gr.Markdown(elem_id="result-box")
|
| 327 |
report_file = gr.File(label="📃 Download PDF Report")
|
| 328 |
submit_btn.click(
|
| 329 |
-
fn=
|
| 330 |
inputs=[equipment_dropdown, project_dropdown, usage, idle, freq, cost, last, ai_dropdown],
|
| 331 |
outputs=[result_txt, report_file] # Only PDF output here now
|
| 332 |
)
|
|
@@ -357,3 +406,6 @@ with gr.Blocks() as app:
|
|
| 357 |
"""
|
| 358 |
if __name__ == "__main__":
|
| 359 |
app.launch()
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
else:
|
| 97 |
conf, score = 0.9, 85.0
|
| 98 |
|
| 99 |
+
for field, value in [("Usage Hours", use_h), ("Idle Hours", idle_h),
|
| 100 |
+
("Movement Frequency", move_f), ("Cost per Hour", cost_h),
|
| 101 |
+
("Confidence", conf), ("Utilization Score", score)]:
|
| 102 |
+
if value is None or np.isnan(value):
|
| 103 |
+
raise ValueError(f"Invalid value for {field}: {value}. Must be a valid number.")
|
| 104 |
+
|
| 105 |
+
if last_maint is None or pd.isna(last_maint):
|
| 106 |
+
last_maint = "N/A"
|
| 107 |
+
|
| 108 |
+
summary = {
|
| 109 |
+
"Equipment Name": equip,
|
| 110 |
+
"Project": proj,
|
| 111 |
+
"Usage Hours": use_h,
|
| 112 |
+
"Idle Hours": idle_h,
|
| 113 |
+
"Suggestion": ai_sug,
|
| 114 |
+
"Confidence": conf,
|
| 115 |
+
"Utilization Score": score,
|
| 116 |
+
"Cost per Hour": cost_h,
|
| 117 |
+
"Last Maintenance": last_maint or "N/A"
|
| 118 |
+
}
|
| 119 |
record_data = {
|
| 120 |
"Equipment_Name__c": equip,
|
| 121 |
"Project_Name__c": proj,
|
|
|
|
| 125 |
"Suggestion_Confidence__c": float(conf * 100),
|
| 126 |
"Utilization_Score__c": float(score),
|
| 127 |
"Cost_per_Hour__c": float(cost_h),
|
| 128 |
+
"Report_Link__c": "Pending",
|
| 129 |
+
"Last_Maintenance__c": last_maint if last_maint != "N/A" else None,
|
| 130 |
+
"Dashboard_Flag__c": False
|
| 131 |
}
|
| 132 |
|
| 133 |
+
for key, value in record_data.items():
|
| 134 |
+
if isinstance(value, float) and np.isnan(value):
|
| 135 |
+
raise ValueError(f"Field {key} contains NaN, which is not allowed in Salesforce requests.")
|
| 136 |
+
|
| 137 |
+
logger.info(f"Sending record data to Salesforce: {record_data}")
|
| 138 |
+
|
| 139 |
resp = sf.Equipment_Utilization_Record__c.create(record_data)
|
| 140 |
if not resp.get("success"):
|
| 141 |
raise ValueError(f"Failed to create Salesforce record: {resp}")
|
|
|
|
| 142 |
rec_id = resp.get("id")
|
| 143 |
if not rec_id:
|
| 144 |
+
raise ValueError("Salesforce record creation succeeded, but no record ID was returned.")
|
| 145 |
+
|
| 146 |
+
uid = uuid.uuid4().hex[:8]
|
| 147 |
+
pdf_path = Path(f"static/reports/report_{uid}.pdf")
|
| 148 |
+
pdf_path.parent.mkdir(parents=True, exist_ok=True)
|
| 149 |
+
|
| 150 |
+
c = canvas.Canvas(str(pdf_path), pagesize=letter)
|
| 151 |
+
c.setFont("Helvetica", 12)
|
| 152 |
+
c.drawString(100, 750, "Equipment Utilization Report")
|
| 153 |
+
c.drawString(100, 735, f"Record ID: {rec_id}")
|
| 154 |
+
y = 710
|
| 155 |
+
for k, v in summary.items():
|
| 156 |
+
c.drawString(100, y, f"{k}: {v}")
|
| 157 |
+
y -= 20
|
| 158 |
+
c.save()
|
| 159 |
+
|
| 160 |
+
encoded = base64.b64encode(pdf_path.read_bytes()).decode()
|
| 161 |
+
cv = sf.ContentVersion.create({
|
| 162 |
+
"Title": "UtilReport",
|
| 163 |
+
"PathOnClient": os.path.basename(str(pdf_path)),
|
| 164 |
+
"VersionData": encoded,
|
| 165 |
+
"FirstPublishLocationId": rec_id
|
| 166 |
+
})
|
| 167 |
+
if not cv.get("success"):
|
| 168 |
+
raise ValueError(f"Failed to upload PDF to Salesforce: {cv}")
|
| 169 |
+
pdf_url = f"https://{sf.sf_instance}/sfc/servlet.shepherd/version/download/{cv['id']}"
|
| 170 |
+
sf.Equipment_Utilization_Record__c.update(rec_id, {"Report_Link__c": pdf_url})
|
| 171 |
+
|
| 172 |
+
return {
|
| 173 |
+
"Salesforce_Record_Id": rec_id,
|
| 174 |
+
"Summary": summary,
|
| 175 |
+
"Report_Link": pdf_url,
|
| 176 |
+
"Report_File_Path": str(pdf_path)
|
| 177 |
+
}
|
| 178 |
except Exception as e:
|
| 179 |
logger.error(f"Error in process_equipment_utilization: {e}")
|
| 180 |
raise ValueError(f"Processing failed: {str(e)}")
|
|
|
|
| 270 |
c.save()
|
| 271 |
return str(pdf_path)
|
| 272 |
|
| 273 |
+
def manual_input(equipment, project, usage, idle, freq, cost, last, ai_suggestion):
|
| 274 |
try:
|
| 275 |
if not equipment or equipment not in equipment_choices:
|
| 276 |
+
raise ValueError("Please select a valid Equipment Name.")
|
| 277 |
if not project or project not in project_choices:
|
| 278 |
+
raise ValueError("Please select a valid Project Name.")
|
| 279 |
if usage is None or usage < 0 or np.isnan(usage):
|
| 280 |
+
raise ValueError("Usage Hours must be a non-negative number.")
|
| 281 |
if idle is None or idle < 0 or np.isnan(idle):
|
| 282 |
+
raise ValueError("Idle Hours must be a non-negative number.")
|
| 283 |
if freq is None or freq < 0 or np.isnan(freq):
|
| 284 |
+
raise ValueError("Movement Frequency must be a non-negative number.")
|
| 285 |
if cost is None or cost < 0 or np.isnan(cost):
|
| 286 |
+
raise ValueError("Cost per Hour must be a non-negative number.")
|
| 287 |
|
| 288 |
last_val = last or "N/A"
|
| 289 |
+
res = process_equipment_utilization(equipment, project, usage, idle, freq, cost, last_val, ai_suggestion)
|
| 290 |
+
formatted = format_output(res)
|
| 291 |
+
return formatted, res.get("Report_File_Path") # Only PDF output here now
|
|
|
|
|
|
|
|
|
|
|
|
|
| 292 |
except Exception as e:
|
| 293 |
+
logger.error(f"Error in manual_input: {e}")
|
| 294 |
return f"Error: {str(e)}", None
|
| 295 |
|
| 296 |
def batch_upload(csv_file):
|
|
|
|
| 375 |
result_txt = gr.Markdown(elem_id="result-box")
|
| 376 |
report_file = gr.File(label="📃 Download PDF Report")
|
| 377 |
submit_btn.click(
|
| 378 |
+
fn=manual_input,
|
| 379 |
inputs=[equipment_dropdown, project_dropdown, usage, idle, freq, cost, last, ai_dropdown],
|
| 380 |
outputs=[result_txt, report_file] # Only PDF output here now
|
| 381 |
)
|
|
|
|
| 406 |
"""
|
| 407 |
if __name__ == "__main__":
|
| 408 |
app.launch()
|
| 409 |
+
|
| 410 |
+
|
| 411 |
+
|