/** * Processors for "claim-submit" and "claim-pre-auth" jobs. * Mirrors routes/claims.ts /selenium-claim and /selenium-claim-pre-auth */ import path from "path"; import axios from "axios"; import { storage } from "../../storage"; import { callPythonSync } from "./_shared"; export interface ClaimSubmitProcessorInput { enrichedPayload: any; files: { originalname: string; bufferBase64: string; mimetype: string }[]; claimId?: number; /** "claimsubmit" (default) or "claim-pre-auth" */ variant?: "claimsubmit" | "claim-pre-auth"; /** When set, the frontend socket listener will handle the PDF download — skip auto-save */ socketId?: string; } export interface ClaimSubmitProcessorResult { status: string; claimNumber?: string; pdf_url?: string; [key: string]: any; } /** Fetch the PDF from the selenium service and save it to cloud storage. */ async function savePdfFromSelenium( pdf_url: string, patientId: number, variant: "claimsubmit" | "claim-pre-auth" ) { try { const filename = path.basename(new URL(pdf_url).pathname); const seleniumPort = process.env.SELENIUM_PORT || "5002"; const localUrl = `http://localhost:${seleniumPort}/downloads/${filename}`; const resp = await axios.get(localUrl, { responseType: "arraybuffer", timeout: 30000 }); const groupTitleKey = variant === "claim-pre-auth" ? "INSURANCE_CLAIM_PREAUTH" : "INSURANCE_CLAIM"; const groupTitle = variant === "claim-pre-auth" ? "Claims Preauth" : "Claims"; let group = await storage.findPdfGroupByPatientTitleKey(patientId, groupTitleKey); if (!group) { group = await storage.createPdfGroup(patientId, groupTitle, groupTitleKey); } await storage.createPdfFile(group.id!, filename, resp.data); console.log(`[claimSubmitProcessor] PDF saved for patient ${patientId}: ${filename}`); } catch (err: any) { // Non-fatal — claim was submitted; just log the PDF failure console.error("[claimSubmitProcessor] failed to save PDF:", err?.message ?? err); } } export async function runClaimSubmitProcessor( input: ClaimSubmitProcessorInput ): Promise { const { enrichedPayload, files, claimId } = input; const variant = input.variant ?? "claimsubmit"; // Build the same payload shape the Python /claimsubmit endpoint expects const pdfs = files .filter((f) => f.mimetype === "application/pdf") .map(({ originalname, bufferBase64 }) => ({ originalname, bufferBase64 })); const images = files .filter((f) => f.mimetype.startsWith("image/")) .map(({ originalname, bufferBase64 }) => ({ originalname, bufferBase64 })); const payload = { claim: enrichedPayload, pdfs, images }; const endpoint = variant === "claim-pre-auth" ? "/claim-pre-auth" : "/claimsubmit"; // 1) Call the Python service synchronously (BullMQ worker handles async) const result = await callPythonSync(endpoint, payload, 10 * 60 * 1000); // 2) Persist claimNumber and update status to REVIEW if (claimId) { try { const updates: Record = { status: "REVIEW" }; if (result?.claimNumber) updates.claimNumber = result.claimNumber; await storage.updateClaim(claimId, updates); } catch (e) { console.error("[claimSubmitProcessor] failed to update claim after submission:", e); } } // 3) Auto-save PDF for batch jobs (no socketId = no frontend listener to call fetchpdf) if (result?.pdf_url && enrichedPayload?.patientId && !input.socketId) { await savePdfFromSelenium( result.pdf_url, Number(enrichedPayload.patientId), variant ); } return { ...result, claimId }; }