diff --git a/apps/Backend/src/queue/processors/claimSubmitProcessor.ts b/apps/Backend/src/queue/processors/claimSubmitProcessor.ts index 0e3019c9..7c818607 100644 --- a/apps/Backend/src/queue/processors/claimSubmitProcessor.ts +++ b/apps/Backend/src/queue/processors/claimSubmitProcessor.ts @@ -42,12 +42,14 @@ export async function runClaimSubmitProcessor( // 1) Call the Python service synchronously (BullMQ worker handles async) const result = await callPythonSync(endpoint, payload, 10 * 60 * 1000); - // 3) Persist claimNumber if returned - if (result?.claimNumber && claimId) { + // 2) Persist claimNumber and update status to REVIEW after successful submission + if (claimId) { try { - await storage.updateClaim(claimId, { claimNumber: result.claimNumber }); + const updates: Record = { status: "REVIEW" }; + if (result?.claimNumber) updates.claimNumber = result.claimNumber; + await storage.updateClaim(claimId, updates); } catch (e) { - console.error("[claimSubmitProcessor] failed to persist claimNumber:", e); + console.error("[claimSubmitProcessor] failed to update claim after submission:", e); } } diff --git a/apps/Frontend/src/pages/claims-page.tsx b/apps/Frontend/src/pages/claims-page.tsx index c2195db2..62a958a9 100755 --- a/apps/Frontend/src/pages/claims-page.tsx +++ b/apps/Frontend/src/pages/claims-page.tsx @@ -57,7 +57,7 @@ export default function ClaimsPage() { patientId: number | null; groupKey: "INSURANCE_CLAIM" | "INSURANCE_CLAIM_PREAUTH"; }>({ patientId: null, groupKey: "INSURANCE_CLAIM" }); - const { status: jobStatus, result: jobResult } = useJobStatus(pendingClaimJobId); + const { status: jobStatus, result: jobResult, socketId } = useJobStatus(pendingClaimJobId); const { toast } = useToast(); const { user } = useAuth(); @@ -332,6 +332,7 @@ export default function ClaimsPage() { const handleMHClaimSubmitSelenium = async (data: any) => { const formData = new FormData(); formData.append("data", JSON.stringify(data)); + if (socketId) formData.append("socketId", socketId); const uploadedFiles: File[] = data.uploadedFiles ?? []; uploadedFiles.forEach((file: File) => { @@ -468,6 +469,7 @@ export default function ClaimsPage() { const handleMHClaimPreAuthSubmitSelenium = async (data: any) => { const formData = new FormData(); formData.append("data", JSON.stringify(data)); + if (socketId) formData.append("socketId", socketId); const uploadedFiles: File[] = data.uploadedFiles ?? []; uploadedFiles.forEach((file: File) => { diff --git a/apps/SeleniumService/selenium_claimSubmitWorker.py b/apps/SeleniumService/selenium_claimSubmitWorker.py index e9d1b4e3..2e0d9358 100755 --- a/apps/SeleniumService/selenium_claimSubmitWorker.py +++ b/apps/SeleniumService/selenium_claimSubmitWorker.py @@ -125,12 +125,14 @@ class AutomationMassHealthClaimsLogin: if self.headless: options.add_argument("--headless") - # Add PDF download preferences (if needed later) + # Required for Page.printToPDF CDP command to work in non-headless Chrome + options.add_argument("--enable-print-browser") + prefs = { "download.default_directory": self.download_dir, "plugins.always_open_pdf_externally": False, "download.prompt_for_download": False, - "download.directory_upgrade": True + "download.directory_upgrade": True, } options.add_experimental_option("prefs", prefs) @@ -1107,77 +1109,72 @@ class AutomationMassHealthClaimsLogin: def save_confirmation_pdf(self): wait = WebDriverWait(self.driver, 30) - + + # Wait for page to fully load + 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(f"DEBUG: Capturing confirmation from: {self.driver.current_url}") + + # Extract claim number first so both PDF and screenshot paths have it + claim_number = self.extract_claim_number() + + safe_member = "".join(c for c in str(self.memberId) if c.isalnum() or c in "-_.") + timestamp = time.strftime("%Y%m%d_%H%M%S") + safe_claim = ("_" + "".join(c for c in str(claim_number) if c.isalnum() or c in "-_.")[:20]) if claim_number else "" + + # --- Primary: print full page to PDF via Chrome DevTools --- try: - print("DEBUG: Saving confirmation page as PDF") - - # Wait for page to fully load - 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(f"DEBUG: Capturing PDF from: {self.driver.current_url}") - - # Extract claim number from confirmation page - claim_number = self.extract_claim_number() - - # Generate safe filename using member ID, claim number and timestamp - safe_member = "".join(c for c in str(self.memberId) if c.isalnum() or c in "-_.") - timestamp = time.strftime("%Y%m%d_%H%M%S") - - if claim_number: - safe_claim = "".join(c for c in str(claim_number) if c.isalnum() or c in "-_.")[:20] - pdf_filename = f"claim_confirmation_{safe_member}_{safe_claim}_{timestamp}.pdf" - else: - pdf_filename = f"claim_confirmation_{safe_member}_{timestamp}.pdf" - - # Use Chrome DevTools to generate PDF + pdf_filename = f"claim_confirmation_{safe_member}{safe_claim}_{timestamp}.pdf" pdf_data = self.driver.execute_cdp_cmd("Page.printToPDF", { - "printBackground": True + "printBackground": True, + "paperWidth": 8.5, + "paperHeight": 11, + "marginTop": 0.4, + "marginBottom": 0.4, + "marginLeft": 0.4, + "marginRight": 0.4, }) - - pdf_bytes = base64.b64decode(pdf_data['data']) + 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(f"DEBUG: PDF saved at: {pdf_path}") - return { "status": "success", "pdf_path": pdf_path, "file_type": "pdf", "claimNumber": claim_number, - "message": "Confirmation PDF captured successfully" + "message": "Confirmation PDF captured successfully", } - except Exception as e: - print(f"PDF capture failed: {e}") - - # Fallback to screenshot - try: - safe_member = "".join(c for c in str(self.memberId) if c.isalnum() or c in "-_.") - timestamp = time.strftime("%Y%m%d_%H%M%S") - screenshot_path = os.path.join(self.download_dir, f"claim_confirmation_{safe_member}_{timestamp}.png") - - self.driver.save_screenshot(screenshot_path) - - print(f"DEBUG: Screenshot saved at: {screenshot_path}") - - return { - "status": "success", - "pdf_path": screenshot_path, - "file_type": "screenshot", - "claimNumber": None, - "message": "Screenshot captured (PDF failed)" - } - - except Exception as ss_error: - return { - "status": "error", - "message": f"PDF + Screenshot failed: {ss_error}" - } + print(f"PDF capture failed, falling back to full-page screenshot: {e}") + + # --- Fallback: full-page screenshot saved as PNG --- + try: + screenshot_filename = f"claim_confirmation_{safe_member}{safe_claim}_{timestamp}.png" + screenshot_path = os.path.join(self.download_dir, screenshot_filename) + + # Expand browser to full page height so the whole confirmation is captured + total_height = self.driver.execute_script("return document.body.scrollHeight") + self.driver.set_window_size(1280, max(total_height, 800)) + time.sleep(1) + + self.driver.save_screenshot(screenshot_path) + print(f"DEBUG: Screenshot saved at: {screenshot_path}") + return { + "status": "success", + "pdf_path": screenshot_path, + "file_type": "screenshot", + "claimNumber": claim_number, + "message": "Full-page screenshot captured (PDF failed)", + } + except Exception as ss_error: + return { + "status": "error", + "message": f"PDF + Screenshot failed: {ss_error}", + } def fill_service_line(self, row_number=1, procedure_code="", tooth_number="", tooth_surface="", quadrant="Upper Right", arch="Entire Oral Cavity", auth_number="AUTH123456", billed_amount=""): wait = WebDriverWait(self.driver, 30)