Problem
Two operations needed by the sheet config edit page currently have inefficient temp implementations:
1. Delete memberships by email list
Current temp: frontend calls GET /tournaments/{id}/memberships/ to fetch all
memberships with joined user data, filters by email client-side, then fires one
DELETE /tournaments/{id}/memberships/{id}/ per match. This is O(n) HTTP
requests — slow and chatty for large volunteer lists.
Proper fix: a single backend endpoint that does the filter and bulk delete in one DB query:
POST /tournaments/{id}/memberships/delete-by-emails/
Body: { emails: ["[a@example.com](mailto:a@example.com)", "[b@example.com](mailto:b@example.com)"] }
Response: { deleted: 3 }
Implementation: join memberships → users on user_id, filter users.email IN (emails) AND tournament_id = id, bulk delete.
2. Fetch raw sheet rows
Currently requires a new endpoint with no temp alternative — sheetsApi.getRows points at a backend route that doesn't exist yet:
GET /tournaments/{id}/sheets/configs/{configId}/rows/
Response: [{ "Email Address": "[a@example.com](mailto:a@example.com)", ... }, ...]
Implementation: call sheets_service.get_rows(config.spreadsheet_id, config.sheet_name) and return the raw row dicts. Used by the nuclear delete to get the live email list from the sheet.
Files to change
app/api/routes/memberships.py — add delete-by-emails endpoint
app/api/routes/sheets.py — add rows endpoint
frontend/lib/api.ts — replace temp deleteByEmails with direct api.post call once backend is live
Problem
Two operations needed by the sheet config edit page currently have inefficient temp implementations:
1. Delete memberships by email list
Current temp: frontend calls
GET /tournaments/{id}/memberships/to fetch allmemberships with joined user data, filters by email client-side, then fires one
DELETE /tournaments/{id}/memberships/{id}/per match. This is O(n) HTTPrequests — slow and chatty for large volunteer lists.
Proper fix: a single backend endpoint that does the filter and bulk delete in one DB query:
Implementation: join
memberships→usersonuser_id, filterusers.email IN (emails)ANDtournament_id = id, bulk delete.2. Fetch raw sheet rows
Currently requires a new endpoint with no temp alternative —
sheetsApi.getRowspoints at a backend route that doesn't exist yet:Implementation: call
sheets_service.get_rows(config.spreadsheet_id, config.sheet_name)and return the raw row dicts. Used by the nuclear delete to get the live email list from the sheet.Files to change
app/api/routes/memberships.py— adddelete-by-emailsendpointapp/api/routes/sheets.py— addrowsendpointfrontend/lib/api.ts— replace tempdeleteByEmailswith directapi.postcall once backend is live