Add "recement" example to LLM classifier so it spreads across multiple
teeth (recement #5, #3 → two D2920 entries). Add "today" to the AI
column claim message so the LLM sets appointmentDate instead of asking
"Which service date?"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- appointments-page: save full queue from current patient on confirm so that
cancelling the claim form resumes at the same patient instead of skipping it
- claims-page: advance ai_claim_queue only after successful submission (CCA,
MH selenium PDF download, or direct non-draft submit) via new advanceAiClaimQueue()
- cdt-lookup: fix extractToothSurface regex to allow space between # and digit
(e.g. "# 32") so tooth number is correctly captured
- cdt-lookup: silently skip bare tooth-number tokens ("# 32", "#32") that the
LLM may emit as standalone items, preventing false "unrecognized procedure" errors
- internal-chat-graph: add explicit rule that a CDT code followed by # NN
(e.g. "D7210 # 32") must stay as one entry and not spread to other procedures
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Claim file uploads (chatbot or manual) now save to both the Cloud
Storage patient folder and the Documents page via new
POST /api/claims/upload-to-cloud endpoint
- MH submit flow now calls uploadAttachmentsToLocalFolder (same as
DDMA/United/Tufts) so chatbot-attached X-rays are persisted
- Removed old /upload-attachments disk route and attachmentDiskStorage
multer config; deleted uploads/patients/ folder
- uploadAttachmentsToLocalFolder now points to /upload-to-cloud and
sends patientId so the backend can create the patient folder
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
UI-only stub — logic to be defined. Mirrors the existing Claim for
Column section with its own column checkboxes and loading state.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove auto-appending of "Appointment with [staff name]" to notes on
save, and preserve existing notes when dragging an appointment to a
new slot.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Move Select Procedures above Check Eligibility in appointment right-click menu
- Show 3 blank service lines by default when opening Select Procedures with no saved procedures
- Fix serviceLines not being preserved when API returns empty procedures list
- CDT combo buttons no longer auto-fill price (only fill codes); user maps price via Map Price button
- Overlap detection in schedule: shorten earlier appointment display span when a later one starts within its range
- Procedures dialog: replace single manual-add row with 3 pre-filled blank rows grid + Add Line / Save Lines buttons
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add appointment type categories matching insurance claim form (recall, filling, pedo, dentures, implant, endo, crown, perio, extraction, ortho, consultation, emergency, other)
- Auto-infer appointment type from CDT codes with priority rules (endo > implant > crown > ...)
- typeLocked flag prevents auto-overwrite when user manually sets type
- Show appointment type label and procedure codes on schedule cards
- Background sync on /day route retroactively fixes stale appointment types
- Fix PUT /api/claims/:id to save claimFiles (previously silently dropped)
- Auto-link AppointmentFile records to ClaimFile when claim is created or updated
- Fix D5750 (denture reline) CDT range to map correctly to dentures category
- Fix typeLocked Zod rejection in appointment update route
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix Express route ordering in appointments-procedures so /prefill-from-appointment
is matched before /:id (D0140 and other codes now always reach the claim)
- claim-form: always fetch AppointmentProcedure records when an existing claim loads
so post-save procedure edits (e.g. adding D0140) are reflected immediately
- appointments-page: replace sessionStorage with React state (newApptPrefill) for
slot-click prefill so columns B-F correctly carry their staffId into the form
- add-appointment-modal / appointment-form: thread prefillData prop; add
NewAppointmentPrefill interface; useEffect applies values via setValue
- appointments upsert: remove per-patient dedup so the same patient can have
multiple appointments on the same day in the same column
- DentaQuest / TuftsSCO: navigate to about:blank and minimize instead of
quit_driver after each run — session cookie stays in memory so OTP is only
required once per app startup, not on every eligibility or claim check
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- claims.ts: batch-column now routes each patient to the correct portal
(MH/CCA/DDMA/TuftsSCO/UnitedSCO) based on patient.insuranceProvider
- appointments-page.tsx: eligibility badge falls back to patientStatus
for all insurance types, not just MassHealth
- unitedDHClaimProcessor/ddmaClaimProcessor/tuftsSCOClaimProcessor:
auto-save claim PDF when no socketId (batch-column path)
- unitedSCOEligibilityProcessor: unknown eligibility no longer stored as INACTIVE
- queues.ts: add tuftssco-claim-submit and uniteddh-claim-submit to SeleniumJobType
- selenium_UnitedSCO_eligibilityCheckWorker.py:
- step1: add Select Insurance OK click with staleness wait; Provider &
Location page just clicks Continue; skip first/last name input
- step2: extract name from eligibility details tab (ALL CAPS → title case);
skip "not available" guard; fix name regex to match only all-caps words
- .gitignore: ignore all chrome_profile_* directories
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add full Selenium automation for United/DentalHub claim submission
(steps 1-8: login, OTP, patient search, practitioner page, code entry,
other coverage No, attachments, submit, Status & History PDF)
- Consolidate UnitedDH siteKey to UNITED_SCO throughout app
- Fix procedure date overwrite with Ctrl+A+Delete before typing service date
- Fix OTP popup reliability: emit every poll (no throttle)
- Fix Chrome session persistence: only clear cookies on startup
- Add touchPatient() to storage: claim submission now pushes patient to
top of list across eligibility, claims, and documents pages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
- Remove "Claim Status" from appointment context menu
- Rename "Eligibility Status" → "Check Eligibility"
- Check Eligibility now navigates to insurance-status page and auto-starts
the correct selenium flow based on the patient's stored insurance provider:
MassHealth 21+ → MH Eligibility & History
MassHealth <21 → CMSP Eligibility & History & Remaining
Delta Dental MA → DDMA selenium
Delta Dental Ins → Delta Ins selenium (OTP modal if needed)
United Healthcare SCO → United SCO selenium
DentaQuest/Tufts → Tufts SCO selenium
Commonwealth Care Alliance → CCA selenium
Unknown → scroll to Other provider checks section
- Add autoTrigger/onAutoTriggered props to all five button components
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Reschedule for Column button on schedule page with AI follow-up toggle (default on)
- Add POST /api/twilio/send-reschedule-batch — sends Reschedule by Office template, starts AI reschedule conversation per patient
- Add {officePhone} (office call-in number) and {twilioPhone} (SMS number) variable replacement in both batch endpoints
- Fix broken variable names in Reschedule by Office template ({office phone number) → {officePhone}, {Twilio phone number} → {twilioPhone})
- Fix reschedule-graph: when patient replies with date in same message as YES/NO (e.g. "ok, 5/18"), AI now checks day open and asks for time instead of asking "what day and time?"
- Fix twilio-webhooks: same date-shortcut logic for reminder flow — "no, 5/18" skips "when to reschedule?" and goes straight to day check
- Update LangGraph SVG: rename to Reminder & Reschedule Flow, combine both entry points (Reminder SMS + Reschedule SMS) into one diagram with date-shortcut annotations
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
time <= amEnd incorrectly allowed 12:00 when the office closes at 12:00.
Changed to time < amEnd (and time < pmEnd) so the session end time is
treated as a closed boundary — a patient cannot start an appointment at
exactly the time the session ends.
Fixes both the SMS reschedule flow and the schedule grid slot highlighting.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add movedByAi boolean column to Appointment table (default false)
- reschedule-graph: set movedByAi=true when AI moves an appointment
- PATCH /api/appointments/:id/confirm endpoint clears the movedByAi flag
- Schedule grid: show teal AI badge on appointment cards where movedByAi=true
- Right-click context menu: 'Manually Confirmed' removes the AI badge via the confirm endpoint
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Reminder flow: send AI self-introduction as message 1 (Twilio REST API), intent response as message 2 (TwiML) so intro always arrives first
- LangGraph reminder graph: classify yes/no/other from patient reply; 'no' now asks 'When would you like to reschedule?' directly
- Reschedule flow: new asked_reschedule_datetime stage replaces multi-step ASAP/next-week flow
- Date-only reply (e.g. '5/18'): ask for time separately, then confirm
- Date+time reply (e.g. '5/18 at 10am'): go straight to confirmation
- new asked_reschedule_time_for_date and asked_reschedule_confirm_datetime stages
- Date/time parsing: regex handles M/D and am/pm formats first; falls back to Gemini for natural language
- Day-level office hours check: if requested day is closed (e.g. Sunday), reply 'Our office is closed on [date]. Choose another day?'
- Time-level office hours check: if requested time is outside working hours (e.g. 12pm during lunch), reply with actual hours (e.g. '9:00 am – 12:00 pm and 1:00 pm – 5:00 pm')
- Slot availability check: verifies no conflicting appointment for same staff member
- After appointment confirmed: patient thank-you reply triggers warm closing with upcoming appointment time
- Schedule page: office hours summary bar above grid showing today's configured hours with link to settings
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Text Reminder for Column button with per-column checkboxes and AI follow-up toggle (default on)
- Batch reminder endpoint resolves {firstName}, {officeName}, {appointmentDate}, {appointmentTime} from AI chat templates
- Add Reschedule for Column UI (logic TBD)
- Move Download Claim PDF for Column below Reschedule for Column
- Add reminderSms template field to AI Chat Settings with variable hints
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Settings > Advanced > Procedure Duration/Time Slot page with three sections:
1. Procedure Duration: CDT codes with durations (editable table, save per section)
2. Doctor Time Slot: drag-to-block visual grid (A/B/C columns, 8 AM–9 PM, edit/delete slots)
3. Hygienist Time Slot: procedure descriptions with durations
- Backend: ProcedureTimeslot Prisma model, storage, and GET/PUT /api/procedure-timeslot route
- DB migration: procedure_timeslot table
- Appointment form: when type is "Other", show a free-text input for custom description; saved as other:<description> and decoded for display on the schedule card
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Time slots now run 8:00 AM – 9:00 PM (was 8:00 AM – 6:00 PM)
- Appointments visually span the correct number of 15-min rows based on startTime/endTime using HTML rowSpan
- Covered rows are skipped so the grid layout stays consistent
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Schedule columns default to labels A–F (localStorage, per-browser, click to rename)
- Settings → Advanced → Office Hours: configure Doctors (A-C) and Hygienists (D-F) AM/PM hours per weekday
- Gray out schedule slots outside office hours; override dialog for manual exceptions
- Override Office Hours toggle: select specific dates where all slots are open
- Fix appointment move: send only real DB fields to avoid Zod strict-mode rejection of computed fields (hasProcedures, hasClaimWithNumber)
- Fix backend PUT /appointments: safe error logging to prevent Prisma error crashing Node inspect
- Add OfficeHours Prisma model and GET/PUT /api/office-hours route
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Default card color: light (bg-slate-100 / dark text)
- Blue card when procedures selected, gray when claim has a number
- Status badge: green/red from appointment or patient-level MassHealth status
- Solid dot badge (removed ring), overflow-visible to prevent corner clipping
- Date nav: << < [today circle] > >> for week/day jumps
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add 'Select Procedures' right-click option on appointment page (separate from Claims/PreAuth)
- Select Procedures form saves CDT codes + NPI provider to AppointmentProcedure storage
- Remove Save button from insurance claim form; Claims/PreAuth opens for insurance submission only
- Claims/PreAuth auto-prefills from saved procedures including NPI provider
- Batch-column: procedures npiProviderId takes priority over stale claim npiProviderId
- Batch-column: auto-save PDF to patient Documents after successful submission (no socket needed)
- Add npiProviderId column to AppointmentProcedure table (prisma db push)
- Fix 'invalid db creation invocation': guard staffId, npiProviderId, procedureDate as Date object, totalBilled NaN guard
- Add full error logging to batch-column catch block
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix status enum in browser.ts (uppercase → lowercase values)
- Fix date validation (z.string → z.coerce.date) so form accepts Date objects
- Add missing type/userId/title fields to browser.ts appointment schema
- Replace nested PatientSearch Select with simple inline Input to fix patient selection
- Fix mutationFn to throw on non-ok responses so backend errors surface correctly
- Connect socket.io directly to backend (port 5000) instead of Vite proxy to fix AggregateError on startup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>