prop/test/microwaveprop/radio
Graham McIntire be6f1a1d28
CsvImport: header-driven column mapping
The /contacts LiveTable export produces a 12-column CSV with label-style
headers (Station 1 / Grid 1 / QSO (UTC) / ...) in a different column
order plus extras (id, distance_km, hrrr_status, flagged_invalid,
inserted_at). The old positional import rejected it with "expected 6 or
7 columns, got 12".

Replace the positional parser with header-driven mapping:
- Parse the header row, normalize each cell (downcase + trim), and look
  it up in an alias map that covers both the raw field names and the
  export labels.
- Required columns: station1, station2, grid1, grid2, band, qso_timestamp
  (mode stays optional). If any are missing the header, return
  {:error, {:missing_required_columns, [...]}}.
- Unknown columns are silently ignored so the export's extras don't break
  round-trip.
- Per-row validation stays the same (changeset errors still reported by
  row number).

Existing 6- or 7-column positional CSVs that already have a header still
work — the header parser recognizes `station1`, `station2`, etc.
directly.
2026-04-16 09:53:14 -05:00
..
adif_import_test.exs User profiles at /u/:callsign, flexible band input, assorted UX cleanup 2026-04-12 16:13:08 -05:00
contact_edit_test.exs Force 24h timestamps and let logged-in owners edit their contacts directly 2026-04-12 15:18:47 -05:00
contact_submission_test.exs Cache /contacts, fix map blink, make mode optional 2026-04-12 12:47:25 -05:00
contact_test.exs Cache /contacts, fix map blink, make mode optional 2026-04-12 12:47:25 -05:00
csv_import_test.exs CsvImport: header-driven column mapping 2026-04-16 09:53:14 -05:00
enrichment_status_test.exs Add Tier 1 test coverage: EnrichmentStatus, Markdown, health, RemoteIp, Maidenhead 2026-04-06 10:15:38 -05:00
maidenhead_test.exs Add /beacons CRUD and /users admin page 2026-04-08 12:01:45 -05:00