diff --git a/INSTRUCTIONS.md b/INSTRUCTIONS.md index 90e8f79..439911a 100644 --- a/INSTRUCTIONS.md +++ b/INSTRUCTIONS.md @@ -6,7 +6,7 @@ This project aims to develop a comprehensive membership management system for th ## Current Implementation Status -The app now includes a FastAPI backend, React/Vite frontend, Docker Compose development gateway, Alembic migrations, Square payment integration, SMTP2GO email integration, event/RSVP endpoints, configurable profile questions, privacy/terms pages, feature flags, and a fast test gate in `restart.sh`. +The app now includes a FastAPI backend, React/Vite frontend, Docker Compose development gateway, Alembic migrations, Square payment integration, SMTP2GO email integration, ESP RFID provisioning/time-sync/tap tracking, event/RSVP endpoints, configurable profile questions, privacy/terms pages, feature flags, UTC backend timestamps with London-facing frontend formatting, and a fast test gate in `restart.sh`. ## Core Features @@ -26,6 +26,8 @@ The app now includes a FastAPI backend, React/Vite frontend, Docker Compose deve - **Membership Tier Management**: Configure different membership levels and associated fees - **Profile Question Management**: Create, edit, deactivate, order, and configure dependencies for member profile questions - **Meeting/Event Management**: Create, edit, and manage events, track RSVPs and attendance +- **Timezone Handling**: Persist timestamps in UTC, display member-facing times in Europe/London, and convert event input back to UTC before saving +- **ESP RFID Readers**: Reader registration, time sync, taps, attendance sessions, and queued card-writing jobs are implemented end to end - **Email Management**: Edit database-backed email templates with escaped previews, send test emails, and monitor SMTP2GO bounces - **Feature Flags**: View backend feature flags and reload them from the super-admin interface - **Reporting**: Planned reports on membership statistics and payment status diff --git a/PROJECT_STRUCTURE.md b/PROJECT_STRUCTURE.md index b2d8637..656db75 100644 --- a/PROJECT_STRUCTURE.md +++ b/PROJECT_STRUCTURE.md @@ -30,10 +30,10 @@ membership/ │ │ ├── email_templates.py │ │ ├── events.py # Events and RSVPs │ │ └── feature_flags.py -│ ├── core/ # Config, database, security, default data +│ ├── core/ # Config, database, security, datetime helpers, default data │ ├── models/ # SQLAlchemy models │ ├── schemas/ # Pydantic schemas -│ ├── services/ # Email, bounce, Square, feature flags +│ ├── services/ # Email, bounce, Square, attendance, feature flags │ └── tests/ # Fast backend pytest unit tests │ ├── docker/ @@ -64,9 +64,11 @@ membership/ - **`backend/app/core/config.py`** - Settings management. - **`backend/app/core/init_db.py`** - Default membership tiers, super admin, email templates, and profile questions. - **`backend/app/core/security.py`** - JWT tokens and password hashing. +- **`backend/app/core/datetime.py`** - UTC helpers and Zulu serialization helpers. - **`backend/app/models/models.py`** - Database tables. - **`backend/app/schemas/schemas.py`** - API request/response models. - **`backend/app/tests/test_profile_question_logic.py`** - Fast backend unit tests for profile answer validation. +- **`backend/app/tests/test_datetime_utc.py`** - UTC normalization and serialization tests. ### Frontend Application - **`frontend/src/pages/Dashboard.tsx`** - Main member/admin dashboard. @@ -76,7 +78,9 @@ membership/ - **`frontend/src/components/ProfileQuestionsForm.tsx`** - Member/admin answer form with dependency handling. - **`frontend/src/components/EmailTemplateManagement.tsx`** - Email template editing. - **`frontend/src/components/BounceManagement.tsx`** - SMTP2GO bounce management. +- **`frontend/src/components/EspReaderManagement.tsx`** - ESP reader, card, tap, and attendance admin UI. - **`frontend/src/utils/profileQuestionLogic.test.ts`** - Fast frontend unit tests for profile-question visibility/editability. +- **`frontend/src/utils/timezone.ts`** - Europe/London display helpers and UTC conversion utilities. ## API Endpoints @@ -87,6 +91,7 @@ membership/ - **`payments.py`** - Payment history, manual payments, Square config/process/refund. - **`events.py`** - Event CRUD, upcoming events, RSVP create/update, RSVP listing. - **`email.py`** - SMTP2GO test emails, welcome email tests, bounce webhook, bounce stats, cleanup, deactivation. +- **`esp.py`** - ESP reader provisioning, time sync, tap capture, dashboard login, attendance, and queued write jobs. - **`email_templates.py`** - Database-backed template listing, lookup, update, and default seeding. - **`feature_flags.py`** - Public feature flag listing/lookup and super-admin-only reload. @@ -104,6 +109,10 @@ Fully implemented: - **EmailTemplate** - Editable database-backed email templates. - **EmailBounce** - SMTP2GO bounce, complaint, and unsubscribe tracking. - **PasswordResetToken** - One-time password reset support. +- **EspReader** - Provisioned RFID readers with UTC heartbeat and time-sync data. +- **RfidTap** - UTC-normalized RFID tap records. +- **AttendanceSession** - Attendance sessions driven by RFID taps. +- **RfidCardWriteJob** - Queued RFID card write jobs. - **VolunteerRole** - Volunteer role definitions. - **VolunteerAssignment** - Member-to-role assignments. - **VolunteerSchedule** - Volunteer shift schedules. diff --git a/QUICKSTART.md b/QUICKSTART.md index 0232b96..5bdde78 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -16,6 +16,8 @@ Wait until you see "Application startup complete", then press Ctrl+C. - API: http://localhost:8050/api/v1 - Docs: http://localhost:8050/docs +API datetimes are stored and returned in UTC/Zulu. The frontend shows member-facing times in Europe/London and converts event input back to UTC before saving. + Set `APP_PORT` in `.env` / `.env.example` to change `8050`. For Square payment form testing, use HTTPS at `https://localhost:8443`. Set `APP_TLS_PORT` in `.env` / `.env.example` to change `8443`. @@ -137,6 +139,12 @@ docker compose logs -f gateway 2. Members can view upcoming events and submit RSVP status 3. Admins can view RSVP lists and attendance data +### ESP RFID readers +1. Readers register with `/api/v1/esp/device/register` +2. Readers sync clocks from `/api/v1/esp/device/time` +3. Tap, heartbeat, and write-job timestamps are UTC-normalized in the backend +4. Admins can review readers, taps, attendance, and card-write jobs from the ESP screens + ### Manage email templates and bounces 1. Super admins can edit database-backed email templates; previews are shown as escaped HTML text 2. SMTP2GO bounce webhooks are stored and visible in bounce management diff --git a/README.md b/README.md index 5b9acd3..f2ac1b3 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ A membership management system for Swansea Airport Stakeholders' Alliance, built - **Membership tiers**: Configurable Personal, Aircraft Owners, Corporate, and custom tiers with annual fees, descriptions, active/inactive state, and benefits. - **Memberships and payments**: Membership lifecycle tracking, Square card payments, cash/check/manual payments, dummy test payments, payment history, transaction IDs, refund state, and payment-to-membership linking. - **Events and RSVPs**: Event CRUD, upcoming event listing, member RSVP updates, RSVP status tracking, attendance fields, and admin RSVP visibility. +- **Time handling**: Backend timestamps are stored and returned as UTC/Zulu, the frontend renders member-facing dates and times in Europe/London, and event entry is converted back to UTC before save. +- **ESP RFID**: Reader provisioning, heartbeat, time sync, tap capture, queued card writes, and admin review of readers/cards/attendance. - **Volunteer and profile data**: Volunteer flag/level support, configurable member profile questions, conditional questions, admin-only answers, seeded aviation/volunteering questions, and data models for volunteer roles, assignments, schedules, and certificates. - **Email system**: SMTP2GO-backed email sending, default database templates, editable templates, welcome/password-reset/test emails, bounce webhooks, bounce stats, cleanup, and manual deactivation. - **Feature flags**: Backend feature-flag service with frontend context and admin status/reload controls. @@ -49,11 +51,13 @@ membership/ │ │ │ │ ├── email.py # SMTP2GO email and bounces │ │ │ │ ├── email_templates.py │ │ │ │ ├── events.py # Events and RSVPs +│ │ │ │ ├── esp.py # ESP RFID provisioning, taps, attendance, write jobs │ │ │ │ └── feature_flags.py │ │ │ └── dependencies.py # Auth dependencies │ │ ├── core/ │ │ │ ├── config.py # Configuration │ │ │ ├── database.py # Database setup +│ │ │ ├── datetime.py # UTC helpers and Zulu serialization helpers │ │ │ └── security.py # Security utilities │ │ ├── models/ │ │ │ └── models.py # Database models @@ -64,11 +68,11 @@ membership/ │ └── requirements.txt ├── frontend/ │ ├── src/ -│ │ ├── components/ # Dashboard, payment, admin, profile components -│ │ ├── contexts/ # Feature flag context +│ │ ├── components/ # Dashboard, payment, admin, profile, ESP components +│ │ ├── contexts/ # Feature flag, toast, and confirm contexts │ │ ├── pages/ # Login, register, dashboard, policy pages │ │ ├── services/ # API clients -│ │ └── utils/ # Tested frontend logic +│ │ └── utils/ # Tested frontend logic and timezone helpers ├── docker-compose.yml ├── .env.example └── README.md @@ -261,6 +265,38 @@ docker compose --profile prod down - `GET /api/v1/feature-flags/flags` - List flags - `POST /api/v1/feature-flags/flags/reload` - Reload flags (super admin) +### ESP RFID +- `POST /api/v1/esp/device/register` - Reader registration and one-time token issuance +- `GET /api/v1/esp/device/provisioning-status` - Poll reader provisioning +- `GET /api/v1/esp/device/time` - UTC clock sync for ESP firmware +- `POST /api/v1/esp/device/heartbeat` - Reader heartbeat with UTC server time +- `POST /api/v1/esp/device/taps` - RFID tap capture with UTC-normalized timestamps +- `GET /api/v1/esp/device/write-jobs/next` - Poll queued card write job +- `POST /api/v1/esp/device/write-jobs/{job_id}/complete` - Complete a queued write job +- `POST /api/v1/esp/device/dashboard-login` - Validate ESP-hosted dashboard login +- `GET /api/v1/esp/admin/readers` - Admin reader list +- `POST /api/v1/esp/admin/readers` - Admin reader create/provision fallback +- `PUT /api/v1/esp/admin/readers/{reader_id}` - Admin reader update / key rotation +- `POST /api/v1/esp/admin/readers/{reader_id}/approve` - Approve a reader +- `POST /api/v1/esp/admin/readers/{reader_id}/reject` - Reject a reader +- `DELETE /api/v1/esp/admin/readers/{reader_id}` - Delete a reader +- `GET /api/v1/esp/admin/cards` - Admin RFID card list +- `POST /api/v1/esp/admin/cards` - Create RFID card +- `PUT /api/v1/esp/admin/cards/{card_id}` - Update RFID card +- `GET /api/v1/esp/admin/write-jobs` - Admin queued write jobs +- `POST /api/v1/esp/admin/write-jobs` - Queue a write job +- `POST /api/v1/esp/admin/write-jobs/{job_id}/cancel` - Cancel a queued write job +- `GET /api/v1/esp/admin/taps` - Admin tap history +- `GET /api/v1/esp/admin/attendance` - Admin attendance sessions +- `POST /api/v1/esp/admin/attendance/close-stale` - Close stale attendance sessions + +## Time Handling + +- Database timestamps are stored as UTC and serialized as Zulu (`...Z`) in API responses. +- Frontend display uses Europe/London for member-facing dates and times. +- Event creation/editing converts London-local input back to UTC before sending it to the backend. +- ESP devices sync their clocks from `/api/v1/esp/device/time` and persist tap times as UTC. + ## Docker Compose Commands ### Basic Operations