Commit Graph

246 Commits

Author SHA1 Message Date
e60110226b chore: remove all .jsx files from Frontend src
Vite resolves .tsx before .jsx (per extensions order in vite.config.ts),
so .jsx files were never loaded at runtime. Switching to TSX-only source.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 21:40:59 -04:00
00fd213291 feat: add Dental Office Name to Lab RX form, pre-filled from office contact settings
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 21:21:59 -04:00
191ed129d8 feat: replace DOB with Age in Lab RX form, auto-calculated from patient DOB
Age is pre-filled when opening the RX popup by calculating from patient.dateOfBirth.
The field is editable in case of override. Both preview card and print output
now show Age instead of DOB.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 21:06:44 -04:00
305a07874d fix: add selenium-settings-card.jsx and wire it into settings-page.jsx
selenium-settings-card.jsx didn't exist and settings-page.jsx was missing
the import and case "selenium" handler, so the Selenium settings section
was invisible on other PCs running the .jsx files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:13:49 -04:00
6e779fc630 fix: update lab-management-tab.jsx and add lab-rx-modal.jsx
JSX files were missing the Lab RX feature — lab-management-tab.jsx still had
the old lab order table UI, and lab-rx-modal.jsx didn't exist. The app on
other PCs runs .jsx files, so git pull wasn't showing the new Lab RX feature.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:12:10 -04:00
ce2e03e505 feat: pre-fill doctor name with default NPI provider in Lab RX popup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02 23:55:23 -04:00
75ecd7cc20 feat: add Selenium Settings page to configure paymentGroupId per office
Adds a new Settings → Advanced → Selenium Settings page where the office
name (paymentGroupId) used in United/DentalHub portal dropdowns can be
configured without touching code. Previously hardcoded as "Summit Dental
Care"; now injected from DB into the three United workers at job dispatch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02 23:53:43 -04:00
abb2a0ac96 feat: add Lab RX feature with template management and auto-seed defaults
- New lab_rx_template table with sortOrder and Prisma migrations
- Backend CRUD + reorder routes at /api/lab-rx/templates
- Auto-seeds 3 Highland Dental Studio defaults on first use per user
- LabRxModal: template picker, inline rename, up/down reorder, full
  template form with sections (Template Name / Lab Info / Case Details)
- RX popup: Tooth Number, Shade, Due Date, Doctor (from NPI providers),
  Instructions pre-filled with "Please make / Thank you!", print output
- lab-rx-templates.ts config file for future git-managed additions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02 23:20:44 -04:00
ac4d8c4c74 feat: add lab management layout, barcode generation, and dental education page
- Redesign lab management tab with patient search table and action buttons
- Add react-barcode integration: generates CODE128 barcode from patient name with print and download support
- Add Dental Education page and sidebar entry between Cloud Storage and AI Input Agent

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02 13:03:58 -04:00
998ef0ac95 feat: add POE and period exam aliases → D0120 in CDT lookup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 23:58:56 -04:00
15a1091f35 fix: stop premature chatbot claim queue advance + skip preview popup mid-batch
handleClaimSubmit advanced the chatbot batch claim queue right after creating
the DB claim record, before the Selenium job even ran. This caused only the
last patient in a multi-patient claim batch to get its PDF saved to
Documents — earlier patients' job tracking got overwritten by the next
patient's submission before their PDF download could complete.

Also make advanceChatbotClaimQueue() report whether it navigated to another
queued patient, and skip the auto PDF preview popup in that case so it only
opens for the last/standalone claim.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 23:44:21 -04:00
26da3394aa fix: extract appointmentDate for multi_claim/batch_claim/preauth intents
The classifier prompt only told the AI that appointmentDate applies to
schedule_appointment/claim_only/check_and_claim, so a trailing date like
"all on 6/23/26" was dropped for multi-patient claims even though the
workflow already reads c.appointmentDate for those intents and silently
defaulted to today.

Also add Prisma config/seed scripts and shopping-vendor types/schema updates.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 22:52:48 -04:00
cdda91f2b4 feat: add multi_claim intent for different procedures per patient + fix batch claim PDF race
- Add multi_claim intent so AI correctly handles "claim X for patient A and Y for patient B"
  instead of applying all procedures to all patients (batch_claim)
