diff --git a/apps/Backend/src/routes/payments.ts b/apps/Backend/src/routes/payments.ts index 1a7bc082..2813e0bb 100755 --- a/apps/Backend/src/routes/payments.ts +++ b/apps/Backend/src/routes/payments.ts @@ -15,6 +15,7 @@ import { import { prisma } from "@repo/db/client"; import { PaymentStatusSchema } from "@repo/db/types"; import * as paymentService from "../services/paymentService"; +import { callPythonSync } from "../queue/processors/_shared"; const paymentFilterSchema = z.object({ from: z.string().datetime(), @@ -426,6 +427,54 @@ router.patch( } ); +// PATCH /api/payments/:id/mh-payment-check +router.patch( + "/:id/mh-payment-check", + async (req: Request, res: Response): Promise => { + try { + const userId = req.user?.id; + if (!userId) return res.status(401).json({ message: "Unauthorized" }); + + const paymentId = parseIntOrError(req.params.id, "Payment ID"); + + const payment = await storage.getPaymentById(paymentId); + if (!payment) return res.status(404).json({ message: "Payment not found" }); + + const claimNumber = payment.claim?.claimNumber; + if (!claimNumber) { + return res.status(400).json({ message: "No claim number found for this payment" }); + } + + const credentials = await storage.getInsuranceCredentialByUserAndSiteKey(userId, "MH"); + if (!credentials) { + return res.status(404).json({ + message: "No MassHealth credentials found. Please add them in Settings.", + }); + } + + const seleniumResult = await callPythonSync("/mh-payment-check", { + data: { + massdhpUsername: credentials.username, + massdhpPassword: credentials.password, + claimNumber, + }, + }); + + const mhPaidAmount = seleniumResult?.mhPaidAmount ?? 0; + + const updated = await prisma.payment.update({ + where: { id: paymentId }, + data: { mhPaidAmount, updatedById: userId }, + }); + + return res.json({ ...updated, mhPaidAmount: Number(updated.mhPaidAmount) }); + } catch (err: unknown) { + const message = err instanceof Error ? err.message : "MH payment check failed"; + return res.status(500).json({ message }); + } + } +); + // DELETE /api/payments/:id router.delete("/:id", async (req: Request, res: Response): Promise => { try { diff --git a/apps/Frontend/src/components/payments/payments-recent-table.tsx b/apps/Frontend/src/components/payments/payments-recent-table.tsx index 061258c6..2f195754 100755 --- a/apps/Frontend/src/components/payments/payments-recent-table.tsx +++ b/apps/Frontend/src/components/payments/payments-recent-table.tsx @@ -98,6 +98,7 @@ export default function PaymentsRecentTable({ >(undefined); const [selectedPaymentId, setSelectedPaymentId] = useState(null); const [checkedPaymentIds, setCheckedPaymentIds] = useState>(new Set()); + const [isMhChecking, setIsMhChecking] = useState(false); const [isRevertOpen, setIsRevertOpen] = useState(false); const [revertPaymentId, setRevertPaymentId] = useState(null); @@ -517,11 +518,44 @@ export default function PaymentsRecentTable({