feat: MassHealth member detail demographics, wait for name/plan before PDF
- Extract gender, address (street/city/state/zip) and home phone from the MassHealth Member Detail page and save to the patient; phone is only filled when the patient has none - Shared extract_eligibility_row polls up to 30s until the matching results row has both name and plan before the PDF is printed (AngularJS fills cell text after the rows appear); used by all three MH eligibility workers - Fall back to the Member Detail heading for the name when the results table never filled it in Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
import re
|
||||
|
||||
from selenium.webdriver.common.by import By
|
||||
|
||||
# Labels shown in the MassHealth Member Detail block, e.g.
|
||||
# Date of Birth: 4/21/1958
|
||||
# Gender: Female
|
||||
# Address: 169 CYPRESS ST, NEWTON, MA 02459
|
||||
# Home Phone: 6036789376
|
||||
# Registered Not Registered in Member Community
|
||||
_LABELS = ("Date of Birth", "Gender", "Address", "Home Phone", "Phone", "Registered")
|
||||
|
||||
|
||||
def _label_value(text, label):
|
||||
"""Value next to "Label:" — same line or the next line (innerText of a
|
||||
two-column layout can put the value on its own line). Empty when the
|
||||
portal leaves the field blank."""
|
||||
m = re.search(rf"(?:^|\n)[ \t]*{re.escape(label)}:[ \t]*\n?[ \t]*([^\n]*)", text)
|
||||
if not m:
|
||||
return ""
|
||||
value = m.group(1).strip()
|
||||
# Blank field — we grabbed the next row's label instead of a value
|
||||
if value.endswith(":") or any(value.startswith(f"{l}:") or value == l for l in _LABELS):
|
||||
return ""
|
||||
return value
|
||||
|
||||
|
||||
def extract_member_demographics(driver):
|
||||
"""Read gender, address and phone from the MassHealth Member Detail page.
|
||||
|
||||
Returns only the fields that were found:
|
||||
gender — "Female" / "Male" as shown by the portal
|
||||
address, city, state, zipCode — split from "STREET, CITY, ST 12345"
|
||||
phone — 10 digits
|
||||
memberName — the heading above "Date of Birth:" (e.g. "OLHA SVYSHCH")
|
||||
"""
|
||||
result = {}
|
||||
try:
|
||||
text = driver.find_element(By.TAG_NAME, "body").get_attribute("innerText") or ""
|
||||
|
||||
# Name is the last non-empty line before the "Date of Birth:" row
|
||||
dob = re.search(r"(?:^|\n)[ \t]*Date of Birth:", text)
|
||||
if dob:
|
||||
lines = [l.strip() for l in text[:dob.start()].split("\n") if l.strip()]
|
||||
if lines and ":" not in lines[-1]:
|
||||
result["memberName"] = lines[-1]
|
||||
|
||||
gender = _label_value(text, "Gender")
|
||||
if gender:
|
||||
result["gender"] = gender
|
||||
|
||||
address = _label_value(text, "Address")
|
||||
if address:
|
||||
# "169 CYPRESS ST, NEWTON, MA 02459" — street may itself contain commas (APT 2)
|
||||
m = re.match(r"^(.*),\s*([^,]+?),?\s+([A-Z]{2})\s+(\d{5})(?:-?\d{4})?$", address)
|
||||
if m:
|
||||
result["address"] = m.group(1).strip()
|
||||
result["city"] = m.group(2).strip()
|
||||
result["state"] = m.group(3)
|
||||
result["zipCode"] = m.group(4)
|
||||
else:
|
||||
result["address"] = address
|
||||
|
||||
phone = _label_value(text, "Home Phone") or _label_value(text, "Phone")
|
||||
digits = re.sub(r"\D", "", phone)
|
||||
if len(digits) == 11 and digits.startswith("1"):
|
||||
digits = digits[1:]
|
||||
if len(digits) == 10:
|
||||
result["phone"] = digits
|
||||
|
||||
print(f"[extract_member_demographics] {result}")
|
||||
except Exception as e:
|
||||
print(f"[extract_member_demographics] failed: {e}")
|
||||
return result
|
||||
Reference in New Issue
Block a user