From 4cada298abe9e2a5fa6c4d4cf7a62a9d5a35cde2 Mon Sep 17 00:00:00 2001 From: Jack Levy Date: Sun, 15 Mar 2026 10:29:09 -0400 Subject: [PATCH] =?UTF-8?q?fix:=20ZIP=20rep=20lookup=20=E2=80=94=20handle?= =?UTF-8?q?=20GEOID20=20for=20119th=20Congress=20TIGERweb=20layers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 119th Congressional Districts layer uses 2020 Census vintage field names (GEOID20, STATEFP20, CD119FP) instead of GEOID. The GEOID check was silently falling through; added GEOID20 fallback, isdigit() guard, try/except on CD field parsing, and debug logging of unparseable layers. Authored by: Jack Levy --- backend/app/api/members.py | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/backend/app/api/members.py b/backend/app/api/members.py index 1b965a8..8c02050 100644 --- a/backend/app/api/members.py +++ b/backend/app/api/members.py @@ -93,9 +93,11 @@ async def get_members_by_zip(zip_code: str, db: AsyncSession = Depends(get_db)): if "Congressional" not in (item.get("layerName") or ""): continue attrs = item.get("attributes", {}) - # GEOID = 2-char state FIPS + 2-char district (e.g. "1218" = FL-18) - geoid = str(attrs.get("GEOID") or "").strip() - if len(geoid) == 4: + + # 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() + if len(geoid) == 4 and geoid.isdigit(): state_fips = geoid[:2] district_fips = geoid[2:] state_code = _FIPS_TO_STATE.get(state_fips) @@ -103,16 +105,24 @@ async def get_members_by_zip(zip_code: str, db: AsyncSession = Depends(get_db)): if state_code: break - # Fallback: explicit field names + # 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: - state_fips = str(attrs[state_field]).zfill(2) - district_fips = str(attrs[cd_field]) - state_code = _FIPS_TO_STATE.get(state_fips) - district_num = str(int(district_fips)) if district_fips.strip("0") else None - if state_code: - break + try: + state_fips = str(attrs[state_field]).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 + if state_code: + break + 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(