import { Router, Request, Response } from "express"; import { storage } from "../storage"; import { enqueueSeleniumJob } from "../queue/jobRunner"; import { forwardOtpToSeleniumUnitedDHPreAuthAgent } from "../services/seleniumUnitedDHPreAuthClient"; import { io } from "../socket"; const router = Router(); /** * POST /uniteddh-preauth * * Enqueues a United/DentalHub pre-authorization submission job. * * Body fields (JSON): * data — preauth payload (memberId, dateOfBirth, serviceDate, serviceLines, patientName, etc.) * socketId — socket.io client id * claimId — existing claim DB id (optional) * * Response: { status: "queued", jobId: "…" } */ router.post("/uniteddh-preauth", async (req: Request, res: Response): Promise => { if (!req.user?.id) { return res.status(401).json({ error: "Unauthorized: user info missing" }); } try { const claimData = typeof req.body.data === "string" ? JSON.parse(req.body.data) : req.body.data ?? req.body ?? {}; // Fetch United/DentalHub credentials — same portal as UnitedSCO const credentials = await storage.getInsuranceCredentialByUserAndSiteKey( req.user.id, "UNITED_SCO" ); if (!credentials) { return res.status(404).json({ error: "No United/DentalHub credentials found. Please add them on the Settings page.", }); } const enrichedPayload = { claim: { ...claimData, uniteddhUsername: credentials.username, uniteddhPassword: credentials.password, }, }; const socketId: string | undefined = req.body.socketId; let claimId: number | undefined = claimData.claimId ? Number(claimData.claimId) : undefined; // Create a PREAUTH claim record so preAuthNumber can be stored if (!claimId && claimData.patientId) { try { const serviceDate = claimData.serviceDate ? new Date(claimData.serviceDate) : new Date(); const dob = claimData.dateOfBirth ? new Date(claimData.dateOfBirth) : new Date("2000-01-01"); const record = await storage.createClaim({ patientId: Number(claimData.patientId), appointmentId: claimData.appointmentId ? Number(claimData.appointmentId) : null, userId: req.user.id, staffId: Number(claimData.staffId) || 1, patientName: claimData.patientName || "", memberId: claimData.memberId || "", dateOfBirth: dob, remarks: claimData.remarks || "", missingTeethStatus: claimData.missingTeethStatus || "No_missing", serviceDate, insuranceProvider: "United/DentalHub", status: "PREAUTH", } as any); claimId = record.id; console.log(`[uniteddh-preauth route] created claim record id=${claimId}`); } catch (e: any) { console.error("[uniteddh-preauth route] failed to create claim record:", e?.message); } } const jobId = enqueueSeleniumJob({ jobType: "uniteddh-preauth-submit", userId: req.user.id, socketId, enrichedPayload, claimId, }); return res.json({ status: "queued", jobId }); } catch (err: any) { console.error("[uniteddh-preauth route] error:", err); return res.status(500).json({ error: err.message || "Failed to enqueue United/DentalHub preauth job", }); } }); /** * POST /claims/uniteddh-preauth/selenium/submit-otp * Body: { session_id, otp, socketId? } */ router.post("/uniteddh-preauth/selenium/submit-otp", async (req: Request, res: Response): Promise => { const { session_id: sessionId, otp, socketId } = req.body; if (!sessionId || !otp) { return res.status(400).json({ error: "session_id and otp are required" }); } try { const r = await forwardOtpToSeleniumUnitedDHPreAuthAgent(sessionId, otp); if (socketId && io) { io.to(socketId).emit("selenium:otp_submitted", { session_id: sessionId }); } return res.json(r); } catch (err: any) { console.error("[uniteddh-preauth] submit-otp failed:", err?.message); return res.status(500).json({ error: err?.message || "Failed to forward OTP" }); } }); export default router;