fixes - dob state fixed, combo added
This commit is contained in:
@@ -47,6 +47,8 @@ import {
|
|||||||
getDescriptionForCode,
|
getDescriptionForCode,
|
||||||
} from "@/utils/procedureCombosMapping";
|
} from "@/utils/procedureCombosMapping";
|
||||||
import { COMBO_CATEGORIES, PROCEDURE_COMBOS } from "@/utils/procedureCombos";
|
import { COMBO_CATEGORIES, PROCEDURE_COMBOS } from "@/utils/procedureCombos";
|
||||||
|
import { DateInputField } from "../ui/dateInputField";
|
||||||
|
import { DateInput } from "../ui/dateInput";
|
||||||
|
|
||||||
interface ClaimFileMeta {
|
interface ClaimFileMeta {
|
||||||
filename: string;
|
filename: string;
|
||||||
@@ -251,22 +253,86 @@ export function ClaimForm({
|
|||||||
}, [serviceDate]);
|
}, [serviceDate]);
|
||||||
|
|
||||||
// Determine patient date of birth format - required as date extracted from pdfs has different format.
|
// Determine patient date of birth format - required as date extracted from pdfs has different format.
|
||||||
const formatDOB = (dob: string | Date | undefined) => {
|
// Replace previous implementation with this type-safe normalizer.
|
||||||
|
// Always returns canonical YYYY-MM-DD or "" if it cannot parse.
|
||||||
|
function normalizeToIsoDateString(dob: string | Date | undefined): string {
|
||||||
if (!dob) return "";
|
if (!dob) return "";
|
||||||
|
|
||||||
const normalized = formatLocalDate(parseLocalDate(dob));
|
// Date object -> canonicalize
|
||||||
|
if (dob instanceof Date) {
|
||||||
// If it's already MM/DD/YYYY, leave it alone
|
if (isNaN(dob.getTime())) return "";
|
||||||
if (/^\d{2}\/\d{2}\/\d{4}$/.test(normalized)) return normalized;
|
return formatLocalDate(dob);
|
||||||
|
|
||||||
// If it's yyyy-MM-dd, swap order to MM/DD/YYYY
|
|
||||||
if (/^\d{4}-\d{2}-\d{2}$/.test(normalized)) {
|
|
||||||
const [year, month, day] = normalized.split("-");
|
|
||||||
return `${month}/${day}/${year}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return normalized;
|
const raw = String(dob).trim();
|
||||||
};
|
if (!raw) return "";
|
||||||
|
|
||||||
|
// 1) If already date-only ISO (yyyy-mm-dd)
|
||||||
|
if (/^\d{4}-\d{2}-\d{2}$/.test(raw)) {
|
||||||
|
try {
|
||||||
|
parseLocalDate(raw); // validate
|
||||||
|
return raw;
|
||||||
|
} catch {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Try parseLocalDate for ISO-like inputs (will throw if not suitable)
|
||||||
|
try {
|
||||||
|
const parsed = parseLocalDate(raw);
|
||||||
|
return formatLocalDate(parsed);
|
||||||
|
} catch {
|
||||||
|
// continue to other fallbacks
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3) MM/DD/YYYY or M/D/YYYY -> convert to ISO
|
||||||
|
const m1 = raw.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/);
|
||||||
|
if (m1) {
|
||||||
|
const mm = m1[1] ?? "";
|
||||||
|
const dd = m1[2] ?? "";
|
||||||
|
const yyyy = m1[3] ?? "";
|
||||||
|
if (mm && dd && yyyy) {
|
||||||
|
const iso = `${yyyy}-${mm.padStart(2, "0")}-${dd.padStart(2, "0")}`;
|
||||||
|
try {
|
||||||
|
parseLocalDate(iso);
|
||||||
|
return iso;
|
||||||
|
} catch {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4) OCR-ish short form: MMDDYY (exactly 6 digits) -> guess century
|
||||||
|
const m2 = raw.match(/^(\d{6})$/);
|
||||||
|
if (m2) {
|
||||||
|
const s = m2[1];
|
||||||
|
if (s && s.length === 6) {
|
||||||
|
const mm = s.slice(0, 2);
|
||||||
|
const dd = s.slice(2, 4);
|
||||||
|
const yy = s.slice(4, 6);
|
||||||
|
const year = Number(yy) < 50 ? 2000 + Number(yy) : 1900 + Number(yy);
|
||||||
|
const iso = `${year}-${mm.padStart(2, "0")}-${dd.padStart(2, "0")}`;
|
||||||
|
try {
|
||||||
|
parseLocalDate(iso);
|
||||||
|
return iso;
|
||||||
|
} catch {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5) Last resort: naive Date parse -> normalize to local calendar fields
|
||||||
|
try {
|
||||||
|
const maybe = new Date(raw);
|
||||||
|
if (!isNaN(maybe.getTime())) {
|
||||||
|
return formatLocalDate(maybe);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
// MAIN FORM INITIAL STATE
|
// MAIN FORM INITIAL STATE
|
||||||
const [form, setForm] = useState<ClaimFormData & { uploadedFiles: File[] }>({
|
const [form, setForm] = useState<ClaimFormData & { uploadedFiles: File[] }>({
|
||||||
@@ -276,7 +342,7 @@ export function ClaimForm({
|
|||||||
staffId: Number(staff?.id),
|
staffId: Number(staff?.id),
|
||||||
patientName: `${patient?.firstName} ${patient?.lastName}`.trim(),
|
patientName: `${patient?.firstName} ${patient?.lastName}`.trim(),
|
||||||
memberId: patient?.insuranceId ?? "",
|
memberId: patient?.insuranceId ?? "",
|
||||||
dateOfBirth: formatDOB(patient?.dateOfBirth),
|
dateOfBirth: normalizeToIsoDateString(patient?.dateOfBirth),
|
||||||
remarks: "",
|
remarks: "",
|
||||||
serviceDate: serviceDate,
|
serviceDate: serviceDate,
|
||||||
insuranceProvider: "",
|
insuranceProvider: "",
|
||||||
@@ -304,7 +370,7 @@ export function ClaimForm({
|
|||||||
...prev,
|
...prev,
|
||||||
patientId: Number(patient.id),
|
patientId: Number(patient.id),
|
||||||
patientName: fullName,
|
patientName: fullName,
|
||||||
dateOfBirth: formatDOB(patient.dateOfBirth),
|
dateOfBirth: normalizeToIsoDateString(patient.dateOfBirth),
|
||||||
memberId: patient.insuranceId || "",
|
memberId: patient.insuranceId || "",
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -406,6 +472,20 @@ export function ClaimForm({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// require at least one procedure code before proceeding
|
||||||
|
const filteredServiceLines = (f.serviceLines || []).filter(
|
||||||
|
(line) => (line.procedureCode ?? "").trim() !== ""
|
||||||
|
);
|
||||||
|
if (filteredServiceLines.length === 0) {
|
||||||
|
toast({
|
||||||
|
title: "No procedure codes",
|
||||||
|
description:
|
||||||
|
"Please add at least one procedure code before submitting the claim.",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 1. Create or update appointment
|
// 1. Create or update appointment
|
||||||
let appointmentIdToUse = appointmentId;
|
let appointmentIdToUse = appointmentId;
|
||||||
|
|
||||||
@@ -443,9 +523,6 @@ export function ClaimForm({
|
|||||||
|
|
||||||
// 3. Create Claim(if not)
|
// 3. Create Claim(if not)
|
||||||
// Filter out empty service lines (empty procedureCode)
|
// Filter out empty service lines (empty procedureCode)
|
||||||
const filteredServiceLines = f.serviceLines.filter(
|
|
||||||
(line) => line.procedureCode.trim() !== ""
|
|
||||||
);
|
|
||||||
const { uploadedFiles, insuranceSiteKey, ...formToCreateClaim } = f;
|
const { uploadedFiles, insuranceSiteKey, ...formToCreateClaim } = f;
|
||||||
|
|
||||||
// build claimFiles metadata from uploadedFiles (only filename + mimeType)
|
// build claimFiles metadata from uploadedFiles (only filename + mimeType)
|
||||||
@@ -498,6 +575,20 @@ export function ClaimForm({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// require at least one procedure code before proceeding
|
||||||
|
const filteredServiceLines = (form.serviceLines || []).filter(
|
||||||
|
(line) => (line.procedureCode ?? "").trim() !== ""
|
||||||
|
);
|
||||||
|
if (filteredServiceLines.length === 0) {
|
||||||
|
toast({
|
||||||
|
title: "No procedure codes",
|
||||||
|
description:
|
||||||
|
"Please add at least one procedure code before submitting the claim.",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 1. Create or update appointment
|
// 1. Create or update appointment
|
||||||
let appointmentIdToUse = appointmentId;
|
let appointmentIdToUse = appointmentId;
|
||||||
|
|
||||||
@@ -535,9 +626,6 @@ export function ClaimForm({
|
|||||||
|
|
||||||
// 3. Create Claim(if not)
|
// 3. Create Claim(if not)
|
||||||
// Filter out empty service lines (empty procedureCode)
|
// Filter out empty service lines (empty procedureCode)
|
||||||
const filteredServiceLines = form.serviceLines.filter(
|
|
||||||
(line) => line.procedureCode.trim() !== ""
|
|
||||||
);
|
|
||||||
const { uploadedFiles, insuranceSiteKey, ...formToCreateClaim } = form;
|
const { uploadedFiles, insuranceSiteKey, ...formToCreateClaim } = form;
|
||||||
|
|
||||||
// build claimFiles metadata from uploadedFiles (only filename + mimeType)
|
// build claimFiles metadata from uploadedFiles (only filename + mimeType)
|
||||||
@@ -608,24 +696,24 @@ export function ClaimForm({
|
|||||||
<Input
|
<Input
|
||||||
id="memberId"
|
id="memberId"
|
||||||
value={form.memberId}
|
value={form.memberId}
|
||||||
onChange={(e) =>
|
onChange={(e) => {
|
||||||
setForm({ ...form, memberId: e.target.value })
|
setForm({ ...form, memberId: e.target.value });
|
||||||
}
|
updatePatientField("insuranceId", e.target.value);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Label htmlFor="dateOfBirth">Date Of Birth</Label>
|
<Label htmlFor="dateOfBirth">Date Of Birth</Label>
|
||||||
<Input
|
<DateInput
|
||||||
id="dateOfBirth"
|
value={
|
||||||
value={form.dateOfBirth}
|
form.dateOfBirth ? parseLocalDate(form.dateOfBirth) : null
|
||||||
onChange={(e) => {
|
}
|
||||||
updatePatientField("dateOfBirth", e.target.value);
|
onChange={(date: Date | null) => {
|
||||||
setForm((prev) => ({
|
const formatted = date ? formatLocalDate(date) : "";
|
||||||
...prev,
|
setForm((prev) => ({ ...prev, dateOfBirth: formatted }));
|
||||||
dateOfBirth: e.target.value,
|
updatePatientField("dateOfBirth", formatted);
|
||||||
}));
|
|
||||||
}}
|
}}
|
||||||
disabled={isLoading}
|
disableFuture
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -782,7 +870,7 @@ export function ClaimForm({
|
|||||||
"childRecallDirect4BW",
|
"childRecallDirect4BW",
|
||||||
"childRecallDirect2PA2BW",
|
"childRecallDirect2PA2BW",
|
||||||
"childRecallDirect2PA4BW",
|
"childRecallDirect2PA4BW",
|
||||||
"childRecallDirectPANO2PA2BW",
|
"childRecallDirectPANO",
|
||||||
].map((comboId) => {
|
].map((comboId) => {
|
||||||
const b = PROCEDURE_COMBOS[comboId];
|
const b = PROCEDURE_COMBOS[comboId];
|
||||||
if (!b) return null;
|
if (!b) return null;
|
||||||
@@ -797,7 +885,7 @@ export function ClaimForm({
|
|||||||
childRecallDirect4BW: "Direct 4BW",
|
childRecallDirect4BW: "Direct 4BW",
|
||||||
childRecallDirect2PA2BW: "Direct 2PA 2BW",
|
childRecallDirect2PA2BW: "Direct 2PA 2BW",
|
||||||
childRecallDirect2PA4BW: "Direct 2PA 4BW",
|
childRecallDirect2PA4BW: "Direct 2PA 4BW",
|
||||||
childRecallDirectPANO2PA2BW: "Direct PANO 2PA 2BW",
|
childRecallDirectPANO: "Direct Pano",
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Tooltip key={b.id}>
|
<Tooltip key={b.id}>
|
||||||
@@ -829,9 +917,10 @@ export function ClaimForm({
|
|||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2">
|
||||||
{[
|
{[
|
||||||
"adultRecallDirect",
|
"adultRecallDirect",
|
||||||
"adultRecallDirect2bw",
|
"adultRecallDirect2BW",
|
||||||
"adultRecallDirect4bw",
|
"adultRecallDirect4BW",
|
||||||
"adultRecallDirect4bw2pa",
|
"adultRecallDirect2PA2BW",
|
||||||
|
"adultRecallDirect2PA4BW",
|
||||||
"adultRecallDirectPano",
|
"adultRecallDirectPano",
|
||||||
].map((comboId) => {
|
].map((comboId) => {
|
||||||
const b = PROCEDURE_COMBOS[comboId];
|
const b = PROCEDURE_COMBOS[comboId];
|
||||||
@@ -843,9 +932,10 @@ export function ClaimForm({
|
|||||||
const tooltipText = codesWithTooth.join(", ");
|
const tooltipText = codesWithTooth.join(", ");
|
||||||
const labelMap: Record<string, string> = {
|
const labelMap: Record<string, string> = {
|
||||||
adultRecallDirect: "Direct",
|
adultRecallDirect: "Direct",
|
||||||
adultRecallDirect2bw: "Direct 2BW",
|
adultRecallDirect2BW: "Direct 2BW",
|
||||||
adultRecallDirect4bw: "Direct 4BW",
|
adultRecallDirect4BW: "Direct 4BW",
|
||||||
adultRecallDirect4bw2pa: "Direct 4BW2PA",
|
adultRecallDirect2PA2BW: "Direct 2PA 2BW",
|
||||||
|
adultRecallDirect2PA4BW: "Direct 2PA 4BW",
|
||||||
adultRecallDirectPano: "Direct Pano",
|
adultRecallDirectPano: "Direct Pano",
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import {
|
|||||||
UpdatePatient,
|
UpdatePatient,
|
||||||
} from "@repo/db/types";
|
} from "@repo/db/types";
|
||||||
import ClaimDocumentsUploadMultiple from "@/components/claims/claim-document-upload-modal";
|
import ClaimDocumentsUploadMultiple from "@/components/claims/claim-document-upload-modal";
|
||||||
|
import { QK_PATIENTS_BASE } from "@/components/patients/patient-table";
|
||||||
|
|
||||||
export default function ClaimsPage() {
|
export default function ClaimsPage() {
|
||||||
const [isClaimFormOpen, setIsClaimFormOpen] = useState(false);
|
const [isClaimFormOpen, setIsClaimFormOpen] = useState(false);
|
||||||
@@ -64,6 +65,8 @@ export default function ClaimsPage() {
|
|||||||
description: "Patient updated successfully!",
|
description: "Patient updated successfully!",
|
||||||
variant: "default",
|
variant: "default",
|
||||||
});
|
});
|
||||||
|
queryClient.invalidateQueries({ queryKey: QK_CLAIMS_BASE });
|
||||||
|
queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE });
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
toast({
|
toast({
|
||||||
|
|||||||
@@ -39,9 +39,9 @@ export const PROCEDURE_COMBOS: Record<
|
|||||||
codes: ["D0120", "D1120", "D1208", "D0220", "D0230", "D0274"],
|
codes: ["D0120", "D1120", "D1208", "D0220", "D0230", "D0274"],
|
||||||
toothNumbers: [null, null, null, "9", "24", null], // only these two need values
|
toothNumbers: [null, null, null, "9", "24", null], // only these two need values
|
||||||
},
|
},
|
||||||
childRecallDirectPANO2PA2BW: {
|
childRecallDirectPANO: {
|
||||||
id: "childRecallDirectPANO2PA2BW",
|
id: "childRecallDirectPANO",
|
||||||
label: "Child Recall Direct PANO 2PA 2BW",
|
label: "Child Recall Direct PANO",
|
||||||
codes: ["D0120", "D1120", "D1208", "D0330"],
|
codes: ["D0120", "D1120", "D1208", "D0330"],
|
||||||
},
|
},
|
||||||
adultRecall: {
|
adultRecall: {
|
||||||
@@ -55,25 +55,31 @@ export const PROCEDURE_COMBOS: Record<
|
|||||||
label: "Adult Recall Direct(no x-ray)",
|
label: "Adult Recall Direct(no x-ray)",
|
||||||
codes: ["D0120", "D1110"],
|
codes: ["D0120", "D1110"],
|
||||||
},
|
},
|
||||||
adultRecallDirect2bw: {
|
adultRecallDirect2BW: {
|
||||||
id: "adultRecallDirect2bw",
|
id: "adultRecallDirect2BW",
|
||||||
label: "Adult Recall Direct - 2bw (no x-ray)",
|
label: "Adult Recall Direct - 2bw (no x-ray)",
|
||||||
codes: ["D0120", "D1110", "D0272"],
|
codes: ["D0120", "D1110", "D0272"],
|
||||||
},
|
},
|
||||||
adultRecallDirect4bw: {
|
adultRecallDirect4BW: {
|
||||||
id: "adultRecallDirect4bw",
|
id: "adultRecallDirect4BW",
|
||||||
label: "Adult Recall Direct - 4bw (no x-ray)",
|
label: "Adult Recall Direct - 4bw (no x-ray)",
|
||||||
codes: ["D0120", "D1110", "D0274"],
|
codes: ["D0120", "D1110", "D0274"],
|
||||||
},
|
},
|
||||||
adultRecallDirect4bw2pa: {
|
adultRecallDirect2PA2BW: {
|
||||||
id: "adultRecallDirect4bw",
|
id: "adultRecallDirect2PA2BW",
|
||||||
label: "Adult Recall Direct - 4bw (no x-ray)",
|
label: "Adult Recall Direct - 2PA 2BW",
|
||||||
|
codes: ["D0120", "D0220", "D0230", "D0272", "D1110"],
|
||||||
|
toothNumbers: [null, "9", "24", null, null], // only these two need values
|
||||||
|
},
|
||||||
|
adultRecallDirect2PA4BW: {
|
||||||
|
id: "adultRecallDirect2PA4BW",
|
||||||
|
label: "Adult Recall Direct - 2PA 4BW",
|
||||||
codes: ["D0120", "D0220", "D0230", "D0274", "D1110"],
|
codes: ["D0120", "D0220", "D0230", "D0274", "D1110"],
|
||||||
toothNumbers: [null, "9", "24", null, null], // only these two need values
|
toothNumbers: [null, "9", "24", null, null], // only these two need values
|
||||||
},
|
},
|
||||||
adultRecallDirectPano: {
|
adultRecallDirectPano: {
|
||||||
id: "adultRecallDirectPano",
|
id: "adultRecallDirectPano",
|
||||||
label: "Adult Recall Direct - Pano",
|
label: "Adult Recall Direct - PANO",
|
||||||
codes: ["D0120", "D1110", "D0330"],
|
codes: ["D0120", "D1110", "D0330"],
|
||||||
},
|
},
|
||||||
newChildPatient: {
|
newChildPatient: {
|
||||||
@@ -83,7 +89,7 @@ export const PROCEDURE_COMBOS: Record<
|
|||||||
},
|
},
|
||||||
newAdultPatientPano: {
|
newAdultPatientPano: {
|
||||||
id: "newAdultPatientPano",
|
id: "newAdultPatientPano",
|
||||||
label: "New Adult Patient (Pano)",
|
label: "New Adult Patient - PANO",
|
||||||
codes: ["D0150", "D0330", "D1110"],
|
codes: ["D0150", "D0330", "D1110"],
|
||||||
},
|
},
|
||||||
newAdultPatientFMX: {
|
newAdultPatientFMX: {
|
||||||
|
|||||||
@@ -107,17 +107,56 @@ const ageOnDate = (dob: DateInput, on: DateInput): number => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Price chooser that respects your age rules and IC/NC semantics.
|
* we can implement per-code age buckets without changing the JSON.
|
||||||
* - If <=21 → PriceLTEQ21 (if present and not IC/NC/blank) else Price.
|
*
|
||||||
* - If >21 → PriceGT21 (if present and not IC/NC/blank) else Price.
|
* Behavior:
|
||||||
* - If chosen field is IC/NC/blank → 0 (leave empty).
|
* - Default: same as before: age <= 21 -> PriceLTEQ21, else PriceGT21
|
||||||
|
* - Fallback to Price if tiered field is blank/IC/NC
|
||||||
|
* - Special-cases D1110 and D1120 according to MH rules
|
||||||
*/
|
*/
|
||||||
export function pickPriceForRowByAge(row: CodeRow, age: number): Decimal {
|
export function pickPriceForRowByAge(
|
||||||
|
row: CodeRow,
|
||||||
|
age: number,
|
||||||
|
normalizedCode?: string
|
||||||
|
): Decimal {
|
||||||
|
// Special-case rules (add more codes here if needed)
|
||||||
|
if (normalizedCode) {
|
||||||
|
// D1110: only valid for age >=14 (14..21 => PriceLTEQ21, >21 => PriceGT21)
|
||||||
|
if (normalizedCode === "D1110") {
|
||||||
|
if (age < 14) {
|
||||||
|
// D1110 not applicable to children <14 (those belong to D1120)
|
||||||
|
return new Decimal(0);
|
||||||
|
}
|
||||||
|
if (age >= 14 && age <= 21) {
|
||||||
|
// use PriceLTEQ21 only if present
|
||||||
|
if (!isBlankPrice(row.PriceLTEQ21))
|
||||||
|
return toDecimalOrZero(row.PriceLTEQ21);
|
||||||
|
return new Decimal(0);
|
||||||
|
}
|
||||||
|
// age > 21
|
||||||
|
if (!isBlankPrice(row.PriceGT21)) return toDecimalOrZero(row.PriceGT21);
|
||||||
|
return new Decimal(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// D1120: child 0-13 => PriceLTEQ21, otherwise no price (NC)
|
||||||
|
if (normalizedCode === "D1120") {
|
||||||
|
if (age < 14) {
|
||||||
|
if (!isBlankPrice(row.PriceLTEQ21))
|
||||||
|
return toDecimalOrZero(row.PriceLTEQ21);
|
||||||
|
return new Decimal(0);
|
||||||
|
}
|
||||||
|
// age >= 14 => NC / no price
|
||||||
|
return new Decimal(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generic/default behavior (unchanged)
|
||||||
if (age <= 21) {
|
if (age <= 21) {
|
||||||
if (!isBlankPrice(row.PriceLTEQ21)) return toDecimalOrZero(row.PriceLTEQ21);
|
if (!isBlankPrice(row.PriceLTEQ21)) return toDecimalOrZero(row.PriceLTEQ21);
|
||||||
} else {
|
} else {
|
||||||
if (!isBlankPrice(row.PriceGT21)) return toDecimalOrZero(row.PriceGT21);
|
if (!isBlankPrice(row.PriceGT21)) return toDecimalOrZero(row.PriceGT21);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback to Price if tiered not available/blank
|
// Fallback to Price if tiered not available/blank
|
||||||
if (!isBlankPrice(row.Price)) return toDecimalOrZero(row.Price);
|
if (!isBlankPrice(row.Price)) return toDecimalOrZero(row.Price);
|
||||||
return new Decimal(0);
|
return new Decimal(0);
|
||||||
@@ -131,8 +170,9 @@ function getPriceForCodeWithAgeFromMap(
|
|||||||
code: string,
|
code: string,
|
||||||
age: number
|
age: number
|
||||||
): Decimal {
|
): Decimal {
|
||||||
const row = map.get(normalizeCode(code));
|
const norm = normalizeCode(code);
|
||||||
return row ? pickPriceForRowByAge(row, age) : new Decimal(0);
|
const row = map.get(norm);
|
||||||
|
return row ? pickPriceForRowByAge(row, age, norm) : new Decimal(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper keeping lines empty,
|
// helper keeping lines empty,
|
||||||
@@ -251,10 +291,7 @@ export function applyComboToForm<T extends ClaimFormLike>(
|
|||||||
procedureCode: code,
|
procedureCode: code,
|
||||||
procedureDate: lineDate,
|
procedureDate: lineDate,
|
||||||
oralCavityArea: original?.oralCavityArea ?? "",
|
oralCavityArea: original?.oralCavityArea ?? "",
|
||||||
toothNumber:
|
toothNumber: preset.toothNumbers?.[j] ?? original?.toothNumber ?? "",
|
||||||
preset.toothNumbers?.[j] ??
|
|
||||||
original?.toothNumber ??
|
|
||||||
"",
|
|
||||||
toothSurface: original?.toothSurface ?? "",
|
toothSurface: original?.toothSurface ?? "",
|
||||||
totalBilled: price,
|
totalBilled: price,
|
||||||
totalAdjusted: new Decimal(0),
|
totalAdjusted: new Decimal(0),
|
||||||
|
|||||||
Reference in New Issue
Block a user