Commit Graph

142 Commits

Author SHA1 Message Date
ff
3e61bdec36 feat: route batch-column claims by insurance type, fix eligibility UX
- 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>
2026-05-27 23:07:42 -04:00
ff
1b017177e9 feat: add stop-app script and update desktop shortcut setup
Adds stop-app.sh to kill all services by port (5000-5003, 3000/3001)
and updates setup-desktop-shortcut.sh to create both Start and Stop
desktop shortcuts in a single run. README Step 13 updated accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 22:00:06 -04:00
ff
080b0c65b8 fix: correct license key part count validation (5 not 6)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 21:50:30 -04:00
ff
070752380d feat: add license activation system with feature gates
- License key generator tool at ~/Desktop/LicenseGenerator
- Backend validator route (GET /api/license/status, POST /api/license/activate)
- Activation page in sidebar with status, key input, and free/premium feature list
- useLicense hook for frontend license state
- Feature gates: premium eligibility buttons (DDMA, DeltaIns, Tufts, United, CCA) disabled without license
- Feature gates: premium claim buttons (CCA, Delta MA, United, Tufts) and all PreAuth buttons disabled without license
- Free features always active: MassHealth eligibility/claim, Documents, Payments, Backups, Reports
- README: license key generator usage instructions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 21:22:34 -04:00
ff
594df39741 docs: add Claude Code memory backup instructions to README
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 12:43:09 -04:00
ff
5dcc1b2af5 docs: document per-office Cloudflare env setup in README
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 12:01:24 -04:00
ff
816d9e0ee7 feat: make Cloudflare host configurable per office via env
Each office sets VITE_CLOUDFLARE_HOST and CLOUDFLARE_HOST in their
local .env files instead of hardcoding the subdomain in source code.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 11:55:28 -04:00
Gitead
4f88352447 feat: add tooth icon for desktop shortcut
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 00:05:55 -04:00
Gitead
427cca7f40 docs: add desktop shortcut setup instructions to README
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 00:03:10 -04:00
Gitead
783e63c9ea feat: add app launcher and desktop shortcut setup scripts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 23:54:55 -04:00
Gitead
fcb049273a feat: add missing backend route and frontend utility/config files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 22:26:58 -04:00
Gitead
adb5801023 feat: add missing selenium CCA preauth and UnitedDH claim client services
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 22:26:03 -04:00
Gitead
3534ecb3c9 feat: Tufts SCO claim automation, Claim All button, fee schedule updates
- Add full Tufts SCO claim Selenium worker (steps 1-8): login with OTP
  support, member search, Create Claim, fill form, attach files, submit,
  extract claim number and save confirmation PDF
- Fix DentaQuest browser manager to preserve device trust token on startup
  (only clear cookies, not LocalStorage/IndexedDB) so OTP is only needed
  once for both eligibility and Tufts claim
- Fix Tufts SCO claim route credential lookup key (TUFTS_SCO not TuftsSCO)
- Add Tufts SCO and United/DentalHub entries to fee schedule update route
- Add "Claim All" button that auto-routes to the correct claim handler
  based on the Insurance Type dropdown value
- Add fee schedule JSON files for DDMA, Tufts SCO, and United/DentalHub

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 20:22:26 -04:00
Gitead
1e581c193c feat: United/DentalHub claim submission automation and patient list sync
- 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>
2026-05-25 00:29:04 -04:00
Gitead
cd1381e9c6 feat: DDMA claim submission with OTP, PDF, claim number extraction
- Add full DDMA claim Selenium flow (steps 1-8): search patient, open
  member page, create claim, fill form, attach files, next, submit,
  extract claim number and save confirmation PDF
- Add fee schedule price-mismatch dialog for all claim buttons (MH,
  CCA, DDMA, United, Tufts, Save) with optional price update to JSON
- Add OTP modal for DDMA claim when session expires, mirroring
  eligibility OTP flow
- Close Chrome after claim submission via quit_driver() (session
  preserved in profile)
- Move Map Price button between Direct Submission and procedure table,
  right-aligned above Billed Amount column
