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:
@@ -98,6 +98,7 @@ export default function PaymentsRecentTable({
|
||||
>(undefined);
|
||||
const [selectedPaymentId, setSelectedPaymentId] = useState<number | null>(null);
|
||||
const [checkedPaymentIds, setCheckedPaymentIds] = useState<Set<number>>(new Set());
|
||||
const [isMhChecking, setIsMhChecking] = useState(false);
|
||||
|
||||
const [isRevertOpen, setIsRevertOpen] = useState(false);
|
||||
const [revertPaymentId, setRevertPaymentId] = useState<number | null>(null);
|
||||
@@ -517,11 +518,44 @@ export default function PaymentsRecentTable({
|
||||
<Button
|
||||
size="sm"
|
||||
variant="default"
|
||||
onClick={() => {
|
||||
// Logic to be defined later
|
||||
disabled={isMhChecking}
|
||||
onClick={async () => {
|
||||
setIsMhChecking(true);
|
||||
let successCount = 0;
|
||||
let failCount = 0;
|
||||
for (const paymentId of checkedPaymentIds) {
|
||||
try {
|
||||
const res = await apiRequest(
|
||||
"PATCH",
|
||||
`/api/payments/${paymentId}/mh-payment-check`
|
||||
);
|
||||
if (res.ok) {
|
||||
successCount++;
|
||||
} else {
|
||||
const err = await res.json();
|
||||
console.error(`MH check failed for payment ${paymentId}:`, err.message);
|
||||
failCount++;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`MH check error for payment ${paymentId}:`, e);
|
||||
failCount++;
|
||||
}
|
||||
}
|
||||
setIsMhChecking(false);
|
||||
setCheckedPaymentIds(new Set());
|
||||
await queryClient.invalidateQueries({ queryKey: QK_PAYMENTS_RECENT_BASE });
|
||||
if (failCount === 0) {
|
||||
toast({ title: "MH Payment Check Complete", description: `${successCount} record(s) updated.` });
|
||||
} else {
|
||||
toast({
|
||||
title: "MH Payment Check Done",
|
||||
description: `${successCount} succeeded, ${failCount} failed. Check credentials or claim numbers.`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
Check MH Payment
|
||||
{isMhChecking ? "Checking..." : "Check MH Payment"}
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
@@ -548,14 +582,16 @@ export default function PaymentsRecentTable({
|
||||
/>
|
||||
</TableHead>
|
||||
)}
|
||||
<TableHead>Payment ID</TableHead>
|
||||
<TableHead>Claim ID</TableHead>
|
||||
<TableHead>Claim No.</TableHead>
|
||||
<TableHead>Patient Name</TableHead>
|
||||
<TableHead>Amount</TableHead>
|
||||
<TableHead>Service Date</TableHead>
|
||||
<TableHead>Status</TableHead>
|
||||
<TableHead>Attachments</TableHead>
|
||||
<TableHead>MH Paid</TableHead>
|
||||
<TableHead className="text-right">Actions</TableHead>
|
||||
<TableHead>Payment ID</TableHead>
|
||||
<TableHead>Claim ID</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
@@ -612,15 +648,9 @@ export default function PaymentsRecentTable({
|
||||
</TableCell>
|
||||
)}
|
||||
<TableCell>
|
||||
{typeof payment.id === "number"
|
||||
? `PAY-${payment.id.toString().padStart(4, "0")}`
|
||||
: "N/A"}
|
||||
</TableCell>
|
||||
|
||||
<TableCell>
|
||||
{typeof payment.claimId === "number"
|
||||
? `CLM-${payment.claimId.toString().padStart(4, "0")}`
|
||||
: "N/A"}
|
||||
<span className="text-sm font-mono">
|
||||
{payment.claim?.claimNumber ?? <span className="text-gray-400">—</span>}
|
||||
</span>
|
||||
</TableCell>
|
||||
|
||||
<TableCell>
|
||||
@@ -710,6 +740,16 @@ export default function PaymentsRecentTable({
|
||||
)}
|
||||
</TableCell>
|
||||
|
||||
<TableCell>
|
||||
{payment.mhPaidAmount != null ? (
|
||||
<span className="text-sm font-medium text-green-700">
|
||||
${Number(payment.mhPaidAmount).toFixed(2)}
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-xs text-gray-400">—</span>
|
||||
)}
|
||||
</TableCell>
|
||||
|
||||
<TableCell className="text-right">
|
||||
<div className="flex justify-end space-x-2">
|
||||
{allowDelete && (
|
||||
@@ -795,6 +835,18 @@ export default function PaymentsRecentTable({
|
||||
)}
|
||||
</div>
|
||||
</TableCell>
|
||||
|
||||
<TableCell className="text-xs text-gray-500">
|
||||
{typeof payment.id === "number"
|
||||
? `PAY-${payment.id.toString().padStart(4, "0")}`
|
||||
: "N/A"}
|
||||
</TableCell>
|
||||
|
||||
<TableCell className="text-xs text-gray-500">
|
||||
{typeof payment.claimId === "number"
|
||||
? `CLM-${payment.claimId.toString().padStart(4, "0")}`
|
||||
: "N/A"}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user