prop/lib/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.ex User profiles at /u/:callsign, flexible band input, assorted UX cleanup 2026-04-12 16:13:08 -05:00
band_resolver.ex User profiles at /u/:callsign, flexible band input, assorted UX cleanup 2026-04-12 16:13:08 -05:00
callsign_client.ex Drop gridmap.org dependency, resolve callsigns locally 2026-04-12 17:43:29 -05:00
contact.ex User profiles at /u/:callsign, flexible band input, assorted UX cleanup 2026-04-12 16:13:08 -05:00
contact_edit.ex User profiles at /u/:callsign, flexible band input, assorted UX cleanup 2026-04-12 16:13:08 -05:00
csv_import.ex CsvImport: header-driven column mapping 2026-04-16 09:53:14 -05:00
edit_notifier.ex Send mail as prop@w5isp.com with reply-to graham@mcintire.me 2026-04-12 14:00:38 -05:00
enrichment_status.ex Add dialyzer specs and types across the codebase 2026-04-12 08:55:04 -05:00
maidenhead.ex Add /beacons CRUD and /users admin page 2026-04-08 12:01:45 -05:00