- Add fee-schedule update-price backend route
- Add DDMA claim processor with claimNumber/pdf_url result handling

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 13:35:04 -04:00
Gitead
5ceecbeb7f feat: improve CCA preauth cell filling, implants category, preauth no recording
- Selenium: bulletproof Wait→Click→Clear→Type→Verify for tooth, billed amt cells
- Selenium: fix billed amt to click td[23] (correct column) to trigger edit mode
- Selenium: skip tentative date (auto-filled by page after tooth entry)
- Frontend: add Implants category with Implant/Abut/Crown, Fixture, Abutment, Crown buttons (D6010/D6057/D6058)
- Frontend: pdf-preview-modal renders PNG screenshots as <img> instead of PDF iframe
- Backend: CCA preauth route creates claim record if none exists
- Backend: CCA preauth processor saves authNumber into claimNumber column after submission

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 22:01:52 -04:00
Gitead
0e664e4813 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>
2026-05-22 13:34:03 -04:00
Gitead
58b2e4af93 docs: add Cloudflare tunnel setup guide and ports reference
Add step-by-step Cloudflare tunnel setup to README.md with Summit Dental Care as a multi-office example. Create docs/ports.md documenting all service hosts and ports.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 23:25:44 -04:00
Gitead
8e6ada87d6 fix: set empty VITE_API_BASE_URL_BACKEND and add HTTPS origin to CORS
External browsers were hitting localhost:5000 instead of going through
nginx. VITE_API_BASE_URL_BACKEND is now empty so all API calls use
relative /api/ paths that nginx proxies to the backend. Also adds
https://communitydentistsoflowell.mydentalofficemanagement.com to
FRONTEND_URLS for CORS. Updated .env.example to match so setup from
template doesn't silently revert this fix.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 22:35:53 -04:00
Gitead
a03f3f25dd fix: handle new-tab SSO redirect for MassHealth eligibility and history
After login, Chrome on some machines opens the portal dashboard in a new
tab and closes the SSO tab. Poll all window handles until the portal URL
is found, then switch to it — works for both same-tab and new-tab redirects.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 08:52:11 -04:00
Gitead
7284598c97 fix: improve eligibility checks for MassHealth and DentaQuest
- MassHealth: detect SSO/portal maintenance page and return clear error
  instead of cryptic step1 timeout; wait for SSO redirect to complete
  before running step1; add modal dismissal and failure screenshot/logging
- DentaQuest: detect maintenance page in login and step1; search by
  member ID + DOB only (remove first/last name to prevent stale data
  from previous patient being submitted)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 23:05:48 -04:00
Gitead
95ce4c2fb4 feat: restore Simple/Baby Teeth EXT combos, hide from PreAuth only
- Restore simpleExtraction (D7140), surgicalExtraction (D7210), babyTeethExtraction (D7111)
- Add excludeIds prop to RegularComboButtons for per-button filtering
- PreAuth tab excludes Simple EXT and Baby Teeth EXT; Insurance Claim tab shows all

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 23:40:44 -04:00
ff
de995de2ad fix: allow deleting users by reassigning their records to admin first
Deleting users with patients/appointments/claims was blocked by FK
constraints. Now reassigns those records to the requesting admin before
deletion, and cleans up user-specific data (backups, cloud files).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 23:06:36 -04:00
ff
8cab823d60 feat: share patients across all users
Removed per-user patient filtering so all staff accounts see the same
patient pool. Previously each user only saw patients they created.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 23:04:26 -04:00
ff
b148c0de30 fix: apply missing migrations directly after DB restore
Replace the prisma migrate deploy subprocess with a custom
applyMissingMigrations() that reads each migration SQL file and runs it
via prisma.$executeRawUnsafe. This avoids the Prisma CLI aborting when
the restored _prisma_migrations table contains orphaned entries (migration
names that no longer have a corresponding file in the migrations folder).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 22:36:35 -04:00
ff
5508a90d28 fix: auto-migrate after DB restore and force re-login
- After importing a backup, run prisma migrate deploy so any schema
  migrations the backup is missing are applied automatically. This
  prevents pages from failing due to missing tables/columns when the
  backup was taken on an older version of the app.
- Force logout and redirect to login after a successful restore so the
  JWT is refreshed against the restored database (prevents userId
  mismatch causing user-scoped queries to return empty results).
