POST /analyze 500'd (TypeError: float(None)) for ~964 cad_parcels_geom rows
that have a meta row but geom IS NULL: the resolution query returned the row
(no NULL filter), geom_wkt became NULL → ST_Centroid(NULL) → NULL lat/lon →
float(centroid_row["lat"]) crashed (the `if centroid_row else` guard checked
row existence, not NULL values). A user entering any such "random parcel" hit
a 500.
Fix:
- Add `AND geom IS NOT NULL` to all three geometry-resolution queries (initial
UNION, inline-refetch UNION, geom_row WKT subquery) so a NULL-geometry parcel
is treated as "no usable geometry" → falls into the #93 graceful fallback
(enqueue NSPD on-demand fetch → 202 polling), exactly like a parcel absent
from the DB. The fetch then populates real geometry and analyze succeeds.
- Defensive: centroid_lat/lon now check the VALUE is not None (not just row
existence) before float(), falling back to EKB center.
Verified: badformat→400, not-in-DB→202(fetching), valid parcel→200 unaffected.
39 analyze/by-bbox tests green. Refs #944.