6.1 KiB
ТЗ: Дополнение расписания из FR24 flight-summary/full
Дата: 2026-04-21
Статус: READY FOR DEV
Приоритет: Высокий
Контекст
FR24 /api/flight-summary/full уже используется в fr24_worker.py и возвращает
все реальные рейсы через московские аэропорты за сутки (до 20 000 записей).
Текущее поведение:
enrich_schedule()— только UPDATE существующих строк вfr24_ext.schedule- Рейсы из
flight_actual, которых нет в Яндекс.Расписании, теряются
Проблема: Яндекс не покрывает 100% рейсов (чартеры, грузовые, технические, задержанные).
FR24 имеет полные данные. Нужно использовать flight_actual как дополнительный источник расписания.
Что нужно сделать
1. Функция supplement_schedule() в fr24_worker.py
def supplement_schedule(conn, target_date: date) -> int:
"""
Insert into fr24_ext.schedule flights from flight_actual
that have no matching schedule record.
Source: fr24_ext.flight_actual
Target: fr24_ext.schedule (source='fr24')
Returns: number of rows inserted
"""
Логика:
- Найти все рейсы в
flight_actualза дату, у которых нет соответствия вschedule - Определить direction: если
origin_icaoв московских аэропортах → departure, иначе arrival - INSERT в
scheduleсsource='fr24',status='actual'
SQL-скелет для поиска незаматченных:
SELECT fa.*
FROM fr24_ext.flight_actual fa
WHERE fa.flight_date = %(date)s
AND NOT EXISTS (
SELECT 1 FROM fr24_ext.schedule s
WHERE UPPER(REPLACE(s.flight_number,' ','')) = UPPER(REPLACE(fa.flight,' ',''))
AND s.flight_date = fa.flight_date
)
AND fa.flight IS NOT NULL
AND fa.flight != ''
Поля для INSERT в schedule:
flight_date = target_date
airport_iata = ICAO_TO_IATA[origin_icao или dest_icao] (московский аэропорт)
direction = 'departure' если origin_icao московский, иначе 'arrival'
flight_number = fa.flight (нормализовать: убрать лишние пробелы)
airline_iata = первые 2 символа IATA (если можно определить)
origin_iata = ICAO_TO_IATA.get(fa.origin_icao)
destination_iata = ICAO_TO_IATA.get(fa.dest_icao)
aircraft_type = NULL (нет в flight_actual)
scheduled_at = fa.datetime_takeoff (или datetime_landed для arrival)
actual_takeoff = fa.datetime_takeoff
actual_landed = fa.datetime_landed
status = 'actual'
source = 'fr24'
fr24_id = fa.fr24_id
ON CONFLICT: (flight_number, airport_iata, scheduled_at, direction) — уже есть.
2. Также исправить баги из ревью
Баг A: ZBAD/PKX не в словаре ICAO_TO_IATA
Файл: build_mart.py
Добавить в словарь ICAO_TO_IATA:
"ZBAD": "PKX", # Beijing Daxing
"RKSI": "ICN", # Seoul Incheon (уже есть, проверить)
Баг B: Soft match для FA/FR24 когда destination не совпадает
Файл: build_mart.py, функции find_fa_track() и find_fr24_track()
Текущая логика:
if origin_iata and not destination_iata: # только если dest == NULL
# soft match by origin only
Нужно изменить на:
# Если полный матч не нашёл → fallback на origin only
if origin_iata:
for row in rows:
orig_iata = ICAO_TO_IATA.get(row[2])
if orig_iata == origin_iata:
return (row[0], row[1])
(убрать условие not destination_iata)
3. Вызов supplement_schedule() в run() fr24_worker.py
После enrich_schedule():
# 4. Supplement schedule with flights from FR24 not in Yandex
try:
supplemented = supplement_schedule(conn, target_date)
conn.commit()
stats["schedule_supplemented"] = supplemented
log.info("FR24 worker: supplemented %d new schedule rows", supplemented)
except Exception as e:
conn.rollback()
log.error("FR24 worker: supplement_schedule failed: %s", e)
stats["errors"] += 1
Что НЕ нужно делать
- НЕ менять DDL/схему БД (колонки
fr24_id,actual_takeoff,actual_landedв schedule уже есть или добавить как nullable) - НЕ трогать RTL-SDR матч — он работает корректно
- НЕ запускать backfill — только текущая логика для новых дат
Проверка результата
- Запустить build для 19.04 или 20.04 (данные уже есть в
flight_actual) - Проверить:
SELECT source, count(*) FROM fr24_ext.schedule
WHERE flight_date = '2026-04-19' GROUP BY source;
-- Ожидаемо: yandex=~1570, fr24=N (новые)
SELECT count(*) FROM fr24_ext.schedule s
JOIN fr24_ext.flight_actual fa ON UPPER(REPLACE(fa.flight,' ','')) = UPPER(REPLACE(s.flight_number,' ',''))
WHERE s.flight_date = '2026-04-19' AND s.source = 'fr24';
- Перезапустить mart build для даты — посмотреть увеличение
schedule_flightsиwith_track
Файлы для изменения
| Файл | Изменение |
|---|---|
ingest/tracks_fr24/fr24_worker.py |
Добавить supplement_schedule(), вызвать в run() |
ingest/mart/build_mart.py |
Добавить ZBAD→PKX в словарь, исправить soft match |
Путь к проекту на VM
/home/fr24/fr24/ingest/
Деплой: docker cp <file> fr24-tracks-fr24:/app/<file> && docker restart fr24-tracks-fr24