From bb10ff6dac2c760baabc2d82374f38073966e68a Mon Sep 17 00:00:00 2001 From: Jack Levy Date: Sun, 15 Mar 2026 10:58:50 -0400 Subject: [PATCH] =?UTF-8?q?fix:=20ZIP=20rep=20lookup=20=E2=80=94=20correct?= =?UTF-8?q?=20TIGERweb=20field=20names=20for=20119th=20Congress?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Actual API fields are STATE (not STATEFP) and CD119 (not CD119FP). GEOID primary path works for regular districts; fallback now uses STATE + CD\d+ pattern confirmed against live TIGERweb responses. Authored by: Jack Levy --- backend/app/api/members.py | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/backend/app/api/members.py b/backend/app/api/members.py index 8c02050..eeb6b55 100644 --- a/backend/app/api/members.py +++ b/backend/app/api/members.py @@ -94,9 +94,8 @@ async def get_members_by_zip(zip_code: str, db: AsyncSession = Depends(get_db)): continue attrs = item.get("attributes", {}) - # GEOID / GEOID20 — 2-char state FIPS + 2-char district (e.g. "0618" = CA-18) - # 119th Congress layers use GEOID20 (2020 Census vintage) - geoid = str(attrs.get("GEOID") or attrs.get("GEOID20") or "").strip() + # Primary: GEOID = 2-char state FIPS + 2-char district (e.g. "0630" = CA-30) + geoid = str(attrs.get("GEOID") or "").strip() if len(geoid) == 4 and geoid.isdigit(): state_fips = geoid[:2] district_fips = geoid[2:] @@ -105,12 +104,12 @@ async def get_members_by_zip(zip_code: str, db: AsyncSession = Depends(get_db)): if state_code: break - # Fallback: explicit field names (e.g. CD119FP + STATEFP20) - cd_field = next((k for k in attrs if re.match(r"CD\d+FP$", k)), None) - state_field = next((k for k in attrs if "STATEFP" in k.upper()), None) - if cd_field and state_field: + # Fallback: STATE + CD{session} fields (e.g. STATE="06", CD119="30") + state_val = attrs.get("STATE") + cd_field = next((k for k in attrs if re.match(r"CD\d+$", k)), None) + if state_val and cd_field: try: - state_fips = str(attrs[state_field]).zfill(2) + state_fips = str(state_val).zfill(2) district_fips = str(attrs[cd_field]).zfill(2) state_code = _FIPS_TO_STATE.get(state_fips) district_num = str(int(district_fips)) if district_fips.strip("0") else None @@ -119,11 +118,6 @@ async def get_members_by_zip(zip_code: str, db: AsyncSession = Depends(get_db)): except (ValueError, TypeError): pass - logger.debug( - "ZIP %s: could not parse layer %r — attrs: %s", - zip_code, item.get("layerName"), list(attrs.keys()), - ) - if not state_code: logger.warning( "ZIP %s: no CD found. Layers: %s",