- Each patient carries their own matchedCodes in the queue
- Fix batch claim PDF race condition: chatbot queue no longer advances in closeClaim(),
  instead advances after selenium PDF is downloaded (matching column claim behavior)
- Align United SCO eligibility worker with claim worker: only fill subscriber ID + DOB,
  use treatmentLocation by ID instead of arrow-wrapper click

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 01:08:41 -04:00
cb49298b66 fix: teach AI to recognize recement and fix missing service date in column claim
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>
2026-06-29 00:02:26 -04:00
31505af72d fix: pass chatbot attachments to Selenium claim worker and add missing re import
- Add `import re` to all Selenium workers that use re.search() for claim number extraction
- Pass uploadedFiles to onHandleForMHSeleniumClaim so attachments reach the MH website
- Save chatbot pending files in check-and-claim and batch-check-and-claim flows

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 23:30:28 -04:00
e1fe4862d5 fix: allow claims without appointment + support post/core multi-tooth input
- Make appointmentId nullable/optional in Prisma Zod schema via @zod rich
  comment so claims can be submitted without an existing appointment
- Convert undefined appointmentId to null in all claim form handlers and
  the backend claim creation endpoint
- Add AI classifier rule for expanding one procedure across multiple
  comma-separated tooth numbers (e.g. "post/core on #23, 24, 25, 26")
- Add "post/core" (slash) alias to CDT lookup maps

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 22:57:24 -04:00
c9d08028a9 feat: teach AI classifier to recognize "comp" and tooth surface notation
Add "comp" as alias for composite in CDT lookup. Update classifier
prompt with explicit examples for "claim comp #8 ml for lisa today"
and dental surface letter definitions (M/D/L/F/B/O/V/I) so the LLM
correctly treats #tooth+surfaces as composite fillings, not insurance.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 20:55:41 -04:00
fc3e8c0e25 feat: add Auto Check MH Payment toggle with weekly schedule
Adds a toggle behind the Go button on the Payments page to automatically run the MH batch payment check on a user-selected day of week and hour. Default is off.

- Schema: added autoMhCheckEnabled, autoMhCheckDayOfWeek, autoMhCheckHour to User model
- Backend: new mhBatchPaymentService (shared logic), GET/PUT /auto-mh-check-setting routes, hourly cron job that fires on matching day+hour
- Frontend: toggle + day select (Mon–Sun) + time select (hourly) that persist immediately to DB

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 22:58:36 -04:00
Summit Dental Care
27d9132820 fix: use in-memory startedAt for cron job log to survive DB restore
The auto-import wipes the database, destroying the cronJobLog record
created at the start of the job. Now duration is calculated from a
local variable instead of querying the DB, and if the record is gone
a fresh log entry is created in the restored database.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 22:55:07 -04:00
1edf73fdc8 feat: add new frontend components, MH batch worker, and gitignore rules
- Add all new Frontend source files (pages, components, hooks, utils)
- Add selenium_MHBatchPaymentCheckWorker.py and MHSinglePaymentCheckWorker.py
- Add install-steps-5-13.sh setup script
- Update .gitignore to exclude runtime/sensitive data (backups, uploads,
  chat-history, keys, downloads, generated .d.ts files) while keeping folders
- Add .gitkeep to preserve empty runtime folders in git

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 00:23:43 -04:00
b7e06adf2f feat: MassHealth PDF import auto-pays full balance + patient name fix
- PDF import now marks payments as PAID when MassHealth patient's
  mhPaidAmount >= totalBilled (no patient balance)
