Add Playwright automation for BOC-3 filing on processagent.com
- boc3_playwright.py: 4-step form automation (company info, contact, account, payment) using patchright/undetected Playwright - Payment with PW company card ($25/filing), credentials from env - CAPTCHA detection — falls back to admin todo if reCAPTCHA triggers - boc3_filing.py: process() tries Playwright first, falls back to manual admin todo on failure - Env vars needed: PW_CARD_NUMBER, PW_CARD_CVC, PW_CARD_EXP_MONTH, PW_CARD_EXP_YEAR, BOC3_ACCOUNT_PASSWORD Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
584f887f82
commit
46411c09c6
2 changed files with 489 additions and 5 deletions
|
|
@ -35,6 +35,7 @@ Filing flow:
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
|
|
@ -63,8 +64,53 @@ class BOC3FilingHandler:
|
|||
SERVICE_NAME = "BOC-3 Process Agent Filing"
|
||||
|
||||
async def process(self, order_data: dict) -> list[str]:
|
||||
"""Entry point called by job_server. Delegates to handle()."""
|
||||
"""Entry point called by job_server. Tries Playwright, falls back to handle()."""
|
||||
order_number = order_data.get("order_number", order_data.get("name", ""))
|
||||
|
||||
intake = order_data.get("intake_data") or {}
|
||||
if isinstance(intake, str):
|
||||
intake = json.loads(intake)
|
||||
|
||||
dot_number = intake.get("dot_number", "")
|
||||
customer_email = order_data.get("customer_email", "")
|
||||
|
||||
# Try Playwright automation if credentials are configured
|
||||
if dot_number and os.environ.get("PW_CARD_NUMBER") and os.environ.get("BOC3_ACCOUNT_PASSWORD"):
|
||||
try:
|
||||
from .boc3_playwright import BOC3ProcessAgent
|
||||
adapter = BOC3ProcessAgent()
|
||||
result = await adapter.file_boc3({
|
||||
"dot_number": dot_number,
|
||||
"docket_number": intake.get("docket_number", ""),
|
||||
"legal_name": intake.get("entity_name", order_data.get("customer_name", "")),
|
||||
"entity_type": intake.get("entity_type", "carrier"),
|
||||
"contact": {
|
||||
"first_name": (order_data.get("customer_name") or "").split()[0] if order_data.get("customer_name") else "",
|
||||
"last_name": " ".join((order_data.get("customer_name") or "").split()[1:]),
|
||||
"phone": intake.get("phone", ""),
|
||||
"street": intake.get("address_street", ""),
|
||||
"city": intake.get("address_city", ""),
|
||||
"state": intake.get("address_state", ""),
|
||||
"zip": intake.get("address_zip", ""),
|
||||
},
|
||||
"email": customer_email,
|
||||
})
|
||||
if result.success:
|
||||
LOG.info("[%s] BOC-3 filed via Playwright! Order: %s", order_number, result.order_id)
|
||||
self._send_confirmation_email(
|
||||
order_number,
|
||||
intake.get("entity_name", order_data.get("customer_name", "")),
|
||||
dot_number, customer_email,
|
||||
)
|
||||
return []
|
||||
elif result.captcha_hit:
|
||||
LOG.warning("[%s] CAPTCHA on processagent.com — falling back to admin todo", order_number)
|
||||
else:
|
||||
LOG.warning("[%s] Playwright filing failed: %s — admin todo", order_number, result.error)
|
||||
except Exception as exc:
|
||||
LOG.warning("[%s] Playwright error: %s — admin todo", order_number, exc)
|
||||
|
||||
# Fall back to manual admin todo
|
||||
return self.handle(order_data, order_number)
|
||||
|
||||
def handle(self, order_data: dict, order_number: str) -> list[str]:
|
||||
|
|
@ -111,10 +157,7 @@ class BOC3FilingHandler:
|
|||
"requested_at": datetime.utcnow().isoformat(),
|
||||
}
|
||||
|
||||
# TODO: Automate via Playwright on processagent.com/order
|
||||
# For now, create admin todo for manual filing
|
||||
|
||||
# Create admin todo
|
||||
# Create admin todo for manual filing (Playwright attempt already made in process())
|
||||
todo_data = {
|
||||
"order_number": order_number,
|
||||
"service": self.SERVICE_NAME,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue