77 lines
3.3 KiB
Markdown
77 lines
3.3 KiB
Markdown
# 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`
|