feat: age overrides notes text for prophy code (D1110/D1120)

Patient's actual age now decides adult vs child prophylaxis instead of
trusting literal "adult prophy"/"child prophy" wording in notes. Applies
bidirectionally (corrects both D1110-on-a-child and D1120-on-an-adult) and
also resolves ambiguous bare "prophy"/"cleaning" input purely from age.
Wired into all single- and batch-claim chat flows.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-10-05 21:58:21 -04:00
co-authored by Claude Sonnet 5
parent d235845ea2
commit 6148cfa848
4 changed files with 92 additions and 33 deletions
@@ -256,12 +256,12 @@ export function ChatbotButton() {
renderingProvider: string | null;
} | null>(null);
const [batchCheckAndClaimData, setBatchCheckAndClaimData] = useState<{
queue: { memberId: string; dob: string; siteKey: string; autoCheck: string; patient: PatientResult | null }[];
queue: { memberId: string; dob: string; siteKey: string; autoCheck: string; patient: PatientResult | null; matchedCodes?: { code: string; description: string; toothNumber?: string; toothSurface?: string; quad?: string }[] }[];
matchedCodes: { code: string; description: string; toothNumber?: string; toothSurface?: string; quad?: string }[];
renderingProvider: string | null;
} | null>(null);
const [batchClaimData, setBatchClaimData] = useState<{
queue: { patient: PatientResult; siteKey: string; serviceDate: string | null; appointmentId: number | null }[];
queue: { patient: PatientResult; siteKey: string; serviceDate: string | null; appointmentId: number | null; matchedCodes?: { code: string; description: string; toothNumber?: string; toothSurface?: string; quad?: string }[] }[];
matchedCodes: { code: string; description: string; toothNumber?: string; toothSurface?: string; quad?: string }[];
renderingProvider: string | null;
} | null>(null);
@@ -1461,7 +1461,7 @@ export function ChatbotButton() {
}));
}
sessionStorage.setItem("chatbot_claim_codes", JSON.stringify({
codes: matchedCodes,
codes: first!.matchedCodes?.length ? first!.matchedCodes : matchedCodes,
siteKey: first!.siteKey,
patientId: first!.patient?.id ?? null,
memberId: first!.memberId,
@@ -1492,6 +1492,9 @@ export function ChatbotButton() {
{batchClaimData.queue.map((item, i) => (
<p key={i} className="text-xs text-orange-600 pl-2">
{i + 1}. {item.patient.firstName} {item.patient.lastName}
{item.matchedCodes?.some((c, idx) => c.code !== batchClaimData.matchedCodes[idx]?.code) && (
<span className="text-gray-500"> — {item.matchedCodes.map((c) => c.code).join(", ")} (adjusted for age)</span>
)}
</p>
))}
{batchClaimData.matchedCodes.length > 0 && (
@@ -1520,9 +1523,10 @@ export function ChatbotButton() {
renderingProvider,
}));
}
if (first!.patient.id && matchedCodes.length > 0) {
const firstCodes = first!.matchedCodes?.length ? first!.matchedCodes : matchedCodes;
if (first!.patient.id && firstCodes.length > 0) {
sessionStorage.setItem("chatbot_claim_prefill", JSON.stringify({
codes: matchedCodes,
codes: firstCodes,
siteKey: first!.siteKey,
serviceDate: first!.serviceDate,
autoSubmit: true,
+2 -1
View File
@@ -381,8 +381,9 @@ export default function ClaimsPage() {
} else {
sessionStorage.removeItem("chatbot_check_claim_queue");
}
const codes = next.matchedCodes?.length > 0 ? next.matchedCodes : matchedCodes;
sessionStorage.setItem("chatbot_claim_codes", JSON.stringify({
codes: matchedCodes,
codes,
siteKey: next.siteKey,
patientId: next.patient?.id ?? null,
memberId: next.memberId,