- Newly created patients from MH vouchers get insuranceProvider = 'MassHealth'
- Existing patients with blank insuranceProvider get it filled on import
- Fix: update patient name from PDF if existing record has empty name
- Various frontend/selenium/route updates

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 00:16:31 -04:00
9efe5c8469 feat: add Auto Claim toggle with hourly time picker to AI column claim section
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 20:48:35 -04:00
Summit Dental Care
7deba90db3 fix: use prisma db push after backup import to sync schema reliably
applyMissingMigrations ran the entire migration SQL as one transaction,
which rolled back all changes when any statement failed (e.g. adding a
NOT NULL column to a non-empty table). Replaced with prisma db push
which compares the schema and applies only what's needed. Also added
support for importing .sql files (not just .zip) in auto-import.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 16:05:18 -04:00
Summit Dental Care
f93fef56aa docs: move rclone install to Step 7 with other system dependencies
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 00:28:30 -04:00
Summit Dental Care
3d0af3bcb6 docs: add rclone install step to README setup guide
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 00:09:57 -04:00
ff
99a54cee9a feat: rclone syncs all 3 folders (backups, chat-history, uploads)
WebDAV server now serves the Backend root directory. Receiver pulls
backups/, chat-history/, and uploads/ individually so all data is
synced between PCs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 23:50:40 -04:00
ff
cbe7d13dd2 feat: add auto-import toggle to restore latest backup after rclone pull
Adds autoImportEnabled/autoImportHour to rclone config. A separate
hourly cron finds the latest .zip in backups/ and restores it to the
database (drop schema, psql restore, apply migrations). Frontend shows
toggle + time picker + Import Now button in the Receiver PC section.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 23:45:15 -04:00
ff
70b5e2ba47 feat: add configurable backup time for local and USB backups
Replace hardcoded 8 PM / 9 PM backup schedules with user-selectable
hour dropdowns. Adds autoBackupHour and usbBackupHour fields to User
model. Cron jobs now check every hour against the configured time.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 23:37:34 -04:00
ff
5e881c9ff7 feat: integrate rclone WebDAV backup for PC-to-PC file sync
Source PC serves backups/ folder via rclone WebDAV server (auto-starts with app).
Receiver PC pulls backups on schedule using rclone sync.
Network Backup UI now has two tabs: Rclone and API Key.
Rclone installed automatically via postinstall script.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 23:29:36 -04:00
24e66bfaf9 fix: select Treatment Location by ID click like Billing Entity in UnitedDH claim step1
Replaces arrow-wrapper click (which hit the "Type to search" placeholder) with
find_element(By.ID, "treatmentLocation") + click, mirroring the paymentGroupId
approach. Looks for "Summit Dental Care" first, falls back to first available option.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 14:41:26 -04:00
528a30efc6 fix: recognize limited exam, 1 PA (#tooth), composite # NN surfaces, and check [patient name]
- Add limited exam / emergency exam → D0140 to DIRECT_CODE_MAP for reliable lookup
- Fix parseCompositeCode regex to allow space between # and digit (# 10 DL, # 11 ML)
- Strip empty parens from strippedCleaned so "1 pa (#13)" → "1 pa" hits DIRECT_CODE_MAP
- LLM prompt: add single-PA-with-tooth examples (1 PA (#13) → ["1 pa, #13"])
- LLM prompt: clarify check_eligibility vs navigate_eligibility — "check Qu" is patient name, not insurance

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 09:05:33 -04:00
Summit Dental Care
8154e904b9 security: restrict network-backup endpoints to LAN IPs only
Requests from outside 10.x, 192.168.x, 172.16-31.x, 127.x are rejected
with 403 before the API key is even checked. This prevents the database
dump endpoint from being reachable from the internet even if the key leaked.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 23:53:28 -04:00
Summit Dental Care
fcf6effb7b fix: move network-backup endpoints outside JWT auth middleware
The /network-backup and /network-backup-files routes use their own
X-Network-Backup-Key authentication. Mounting them behind authenticateJWT
blocked all receiver sync requests before they could be validated.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 23:50:19 -04:00
Summit Dental Care
cee84bcd61 feat: add eye icon toggle to source PC API key field
Allows verifying the pasted key is correct before saving.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 23:34:07 -04:00
Summit Dental Care
8572f44386 fix: move network sync form population out of queryFn into useEffect
Side effects inside queryFn caused the enabled toggle and other fields to
reset on refetch because SyncStatus shares the same query key with a
different queryFn, making formLoaded unreliable.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 23:32:04 -04:00
Summit Dental Care
8e18e96db4 fix: trim whitespace from network sync URL and API key; clarify source URL format in UI
Copy-paste often adds trailing whitespace that breaks the API key comparison.
Updated placeholder and description to show the correct URL format (no port number).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 23:14:00 -04:00
a2621eba6c fix: recognize NPA shorthand and ordinal PA names (3rd pa → D0230)
- Add parseMultiPaCode: "4PA #3 #14 #19 #30" expands to D0220 + 3× D0230 with tooth numbers
- Add "3rd pa"–"6th pa" direct aliases → D0230 as fallback
- Tighten LLM prompt to always use "2nd pa" for all additional PAs, never "3rd pa" etc.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 12:15:22 -04:00
91adac89e5 fix: AI claim queue restart from first patient; recognize D7210 # 32 in notes
- 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>
2026-06-22 10:31:03 -04:00
029a0e9d53 fix: hardcode LICENSE_SECRET default so no .env setup needed on new installs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 00:13:02 -04:00
ff
921ecbe10a docs: add security setup section to README — passwd, root password, SSH check
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 15:51:15 -04:00
ff
0139f89e2f feat: drag-to-resize appointment blocks on schedule to adjust duration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 00:39:38 -04:00
ff
20b478a7a9 fix: United claim — add procedure date, fix file attachments, persist chatbot files, enforce M/D/YYYY date parsing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 00:42:43 -04:00
ff
60689e58f6 feat: batch eligibility by patient name + "Check All & Appointment Today" option
- Add batch_eligibility_by_name intent so "check Mary and Sinthia" resolves multiple names
- Add "Check All & Appointment Today" button to batch eligibility UI — creates appointment for each patient after their eligibility check completes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 23:32:05 -04:00
ff
e081f32648 fix: DentaQuest/Tufts eligibility PDF — switch to landscape to capture all columns
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 20:30:47 -04:00
ff
9f0e2514b0 fix: rename pre-auth PDF group title from "Claims Preauth" to "Preauth"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 20:24:42 -04:00
ff
a52ff2d723 feat: batch eligibility, batch claim, and batch check+claim from AI chat
- Add batch_eligibility, batch_claim, and batch_check_and_claim intents
  to AI classifier so multiple patients can be processed one by one
- Add queue processing on insurance-status and claims pages to auto-start
  the next patient after each check/claim completes
- Make patient schema firstName, lastName, phone optional so patients can
  be created with just member ID + DOB from eligibility checks
- Cancel buttons now preserve chat history instead of clearing it
- Patient-found card shows Check Eligibility, Eligibility & Appointment
  Today, and Cancel buttons
- Claim service date asks user to pick between latest appointment and
  today when they differ
- Login page subtitle styled with animated gradient

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 23:41:56 -04:00
ff
a2e5c157ad feat: persist AI chat history to server-side JSON file
Chat history was stored only in sessionStorage, causing member ID and DOB
to be lost when the session expired or corrupted — requiring logout/login.
Now history is saved to a per-user JSON file on the backend and loaded on
mount, so the LLM always has full conversation context.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 17:11:13 -04:00
ff
092f0778fe fix: DDMA eligibility worker — extract name from row, pass DOB from input, wait for page load
- Extract patient name from search results row instead of failing on detail page
- Return dateOfBirth from input data (no need to scrape from webpage)
- Wait for search page to fully load before provider dropdown selection
- Add 3s wait after search results appear for row content to render
- Backend: fallback to update existing patient DOB instead of creating duplicate

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 15:06:45 -04:00
ff
6958d13282 fix: pass DOB from chatbot through to claim form for DDMA claims
The chatbot-extracted DOB was stored in chatbot_claim_codes but never
forwarded to chatbot_claim_prefill, leaving the claim form DOB empty
when the patient DB record lacked it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 13:58:12 -04:00
ff
3e919ec1c5 feat: AI-powered login page with daily greeting and animated blob background
- Add public /api/greeting endpoint that generates a daily AI greeting (cached per day)
- Replace static hero text with dynamic AI greeting (ChatGPT/Claude style)
- Add Stripe-style animated gradient blobs with 14 daily-rotating color palettes
- Use Plus Jakarta Sans font and Sparkles icon for modern AI look
- Update subtitle to "Driven by multiple AI agents"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 00:14:32 -04:00