feat: United/DentalHub + Tufts SCO pre-auth, cloud storage search & file thumbnails

- Add United/DentalHub pre-authorization Selenium worker, helpers, backend route/processor/client, and frontend OTP modal + wired button
- Add Tufts SCO pre-authorization Selenium worker, helpers, backend route/processor/client, and frontend OTP modal + wired button
- Fix btnSubmitAuthorization selector for UnitedDH preauth step2
- Fix Tufts SCO preauth step3 to target <span>pre-authorization</span> button
- Cloud storage search: default to "both" mode so patient folder names match on first search
- Cloud storage folder panel: auto-scroll to panel when opened from search results
- Cloud storage files: show inline image thumbnails and PDF badge in file grid

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
ff
2026-06-13 00:03:58 -04:00
parent fd4feb3e76
commit 3978b16d7d
20 changed files with 4044 additions and 19 deletions

View File

@@ -22,7 +22,9 @@ import helpers_cca_claim as hcca_claim
import helpers_cca_preauth as hcca_preauth
import helpers_ddma_claim as hddma_claim
import helpers_uniteddh_claim as huniteddh_claim
import helpers_uniteddh_preauth as huniteddh_preauth
import helpers_tuftssco_claim as htuftssco_claim
import helpers_tuftssco_preauth as htuftssco_preauth
import helpers_bcbs_ma_eligibility as hbcbs_ma
# Import startup session-clear functions
@@ -757,6 +759,90 @@ async def tuftssco_claim(request: Request):
return {"status": "started", "session_id": sid}
async def _uniteddh_preauth_worker_wrapper(sid: str, data: dict, url: str):
"""Background worker for United/DentalHub pre-authorization submission."""
global active_jobs, waiting_jobs
async with semaphore:
async with lock:
waiting_jobs -= 1
active_jobs += 1
try:
await huniteddh_preauth.start_uniteddh_preauth_run(sid, data, url)
finally:
async with lock:
active_jobs -= 1
@app.post("/uniteddh-preauth")
async def uniteddh_preauth(request: Request):
"""
Starts a United/DentalHub pre-authorization session in the background.
Logs in (persistent session, OTP on first use), searches patient, clicks Submit
Pre-Authorization, fills the form and submits.
Body: { "claim": { "uniteddhUsername": "...", "uniteddhPassword": "...", ... } }
Returns: { status: "started", session_id: "<uuid>" }
"""
global waiting_jobs
body = await request.json()
sid = huniteddh_preauth.make_session_entry()
huniteddh_preauth.sessions[sid]["type"] = "uniteddh_preauth"
huniteddh_preauth.sessions[sid]["last_activity"] = time.time()
async with lock:
waiting_jobs += 1
asyncio.create_task(_uniteddh_preauth_worker_wrapper(
sid, body,
url="https://app.dentalhub.com/app/login"
))
return {"status": "started", "session_id": sid}
async def _tuftssco_preauth_worker_wrapper(sid: str, data: dict, url: str):
"""Background worker for Tufts SCO (DentaQuest) pre-authorization submission."""
global active_jobs, waiting_jobs
async with semaphore:
async with lock:
waiting_jobs -= 1
active_jobs += 1
try:
await htuftssco_preauth.start_tuftssco_preauth_run(sid, data, url)
finally:
async with lock:
active_jobs -= 1
@app.post("/tuftssco-preauth")
async def tuftssco_preauth(request: Request):
"""
Starts a Tufts SCO (DentaQuest) pre-authorization session in the background.
Logs in (persistent session, OTP on first use), searches patient, clicks
Create Prior Authorization, fills the form and submits.
Body: { "claim": { "dentaquestUsername": "...", "dentaquestPassword": "...", ... } }
Returns: { status: "started", session_id: "<uuid>" }
"""
global waiting_jobs
body = await request.json()
sid = htuftssco_preauth.make_session_entry()
htuftssco_preauth.sessions[sid]["type"] = "tuftssco_preauth"
htuftssco_preauth.sessions[sid]["last_activity"] = time.time()
async with lock:
waiting_jobs += 1
asyncio.create_task(_tuftssco_preauth_worker_wrapper(
sid, body,
url="https://providers.dentaquest.com/"
))
return {"status": "started", "session_id": sid}
async def _cca_preauth_worker_wrapper(sid: str, data: dict, url: str):
"""Background worker for CCA pre-authorization submission."""
global active_jobs, waiting_jobs
@@ -823,8 +909,12 @@ async def submit_otp(request: Request):
res = hddma_claim.submit_otp(sid, otp)
elif sid in huniteddh_claim.sessions:
res = huniteddh_claim.submit_otp(sid, otp)
elif sid in huniteddh_preauth.sessions:
res = huniteddh_preauth.submit_otp(sid, otp)
elif sid in htuftssco_claim.sessions:
res = htuftssco_claim.submit_otp(sid, otp)
elif sid in htuftssco_preauth.sessions:
res = htuftssco_preauth.submit_otp(sid, otp)
elif sid in hbcbs_ma.sessions:
res = hbcbs_ma.submit_otp(sid, otp)
else:
@@ -856,8 +946,12 @@ async def session_status(sid: str):
s = hddma_claim.get_session_status(sid)
elif sid in huniteddh_claim.sessions:
s = huniteddh_claim.get_session_status(sid)
elif sid in huniteddh_preauth.sessions:
s = huniteddh_preauth.get_session_status(sid)
elif sid in htuftssco_claim.sessions:
s = htuftssco_claim.get_session_status(sid)
elif sid in htuftssco_preauth.sessions:
s = htuftssco_preauth.get_session_status(sid)
elif sid in hbcbs_ma.sessions:
s = hbcbs_ma.get_session_status(sid)
else: