# DEV REPORT: FR24 Schedule Supplement **Дата:** 2026-04-21 **Статус:** ✅ DONE **Задача:** TZ-fr24-schedule-supplement --- ## Прогресс - [x] Создан отчёт - [x] Прочитаны исходники - [x] Реализована `supplement_schedule()` в `fr24_worker.py` - [x] Баг A (ZBAD/PKX) — уже был исправлен в коде (строка 65 build_mart.py), изменений не потребовалось - [x] Исправлен баг B (soft match) в `build_mart.py` — оба find_fr24_track и find_fa_track - [x] Добавлен вызов `supplement_schedule()` в `run()` fr24_worker.py (шаг 4) - [x] Синтаксис проверен: оба файла проходят `python3 -m py_compile` без ошибок --- ## Изменённые файлы ### 1. `ingest/tracks_fr24/fr24_worker.py` **Добавлено:** - Константы `_MOSCOW_ICAO_TO_IATA` и `_MOSCOW_ICAO_SET` (строки ~302-308) - Функция `supplement_schedule(conn, target_date: date) -> int` (строки 312-400) - Вызов `supplement_schedule()` в `run()` как шаг 4 (строки 475-481) - Новый ключ в `stats`: `"schedule_supplemented"` **Логика `supplement_schedule()`:** - Одним INSERT...SELECT вставляет в `fr24_ext.schedule` все рейсы из `flight_actual`, у которых нет совпадений по нормализованному номеру рейса + дате - Определяет `direction` по московскому аэропорту: origin → departure, dest → arrival - `airport_iata` = московский аэропорт рейса (CASE WHEN по 4 ICAO) - `flight_number` = нормализован (пробелы убраны, UPPER) - `airline_iata` = буквенный префикс номера рейса - `scheduled_at` = datetime_takeoff для вылетов, datetime_landed для прилётов - `source = 'fr24'`, `status = 'actual'` - `ON CONFLICT (flight_number, airport_iata, scheduled_at, direction) DO NOTHING` ### 2. `ingest/mart/build_mart.py` **Баг A:** `ZBAD→PKX` уже присутствовал в `ICAO_TO_IATA` (строка 65). Изменений не потребовалось. **Баг B (исправлен в двух местах):** - `find_fr24_track()` строка ~215: убрано условие `not destination_iata` — soft match по origin теперь работает как fallback даже когда destination известен - `find_fa_track()` строка ~283: аналогично Было: ```python if origin_iata and not destination_iata: ``` Стало: ```python # Fallback: match by origin only (full route match failed) if origin_iata: ``` --- ## Результат проверки синтаксиса ``` fr24_worker.py: OK build_mart.py: OK ``` `python3 -m py_compile` — оба файла без ошибок. --- ## Примечания - Деплой НЕ выполнялся (согласно ТЗ) - Non-Moscow аэропорты в `origin_iata`/`destination_iata` будут NULL — это допустимо, т.к. полный ICAO→IATA словарь в fr24_worker не дублировался - При желании можно расширить CASE WHEN или вынести общий словарь в `config.py` / `constants.py`