feat: AI chat claim confirmation, CDT alias learning, and eligibility auto-trigger fixes
- Claim flow: show green confirm card (patient, CDT codes, service date) before Selenium starts - CDT lookup: add DIRECT_CODE_MAP + ALIAS_MAP with 60+ dental abbreviations from office fee schedule (2BW→D0272, 4BW→D0274, PA→D0220, FL→D1208, RCT codes, composite tooth#/surface parser, etc.) - Composite filling parser: auto-map "#29 OB" → D2392 based on tooth# (front/back) and surface count - Ask-and-learn: unknown CDT terms block claim and ask user; answer saved to DB alias map for future use - Cancel on confirm card returns to chat (not full reset) so user can correct and retry - Eligibility auto-trigger fix: reset autoTriggeredRef when autoTrigger resets to false so second chatbot eligibility check on same page visit fires correctly (all 5 provider buttons fixed) - check_eligibility by name now returns eligibility_id_ready with correct siteKey for non-MH patients - DDMA/CCA/United/Tufts fee schedules updated with office prices (single Price field, no age split) - getCodeMap case-insensitive matching fix (ddma/cca/etc. now correctly selected) - Family plan member disambiguation: insuranceId+DOB composite lookup prevents overwriting siblings - AI chat date fix: send clientDate from browser to avoid UTC midnight rollover (EST→wrong day) - AI prompt: appointmentDate extracted for claim_only intent when user says "today" or a date Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -251,13 +251,32 @@ router.put("/cdt-aliases", async (req: Request, res: Response): Promise<any> =>
|
||||
}
|
||||
});
|
||||
|
||||
// POST /api/ai/cdt-aliases/add — add/update a single alias without overwriting others
|
||||
router.post("/cdt-aliases/add", async (req: Request, res: Response): Promise<any> => {
|
||||
try {
|
||||
const userId = req.user?.id;
|
||||
if (!userId) return res.status(401).json({ message: "Unauthorized" });
|
||||
const { phrase, cdtCode } = req.body;
|
||||
if (typeof phrase !== "string" || typeof cdtCode !== "string") {
|
||||
return res.status(400).json({ message: "Body must be { phrase, cdtCode }" });
|
||||
}
|
||||
const existing = await storage.getCdtAliases(userId);
|
||||
const newEntry = { phrase: phrase.trim().toLowerCase(), cdtCode: cdtCode.trim().toUpperCase() };
|
||||
const updated = [...existing.filter((a) => a.phrase !== newEntry.phrase), newEntry];
|
||||
await storage.saveCdtAliases(userId, updated);
|
||||
return res.status(200).json(newEntry);
|
||||
} catch (err) {
|
||||
return res.status(500).json({ error: "Failed to add CDT alias", details: String(err) });
|
||||
}
|
||||
});
|
||||
|
||||
// POST /api/ai/internal-chat
|
||||
router.post("/internal-chat", async (req: Request, res: Response): Promise<any> => {
|
||||
try {
|
||||
const userId = req.user?.id;
|
||||
if (!userId) return res.status(401).json({ message: "Unauthorized" });
|
||||
|
||||
const { message, history } = req.body;
|
||||
const { message, history, clientDate } = req.body;
|
||||
if (!message?.trim()) return res.status(400).json({ message: "message is required" });
|
||||
|
||||
const aiSettings = await storage.getAiSettings(userId);
|
||||
@@ -279,7 +298,8 @@ router.post("/internal-chat", async (req: Request, res: Response): Promise<any>
|
||||
extraSystemPrompt || undefined,
|
||||
Array.isArray(history) ? history : [],
|
||||
activeAi.provider,
|
||||
activeAi.model
|
||||
activeAi.model,
|
||||
typeof clientDate === "string" ? clientDate : undefined
|
||||
);
|
||||
|
||||
const response = await runInternalChatWorkflow(classification, userId, storage, customAliases);
|
||||
|
||||
Reference in New Issue
Block a user