- Fix getTotalPatientCount() in /status route to pass userId so it
  counts only the current user's patients instead of all patients.
- Add prisma.$connect() after $disconnect() to ensure a clean reconnect.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 22:31:12 -04:00
Gitead
b9e888fc7f feat: show weekday name and MM-DD-YYYY format in schedule date button
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 10:16:39 -04:00
Gitead
208ccf3549 feat: add Claim Saved button and use patient insurance provider
- Replace Others button with Claim Saved (blue MH, green Claim Saved)
- Claim Saved saves full claim to DB using patient's insuranceProvider
- No Selenium triggered — works like a real claim for payment/report tracking

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 10:01:21 -04:00
Gitead
e34140c2b1 feat: add AI Dental Shopping section with sidebar nav and Login Info page
- Add AI Dental Shopping to sidebar with Search/Tag and Login Info sub-pages
- Build full-stack Login Info CRUD: save vendor name, website, username, password per user
- Add ShoppingVendor Prisma model, run db push, regenerate client and Zod schemas
- Add storage layer, REST API at /api/shopping-vendors/, and frontend table with add/edit/delete modal

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 00:35:38 -04:00
Gitead
edec03e893 feat: auto-trigger eligibility selenium from schedule right-click menu
- 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>
2026-05-17 00:12:09 -04:00
Gitead
4127861d06 fix: remove patient update calls from claim/preauth handlers to stop validation errors
The insuranceId format check on the backend rejected updates when the member ID
contained non-digit characters. Tagging insuranceProvider on the patient is not
required for selenium to run, so the calls are removed from handleMHSubmit,
handleMHPreAuth, and handleAddService.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 23:04:57 -04:00
Gitead
cf85750d90 feat: add PreAuth tab, preauth selenium flow, and PreAuth No column
- Insurance Forms modal: split into Insurance Claim / PreAuth tabs
- PreAuth tab: same patient info + service lines, no toggle/direct combos
- Excluded Recalls & New Patients, Composite Fillings (Front/Back), Pedo from PreAuth combos
- Extractions: replaced Simple/Surg/Baby Teeth EXT with Full Bony EXT (D7240)
- MH PreAuth button: rewritten selenium worker to use masshealth-dental.org,
  selects Dental Prior Authorization (2nd option), skips Date of Service field
- agent.py: convert pdf_path to pdf_url for /claim-pre-auth endpoint
- nginx + Express: raise body size limit to 50mb (fix 413 errors)
- DB schema: appointmentId optional on Claim, add preAuthNumber field, add PREAUTH status
- Backend: create PREAUTH claim record on preauth submit, save preAuthNumber on completion
- Claims table: add PreAuth No column (blue) next to Claim No

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 22:53:41 -04:00
Gitead
7360b1930b feat: add provider column, commission tracking, and report provider filter
- Claims & Payments: save npiProviderId when submitting MH claim; sync between claim and payment on update
- Claims table: add Provider column showing rendering provider name
- Payments table: add Provider column + purple Commissioned badge on status
- Claim edit modal: add Rendering Provider dropdown (defaults to Mary Scannell)
- Payment edit modal: add Rendering Provider dropdown + Commissioned metadata display
- Reports page: add Provider filter dropdown (dynamic from NPI providers settings)
- Reports page: remove Collections by Doctor report type and Select Doctor dropdown
- Commission section: new section in reports page with date range + provider filter, shows eligible paid claims/payments per provider, multi-select checkboxes, Pay Commission modal with print + save, marks payments as commissioned so they are excluded from future cycles
- DB: add CommissionBatch and CommissionBatchItem tables; backfill Payment.npiProviderId from linked claims
- Backend: PATCH /api/payments/:id/provider syncs to linked claim; PUT /api/claims/:id syncs to linked payment; new /api/commissions routes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 23:51:39 -04:00
Gitead
25a20e8a16 feat: auto-popup claim confirmation PDF after selenium submission
After the MH claim selenium job completes and the PDF is saved to the
database, immediately open the PdfPreviewModal so the user can view the
confirmation without navigating to the Documents page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 09:43:46 -04:00
Gitead
a485396a96 fix: add HTTP polling fallback for selenium job results through Cloudflare
Socket.IO reconnects through Cloudflare proxy get a new socket.id, causing
the backend to emit job:update to a stale socket that no longer exists. The
PDF viewer modal never opened even though PDFs were saved successfully.

