feat: integrate DDMA eligibility into BullMQ queue with persistent session

- Route DDMA eligibility through InProcessQueue (concurrency=1) so it
  queues behind other selenium jobs instead of running concurrently
- New ddmaEligibilityProcessor: starts Python session, polls for OTP/
  completion via socket events, saves PDF and updates patient DB
- Frontend ddma-buton-modal now uses shared app socket + job:update
  pattern (drops private socket connection)
- SeleniumService: upgrade ddma_browser_manager with credential hash
  tracking, anti-detection options, and startup session clearing;
  upgrade DDMA worker with firstName/lastName support, PDF via
  printToPDF, force-logout on credential change; upgrade helpers with
  dual OTP strategy (app API + browser polling); add /clear-ddma-session
  endpoint; reduce fixed sleeps with smart WebDriverWait

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
ff
2026-04-16 09:21:47 -04:00
co-authored by Claude Sonnet 4.6
parent a1cccc8716
commit 289ea426d3
9 changed files with 1429 additions and 1239 deletions
+15
View File
@@ -11,6 +11,7 @@ import { runEligibilityProcessor } from "./processors/eligibilityProcessor";
import { runClaimStatusProcessor } from "./processors/claimStatusProcessor";
import { runClaimSubmitProcessor } from "./processors/claimSubmitProcessor";
import { runOcrProcessor } from "./processors/ocrProcessor";
import { runDdmaEligibilityProcessor } from "./processors/ddmaEligibilityProcessor";
import type { SeleniumJobData, OcrJobData } from "./queues";
// ── Queue instances ──────────────────────────────────────────────────────────
@@ -68,6 +69,20 @@ export function enqueueSeleniumJob(data: SeleniumJobData): string {
variant: jobType === "claim-pre-auth" ? "claim-pre-auth" : "claimsubmit",
});
}
if (jobType === "ddma-eligibility-check") {
return runDdmaEligibilityProcessor(
{
enrichedPayload: data.enrichedPayload,
userId: data.userId,
insuranceId: data.insuranceId!,
formFirstName: data.formFirstName,
formLastName: data.formLastName,
formDob: data.formDob,
socketId: data.socketId,
},
job.id
);
}
throw new Error(`Unknown selenium jobType: ${jobType}`);
});