gendesign/data/sql/100_tradein_fdw_role.sql
lekss361 698ef4f003 feat(tradein): postgres_fdw live read of gendesign.cad_buildings (replaces snapshot)
Replaces tradein.cad_buildings manual snapshot (36k rows, frozen 2026-05-22) with
live postgres_fdw foreign table reading gendesign.v_tradein_cad_buildings directly.
Also reverts PR #492 HTTP-based cadastral.py — superseded by FDW.

Architecture:
- gendesign DB: new role tradein_fdw_reader + flat view v_tradein_cad_buildings
  (EKB-only slice of cad_buildings with lat/lon flattened from geom)
- networks: gendesign-postgres added to gendesign_shared (alias);
  tradein-postgres added to gendesign_shared for FDW connect
- tradein DB: postgres_fdw extension + FOREIGN TABLE gendesign_cad_buildings
- tradein backend: startup hook creates/refreshes USER MAPPING with password
  from env GENDESIGN_FDW_PASSWORD (password rotation handled via restart)
- geocoder.py: cadastral primary for forward + reverse + suggest;
  Yandex/Nominatim fallback. reverse_geocode wraps Nominatim in try/except —
  no more HTTPStatusError → 500.
- house_metadata.py and trade_in.py admin stats switched to foreign table
- DROP TABLE cad_buildings in tradein (legacy snapshot removed entirely)
- import-cadastre.sh deleted (no manual sync needed)

Fixes:
- /trade-in/api/v1/geocode/reverse 500 (Nominatim ban → no fallback)
- estimate confidence_explanation=address_not_geocoded for addresses in our
  cadastre (e.g. Хохрякова 81) that Nominatim doesn't return

Deploy ordering: main migration 100_tradein_fdw_role.sql adds role+view first
(strict deploy.yml). Tradein next deploy applies 060_postgres_fdw_extension.sql
and 061_drop_legacy_cad_buildings.sql (idempotent, errors ignored). Tradein
backend startup creates USER MAPPING when env var present. Verify post-deploy
with: docker exec tradein-postgres psql -U tradein -d tradein -c \
  "SELECT count(*) FROM gendesign_cad_buildings"  # expect ~36k EKB buildings.
2026-05-24 11:13:44 +03:00

36 lines
1.3 KiB
PL/PgSQL

-- tradein_fdw_reader role + v_tradein_cad_buildings view
-- Used by tradein-postgres via postgres_fdw to read live cad_buildings.
-- See meta/00_credentials.md for password rotation procedure.
BEGIN;
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'tradein_fdw_reader') THEN
CREATE ROLE tradein_fdw_reader LOGIN PASSWORD '40473b7c10c7474855c7d1aa98f0fd0a0de2499aef0cbd1fead06c9641e4dcd8';
END IF;
END$$;
GRANT CONNECT ON DATABASE gendesign TO tradein_fdw_reader;
GRANT USAGE ON SCHEMA public TO tradein_fdw_reader;
CREATE OR REPLACE VIEW v_tradein_cad_buildings AS
SELECT
cad_num,
NULLIF(trim(readable_address), '') AS readable_address,
NULLIF(floors, 0) AS floors,
CASE WHEN year_built BETWEEN 1800 AND 2100 THEN year_built END AS year_built,
round(COALESCE(build_record_area, area), 2)::numeric AS area_m2,
purpose,
ST_Y(ST_Centroid(geom))::double precision AS lat,
ST_X(ST_Centroid(geom))::double precision AS lon
FROM cad_buildings
WHERE cad_num LIKE '66:41:%'
AND geom IS NOT NULL
AND readable_address IS NOT NULL;
GRANT SELECT ON v_tradein_cad_buildings TO tradein_fdw_reader;
COMMENT ON VIEW v_tradein_cad_buildings IS
'FDW source for tradein-mvp (postgres_fdw). Flat 8-col EKB-only slice of cad_buildings. tradein.gendesign_cad_buildings maps here.';
COMMIT;