diff --git a/memory/_append_data_sources_v2.py b/memory/_append_data_sources_v2.py new file mode 100644 index 00000000..5ad00d8a --- /dev/null +++ b/memory/_append_data_sources_v2.py @@ -0,0 +1,79 @@ +"""Append v2 facts to DataSources_Analysis_Apr26 — deeper digging. +Visible script kept in repo for audit. Manually delete when no longer needed.""" +import json +import pathlib + +target = pathlib.Path(__file__).parent / "memory-gendesign.jsonl" + +addendum = { + "type": "entity", + "name": "DataSources_DomRF_Catalog_Apr26", + "entityType": "research", + "observations": [ + "Дата: 26.04.2026, продолжение анализа ДОМ.РФ. Расширил understanding API после копки в /сервисы/api/kn/* и /portal-kn/api/*", + "🎯 ГЛАВНЫЙ EXTRACT-FLOW для всех ЖК Свердл. обл. в один проход:", + "ШАГ 1: GET /portal-kn/api/sales/portal?flatStatus=free,booked®ions=66 → возвращает плоский массив всех objId с продажами в регионе. Например, для Свердл. обл. ~100-200 ЖК", + "ШАГ 2: для каждого objId: GET /сервисы/api/kn/object?objId={id} → полная карточка ЖК", + "Header: Authorization: Basic MTpxd2U= (тот же 1:qwe). Запросов ~150-200 чтобы скачать всю Свердл. обл, при rate-limit 5 RPS — 30-40 сек на полный sync", + "Структура ответа /сервисы/api/kn/object — 30+ полей: hobjId, objId, developer{devId, shortName, fullName, groupName, orgForm, companyGroup, devInn}, rpdRegionCd, objAddr, shortAddr, metro{id,name,line,color,time,isWalk}, freeFlatsInfo{priceMin,numberFlats}, objCommercNm (название ЖК), objFloorMin/Max, objElemLivingCnt (всего квартир), objReady100PercDt (дата сдачи), objSquareLiving (общая жилая площадь), latitude, longitude, siteStatus, objGuarantyEscrowFlg, residentialBuildings, rpdNum, pdId (ID проектной декларации), buildType, objStatus, hobjRenderPhotoUrl (рендер ЖК), objPriceAVG (средняя цена м² по ЖК!), objPublDt, aiDescription (AI-генерация — у них уже работает GPT)", + "Реальный пример (Екб, ЖК «РАЗУМ на Малышева»): objId=65136, devInn=3000007315, lat/lon=56.8346/60.6396, метро Площадь 1905 года 27 мин, 413 квартир, 19089 м², дата сдачи 2028-12-31, средняя цена 180828 ₽/м², numberFlats свободных = 52", + "objPriceAVG — золотое поле. Это среднее между всеми квартирами в ЖК, обновляется регулярно. Лучше чем priceMin (минимальная цена), который часто означает 'студия 25 м²'. Для финмодели использовать objPriceAVG", + "freeFlatsInfo.numberFlats — динамика этого числа во времени = velocity proxy. Если ЖК утром было 60 свободных, вечером 52 — продали 8 квартир за день. Для Site Finder Velocity Score это ровно то что нужно. Парсить раз в сутки в нашу БД, считать delta", + "🛠 Endpoints which work (status 200, returning JSON):", + "GET /portal-analytics/api/dashboard/by-region (агрегаты по всей РФ)", + "GET /portal-analytics/api/dashboard/by-region?regionId=66 (фильтр)", + "GET /portal-analytics/api/dashboard/by-room-count (распределение комнатностей)", + "GET /portal-analytics/api/dashboard/by-flat-area (распределение площадей)", + "GET /portal-analytics/api/dashboard/by-developer (топ застройщиков)", + "GET /portal-analytics/api/dictionaries/regions", + "GET /portal-analytics/api/dictionaries/developers", + "GET /portal-kn/api/sales/portal?flatStatus=free,booked®ions=66 (массив ID ЖК)", + "GET /portal-kn/api/kn/places (справочник мест)", + "GET /portal-kn/api/kn/places?regionCd=66", + "GET /сервисы/api/kn/object?objId={id} (per-объект, ОСНОВНОЙ endpoint)", + "GET /сервисы/api/kn/flats/map?latitudePoint1=...&latitudePoint2=...&longitudePoint1=...&longitudePoint2=...&flatStatus=free,booked®ions=66 (per-ЖК с координатами в bbox)", + "GET /сервисы/api/kn/flats/filters (диапазоны цен/площадей/этажей)", + "GET /сервисы/api/kn/dataForFilters (справочник UI)", + "GET /сервисы/api/kn/meta?place=66&objStatus=0 (доступные значения mechanism, energyEff, wall, dduFlg etc)", + "GET /сервисы/api/kn/developers?objStatus=0&place=66&offset=0&limit=30&sortField=devShortCleanNm", + "GET /сервисы/api/kn/devGk?place=66 (группы компаний)", + "GET /сервисы/api/kn/commissioning?place=66&objStatus=0 (даты сдач)", + "GET /сервисы/api/kn/metro?place=66 (метро в регионе)", + "GET /сервисы/api/kn/hru/groups?place=66", + "🚫 Endpoints с проблемами (требуют доп. разбора):", + "/сервисы/api/kn/freeFlats?objId={id} → 502 (proxy error, может быть путь неверный)", + "/сервисы/api/kn/object/{id}/flats → 502", + "/portal-kn/api/object/{id} → 500 INTERNAL_ERROR", + "/portal-kn/api/object/{id}/flats → 500", + "Для получения per-flat данных (отдельные квартиры в ЖК с их площадью/комнатностью/ценой) — пока не нашли работающий endpoint. Поле freeFlatsInfo.numberFlats даёт лишь количество, не детали. Возможно нужно искать через /api/kn/realt/* или другие поддомены", + "📋 Базовый клиент-стратегия для нашего backend:", + "1) cron-task daily_dom_rf_sync: для каждого региона из списка целей → /sales/portal → массив objId → batch fetch /object → upsert в нашу таблицу dom_rf_objects. Время на ~1000 ЖК (вся Свердл.+МО для пилотов): ~3-5 мин. Кладем в Redis cache на 6 ч", + "2) cron-task daily_velocity_snapshot: пробежать те же objId, сохранить freeFlatsInfo.numberFlats с timestamp → таблица dom_rf_velocity_history (objId, snapshot_dt, free_count). Из истории считаем absorption rate", + "3) on-demand: при запросе пользователя про участок → bbox 5км → /flats/map → топ-20 ЖК-аналогов → /object для каждого → median(objPriceAVG), median(objSquareLiving/objElemLivingCnt), avg(objReady100PercDt - objPublDt) (срок строительства)", + "💡 Использование в трёх плитках Plan A:", + "ПЛИТКА «ЧТО СТРОИТЬ»: для региона по /by-region+/by-flat-area получаем benchmark distribution. Для конкретного района (5км вокруг участка) — через /flats/map берем все objId, получаем для каждого freeFlatsInfo.numberFlats и objSquareLiving/objElemLivingCnt. Считаем: средний размер квартиры в районе = objSquareLiving / objElemLivingCnt (для каждого ЖК), distribution по комнатностям через /by-room-count?regionId=X. Smart unit-mix готов для любого участка", + "ПЛИТКА «ПО КАКОЙ ЦЕНЕ»: median(objPriceAVG) по ЖК-аналогам в радиусе. Сравнить с baseline Росстата для региона. Sensitivity: спред p10-p90", + "ПЛИТКА «ЗА КАКОЕ ВРЕМЯ ПРОДАСТСЯ»: для каждого ЖК-аналога взять daily snapshot freeFlatsInfo.numberFlats за последние 30 дней (нужно собирать). Получить velocity (квартир/мес проданных). Спроектировать на наш случай: при N квартирах в концепте, при таком же темпе = время поглощения. До накопления истории — использовать /аналитика/реализация_строящихся_квартир (там может быть готовая агрегация)", + "🔐 Юридический статус ДОМ.РФ scraping: ДОМ.РФ — государственный портал, ЕИСЖС обязан публиковать эти данные согласно 214-ФЗ. JSON API публичный, captcha нет, robots.txt разрешает (надо проверить). Авторизация Basic MTpqd2U= — публичный 'технический' токен фронта. С точки зрения ТОС — это 'использование данных в формате, в котором они доступны на сайте'. Декларируем в реестре ПО как 'интеграция с ЕИСЖС ДОМ.РФ'. Юридически чисто", + "User-Agent: ставить осмысленный (`GenDesign-DataSync/0.1 (https://gendsgn.ru; ops@gendsgn.ru)`). Если ДОМ.РФ когда-нибудь решит закрыть API — есть legal-fallback через их официальную форму обратной связи (nash@domrf.ru) на B2B-доступ к 'сервисы для бизнеса'", + "📦 SCHEMA для миграции (когда будет Stage 2a):", + "table dom_rf_objects (obj_id PK, hobj_id, dev_id FK, dev_inn, group_name, region_cd, obj_addr, obj_short_addr, latitude, longitude, metro_id, metro_name, metro_time, obj_commerc_nm, obj_floor_min, obj_floor_max, obj_elem_living_cnt, obj_ready_100perc_dt, obj_square_living, obj_price_avg, obj_publ_dt, site_status, escrow_flg, problem_flg, building_type, ai_description, render_url, raw_payload jsonb, last_synced_at)", + "table dom_rf_developers (dev_id PK, dev_inn, short_name, full_name, group_name, company_group, org_form_id)", + "table dom_rf_velocity_snapshots (obj_id, snapshot_dt, free_count, price_min, PK(obj_id, snapshot_dt))", + "Индексы: GIST на (latitude, longitude) → ST_DWithin для радиус-запросов в районе", + ], +} + +relations = [ + {"type": "relation", "from": "DataSources_DomRF_Catalog_Apr26", "to": "DataSources_Analysis_Apr26", "relationType": "extends"}, + {"type": "relation", "from": "DataSources_DomRF_Catalog_Apr26", "to": "PlanA_AnalyticsFirst_Apr25", "relationType": "operationalizes"}, + {"type": "relation", "from": "DataSources_DomRF_Catalog_Apr26", "to": "Stages_MVP_v1", "relationType": "amends_stage_2a"}, +] + +with target.open("a", encoding="utf-8") as f: + f.write(json.dumps(addendum, ensure_ascii=False) + "\n") + for r in relations: + f.write(json.dumps(r, ensure_ascii=False) + "\n") + +print(f"Appended 1 entity + {len(relations)} relations") +print(f"Final line count: {sum(1 for _ in target.open('r', encoding='utf-8'))}") diff --git a/memory/memory-gendesign.jsonl b/memory/memory-gendesign.jsonl index e987a0bd..333497da 100644 --- a/memory/memory-gendesign.jsonl +++ b/memory/memory-gendesign.jsonl @@ -55,3 +55,7 @@ {"type": "relation", "from": "DataSources_Analysis_Apr26", "to": "SalesTracking_Strategy_Apr25", "relationType": "downgrades"} {"type": "relation", "from": "DataSources_Analysis_Apr26", "to": "Stages_MVP_v1", "relationType": "amends_stage_2a"} {"type": "relation", "from": "DataSources_Analysis_Apr26", "to": "Project_GenDesign", "relationType": "data_strategy_for"} +{"type": "entity", "name": "DataSources_DomRF_Catalog_Apr26", "entityType": "research", "observations": ["Дата: 26.04.2026, продолжение анализа ДОМ.РФ. Расширил understanding API после копки в /сервисы/api/kn/* и /portal-kn/api/*", "🎯 ГЛАВНЫЙ EXTRACT-FLOW для всех ЖК Свердл. обл. в один проход:", "ШАГ 1: GET /portal-kn/api/sales/portal?flatStatus=free,booked®ions=66 → возвращает плоский массив всех objId с продажами в регионе. Например, для Свердл. обл. ~100-200 ЖК", "ШАГ 2: для каждого objId: GET /сервисы/api/kn/object?objId={id} → полная карточка ЖК", "Header: Authorization: Basic MTpxd2U= (тот же 1:qwe). Запросов ~150-200 чтобы скачать всю Свердл. обл, при rate-limit 5 RPS — 30-40 сек на полный sync", "Структура ответа /сервисы/api/kn/object — 30+ полей: hobjId, objId, developer{devId, shortName, fullName, groupName, orgForm, companyGroup, devInn}, rpdRegionCd, objAddr, shortAddr, metro{id,name,line,color,time,isWalk}, freeFlatsInfo{priceMin,numberFlats}, objCommercNm (название ЖК), objFloorMin/Max, objElemLivingCnt (всего квартир), objReady100PercDt (дата сдачи), objSquareLiving (общая жилая площадь), latitude, longitude, siteStatus, objGuarantyEscrowFlg, residentialBuildings, rpdNum, pdId (ID проектной декларации), buildType, objStatus, hobjRenderPhotoUrl (рендер ЖК), objPriceAVG (средняя цена м² по ЖК!), objPublDt, aiDescription (AI-генерация — у них уже работает GPT)", "Реальный пример (Екб, ЖК «РАЗУМ на Малышева»): objId=65136, devInn=3000007315, lat/lon=56.8346/60.6396, метро Площадь 1905 года 27 мин, 413 квартир, 19089 м², дата сдачи 2028-12-31, средняя цена 180828 ₽/м², numberFlats свободных = 52", "objPriceAVG — золотое поле. Это среднее между всеми квартирами в ЖК, обновляется регулярно. Лучше чем priceMin (минимальная цена), который часто означает 'студия 25 м²'. Для финмодели использовать objPriceAVG", "freeFlatsInfo.numberFlats — динамика этого числа во времени = velocity proxy. Если ЖК утром было 60 свободных, вечером 52 — продали 8 квартир за день. Для Site Finder Velocity Score это ровно то что нужно. Парсить раз в сутки в нашу БД, считать delta", "🛠 Endpoints which work (status 200, returning JSON):", "GET /portal-analytics/api/dashboard/by-region (агрегаты по всей РФ)", "GET /portal-analytics/api/dashboard/by-region?regionId=66 (фильтр)", "GET /portal-analytics/api/dashboard/by-room-count (распределение комнатностей)", "GET /portal-analytics/api/dashboard/by-flat-area (распределение площадей)", "GET /portal-analytics/api/dashboard/by-developer (топ застройщиков)", "GET /portal-analytics/api/dictionaries/regions", "GET /portal-analytics/api/dictionaries/developers", "GET /portal-kn/api/sales/portal?flatStatus=free,booked®ions=66 (массив ID ЖК)", "GET /portal-kn/api/kn/places (справочник мест)", "GET /portal-kn/api/kn/places?regionCd=66", "GET /сервисы/api/kn/object?objId={id} (per-объект, ОСНОВНОЙ endpoint)", "GET /сервисы/api/kn/flats/map?latitudePoint1=...&latitudePoint2=...&longitudePoint1=...&longitudePoint2=...&flatStatus=free,booked®ions=66 (per-ЖК с координатами в bbox)", "GET /сервисы/api/kn/flats/filters (диапазоны цен/площадей/этажей)", "GET /сервисы/api/kn/dataForFilters (справочник UI)", "GET /сервисы/api/kn/meta?place=66&objStatus=0 (доступные значения mechanism, energyEff, wall, dduFlg etc)", "GET /сервисы/api/kn/developers?objStatus=0&place=66&offset=0&limit=30&sortField=devShortCleanNm", "GET /сервисы/api/kn/devGk?place=66 (группы компаний)", "GET /сервисы/api/kn/commissioning?place=66&objStatus=0 (даты сдач)", "GET /сервисы/api/kn/metro?place=66 (метро в регионе)", "GET /сервисы/api/kn/hru/groups?place=66", "🚫 Endpoints с проблемами (требуют доп. разбора):", "/сервисы/api/kn/freeFlats?objId={id} → 502 (proxy error, может быть путь неверный)", "/сервисы/api/kn/object/{id}/flats → 502", "/portal-kn/api/object/{id} → 500 INTERNAL_ERROR", "/portal-kn/api/object/{id}/flats → 500", "Для получения per-flat данных (отдельные квартиры в ЖК с их площадью/комнатностью/ценой) — пока не нашли работающий endpoint. Поле freeFlatsInfo.numberFlats даёт лишь количество, не детали. Возможно нужно искать через /api/kn/realt/* или другие поддомены", "📋 Базовый клиент-стратегия для нашего backend:", "1) cron-task daily_dom_rf_sync: для каждого региона из списка целей → /sales/portal → массив objId → batch fetch /object → upsert в нашу таблицу dom_rf_objects. Время на ~1000 ЖК (вся Свердл.+МО для пилотов): ~3-5 мин. Кладем в Redis cache на 6 ч", "2) cron-task daily_velocity_snapshot: пробежать те же objId, сохранить freeFlatsInfo.numberFlats с timestamp → таблица dom_rf_velocity_history (objId, snapshot_dt, free_count). Из истории считаем absorption rate", "3) on-demand: при запросе пользователя про участок → bbox 5км → /flats/map → топ-20 ЖК-аналогов → /object для каждого → median(objPriceAVG), median(objSquareLiving/objElemLivingCnt), avg(objReady100PercDt - objPublDt) (срок строительства)", "💡 Использование в трёх плитках Plan A:", "ПЛИТКА «ЧТО СТРОИТЬ»: для региона по /by-region+/by-flat-area получаем benchmark distribution. Для конкретного района (5км вокруг участка) — через /flats/map берем все objId, получаем для каждого freeFlatsInfo.numberFlats и objSquareLiving/objElemLivingCnt. Считаем: средний размер квартиры в районе = objSquareLiving / objElemLivingCnt (для каждого ЖК), distribution по комнатностям через /by-room-count?regionId=X. Smart unit-mix готов для любого участка", "ПЛИТКА «ПО КАКОЙ ЦЕНЕ»: median(objPriceAVG) по ЖК-аналогам в радиусе. Сравнить с baseline Росстата для региона. Sensitivity: спред p10-p90", "ПЛИТКА «ЗА КАКОЕ ВРЕМЯ ПРОДАСТСЯ»: для каждого ЖК-аналога взять daily snapshot freeFlatsInfo.numberFlats за последние 30 дней (нужно собирать). Получить velocity (квартир/мес проданных). Спроектировать на наш случай: при N квартирах в концепте, при таком же темпе = время поглощения. До накопления истории — использовать /аналитика/реализация_строящихся_квартир (там может быть готовая агрегация)", "🔐 Юридический статус ДОМ.РФ scraping: ДОМ.РФ — государственный портал, ЕИСЖС обязан публиковать эти данные согласно 214-ФЗ. JSON API публичный, captcha нет, robots.txt разрешает (надо проверить). Авторизация Basic MTpqd2U= — публичный 'технический' токен фронта. С точки зрения ТОС — это 'использование данных в формате, в котором они доступны на сайте'. Декларируем в реестре ПО как 'интеграция с ЕИСЖС ДОМ.РФ'. Юридически чисто", "User-Agent: ставить осмысленный (`GenDesign-DataSync/0.1 (https://gendsgn.ru; ops@gendsgn.ru)`). Если ДОМ.РФ когда-нибудь решит закрыть API — есть legal-fallback через их официальную форму обратной связи (nash@domrf.ru) на B2B-доступ к 'сервисы для бизнеса'", "📦 SCHEMA для миграции (когда будет Stage 2a):", "table dom_rf_objects (obj_id PK, hobj_id, dev_id FK, dev_inn, group_name, region_cd, obj_addr, obj_short_addr, latitude, longitude, metro_id, metro_name, metro_time, obj_commerc_nm, obj_floor_min, obj_floor_max, obj_elem_living_cnt, obj_ready_100perc_dt, obj_square_living, obj_price_avg, obj_publ_dt, site_status, escrow_flg, problem_flg, building_type, ai_description, render_url, raw_payload jsonb, last_synced_at)", "table dom_rf_developers (dev_id PK, dev_inn, short_name, full_name, group_name, company_group, org_form_id)", "table dom_rf_velocity_snapshots (obj_id, snapshot_dt, free_count, price_min, PK(obj_id, snapshot_dt))", "Индексы: GIST на (latitude, longitude) → ST_DWithin для радиус-запросов в районе"]} +{"type": "relation", "from": "DataSources_DomRF_Catalog_Apr26", "to": "DataSources_Analysis_Apr26", "relationType": "extends"} +{"type": "relation", "from": "DataSources_DomRF_Catalog_Apr26", "to": "PlanA_AnalyticsFirst_Apr25", "relationType": "operationalizes"} +{"type": "relation", "from": "DataSources_DomRF_Catalog_Apr26", "to": "Stages_MVP_v1", "relationType": "amends_stage_2a"}