feat: add manual SD card data upload for offline NRLs; rename RecordingSession to MonitoringSession

- Add POST /api/projects/{project_id}/nrl/{location_id}/upload-data endpoint
  accepting a ZIP or multi-file select of .rnd/.rnh files from an SD card.
  Parses .rnh metadata for session start/stop times, serial number, and store
  name. Creates a MonitoringSession (no unit assignment required) and DataFile
  records for each measurement file.

- Add Upload Data button and collapsible upload panel to the NRL detail Data
  Files tab, with inline success/error feedback and automatic file list refresh
  via HTMX after import.

- Rename RecordingSession -> MonitoringSession throughout the codebase
  (models.py, projects.py, project_locations.py, scheduler.py, roster_rename.py,
  main.py, init_projects_db.py, scripts/rename_unit.py). DB table renamed from
  recording_sessions to monitoring_sessions; old indexes dropped and recreated.

- Update all template UI copy from Recording Sessions to Monitoring Sessions
  (nrl_detail, projects/detail, session_list, schedule_oneoff, roster).

- Add backend/migrate_rename_recording_to_monitoring_sessions.py for applying
  the table rename on production databases before deploying this build.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-24 19:54:40 +00:00
parent da4e5f66c5
commit 7516bbea70
16 changed files with 509 additions and 123 deletions

View File

@@ -90,14 +90,14 @@ def rename_unit(old_id: str, new_id: str):
except Exception:
pass # Table may not exist
# Update recording_sessions table (if exists)
# Update monitoring_sessions table (if exists)
try:
result = session.execute(
text("UPDATE recording_sessions SET unit_id = :new_id WHERE unit_id = :old_id"),
text("UPDATE monitoring_sessions SET unit_id = :new_id WHERE unit_id = :old_id"),
{"new_id": new_id, "old_id": old_id}
)
if result.rowcount > 0:
print(f" ✓ Updated recording_sessions ({result.rowcount} rows)")
print(f" ✓ Updated monitoring_sessions ({result.rowcount} rows)")
except Exception:
pass # Table may not exist