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>
This commit is contained in:
Gitead
2026-05-22 13:34:03 -04:00
parent 58b2e4af93
commit 0e664e4813
21 changed files with 4768 additions and 77 deletions

View File

@@ -18,6 +18,7 @@ import helpers_deltains_eligibility as hdeltains
import helpers_unitedsco_eligibility as hunitedsco
import helpers_dentaquest_eligibility as hdentaquest
import helpers_cca_eligibility as hcca
import helpers_cca_claim as hcca_claim
# Import startup session-clear functions
from ddma_browser_manager import clear_ddma_session_on_startup
@@ -542,6 +543,47 @@ async def cca_eligibility(request: Request):
return {"status": "started", "session_id": sid}
async def _cca_claim_worker_wrapper(sid: str, data: dict, url: str):
"""Background worker for CCA claim submission."""
global active_jobs, waiting_jobs
async with semaphore:
async with lock:
waiting_jobs -= 1
active_jobs += 1
try:
await hcca_claim.start_cca_claim_run(sid, data, url)
finally:
async with lock:
active_jobs -= 1
@app.post("/cca-claim")
async def cca_claim(request: Request):
"""
Starts a CCA claim submission session in the background.
Logs in, navigates Claims > Submit Claims, opens claim entry page.
Body: { "claim": { "cca_username": "...", "cca_password": "...", ... } }
Returns: { status: "started", session_id: "<uuid>" }
"""
global waiting_jobs
body = await request.json()
sid = hcca_claim.make_session_entry()
hcca_claim.sessions[sid]["type"] = "cca_claim"
hcca_claim.sessions[sid]["last_activity"] = time.time()
async with lock:
waiting_jobs += 1
asyncio.create_task(_cca_claim_worker_wrapper(
sid, body,
url="https://pwp.sciondental.com/PWP/Landing"
))
return {"status": "started", "session_id": sid}
@app.post("/submit-otp")
async def submit_otp(request: Request):
"""
@@ -584,6 +626,8 @@ async def session_status(sid: str):
s = hdentaquest.get_session_status(sid)
elif sid in hcca.sessions:
s = hcca.get_session_status(sid)
elif sid in hcca_claim.sessions:
s = hcca_claim.get_session_status(sid)
else:
s = {"status": "not_found"}
if s.get("status") == "not_found":