Adds a GET /api/insurance-status/job-status/:jobId endpoint backed by
InProcessQueue.getJob(), and a waitForSeleniumJob() helper on the frontend
that races socket events against HTTP polling every 3s. Whichever resolves
first wins, so local (socket) and external (Cloudflare) both work reliably.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 09:33:46 -04:00
Gitead
69919e1eca feat: update new patient LangGraph flow diagram to reflect current AI flow
Replaces the old after-hours/new-patient SVG with an accurate diagram of
the current conversation flow: 3-message TwiML entry → insurance check →
MassHealth consent + ID/DOB → Selenium eligibility → ACTIVE/INACTIVE paths,
inactive branch asks for other insurance then collects contact info, and
office-hours-validated date/time scheduling with appointment creation.
Existing patient branch shows same-insurance confirmation, MassHealth
auto-check (stored ID+DOB), and Selenium result paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 00:26:09 -04:00
Gitead
c71624f7e7 feat: enhance new-patient AI chat flow with full scheduling and eligibility
- Add 3-message intro (self-intro → empathetic ack → new/existing question) via single TwiML response to guarantee delivery order
- Detect reschedule intent from first message; look up existing appointment date
- New patient flow: ask insurance type → MassHealth consent → member ID + DOB → Selenium eligibility check
- Post-eligibility: active → ask appointment date/time with office-hours validation; inactive → ask other insurance or collect contact info
- Date/time collection mirrors reschedule flow: check office day open, ask time, validate against office hours
- Auto-create appointment in schedule for known patients on confirmation; use first available staff member
- Add openPhoneReply toggle (Settings → AI Chat) to respond to any number at any time
- Add 5-minute inactivity timeout: reset conversation to initial stage and clear pending state
- Normalize MassHealth DOB to zero-padded MM/DD/YYYY before Selenium submission
- Expand isExistingPatient classifier to recognize "old patient", "old", "previous", "prior"
- Existing patient confirmation message now acknowledges patient type before asking about insurance

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 00:00:56 -04:00
Gitead
c1f55778ca feat: add assistant chatbot with eligibility auto-check
- Add ChatbotButton component to top-app-bar (bot icon, upper right)
- Slide-in chat panel with 4 options: Check Eligibility, Schedule, Claims, Chat
- Single paste area accepts member ID + DOB in either order
- Age-based routing: ≥21 → MH Eligibility & History, <21 → CMSP auto-triggered
- Insurance-status page prefills fields and auto-fires the correct button via sessionStorage + custom event

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 13:42:53 -04:00
Gitead
4f2cbc2c60 fix: prevent double self-introduction in reschedule MSG 2
- reminder-graph: add stripIntroFromFallback() to remove 'Hi! My name is Lisa...'
  from any saved rescheduleGreeting template before using it as the MSG 2 fallback
- reminder-graph: add explicit 'Do NOT introduce yourself' to rescheduleNode Gemini
  prompt so the AI never adds its own intro to MSG 2
- ai-chat-templates-card: add hasIntroPattern() warning on the Reschedule Patients
  template field — shows an amber alert if the saved template starts with a
  self-introduction, guiding users to remove it

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 12:59:43 -04:00
Gitead
fd8e664e7b fix: correct SMS template defaults and add unsupported-variable warning
- reminderSms default: remove {officeAddress} (never replaced by backend) to prevent
  patients receiving literal '{officeAddress}' in reminder texts
- reminderGreeting default: fix typo 'reply you message' → 'reply to your message'
- rescheduleGreeting default: remove duplicate AI intro (intro is now sent separately
  as MSG 1; fallback text should only contain the intent response)
- Add unsupportedVars() detector: highlights any {variable} in the SMS template that
  the backend does not replace, with an amber warning showing the supported list

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 12:51:55 -04:00
Gitead
c40ebae979 fix: remove vm.hasResults wait in accumulator step, print page as-is
Member info is always present on the accumulator page regardless of
whether dollar amounts exist. Removing the button wait eliminates the
15s freeze for patients with no financial data.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 12:09:08 -04:00
Gitead
65b26610b1 refactor: duplicate member details tab for parallel service history & accumulator
Instead of navigating back and forth, step4 opens the member details URL
in a new tab. Tab A clicks service history and CDP-prints the history PDF.
Tab B clicks View Accumulator and CDP-prints the accumulator PDF (waits
up to 15s for vm.hasResults, then captures whatever is on screen).
Eliminates the Chrome freeze from back-navigation and the empty-accumulator
race condition.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 12:06:33 -04:00
Gitead
33dded1813 fix: cap accumulator wait at 15s, always print after 5s render pause
Previously waited up to 60s for vm.hasResults button causing long freeze.
Now caps at 15s then always proceeds — captures data or no-results state.
Extra 5s sleep ensures Angular finishes rendering table rows before CDP print.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 11:54:46 -04:00
Gitead
2baa1b0435 fix: wait for accumulator data before CDP print in CMSP flow
step7 now waits for button[ng-click='vm.printResults()'][ng-if='vm.hasResults']
to become visible before printing — that element only renders once Angular
has loaded the accumulator data, so the CDP capture is no longer racing
against the async data fetch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 11:49:20 -04:00
Gitead
0628f9f7fc feat: add member details PDF step to MH history and CMSP flows
After clicking the member ID link, print the member details page via CDP
before navigating to service history. Adds member details as a panel in
the side-by-side PDF viewer: MH History shows 3 panels (eligibility,
member details, service history); CMSP shows 4 panels (eligibility,
member details, service history, accumulator).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 11:33:02 -04:00
Gitead
06526cd1bc feat: MH eligibility & history, CMSP eligibility & history & remaining
- Add MH Eligibility & History button: runs full MH eligibility flow then
  clicks member ID → service history, prints both PDFs via CDP, opens
  dual side-by-side PDF modal (eligibility auto-downloads, history does not)
- Add CMSP Eligibility & History & Remaining button: same flow plus
  navigates back to member details, clicks View Accumulator, prints
  accumulator PDF via CDP; opens 3-panel side-by-side PDF modal
- Generalize DualPdfPreviewModal to accept panels[] array (works for 2 or 3 PDFs)
- Auto-download eligibility PDF via direct API URL to avoid Chrome Safe
  Browsing pause on blob: URL downloads
- New backend processors, job types, and routes for both flows
- New Python Selenium workers with stable CSS selectors (ng-bind, href*)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 23:29:55 -04:00
Gitead
131733564e feat: reschedule-by-office batch SMS, AI follow-up toggle, date-shortcut fix, combined flow diagram
- 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>
2026-05-13 00:36:38 -04:00
Gitead
7929dc6e19 feat: office address, multi-template SMS manager, hardcoded defaults with auto-seed
- Add streetAddress/city/state/zipCode fields to OfficeContact (schema + storage + UI)
- Support {officeAddress} variable in batch reminder SMS
- Replace single SMS template field with full CRUD template list (add/rename/edit/delete)
- Store SMS template list under _sms_template_list; first template synced to batch reminder
- Hardcode all AI chat template defaults into codebase (reminder SMS, greetings, fallback)
- Add seed-templates.ts that auto-seeds default templates for all users on server boot
- Update README: note that templates are auto-configured on first boot

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 23:18:04 -04:00
Gitead
11244ace7f feat: update LangGraph flow diagram to reflect new reschedule flow
Replace the old ASAP/next-week/Mon-Tue-Wed/morning-afternoon subtree with
the new direct datetime flow:
- MSG 1: AI self-introduction (sent first via REST API)
- MSG 2: "When would you like to reschedule?" (intent response)
- Patient gives date → day-open check (office hours) with fail loop
- AI asks time → hours check (within AM/PM session) with fail loop
- AI confirms: "Just to confirm — [date at time]?"
- Patient YES/NO → slot availability check with fail loop
- DB: appointment moved, AI badge shown on schedule grid
- Patient thanks → closing message

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 22:00:46 -04:00
Gitead
3abccf16a9 fix: use exclusive end-time boundary in office hours check
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>
2026-05-11 21:44:41 -04:00