From 1414ec11fdb2ab2de5499c9a0c030d072b4c2fdb Mon Sep 17 00:00:00 2001 From: Gitead Date: Wed, 22 Apr 2026 14:33:19 -0400 Subject: [PATCH] fix: MH eligibility - auto-select first provider, fix PDF double-quit bug --- .../selenium_eligibilityCheckWorker.py | 133 ++++++++---------- 1 file changed, 59 insertions(+), 74 deletions(-) diff --git a/apps/SeleniumService/selenium_eligibilityCheckWorker.py b/apps/SeleniumService/selenium_eligibilityCheckWorker.py index 68c08f56..c18bb93e 100755 --- a/apps/SeleniumService/selenium_eligibilityCheckWorker.py +++ b/apps/SeleniumService/selenium_eligibilityCheckWorker.py @@ -3,13 +3,10 @@ from selenium.common import TimeoutException from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait, Select -from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from webdriver_manager.chrome import ChromeDriverManager import time import os -import shutil -import stat import base64 class AutomationMassHealthEligibilityCheck: @@ -87,80 +84,86 @@ class AutomationMassHealthEligibilityCheck: def step1(self): wait = WebDriverWait(self.driver, 30) + substep = "init" try: - # Skip My Account - go directly to Patient Management - # Step 1: Click Patient Management directly + print(f"[step1] current URL after login: {self.driver.current_url}") + print(f"[step1] page title: {self.driver.title}") + + substep = "patient_management" patient_mgmt = wait.until( EC.presence_of_element_located( (By.XPATH, "//strong[@translate='Patient Management']") ) ) - - # Scroll + JS click = fixes most dropdown issues self.driver.execute_script("arguments[0].scrollIntoView(true);", patient_mgmt) self.driver.execute_script("arguments[0].click();", patient_mgmt) time.sleep(2) - # Step 3: Click Member Eligibility + substep = "member_eligibility_link" eligibility_link = wait.until( EC.presence_of_element_located( (By.XPATH, "//a[@translate='Member Eligibility']") ) ) - self.driver.execute_script("arguments[0].click();", eligibility_link) time.sleep(2) - # Step 4: Wait for Provider dropdown + substep = "provider_dropdown" provider_dropdown = wait.until( EC.presence_of_element_located((By.NAME, "provider")) ) - - # Use Select class (important!) select_provider = Select(provider_dropdown) - # Step 5: Select correct option - select_provider.select_by_visible_text( - "Summit Dental Care - Framingham - Kai Gao" + # Log available options so we can see if the provider name changed + options = [o.text for o in select_provider.options] + print(f"[step1] provider options: {options}") + + substep = "select_provider" + # Select the first non-empty option (index 0 is usually a blank placeholder) + first_option = next( + (o for o in select_provider.options if o.get_attribute("value").strip()), + select_provider.options[0] ) + print(f"[step1] selecting provider: '{first_option.text}'") + select_provider.select_by_value(first_option.get_attribute("value")) time.sleep(2) - # Step 6: Member Date Of Birth (SECOND dateInput) + substep = "member_dob" member_dob = wait.until( EC.presence_of_all_elements_located((By.NAME, "dateInput")) )[1] member_dob.clear() - member_dob.send_keys(self.dateOfBirth) + member_dob.send_keys(self.dateOfBirth) - # Step 7: Member Number + substep = "member_number" member_number = wait.until( EC.presence_of_element_located((By.NAME, "memberNumber")) ) member_number.clear() member_number.send_keys(self.memberId) - # Step 8: Click Search + substep = "search_button" search_button = wait.until( EC.element_to_be_clickable((By.XPATH, "//button[contains(@class,'btn-primary')]")) ) search_button.click() - # ✅ CRITICAL WAIT FOR RESULTS + substep = "wait_results" wait.until( EC.presence_of_element_located( (By.XPATH, "//h4[text()='Eligible' or text()='Ineligible']") ) ) - # ✅ EXTRACT DATA FROM RESULTS PAGE self.extracted_data = self._extract_data_from_page() - print(f"Data extracted in step1: {self.extracted_data}") + print(f"[step1] data extracted: {self.extracted_data}") return "Success" - except Exception as e: - print(f"Error while step1: {e}") - return "ERROR:STEP1" + except Exception as e: + print(f"[step1] FAILED at substep='{substep}': {e}") + print(f"[step1] URL at failure: {self.driver.current_url}") + return f"ERROR:STEP1:{substep}" def _cell_text(self, cell): """Get text from a cell, falling back to JS innerText if .text is empty.""" @@ -280,11 +283,22 @@ class AutomationMassHealthEligibilityCheck: print("Extraction error:", e) return {"eligibility": None} + def _print_current_page_as_pdf(self): + """Generate PDF from the currently active tab using CDP.""" + safe_member = "".join(c for c in str(self.memberId) if c.isalnum() or c in "-_.") + pdf_filename = f"eligibility_{safe_member}.pdf" + pdf_data = self.driver.execute_cdp_cmd("Page.printToPDF", {"printBackground": True}) + pdf_bytes = base64.b64decode(pdf_data["data"]) + pdf_path = os.path.join(self.download_dir, pdf_filename) + with open(pdf_path, "wb") as f: + f.write(pdf_bytes) + print("PDF saved at:", pdf_path) + return pdf_path + def step2(self): wait = WebDriverWait(self.driver, 30) try: - # ✅ USE STORED EXTRACTED DATA print(f"Using stored extracted data: {self.extracted_data}") # Step 1: Click Printer Friendly Format @@ -296,57 +310,32 @@ class AutomationMassHealthEligibilityCheck: original_tab = self.driver.current_window_handle download_button.click() - # Wait for NEW TAB - wait.until(lambda d: len(d.window_handles) > 1) + # Wait up to 10s for a new tab; if none opens, print the current page + try: + WebDriverWait(self.driver, 10).until(lambda d: len(d.window_handles) > 1) + new_tabs = [tab for tab in self.driver.window_handles if tab != original_tab] + self.driver.switch_to.window(new_tabs[0]) + wait.until(lambda d: d.execute_script("return document.readyState") == "complete") + wait.until(EC.presence_of_element_located((By.TAG_NAME, "body"))) + time.sleep(2) + print("Printer-friendly tab opened:", self.driver.current_url) + except TimeoutException: + # Portal did not open a new tab — print the results page directly + print("No new tab opened; printing results page directly as PDF") - # Switch ONLY to new tab - new_tabs = [tab for tab in self.driver.window_handles if tab != original_tab] - self.driver.switch_to.window(new_tabs[0]) + pdf_path = self._print_current_page_as_pdf() - wait.until(lambda d: d.execute_script("return document.readyState") == "complete") - - # Wait for page to render (CRITICAL) - wait.until(EC.presence_of_element_located((By.TAG_NAME, "body"))) - time.sleep(2) - - print("Capturing PDF from:", self.driver.current_url) - - # Extract data from page BEFORE generating PDF - extracted_data = self._extract_data_from_page() - print(f"Extracted data: {extracted_data}") - - # Step 2: Save PDF using Chrome DevTools (REAL solution) - safe_member = "".join(c for c in str(self.memberId) if c.isalnum() or c in "-_.") - pdf_filename = f"eligibility_{safe_member}.pdf" - - pdf_data = self.driver.execute_cdp_cmd("Page.printToPDF", { - "printBackground": True - }) - - pdf_bytes = base64.b64decode(pdf_data['data']) - pdf_path = os.path.join(self.download_dir, pdf_filename) - - with open(pdf_path, "wb") as f: - f.write(pdf_bytes) - - print("PDF saved at:", pdf_path) - - # Return PDF path along with extracted data result = { "status": "success", "pdf_path": pdf_path, "file_type": "pdf", "message": "PDF captured successfully" } - - # Add stored extracted data to result + if self.extracted_data: result.update(self.extracted_data) - - return result - except Exception as e: - print("PDF capture failed:", e) + return result except Exception as e: print("PDF capture failed:", e) @@ -365,11 +354,11 @@ class AutomationMassHealthEligibilityCheck: "file_type": "screenshot", "message": "Screenshot captured (PDF failed)" } - + # Add stored extracted data to result even for screenshots if self.extracted_data: result.update(self.extracted_data) - + return result except Exception as ss_error: @@ -378,10 +367,6 @@ class AutomationMassHealthEligibilityCheck: "message": f"PDF + Screenshot failed: {ss_error}" } - finally: - if self.driver: - self.driver.quit() - def main_workflow(self, url): try: self.config_driver() @@ -402,10 +387,10 @@ class AutomationMassHealthEligibilityCheck: return {"status": "error", "message": step2_result.get("message")} return step2_result - except Exception as e: + except Exception as e: return { "status": "error", - "message": e + "message": str(e) } finally: