Specific-airports mode scans never resolved full airport names — they
stored the IATA code as destination_name. Fixed in two places:
- airports.py: add lookup_airport(iata) cached helper
- api_server.py: enrich destination_name/city on the fly in the routes
endpoint when the stored value equals the IATA code (fixes all past scans)
- scan_processor.py: resolve airport names at scan time in specific-airports
mode using lookup_airport (fixes future scans at the DB level)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backend:
- DELETE /api/v1/scans/{id} — 204 on success, 404 if missing,
409 if pending/running; CASCADE removes routes and flights
Frontend (api.ts):
- scanApi.delete(id)
Frontend (ScanDetails.tsx):
- Re-run button: derives window_months from stored dates, detects
country vs airports mode via comma in scan.country, creates new
scan and navigates to it; disabled while scan is active
- Delete button: inline two-step confirm (no modal), navigates to
dashboard on success; disabled while scan is active
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rewrite airport search to use priority buckets instead of simple
append: exact IATA → IATA prefix → city prefix → city contains →
name prefix → name contains → country match. This ensures BER
appears before Berlin-Schönefeld when typing "BER".
- Add _MISSING_AIRPORTS patch list to get_airport_data() so airports
absent from the OpenFlights dataset (e.g. BER opened Nov 2020,
IST new Istanbul airport) are included at runtime.
- Deduplicate results via seen-set to avoid duplicate entries.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>