229 lines
6.8 KiB
Python
229 lines
6.8 KiB
Python
from fastapi import FastAPI, Request, HTTPException
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
import uvicorn
|
|
import asyncio
|
|
from selenium_claimSubmitWorker import AutomationMassHealth
|
|
from selenium_eligibilityCheckWorker import AutomationMassHealthEligibilityCheck
|
|
from selenium_claimStatusCheckWorker import AutomationMassHealthClaimStatusCheck
|
|
from selenium_preAuthWorker import AutomationMassHealthPreAuth
|
|
import os
|
|
import time
|
|
import helpers_ddma_eligibility as hddma
|
|
|
|
from dotenv import load_dotenv
|
|
load_dotenv()
|
|
|
|
app = FastAPI()
|
|
# Allow 1 selenium session at a time
|
|
semaphore = asyncio.Semaphore(1)
|
|
|
|
# Manual counters to track active & queued jobs
|
|
active_jobs = 0
|
|
waiting_jobs = 0
|
|
lock = asyncio.Lock() # To safely update counters
|
|
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"], # Replace with your frontend domain for security
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# Endpoint: 1 — Start the automation of submitting Claim.
|
|
@app.post("/claimsubmit")
|
|
async def start_workflow(request: Request):
|
|
global active_jobs, waiting_jobs
|
|
data = await request.json()
|
|
|
|
async with lock:
|
|
waiting_jobs += 1
|
|
|
|
async with semaphore:
|
|
async with lock:
|
|
waiting_jobs -= 1
|
|
active_jobs += 1
|
|
|
|
try:
|
|
bot = AutomationMassHealth(data)
|
|
result = bot.main_workflow("https://providers.massdhp.com/providers_login.asp")
|
|
|
|
if result.get("status") != "success":
|
|
return {"status": "error", "message": result.get("message")}
|
|
|
|
return result
|
|
except Exception as e:
|
|
return {"status": "error", "message": str(e)}
|
|
finally:
|
|
async with lock:
|
|
active_jobs -= 1
|
|
|
|
# Endpoint: 2 — Start the automation of cheking eligibility
|
|
@app.post("/eligibility-check")
|
|
async def start_workflow(request: Request):
|
|
global active_jobs, waiting_jobs
|
|
data = await request.json()
|
|
|
|
async with lock:
|
|
waiting_jobs += 1
|
|
|
|
async with semaphore:
|
|
async with lock:
|
|
waiting_jobs -= 1
|
|
active_jobs += 1
|
|
try:
|
|
bot = AutomationMassHealthEligibilityCheck(data)
|
|
result = bot.main_workflow("https://providers.massdhp.com/providers_login.asp")
|
|
|
|
if result.get("status") != "success":
|
|
return {"status": "error", "message": result.get("message")}
|
|
|
|
return result
|
|
except Exception as e:
|
|
return {"status": "error", "message": str(e)}
|
|
finally:
|
|
async with lock:
|
|
active_jobs -= 1
|
|
|
|
# Endpoint: 3 — Start the automation of cheking claim status
|
|
@app.post("/claim-status-check")
|
|
async def start_workflow(request: Request):
|
|
global active_jobs, waiting_jobs
|
|
data = await request.json()
|
|
|
|
async with lock:
|
|
waiting_jobs += 1
|
|
|
|
async with semaphore:
|
|
async with lock:
|
|
waiting_jobs -= 1
|
|
active_jobs += 1
|
|
try:
|
|
bot = AutomationMassHealthClaimStatusCheck(data)
|
|
result = bot.main_workflow("https://providers.massdhp.com/providers_login.asp")
|
|
|
|
if result.get("status") != "success":
|
|
return {"status": "error", "message": result.get("message")}
|
|
|
|
return result
|
|
except Exception as e:
|
|
return {"status": "error", "message": str(e)}
|
|
finally:
|
|
async with lock:
|
|
active_jobs -= 1
|
|
|
|
# Endpoint: 4 — Start the automation of cheking claim pre auth
|
|
@app.post("/claim-pre-auth")
|
|
async def start_workflow(request: Request):
|
|
global active_jobs, waiting_jobs
|
|
data = await request.json()
|
|
|
|
async with lock:
|
|
waiting_jobs += 1
|
|
|
|
async with semaphore:
|
|
async with lock:
|
|
waiting_jobs -= 1
|
|
active_jobs += 1
|
|
try:
|
|
bot = AutomationMassHealthPreAuth(data)
|
|
result = bot.main_workflow("https://providers.massdhp.com/providers_login.asp")
|
|
|
|
if result.get("status") != "success":
|
|
return {"status": "error", "message": result.get("message")}
|
|
|
|
return result
|
|
except Exception as e:
|
|
return {"status": "error", "message": str(e)}
|
|
finally:
|
|
async with lock:
|
|
active_jobs -= 1
|
|
|
|
# Endpoint:5 - DDMA eligibility (background, OTP)
|
|
|
|
async def _ddma_worker_wrapper(sid: str, data: dict, url: str):
|
|
"""
|
|
Background worker that:
|
|
- acquires semaphore (to keep 1 selenium at a time),
|
|
- updates active/queued counters,
|
|
- runs the DDMA flow via helpers.start_ddma_run.
|
|
"""
|
|
global active_jobs, waiting_jobs
|
|
async with semaphore:
|
|
async with lock:
|
|
waiting_jobs -= 1
|
|
active_jobs += 1
|
|
try:
|
|
await hddma.start_ddma_run(sid, data, url)
|
|
finally:
|
|
async with lock:
|
|
active_jobs -= 1
|
|
|
|
|
|
@app.post("/ddma-eligibility")
|
|
async def ddma_eligibility(request: Request):
|
|
"""
|
|
Starts a DDMA eligibility session in the background.
|
|
Body: { "data": { ... }, "url"?: string }
|
|
Returns: { status: "started", session_id: "<uuid>" }
|
|
"""
|
|
global waiting_jobs
|
|
|
|
body = await request.json()
|
|
data = body.get("data", {})
|
|
|
|
# create session
|
|
sid = hddma.make_session_entry()
|
|
hddma.sessions[sid]["type"] = "ddma_eligibility"
|
|
hddma.sessions[sid]["last_activity"] = time.time()
|
|
|
|
async with lock:
|
|
waiting_jobs += 1
|
|
|
|
# run in background (queued under semaphore)
|
|
asyncio.create_task(_ddma_worker_wrapper(sid, data, url="https://providers.deltadentalma.com/onboarding/start/"))
|
|
|
|
return {"status": "started", "session_id": sid}
|
|
|
|
|
|
@app.post("/submit-otp")
|
|
async def submit_otp(request: Request):
|
|
"""
|
|
Body: { "session_id": "<sid>", "otp": "123456" }
|
|
Node / frontend call this when user provides OTP.
|
|
"""
|
|
body = await request.json()
|
|
sid = body.get("session_id")
|
|
otp = body.get("otp")
|
|
if not sid or not otp:
|
|
raise HTTPException(status_code=400, detail="session_id and otp required")
|
|
|
|
res = hddma.submit_otp(sid, otp)
|
|
if res.get("status") == "error":
|
|
raise HTTPException(status_code=400, detail=res.get("message"))
|
|
return res
|
|
|
|
|
|
@app.get("/session/{sid}/status")
|
|
async def session_status(sid: str):
|
|
s = hddma.get_session_status(sid)
|
|
if s.get("status") == "not_found":
|
|
raise HTTPException(status_code=404, detail="session not found")
|
|
return s
|
|
|
|
|
|
# ✅ Status Endpoint
|
|
@app.get("/status")
|
|
async def get_status():
|
|
async with lock:
|
|
return {
|
|
"active_jobs": active_jobs,
|
|
"queued_jobs": waiting_jobs,
|
|
"status": "busy" if active_jobs > 0 or waiting_jobs > 0 else "idle"
|
|
}
|
|
|
|
if __name__ == "__main__":
|
|
host = os.getenv("HOST")
|
|
port = int(os.getenv("PORT"))
|
|
uvicorn.run(app, host=host, port=port)
|