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:
@@ -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 };
|
||||
Reference in New Issue
Block a user