feat(ClaimStatus) - Schema updated, hence changes made in backend, frontend

This commit is contained in:
2025-09-19 01:41:25 +05:30
parent 9d06e9ded4
commit 6e97e5ab40
14 changed files with 678 additions and 188 deletions

View File

@@ -125,13 +125,14 @@ router.post(
responseType: "arraybuffer",
});
const groupTitle = `Insurance Claim`;
const groupTitle = "Insurance Claim";
const groupTitleKey = "INSURANCE_CLAIM";
const groupCategory = "CLAIM";
// ✅ Find or create PDF group for this claim
let group = await storage.findPdfGroupByPatientTitleAndCategory(
let group = await storage.findPdfGroupByPatientTitleKeyAndCategory(
parsedPatientId,
groupTitle,
groupTitleKey,
groupCategory
);
@@ -139,6 +140,7 @@ router.post(
group = await storage.createPdfGroup(
parsedPatientId,
groupTitle,
groupTitleKey,
groupCategory
);
}

View File

@@ -12,17 +12,18 @@ router.post(
"/pdf-groups",
async (req: Request, res: Response): Promise<any> => {
try {
const { title, category, patientId } = req.body;
if (!title || !category || !patientId) {
const { patientId, groupTitle, groupTitleKey, groupCategory } = req.body;
if (!patientId || !groupTitle || groupTitleKey || !groupCategory) {
return res
.status(400)
.json({ error: "Missing title, category, or patientId" });
.json({ error: "Missing title, titleKey, category, or patientId" });
}
const group = await storage.createPdfGroup(
parseInt(patientId),
title,
category
groupTitle,
groupTitleKey,
groupCategory
);
res.json(group);
@@ -89,8 +90,14 @@ router.put(
return res.status(400).json({ error: "Missing ID" });
}
const id = parseInt(idParam);
const { title, category } = req.body;
const updated = await storage.updatePdfGroup(id, { title, category });
const { title, category, titleKey } = req.body;
const updates: any = {};
updates.title = title;
updates.category = category;
updates.titleKey = titleKey;
const updated = await storage.updatePdfGroup(id, updates);
if (!updated) return res.status(404).json({ error: "Group not found" });
res.json(updated);
} catch (err) {
@@ -144,20 +151,22 @@ router.post(
}
);
router.get("/pdf-files/group/:groupId", async (req: Request, res: Response):Promise<any> => {
try {
const idParam = req.params.groupId;
router.get(
"/pdf-files/group/:groupId",
async (req: Request, res: Response): Promise<any> => {
try {
const idParam = req.params.groupId;
if (!idParam) {
return res.status(400).json({ error: "Missing Groupt ID" });
}
const groupId = parseInt(idParam);
const files = await storage.getPdfFilesByGroupId(groupId); // implement this
res.json(files);
} catch (err) {
res.status(500).json({ error: "Internal server error" });
const groupId = parseInt(idParam);
const files = await storage.getPdfFilesByGroupId(groupId);
res.json(files);
} catch (err) {
res.status(500).json({ error: "Internal server error" });
}
}
});
);
router.get(
"/pdf-files/:id",
@@ -167,13 +176,109 @@ router.get(
if (!idParam) {
return res.status(400).json({ error: "Missing ID" });
}
const id = parseInt(idParam);
const pdf = await storage.getPdfFileById(id);
if (!pdf || !pdf.pdfData)
return res.status(404).json({ error: "PDF not found" });
const id = parseInt(idParam, 10);
if (Number.isNaN(id)) {
return res.status(400).json({ error: "Invalid ID" });
}
if (!Buffer.isBuffer(pdf.pdfData)) {
pdf.pdfData = Buffer.from(Object.values(pdf.pdfData));
const pdf = await storage.getPdfFileById(id);
if (!pdf || !pdf.pdfData) {
return res.status(404).json({ error: "PDF not found" });
}
const data: any = pdf.pdfData;
// Helper: try many plausible conversions into a Buffer
function normalizeToBuffer(d: any): Buffer | null {
// Already a Buffer
if (Buffer.isBuffer(d)) return d;
// Uint8Array or other typed arrays
if (d instanceof Uint8Array) return Buffer.from(d);
// ArrayBuffer
if (d instanceof ArrayBuffer) return Buffer.from(new Uint8Array(d));
// number[] (common)
if (Array.isArray(d) && d.every((n) => typeof n === "number")) {
return Buffer.from(d as number[]);
}
// Some drivers: { data: number[] }
if (
d &&
typeof d === "object" &&
Array.isArray(d.data) &&
d.data.every((n: any) => typeof n === "number")
) {
return Buffer.from(d.data as number[]);
}
// Some drivers return object with numeric keys: { '0': 37, '1': 80, ... }
if (d && typeof d === "object") {
const keys = Object.keys(d);
const numericKeys = keys.filter((k) => /^\d+$/.test(k));
if (numericKeys.length > 0 && numericKeys.length === keys.length) {
// sort numeric keys to correct order and map to numbers
const sorted = numericKeys
.map((k) => parseInt(k, 10))
.sort((a, b) => a - b)
.map((n) => d[String(n)]);
if (sorted.every((v) => typeof v === "number")) {
return Buffer.from(sorted as number[]);
}
}
}
// Last resort: if Object.values(d) yields numbers (this is what you used originally)
try {
const vals = Object.values(d);
if (Array.isArray(vals) && vals.every((v) => typeof v === "number")) {
// coerce to number[] for TS safety
return Buffer.from(vals as number[]);
}
} catch {
// ignore
}
// give up
return null;
}
const pdfBuffer = normalizeToBuffer(data);
if (!pdfBuffer) {
console.error("Unsupported pdf.pdfData shape:", {
typeofData: typeof data,
constructorName:
data && data.constructor ? data.constructor.name : undefined,
keys:
data && typeof data === "object"
? Object.keys(data).slice(0, 20)
: undefined,
sample: (() => {
if (Array.isArray(data)) return data.slice(0, 20);
if (data && typeof data === "object") {
const vals = Object.values(data);
return Array.isArray(vals) ? vals.slice(0, 20) : undefined;
}
return String(data).slice(0, 200);
})(),
});
// Try a safe textual fallback (may produce invalid PDF but avoids crashing)
try {
const fallback = Buffer.from(String(data));
res.setHeader("Content-Type", "application/pdf");
res.setHeader(
"Content-Disposition",
`attachment; filename="${pdf.filename}"; filename*=UTF-8''${encodeURIComponent(pdf.filename)}`
);
return res.send(fallback);
} catch (err) {
console.error("Failed fallback conversion:", err);
return res.status(500).json({ error: "Cannot process PDF data" });
}
}
res.setHeader("Content-Type", "application/pdf");
@@ -181,7 +286,7 @@ router.get(
"Content-Disposition",
`attachment; filename="${pdf.filename}"; filename*=UTF-8''${encodeURIComponent(pdf.filename)}`
);
res.send(pdf.pdfData);
res.send(pdfBuffer);
} catch (err) {
console.error("Error downloading PDF file:", err);
res.status(500).json({ error: "Internal server error" });

View File

@@ -7,7 +7,7 @@ import claimsRoutes from "./claims";
import patientDataExtractionRoutes from "./patientDataExtraction";
import insuranceCredsRoutes from "./insuranceCreds";
import documentsRoutes from "./documents";
import insuranceEligibilityRoutes from "./insuranceEligibility";
import insuranceStatusRoutes from "./insuranceStatus";
import paymentsRoutes from "./payments";
import databaseManagementRoutes from "./database-management";
import notificationsRoutes from "./notifications";
@@ -23,7 +23,7 @@ router.use("/patientDataExtraction", patientDataExtractionRoutes);
router.use("/claims", claimsRoutes);
router.use("/insuranceCreds", insuranceCredsRoutes);
router.use("/documents", documentsRoutes);
router.use("/insuranceEligibility", insuranceEligibilityRoutes);
router.use("/insurance-status", insuranceStatusRoutes);
router.use("/payments", paymentsRoutes);
router.use("/database-management", databaseManagementRoutes);
router.use("/notifications", notificationsRoutes);

View File

@@ -1,110 +0,0 @@
import { Router } from "express";
import { Request, Response } from "express";
import { storage } from "../storage";
import { forwardToSeleniumInsuranceEligibilityAgent } from "../services/seleniumInsuranceEligibilityClient";
import fs from "fs/promises";
import path from "path";
const router = Router();
router.post("/check", async (req: Request, res: Response): Promise<any> => {
if (!req.body.data) {
return res
.status(400)
.json({ error: "Missing Insurance Eligibility data for selenium" });
}
if (!req.user || !req.user.id) {
return res.status(401).json({ error: "Unauthorized: user info missing" });
}
try {
const insuranceEligibilityData = JSON.parse(req.body.data);
const credentials = await storage.getInsuranceCredentialByUserAndSiteKey(
req.user.id,
insuranceEligibilityData.insuranceSiteKey
);
if (!credentials) {
return res.status(404).json({
error:
"No insurance credentials found for this provider, Kindly Update this at Settings Page.",
});
}
const enrichedData = {
...insuranceEligibilityData,
massdhpUsername: credentials.username,
massdhpPassword: credentials.password,
};
const result =
await forwardToSeleniumInsuranceEligibilityAgent(enrichedData);
// ✅ Step 1: Check result and update patient status
const patient = await storage.getPatientByInsuranceId(
insuranceEligibilityData.memberId
);
if (patient && patient.id !== undefined) {
const newStatus = result.eligibility === "Y" ? "active" : "inactive";
await storage.updatePatient(patient.id, { status: newStatus });
result.patientUpdateStatus = `Patient status updated to ${newStatus}`;
// ✅ Step 2: Handle PDF Upload
if (result.pdf_path && result.pdf_path.endsWith(".pdf")) {
const pdfBuffer = await fs.readFile(result.pdf_path);
const groupTitle = "Eligibility PDFs";
const groupCategory = "ELIGIBILITY";
let group = await storage.findPdfGroupByPatientTitleAndCategory(
patient.id,
groupTitle,
groupCategory
);
// Step 2b: Create group if it doesnt exist
if (!group) {
group = await storage.createPdfGroup(
patient.id,
groupTitle,
groupCategory
);
}
if (!group?.id) {
throw new Error("PDF group creation failed: missing group ID");
}
await storage.createPdfFile(
group.id,
path.basename(result.pdf_path),
pdfBuffer
);
await fs.unlink(result.pdf_path);
result.pdfUploadStatus = `PDF saved to group: ${group.title}`;
} else {
result.pdfUploadStatus =
"No valid PDF path provided by Selenium, Couldn't upload pdf to server.";
}
} else {
result.patientUpdateStatus =
"Patient not found or missing ID; no update performed";
}
res.json({
patientUpdateStatus: result.patientUpdateStatus,
pdfUploadStatus: result.pdfUploadStatus,
});
} catch (err: any) {
console.error(err);
return res.status(500).json({
error: err.message || "Failed to forward to selenium agent",
});
}
});
export default router;

View File

@@ -0,0 +1,212 @@
import { Router } from "express";
import { Request, Response } from "express";
import { storage } from "../storage";
import { forwardToSeleniumInsuranceEligibilityAgent } from "../services/seleniumInsuranceEligibilityClient";
import fs from "fs/promises";
import path from "path";
import { forwardToSeleniumInsuranceClaimStatusAgent } from "../services/seleniumInsuranceClaimStatusClient";
const router = Router();
router.post("/eligibility-check", async (req: Request, res: Response): Promise<any> => {
if (!req.body.data) {
return res
.status(400)
.json({ error: "Missing Insurance Eligibility data for selenium" });
}
if (!req.user || !req.user.id) {
return res.status(401).json({ error: "Unauthorized: user info missing" });
}
try {
const insuranceEligibilityData = JSON.parse(req.body.data);
const credentials = await storage.getInsuranceCredentialByUserAndSiteKey(
req.user.id,
insuranceEligibilityData.insuranceSiteKey
);
if (!credentials) {
return res.status(404).json({
error:
"No insurance credentials found for this provider, Kindly Update this at Settings Page.",
});
}
const enrichedData = {
...insuranceEligibilityData,
massdhpUsername: credentials.username,
massdhpPassword: credentials.password,
};
const result =
await forwardToSeleniumInsuranceEligibilityAgent(enrichedData);
// ✅ Step 1: Check result and update patient status
const patient = await storage.getPatientByInsuranceId(
insuranceEligibilityData.memberId
);
if (patient && patient.id !== undefined) {
const newStatus = result.eligibility === "Y" ? "active" : "inactive";
await storage.updatePatient(patient.id, { status: newStatus });
result.patientUpdateStatus = `Patient status updated to ${newStatus}`;
// ✅ Step 2: Handle PDF Upload
if (result.pdf_path && result.pdf_path.endsWith(".pdf")) {
const pdfBuffer = await fs.readFile(result.pdf_path);
const groupTitle = "Insurance Status PDFs";
const groupTitleKey = "INSURANCE_STATUS_PDFs"
const groupCategory = "ELIGIBILITY_STATUS";
let group = await storage.findPdfGroupByPatientTitleKeyAndCategory(
patient.id,
groupTitleKey,
groupCategory
);
// Step 2b: Create group if it doesnt exist
if (!group) {
group = await storage.createPdfGroup(
patient.id,
groupTitle,
groupTitleKey,
groupCategory
);
}
if (!group?.id) {
throw new Error("PDF group creation failed: missing group ID");
}
await storage.createPdfFile(
group.id,
path.basename(result.pdf_path),
pdfBuffer
);
await fs.unlink(result.pdf_path);
result.pdfUploadStatus = `PDF saved to group: ${group.title}`;
} else {
result.pdfUploadStatus =
"No valid PDF path provided by Selenium, Couldn't upload pdf to server.";
}
} else {
result.patientUpdateStatus =
"Patient not found or missing ID; no update performed";
}
res.json({
patientUpdateStatus: result.patientUpdateStatus,
pdfUploadStatus: result.pdfUploadStatus,
});
} catch (err: any) {
console.error(err);
return res.status(500).json({
error: err.message || "Failed to forward to selenium agent",
});
}
});
router.post("/claim-status-check", async (req: Request, res: Response): Promise<any> => {
if (!req.body.data) {
return res
.status(400)
.json({ error: "Missing Insurance Status data for selenium" });
}
if (!req.user || !req.user.id) {
return res.status(401).json({ error: "Unauthorized: user info missing" });
}
try {
const insuranceClaimStatusData = JSON.parse(req.body.data);
const credentials = await storage.getInsuranceCredentialByUserAndSiteKey(
req.user.id,
insuranceClaimStatusData.insuranceSiteKey
);
if (!credentials) {
return res.status(404).json({
error:
"No insurance credentials found for this provider, Kindly Update this at Settings Page.",
});
}
const enrichedData = {
...insuranceClaimStatusData,
massdhpUsername: credentials.username,
massdhpPassword: credentials.password,
};
const result =
await forwardToSeleniumInsuranceClaimStatusAgent(enrichedData);
// ✅ Step 1: Check result
const patient = await storage.getPatientByInsuranceId(
insuranceClaimStatusData.memberId
);
if (patient && patient.id !== undefined) {
// ✅ Step 2: Handle PDF Upload
if (result.pdf_path && result.pdf_path.endsWith(".pdf")) {
const pdfBuffer = await fs.readFile(result.pdf_path);
const groupTitle = "Insurance Status PDFs";
const groupTitleKey = "INSURANCE_STATUS_PDFs"
const groupCategory = "CLAIM_STATUS";
let group = await storage.findPdfGroupByPatientTitleKeyAndCategory(
patient.id,
groupTitleKey,
groupCategory
);
// Step 2b: Create group if it doesnt exist
if (!group) {
group = await storage.createPdfGroup(
patient.id,
groupTitle,
groupTitleKey,
groupCategory
);
}
if (!group?.id) {
throw new Error("PDF group creation failed: missing group ID");
}
await storage.createPdfFile(
group.id,
path.basename(result.pdf_path),
pdfBuffer
);
await fs.unlink(result.pdf_path);
result.pdfUploadStatus = `PDF saved to group: ${group.title}`;
} else {
result.pdfUploadStatus =
"No valid PDF path provided by Selenium, Couldn't upload pdf to server.";
}
} else {
result.patientUpdateStatus =
"Patient not found or missing ID; no update performed";
}
res.json({
patientUpdateStatus: result.patientUpdateStatus,
pdfUploadStatus: result.pdfUploadStatus,
});
} catch (err: any) {
console.error(err);
return res.status(500).json({
error: err.message || "Failed to forward to selenium agent",
});
}
});
export default router;