Skip to content

feat: add CSV export endpoint for alerts (#521)#577

Merged
fe51 merged 5 commits intomainfrom
alexis/521-alerts-csv-export
May 6, 2026
Merged

feat: add CSV export endpoint for alerts (#521)#577
fe51 merged 5 commits intomainfrom
alexis/521-alerts-csv-export

Conversation

@Acruve15
Copy link
Copy Markdown
Collaborator

@Acruve15 Acruve15 commented Apr 28, 2026

Summary

  • Adds GET /alerts/export?from_date=YYYY-MM-DD&to_date=YYYY-MM-DD returning a CSV streamed download with columns id, lat, lon, started_at, last_seen_at.
  • Filters alerts by started_at within the inclusive UTC window [from_date 00:00:00, to_date 23:59:59.999999] and scopes results to the caller's organization_id.
  • Implements the first iteration of #521; the issue's "Future improvements" (sequence ids, camera names) are deliberately left for a follow-up.

Implementation notes

  • Route declared before /{alert_id} in alerts.py so FastAPI doesn't try to parse export as an int path param.
  • Uses stdlib csv + io.StringIO + StreamingResponse (no new dependencies; pandas not needed for this shape).
  • Inline select(Alert).where(...) mirrors fetch_alerts_from_date; nothing added to the CRUD layer.
  • DB columns store naive UTC datetimes (per app.core.time.utcnow), so the bounds are built without tzinfo.
  • Returns 422 when to_date < from_date, 401 when unauthenticated, 200 with header-only body for an empty range.

Test plan

  • pytest tests/endpoints/test_alerts.py -v (all 10 tests, including 6 new export tests, pass)
    • Happy path + ascending order
    • Window narrows correctly (only middle-day alert returned)
    • Org isolation (org 2 alerts absent when called as org 1 user)
    • Empty range returns header-only CSV
    • to_date < from_date → 422
    • No token → 401
  • ruff 0.11.9 check and ruff 0.11.9 format --check pass
  • Manually curl the new endpoint with a valid token and confirm the CSV opens cleanly

@Acruve15 Acruve15 requested review from MateoLostanlen and fe51 April 28, 2026 10:21
@Acruve15 Acruve15 self-assigned this Apr 28, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 28, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.92%. Comparing base (1f67522) to head (656df3e).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #577      +/-   ##
==========================================
+ Coverage   88.75%   89.92%   +1.17%     
==========================================
  Files          52       55       +3     
  Lines        2196     2451     +255     
==========================================
+ Hits         1949     2204     +255     
  Misses        247      247              
Flag Coverage Δ
backend 89.89% <100.00%> (+1.24%) ⬆️
client 90.40% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Add `GET /alerts/export?from_date=...&to_date=...` returning a CSV with
columns id, lat, lon, started_at, last_seen_at, scoped to the caller's
organization. Filters on `started_at` within the inclusive UTC window.
Add a test that exports an alert with NULL coordinates and asserts
the CSV renders them as empty cells, exercising the previously
uncovered None branches in _iter_alerts_csv.
…tch coverage

Lines immediately following an `await` are mishandled by the project's
async coverage tracing, leaving 3 lines reported as uncovered even
though the happy-path test executes them. Move the response build into
a sync helper and inline the awaited fetch into the return statement so
the await is part of the line that is already marked as covered.

No behavioral change.
@Acruve15 Acruve15 force-pushed the alexis/521-alerts-csv-export branch from c4bbb4d to d9b889b Compare April 28, 2026 11:48
fe51
fe51 previously approved these changes May 6, 2026
Copy link
Copy Markdown
Member

@fe51 fe51 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Alexis, thanks a lot for this PR and sorry for the review delay !

Tested it works, and reviewed the code !
This is clean, and quite efficient (have not tested to extract for long time period but the content is light)

I have juste added one remark/question in tests but non blocking to me !

Comment thread src/tests/endpoints/test_alerts.py Outdated
returned_ids == {a_in.id} is set equality and already implies the other
ids are absent. Per review feedback from @fe51.
@fe51 fe51 merged commit 077eeda into main May 6, 2026
24 checks passed
@fe51 fe51 deleted the alexis/521-alerts-csv-export branch May 6, 2026 10:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants