Files
DentalManagement09/apps/Backend/src/routes/insuranceStatusCCAPreAuth.ts
T
GiteadandClaude Opus 5.5 44a1a41efa feat: Preauth column for AI claims; searchable policy holder + ADA box 18; 2PA fix
- Schedule: last column is the Preauth column; "Claim for Column with AI" is now
  "Claim/Preauth for Column with AI" — that column's appointments go to PreAuth
  (MH, CCA, Tufts SCO, United/DentalHub; other insurances are skipped), the rest
  to Claim. Preauthorized appointments (hasPreauth) aren't resubmitted
- PreAuth payloads carry appointmentId; appointment X-rays/attachments are sent
  with MH/CCA/UnitedDH/Tufts preauths (shared appendAppointmentFiles helper)
- Patient form: policy holder is searchable from patients in the DB, plus
  "Relationship to Policy Holder/Subscriber" (Self, Spouse, Dependent Child,
  Other). New Patient columns policyHolderPatientId, policyHolderRelationship;
  browser-side schema updated so the fields aren't stripped on save
- ADA form: box 12-14 filled from the linked policy holder's record; box 18
  ticks the relationship (Self when the patient is the holder)
- AI notes: a bare "2PA" is an image count, not tooth #2 — restored before CDT
  lookup so it maps to D0220 #8 / D0230 #24

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:09:51 -04:00

125 lines
4.1 KiB
TypeScript

import { Router, Request, Response } from "express";
import { storage } from "../storage";
import { enqueueSeleniumJob } from "../queue/jobRunner";
import multer from "multer";
import { appendAppointmentFiles } from "../utils/appointmentAttachments";
const router = Router();
const upload = multer({ storage: multer.memoryStorage() });
/**
* POST /cca-preauth
*
* Enqueues a CCA pre-authorization submission job.
* Accepts multipart/form-data with optional pdfs/images attachments.
*
* Body fields:
* data — JSON string with preauth payload (memberId, dateOfBirth, serviceDate,
* serviceLines, patientName, etc.)
* socketId — socket.io client id
* claimId — existing claim DB id (optional)
*/
router.post(
"/cca-preauth",
upload.fields([
{ name: "pdfs", maxCount: 10 },
{ name: "images", maxCount: 10 },
]),
async (req: Request, res: Response): Promise<any> => {
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 ?? {};
const pdfs =
(req.files as Record<string, Express.Multer.File[]>)?.pdfs ?? [];
const images =
(req.files as Record<string, Express.Multer.File[]>)?.images ?? [];
const credentials = await storage.getInsuranceCredentialByUserAndSiteKey(
req.user.id,
"CCA"
);
if (!credentials) {
return res.status(404).json({
error: "No CCA credentials found. Please add them on the Settings page.",
});
}
const filesForQueue = [...pdfs, ...images].map((f) => ({
originalname: f.originalname,
bufferBase64: f.buffer.toString("base64"),
mimetype: f.mimetype,
}));
// Include X-rays etc. already attached to the appointment
await appendAppointmentFiles(filesForQueue, claimData.appointmentId);
const enrichedPayload = {
claim: {
...claimData,
cca_username: credentials.username,
cca_password: credentials.password,
},
files: filesForQueue,
};
const socketId: string | undefined = req.body.socketId;
let claimId: number | undefined = claimData.claimId
? Number(claimData.claimId)
: undefined;
// Create a PREAUTH claim record so authNumber can be stored in claimNumber column
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: "CCA",
status: "PREAUTH",
} as any);
claimId = record.id;
console.log(`[cca-preauth route] created claim record id=${claimId}`);
} catch (e: any) {
console.error("[cca-preauth route] failed to create claim record:", e?.message);
}
}
const jobId = enqueueSeleniumJob({
jobType: "cca-preauth-submit",
userId: req.user.id,
socketId,
enrichedPayload,
claimId,
});
return res.json({ status: "queued", jobId });
} catch (err: any) {
console.error("[cca-preauth route] error:", err);
return res.status(500).json({
error: err.message || "Failed to enqueue CCA preauth job",
});
}
}
);
export default router;