feat(ocr payment page) - added backend routes on app

This commit is contained in:
2025-08-30 01:11:59 +05:30
parent e5271d6979
commit c5edac2ab8
19 changed files with 314 additions and 109 deletions

View File

@@ -3,14 +3,15 @@ import patientsRoutes from "./patients";
import appointmentsRoutes from "./appointments";
import usersRoutes from "./users";
import staffsRoutes from "./staffs";
import pdfExtractionRoutes from "./pdfExtraction";
import claimsRoutes from "./claims";
import patientDataExtractionRoutes from "./patientdataExtraction";
import insuranceCredsRoutes from "./insuranceCreds";
import documentsRoutes from "./documents";
import insuranceEligibilityRoutes from "./insuranceEligibility";
import paymentsRoutes from "./payments";
import databaseManagementRoutes from "./database-management";
import notificationsRoutes from "./notifications";
import paymentOcrRoutes from "./paymentOcrExtraction";
const router = Router();
@@ -18,7 +19,7 @@ router.use("/patients", patientsRoutes);
router.use("/appointments", appointmentsRoutes);
router.use("/users", usersRoutes);
router.use("/staffs", staffsRoutes);
router.use("/pdfExtraction", pdfExtractionRoutes);
router.use("/patientDataExtraction", patientDataExtractionRoutes);
router.use("/claims", claimsRoutes);
router.use("/insuranceCreds", insuranceCredsRoutes);
router.use("/documents", documentsRoutes);
@@ -26,5 +27,6 @@ router.use("/insuranceEligibility", insuranceEligibilityRoutes);
router.use("/payments", paymentsRoutes);
router.use("/database-management", databaseManagementRoutes);
router.use("/notifications", notificationsRoutes);
router.use("/payment-ocr", paymentOcrRoutes);
export default router;

View File

@@ -2,17 +2,17 @@ import { Router } from "express";
import type { Request, Response } from "express";
const router = Router();
import multer from "multer";
import forwardToPdfService from "../services/pdfClient";
import forwardToPatientDataExtractorService from "../services/patientDataExtractorService";
const upload = multer({ storage: multer.memoryStorage() });
router.post("/extract", upload.single("pdf"), async (req: Request, res: Response): Promise<any>=> {
router.post("/patientdataextract", upload.single("pdf"), async (req: Request, res: Response): Promise<any>=> {
if (!req.file) {
return res.status(400).json({ error: "No PDF file uploaded." });
}
try {
const result = await forwardToPdfService(req.file);
const result = await forwardToPatientDataExtractorService(req.file);
res.json(result);
} catch (err) {
console.error(err);

View File

@@ -0,0 +1,50 @@
import { Router, Request, Response } from "express";
import multer from "multer";
import { forwardToPaymentOCRService } from "../services/paymentOCRService";
const router = Router();
// keep files in memory; FastAPI accepts them as multipart bytes
const upload = multer({ storage: multer.memoryStorage() });
// POST /payment-ocr/extract (field name: "files")
router.post(
"/extract",
upload.array("files"), // allow multiple images
async (req: Request, res: Response): Promise<any> => {
try {
const files = req.files as Express.Multer.File[] | undefined;
if (!files || files.length === 0) {
return res
.status(400)
.json({ error: "No image files uploaded. Use field name 'files'." });
}
// (optional) basic client-side MIME guard
const allowed = new Set([
"image/jpeg",
"image/png",
"image/tiff",
"image/bmp",
"image/jpg",
]);
const bad = files.filter((f) => !allowed.has(f.mimetype.toLowerCase()));
if (bad.length) {
return res.status(415).json({
error: `Unsupported file types: ${bad
.map((b) => b.originalname)
.join(", ")}`,
});
}
const rows = await forwardToPaymentOCRService(files);
return res.json({ rows });
} catch (err) {
console.error(err);
return res.status(500).json({ error: "Payment OCR extraction failed" });
}
}
);
export default router;

View File

@@ -9,7 +9,7 @@ export interface ExtractedData {
[key: string]: any;
}
export default async function forwardToPdfService(
export default async function forwardToPatientDataExtractorService(
file: Express.Multer.File
): Promise<ExtractedData> {
const form = new FormData();

View File

@@ -0,0 +1,34 @@
import axios from "axios";
import FormData from "form-data";
export async function forwardToPaymentOCRService(
files: Express.Multer.File | Express.Multer.File[]
): Promise<any> {
const arr = Array.isArray(files) ? files : [files];
const form = new FormData();
for (const f of arr) {
form.append("files", f.buffer, {
filename: f.originalname,
contentType: f.mimetype, // image/jpeg, image/png, image/tiff, etc.
knownLength: f.size,
});
}
const url = `http://localhost:5003/extract/json`;
try {
const resp = await axios.post<{ rows: any }>(url, form, {
headers: form.getHeaders(),
maxBodyLength: Infinity,
maxContentLength: Infinity,
timeout: 120000, // OCR can be heavy; adjust as needed
});
return resp.data?.rows ?? [];
} catch (err: any) {
// Bubble up a useful error message
const status = err?.response?.status;
const detail = err?.response?.data?.detail || err?.message || "Unknown error";
throw new Error(`Payment OCR request failed${status ? ` (${status})` : ""}: ${detail}`);
}
}