feat: add CCA claim submission with Selenium automation

- Add CCA claim submit Selenium worker (login, fill form, attach docs, submit, capture dashboard PDF)
- Add CCA fee schedule (procedureCodesMH.json renamed, procedureCodesCCA.json added with D6010)
- Add backend route /api/claims/cca-claim, processor, and Selenium client
- Wire CCA claim handler in claims-page with job tracking and PDF preview popup
- Add insurance type dropdown in claim form (same options as eligibility page)
- Auto-populate insurance type from patient.insuranceProvider in claim form and patient edit form
- Map fee schedule by insurance type in Map Price button and combo buttons
- Fix CCA login speed (remove fixed sleeps, use readyState check)
- Fix CCA claim DOB format bug (was sending MM-DD-YYYY, now sends YYYY-MM-DD)
- Fix npiProviderId not saved for CCA claims
- Change Add Service → CCA Claim button (blue), MH → MH Claim

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Gitead
2026-05-22 13:34:03 -04:00
parent 58b2e4af93
commit 0e664e4813
21 changed files with 4768 additions and 77 deletions

View File

@@ -1,6 +1,7 @@
import { InputServiceLine } from "@repo/db/types";
import Decimal from "decimal.js";
import rawCodeTable from "@/assets/data/procedureCodes.json";
import rawCodeTable from "@/assets/data/procedureCodesMH.json";
import rawCCACodeTable from "@/assets/data/procedureCodesCCA.json";
import { PROCEDURE_COMBOS } from "./procedureCombos";
/* ----------------------------- Types ----------------------------- */
@@ -13,6 +14,7 @@ export type CodeRow = {
[k: string]: unknown;
};
const CODE_TABLE = rawCodeTable as CodeRow[];
const CCA_CODE_TABLE = rawCCACodeTable as CodeRow[];
export type ClaimFormLike = {
serviceDate: string; // form-level service date
@@ -45,6 +47,21 @@ const CODE_MAP: Map<string, CodeRow> = (() => {
return m;
})();
const CCA_CODE_MAP: Map<string, CodeRow> = (() => {
const m = new Map<string, CodeRow>();
for (const r of CCA_CODE_TABLE) {
const k = normalizeCode(String(r["Procedure Code"] || ""));
if (k && !m.has(k)) m.set(k, r);
}
return m;
})();
/** Return the correct fee-schedule map for the given insurance type. */
function getCodeMap(insuranceSiteKey?: string): Map<string, CodeRow> {
if (insuranceSiteKey === "CCA") return CCA_CODE_MAP;
return CODE_MAP; // default: MassHealth
}
// this function is solely for abbrevations feature in claim-form
export function getDescriptionForCode(
code: string | undefined
@@ -209,15 +226,17 @@ const ensureCapacity = (
export function mapPricesForForm<T extends ClaimFormLike>(params: {
form: T;
patientDOB: DateInput;
insuranceSiteKey?: string;
}): T {
const { form, patientDOB } = params;
const { form, patientDOB, insuranceSiteKey } = params;
const map = getCodeMap(insuranceSiteKey);
return {
...form,
serviceLines: form.serviceLines.map((ln) => {
const age = ageOnDate(patientDOB, form.serviceDate);
const code = normalizeCode(ln.procedureCode || "");
if (!code) return { ...ln };
const price = getPriceForCodeWithAgeFromMap(CODE_MAP, code, age);
const price = getPriceForCodeWithAgeFromMap(map, code, age);
return { ...ln, procedureCode: code, totalBilled: price };
}),
};
@@ -231,7 +250,8 @@ export function applyComboToForm<T extends ClaimFormLike>(
form: T,
comboId: keyof typeof PROCEDURE_COMBOS,
patientDOB: DateInput,
options: ApplyOptions = {}
options: ApplyOptions = {},
insuranceSiteKey?: string
): T {
const preset = PROCEDURE_COMBOS[String(comboId)];
if (!preset) return form;
@@ -275,6 +295,7 @@ export function applyComboToForm<T extends ClaimFormLike>(
// Age on the specific line date we will set
const age = ageOnDate(patientDOB, lineDate);
const map = getCodeMap(insuranceSiteKey);
for (let j = 0; j < preset.codes.length; j++) {
const i = insertAt + j;
@@ -283,7 +304,7 @@ export function applyComboToForm<T extends ClaimFormLike>(
const codeRaw = preset.codes[j];
if (!codeRaw) continue;
const code = normalizeCode(codeRaw);
const price = getPriceForCodeWithAgeFromMap(CODE_MAP, code, age);
const price = getPriceForCodeWithAgeFromMap(map, code, age);
const original = next.serviceLines[i];
@@ -312,4 +333,4 @@ export function applyComboToForm<T extends ClaimFormLike>(
}
export { CODE_MAP, getPriceForCodeWithAgeFromMap };
export { CODE_MAP, CCA_CODE_MAP, getCodeMap, getPriceForCodeWithAgeFromMap };