Дом берёт координаты один раз — при создании, из породившего его объявления.
Объявление геокодируется ПОЗЖЕ (geoportal_coords_backfill, geocode_missing_listings)
и пишет в listings; ON CONFLICT у вставки дома обновляет только address. Обратно
координаты не возвращались: на проде 1945 домов из 9625 (20.2%) без координат, при
этом у 1490 из них объявления с координатами уже есть.
Новая ежедневная задача house_coords_from_listings (окно 03:00-04:00 UTC, перед
house_dedup_merge) считает центроид объявлений дома и их разброс — max
ST_DistanceSphere до центроида. Разброс <= 125 м → центроид пишется в дом.
Порог 125 м взят не из данных (гистограмма обрыва не даёт: ядро 0-125 м, дальше
ровное плато до 400 м), а от потребителя координат: это половина 250-метрового
гео-ограждения house_dedup_merge (#2187). Записанный центроид — оценка с
погрешностью ровно в разброс; отдать ей весь бюджет ограждения значит позволить
двум домам разъехаться на 500 м. Цена решения мала: 125 м пропускает 1382 дома,
250 м — 1403.
Дома с бо́льшим разбросом не трогаются и считаются отдельным счётчиком: это дефект
сопоставителя (#2777), а не задача переноса — в одну запись дома сшиты объявления
разных населённых пунктов, худший разброс 289.9 км. Пропуск виден по каждой
причине отдельно (no_listings / no_listing_coords / scattered), худшие дома
называются в логе поимённо.
Идемпотентно: UPDATE только по lat IS NULL, повторный прогон — no-op.
Замер тем же SQL, что мержится (прод, read-only, ROLLBACK):
candidates=1945 eligible=1382 no_listings=114 no_listing_coords=341
scattered=108 (18 дальше 5 км, худший 289.9 км).