feat: add Check MH Payment automation and MH Paid column

- Add selenium_MHPaymentCheckWorker.py: logs into MassHealth portal, navigates to Search Claims, enters claim number, extracts totalPaidAmount from results table
- Register /mh-payment-check endpoint in Selenium agent
- Add mhPaidAmount field to Payment model with migration
- Add PATCH /api/payments/:id/mh-payment-check backend route: fetches MH credentials, calls selenium, stores result
- Add Claim No. column (MassHealth claim number) as first data column in payments table
- Move Payment ID and Claim ID columns to end of table
- Add MH Paid column showing mhPaidAmount in green
- Wire Check MH Payment button to call API for each selected payment and refresh table

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Gitead
2026-05-06 15:12:56 -04:00
parent 4989201c62
commit 1196e2afee
6 changed files with 364 additions and 14 deletions

View File

@@ -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<any> => {
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<any> => {
try {