Update app.py
Browse files
app.py
CHANGED
|
@@ -10,7 +10,6 @@ from retry import retry
|
|
| 10 |
import time
|
| 11 |
from datetime import datetime
|
| 12 |
import base64
|
| 13 |
-
import sys
|
| 14 |
|
| 15 |
# Print statement to confirm script initialization
|
| 16 |
print("Starting Project Closure Readiness Evaluator app...")
|
|
@@ -25,11 +24,9 @@ formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
|
|
| 25 |
console_handler.setFormatter(formatter)
|
| 26 |
logger.addHandler(console_handler)
|
| 27 |
|
| 28 |
-
#
|
| 29 |
-
logging.info(f"Python version: {sys.version}")
|
| 30 |
try:
|
| 31 |
-
import
|
| 32 |
-
logging.info("simple-salesforce module imported successfully")
|
| 33 |
SALESFORCE_AVAILABLE = True
|
| 34 |
except ImportError as e:
|
| 35 |
logging.error(f"Failed to import simple-salesforce: {str(e)}. Salesforce functionality will be disabled.")
|
|
@@ -60,12 +57,7 @@ if not HF_API_TOKEN:
|
|
| 60 |
HF_AVAILABLE = False
|
| 61 |
else:
|
| 62 |
HF_AVAILABLE = True
|
| 63 |
-
|
| 64 |
-
hf_client = InferenceClient(token=HF_API_TOKEN)
|
| 65 |
-
logging.info("Hugging Face InferenceClient initialized successfully")
|
| 66 |
-
except Exception as e:
|
| 67 |
-
logging.error(f"Failed to initialize Hugging Face InferenceClient: {str(e)}")
|
| 68 |
-
HF_AVAILABLE = False
|
| 69 |
|
| 70 |
# Initialize Salesforce connection with retry mechanism
|
| 71 |
@retry(tries=3, delay=2, backoff=2, logger=logger)
|
|
@@ -78,7 +70,7 @@ def init_salesforce():
|
|
| 78 |
logging.info("Attempting to connect to Salesforce with the following credentials:")
|
| 79 |
logging.info(f"Username: {SF_USERNAME}")
|
| 80 |
logging.info(f"Instance URL: {SF_INSTANCE_URL}")
|
| 81 |
-
sf =
|
| 82 |
username=SF_USERNAME,
|
| 83 |
password=SF_PASSWORD,
|
| 84 |
security_token=SF_SECURITY_TOKEN,
|
|
@@ -88,11 +80,11 @@ def init_salesforce():
|
|
| 88 |
# Test read access on Project_Closure_Handover__c
|
| 89 |
test_query = sf.query("SELECT Id FROM Project_Closure_Handover__c LIMIT 1")
|
| 90 |
logging.info(f"Test query result (read access): {test_query}")
|
| 91 |
-
# Test create access by attempting to describe the object
|
| 92 |
object_description = sf.Project_Closure_Handover__c.describe()
|
| 93 |
logging.info(f"Object description: {object_description}")
|
| 94 |
return sf, "Salesforce connected successfully"
|
| 95 |
-
except
|
| 96 |
logging.error(f"Salesforce authentication failed: {str(e)}")
|
| 97 |
logging.error("Possible issues: Incorrect credentials, IP restrictions, or insufficient permissions.")
|
| 98 |
raise
|
|
@@ -101,26 +93,6 @@ def init_salesforce():
|
|
| 101 |
logging.error("Check your Salesforce org settings, network restrictions, or API access.")
|
| 102 |
raise
|
| 103 |
|
| 104 |
-
# Function to query a valid Project ID from the related object (assumed to be Project__c)
|
| 105 |
-
def get_project_id(sf):
|
| 106 |
-
try:
|
| 107 |
-
# Query the most recent active project (modify the WHERE clause as needed)
|
| 108 |
-
project_query = sf.query("SELECT Id FROM Project__c WHERE IsActive__c = true ORDER BY CreatedDate DESC LIMIT 1")
|
| 109 |
-
if project_query['records']:
|
| 110 |
-
project_id = project_query['records'][0]['Id']
|
| 111 |
-
logging.info(f"Found Project ID: {project_id}")
|
| 112 |
-
return project_id
|
| 113 |
-
else:
|
| 114 |
-
logging.warning("No active Project__c records found. Omitting Project_ID__c.")
|
| 115 |
-
return None
|
| 116 |
-
except simple_salesforce.SalesforceError as e:
|
| 117 |
-
logging.error(f"Error querying Project__c: {str(e)}")
|
| 118 |
-
logging.error("Possible issues: Object does not exist, insufficient permissions, or incorrect field name.")
|
| 119 |
-
return None
|
| 120 |
-
except Exception as e:
|
| 121 |
-
logging.error(f"Unexpected error while querying Project ID: {str(e)}")
|
| 122 |
-
return None
|
| 123 |
-
|
| 124 |
# Summarize text using Hugging Face Inference API
|
| 125 |
def summarize_text(text, max_length=100, min_length=30):
|
| 126 |
if not HF_AVAILABLE:
|
|
@@ -145,7 +117,7 @@ def summarize_text(text, max_length=100, min_length=30):
|
|
| 145 |
def create_salesforce_record(score, checklist_summary, missing_summary, status, escalated, logs, qa_report, punch_list_text, open_punch_items, pdf_path=None):
|
| 146 |
if not SALESFORCE_AVAILABLE:
|
| 147 |
logging.error("Salesforce library not available. Skipping record creation.")
|
| 148 |
-
return "Salesforce library not available
|
| 149 |
|
| 150 |
try:
|
| 151 |
sf, connection_message = init_salesforce()
|
|
@@ -157,9 +129,6 @@ def create_salesforce_record(score, checklist_summary, missing_summary, status,
|
|
| 157 |
summarized_checklist = summarize_text(checklist_summary)
|
| 158 |
summarized_missing = summarize_text(missing_summary)
|
| 159 |
|
| 160 |
-
# Query a valid Project ID for the Lookup field
|
| 161 |
-
project_id = get_project_id(sf)
|
| 162 |
-
|
| 163 |
# Ensure inputs are properly formatted
|
| 164 |
score = float(score) if score is not None else 0.0
|
| 165 |
checklist_summary = str(checklist_summary) if checklist_summary else ""
|
|
@@ -195,10 +164,6 @@ def create_salesforce_record(score, checklist_summary, missing_summary, status,
|
|
| 195 |
"QA_Report__c": qa_report
|
| 196 |
}
|
| 197 |
|
| 198 |
-
# Include Project_ID__c only if a valid ID was found
|
| 199 |
-
if project_id:
|
| 200 |
-
record["Project_ID__c"] = project_id
|
| 201 |
-
|
| 202 |
logging.debug(f"Attempting to create Salesforce record in Project_Closure_Handover__c with data: {record}")
|
| 203 |
result = sf.Project_Closure_Handover__c.create(record)
|
| 204 |
logging.info(f"Successfully created Salesforce record: {result}")
|
|
@@ -238,15 +203,14 @@ def create_salesforce_record(score, checklist_summary, missing_summary, status,
|
|
| 238 |
else:
|
| 239 |
logging.warning(f"No PDF file found at {pdf_path}. Skipping attachment and URL update.")
|
| 240 |
|
| 241 |
-
|
| 242 |
-
|
| 243 |
-
except simple_salesforce.SalesforceError as e:
|
| 244 |
logging.error(f"Salesforce error while creating Project_Closure_Handover__c record: {str(e)}")
|
| 245 |
logging.error("Possible issues: Object permissions, field-level security, validation rules, or required fields.")
|
| 246 |
logging.error("Check the following in your Salesforce org:")
|
| 247 |
logging.error("- Ensure the user has Create and Edit permission on Project_Closure_Handover__c.")
|
| 248 |
logging.error("- Ensure the user has permission to create and read Attachments.")
|
| 249 |
-
logging.error("- Verify field-level security for all fields in the record
|
| 250 |
logging.error("- Check for validation rules or required fields that might be failing.")
|
| 251 |
return f"Salesforce error: {str(e)}"
|
| 252 |
except Exception as e:
|
|
@@ -408,7 +372,7 @@ def generate_pdf(score, checklist_summary, missing_summary, checklist_status, lo
|
|
| 408 |
return pdf_path, "PDF generation completed. Click the link to download."
|
| 409 |
except Exception as e:
|
| 410 |
logging.error(f"Error in generate_pdf: {str(e)}")
|
| 411 |
-
|
| 412 |
|
| 413 |
# Gradio interface with updated UI
|
| 414 |
with gr.Blocks(css="""
|
|
@@ -421,7 +385,7 @@ with gr.Blocks(css="""
|
|
| 421 |
gr.Markdown(
|
| 422 |
"""
|
| 423 |
# Project Closure Readiness Evaluator
|
| 424 |
-
Evaluate project readiness, generate a PDF report with signature slots
|
| 425 |
"""
|
| 426 |
)
|
| 427 |
with gr.Row():
|
|
@@ -439,7 +403,7 @@ with gr.Blocks(css="""
|
|
| 439 |
value="Open Items",
|
| 440 |
allow_custom_value=False
|
| 441 |
)
|
| 442 |
-
submit_btn = gr.Button("Evaluate
|
| 443 |
with gr.Column(scale=3):
|
| 444 |
score_output = gr.Number(label="Readiness Score (%)")
|
| 445 |
progress_output = gr.HTML(label="Alert Indicator: Progress")
|
|
@@ -452,45 +416,25 @@ with gr.Blocks(css="""
|
|
| 452 |
open_punch_items_output = gr.Number(label="Open Punch Items (Debug)")
|
| 453 |
pdf_output = gr.File(label="Download PDF Report", type="filepath", interactive=False)
|
| 454 |
pdf_debug = gr.Textbox(label="PDF Debug Output")
|
| 455 |
-
salesforce_output = gr.Textbox(label="Salesforce Save Status")
|
| 456 |
-
error_output = gr.Textbox(label="Error Details (if any)")
|
| 457 |
|
| 458 |
# Chain the evaluation, PDF generation, and Salesforce record creation
|
| 459 |
-
def handle_submission(logs, qa_report, punch_list_text):
|
| 460 |
-
try:
|
| 461 |
-
# Evaluate readiness
|
| 462 |
-
result = evaluate_readiness(logs, qa_report, punch_list_text)
|
| 463 |
-
score, checklist_summary, missing_summary, status, progress_bar, escalated, logs, qa_report, punch_list_text, open_punch_items, checklist_status = result
|
| 464 |
-
|
| 465 |
-
# Generate PDF
|
| 466 |
-
pdf_path, pdf_message = generate_pdf(score, checklist_summary, missing_summary, checklist_status, logs, qa_report, punch_list_text)
|
| 467 |
-
|
| 468 |
-
# Save to Salesforce
|
| 469 |
-
salesforce_message = create_salesforce_record(
|
| 470 |
-
score, checklist_summary, missing_summary, status, escalated, logs, qa_report, punch_list_text, open_punch_items, pdf_path
|
| 471 |
-
)
|
| 472 |
-
|
| 473 |
-
return [
|
| 474 |
-
score, checklist_summary, missing_summary, status, progress_bar, escalated, logs, qa_report, punch_list_text, open_punch_items, checklist_status,
|
| 475 |
-
pdf_path, pdf_message, salesforce_message, ""
|
| 476 |
-
]
|
| 477 |
-
except Exception as e:
|
| 478 |
-
logging.error(f"Submission error: {str(e)}")
|
| 479 |
-
return [None, None, None, None, None, None, None, None, None, None, None, None, None, f"Error: {str(e)}"]
|
| 480 |
-
|
| 481 |
submit_btn.click(
|
| 482 |
-
fn=
|
| 483 |
inputs=[logs_input, qa_input, punch_input],
|
| 484 |
outputs=[
|
| 485 |
score_output, checklist_output, missing_output, status_output, progress_output,
|
| 486 |
-
gr.State(), gr.State(), gr.State(), gr.State(), open_punch_items_output, status_output
|
| 487 |
-
pdf_output, pdf_debug, salesforce_output, error_output
|
| 488 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 489 |
)
|
| 490 |
-
|
| 491 |
-
if __name__ == "__main__":
|
| 492 |
-
try:
|
| 493 |
-
demo.launch()
|
| 494 |
-
except Exception as e:
|
| 495 |
-
logging.error(f"Failed to launch Gradio app: {str(e)}")
|
| 496 |
-
raise
|
|
|
|
| 10 |
import time
|
| 11 |
from datetime import datetime
|
| 12 |
import base64
|
|
|
|
| 13 |
|
| 14 |
# Print statement to confirm script initialization
|
| 15 |
print("Starting Project Closure Readiness Evaluator app...")
|
|
|
|
| 24 |
console_handler.setFormatter(formatter)
|
| 25 |
logger.addHandler(console_handler)
|
| 26 |
|
| 27 |
+
# Attempt to import Salesforce library with fallback
|
|
|
|
| 28 |
try:
|
| 29 |
+
from simple_salesforce import Salesforce, SalesforceError
|
|
|
|
| 30 |
SALESFORCE_AVAILABLE = True
|
| 31 |
except ImportError as e:
|
| 32 |
logging.error(f"Failed to import simple-salesforce: {str(e)}. Salesforce functionality will be disabled.")
|
|
|
|
| 57 |
HF_AVAILABLE = False
|
| 58 |
else:
|
| 59 |
HF_AVAILABLE = True
|
| 60 |
+
hf_client = InferenceClient(token=HF_API_TOKEN)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
|
| 62 |
# Initialize Salesforce connection with retry mechanism
|
| 63 |
@retry(tries=3, delay=2, backoff=2, logger=logger)
|
|
|
|
| 70 |
logging.info("Attempting to connect to Salesforce with the following credentials:")
|
| 71 |
logging.info(f"Username: {SF_USERNAME}")
|
| 72 |
logging.info(f"Instance URL: {SF_INSTANCE_URL}")
|
| 73 |
+
sf = Salesforce(
|
| 74 |
username=SF_USERNAME,
|
| 75 |
password=SF_PASSWORD,
|
| 76 |
security_token=SF_SECURITY_TOKEN,
|
|
|
|
| 80 |
# Test read access on Project_Closure_Handover__c
|
| 81 |
test_query = sf.query("SELECT Id FROM Project_Closure_Handover__c LIMIT 1")
|
| 82 |
logging.info(f"Test query result (read access): {test_query}")
|
| 83 |
+
# Test create access by attempting to describe the object and check permissions
|
| 84 |
object_description = sf.Project_Closure_Handover__c.describe()
|
| 85 |
logging.info(f"Object description: {object_description}")
|
| 86 |
return sf, "Salesforce connected successfully"
|
| 87 |
+
except SalesforceError as e:
|
| 88 |
logging.error(f"Salesforce authentication failed: {str(e)}")
|
| 89 |
logging.error("Possible issues: Incorrect credentials, IP restrictions, or insufficient permissions.")
|
| 90 |
raise
|
|
|
|
| 93 |
logging.error("Check your Salesforce org settings, network restrictions, or API access.")
|
| 94 |
raise
|
| 95 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
# Summarize text using Hugging Face Inference API
|
| 97 |
def summarize_text(text, max_length=100, min_length=30):
|
| 98 |
if not HF_AVAILABLE:
|
|
|
|
| 117 |
def create_salesforce_record(score, checklist_summary, missing_summary, status, escalated, logs, qa_report, punch_list_text, open_punch_items, pdf_path=None):
|
| 118 |
if not SALESFORCE_AVAILABLE:
|
| 119 |
logging.error("Salesforce library not available. Skipping record creation.")
|
| 120 |
+
return "Salesforce library not available"
|
| 121 |
|
| 122 |
try:
|
| 123 |
sf, connection_message = init_salesforce()
|
|
|
|
| 129 |
summarized_checklist = summarize_text(checklist_summary)
|
| 130 |
summarized_missing = summarize_text(missing_summary)
|
| 131 |
|
|
|
|
|
|
|
|
|
|
| 132 |
# Ensure inputs are properly formatted
|
| 133 |
score = float(score) if score is not None else 0.0
|
| 134 |
checklist_summary = str(checklist_summary) if checklist_summary else ""
|
|
|
|
| 164 |
"QA_Report__c": qa_report
|
| 165 |
}
|
| 166 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
logging.debug(f"Attempting to create Salesforce record in Project_Closure_Handover__c with data: {record}")
|
| 168 |
result = sf.Project_Closure_Handover__c.create(record)
|
| 169 |
logging.info(f"Successfully created Salesforce record: {result}")
|
|
|
|
| 203 |
else:
|
| 204 |
logging.warning(f"No PDF file found at {pdf_path}. Skipping attachment and URL update.")
|
| 205 |
|
| 206 |
+
return f"Record created successfully. Record ID: {record_id}. PDF attached and URL set to: {pdf_download_url}"
|
| 207 |
+
except SalesforceError as e:
|
|
|
|
| 208 |
logging.error(f"Salesforce error while creating Project_Closure_Handover__c record: {str(e)}")
|
| 209 |
logging.error("Possible issues: Object permissions, field-level security, validation rules, or required fields.")
|
| 210 |
logging.error("Check the following in your Salesforce org:")
|
| 211 |
logging.error("- Ensure the user has Create and Edit permission on Project_Closure_Handover__c.")
|
| 212 |
logging.error("- Ensure the user has permission to create and read Attachments.")
|
| 213 |
+
logging.error("- Verify field-level security for all fields in the record.")
|
| 214 |
logging.error("- Check for validation rules or required fields that might be failing.")
|
| 215 |
return f"Salesforce error: {str(e)}"
|
| 216 |
except Exception as e:
|
|
|
|
| 372 |
return pdf_path, "PDF generation completed. Click the link to download."
|
| 373 |
except Exception as e:
|
| 374 |
logging.error(f"Error in generate_pdf: {str(e)}")
|
| 375 |
+
raise
|
| 376 |
|
| 377 |
# Gradio interface with updated UI
|
| 378 |
with gr.Blocks(css="""
|
|
|
|
| 385 |
gr.Markdown(
|
| 386 |
"""
|
| 387 |
# Project Closure Readiness Evaluator
|
| 388 |
+
Evaluate project readiness, generate a PDF report with signature slots.
|
| 389 |
"""
|
| 390 |
)
|
| 391 |
with gr.Row():
|
|
|
|
| 403 |
value="Open Items",
|
| 404 |
allow_custom_value=False
|
| 405 |
)
|
| 406 |
+
submit_btn = gr.Button("Evaluate and Generate PDF")
|
| 407 |
with gr.Column(scale=3):
|
| 408 |
score_output = gr.Number(label="Readiness Score (%)")
|
| 409 |
progress_output = gr.HTML(label="Alert Indicator: Progress")
|
|
|
|
| 416 |
open_punch_items_output = gr.Number(label="Open Punch Items (Debug)")
|
| 417 |
pdf_output = gr.File(label="Download PDF Report", type="filepath", interactive=False)
|
| 418 |
pdf_debug = gr.Textbox(label="PDF Debug Output")
|
|
|
|
|
|
|
| 419 |
|
| 420 |
# Chain the evaluation, PDF generation, and Salesforce record creation
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 421 |
submit_btn.click(
|
| 422 |
+
fn=evaluate_readiness,
|
| 423 |
inputs=[logs_input, qa_input, punch_input],
|
| 424 |
outputs=[
|
| 425 |
score_output, checklist_output, missing_output, status_output, progress_output,
|
| 426 |
+
gr.State(), gr.State(), gr.State(), gr.State(), open_punch_items_output, status_output
|
|
|
|
| 427 |
]
|
| 428 |
+
).then(
|
| 429 |
+
fn=generate_pdf,
|
| 430 |
+
inputs=[score_output, checklist_output, missing_output, status_output, gr.State(), gr.State(), gr.State()],
|
| 431 |
+
outputs=[pdf_output, pdf_debug]
|
| 432 |
+
).then(
|
| 433 |
+
fn=create_salesforce_record,
|
| 434 |
+
inputs=[
|
| 435 |
+
score_output, checklist_output, missing_output, status_output,
|
| 436 |
+
gr.State(), gr.State(), gr.State(), gr.State(), open_punch_items_output, pdf_output
|
| 437 |
+
],
|
| 438 |
+
outputs=None
|
| 439 |
)
|
| 440 |
+
demo.launch()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|