invy/REFACTORING_GUIDE.md

362 lines
12 KiB
Markdown

# Multi-Event Invitation Management System - Refactoring Guide
## Overview
The wedding guest list application has been refactored from a single-event system to a **multi-event architecture** that can manage invitations for multiple events (weddings, parties, conferences, etc.).
## Key Architectural Changes
### Database Schema (PostgreSQL)
**New Tables:**
1. **users** - User accounts (organizers/event managers)
```sql
id (UUID PK) | email (unique) | created_at
```
2. **events** - Individual events
```sql
id (UUID PK) | name | date | location | created_at | updated_at
```
3. **event_members** - User membership in events with roles
```sql
id (UUID PK) | event_id (FK) | user_id (FK) | role | display_name | created_at
- Roles: admin, editor, viewer
- UNIQUE constraint on (event_id, user_id)
```
4. **guests_v2** - Guest information (scoped by event, NO separate table per event)
```sql
id (UUID PK) | event_id (FK) | added_by_user_id (FK) | first_name | last_name |
phone | side | status | notes | created_at | updated_at
- Status: invited, confirmed, declined
- Indexed: (event_id), (event_id, added_by_user_id), (event_id, phone)
```
### Database Migration
Run the SQL migration to create new tables:
```bash
psql -U wedding_admin -d wedding_guests -f backend/migrations.sql
```
The migration includes a commented-out data migration script that can import existing data to a default event.
## Backend Changes (FastAPI)
### New Core Modules
#### 1. **models.py** - SQLAlchemy Models
- `User` - User accounts with relationships
- `Event` - Event details with cascade delete
- `EventMember` - Role-based event membership
- `Guest` - Guest entries (links to events with added_by_user)
- Uses UUID primary keys throughout
- Uses SQLAlchemy enums for roles and status
#### 2. **schemas.py** - Pydantic Validation Models
- Organized into sections: User, Event, EventMember, Guest, WhatsApp
- Clear separation between Create/Update/Read schemas
- Type-safe with UUID and enum validation
#### 3. **crud.py** - Database Operations
Reorganized into logical groups:
- **User CRUD**: `get_or_create_user()`, `get_user_by_email()`
- **Event CRUD**: `create_event()`, `get_events_for_user()`, etc.
- **Event Member CRUD**: `create_event_member()`, `get_event_member()`, etc.
- **Guest CRUD (Event-scoped)**: All operations now take `event_id` parameter
- **Statistics**: `get_event_stats()`, `get_sides_summary()`
#### 4. **authz.py** - Authorization (NEW)
Role-based access control with permission checks:
```python
class Permission:
can_edit_event(role) # admin only
can_manage_members(role) # admin only
can_add_guests(role) # editor+
can_send_messages(role) # all members
```
#### 5. **whatsapp.py** - WhatsApp Integration (NEW)
- Phone number normalization to E.164 format
- `send_text_message()` - Send direct messages
- `send_template_message()` - Send approved templates
- `verify_webhook_signature()` - Validate Meta webhooks
- Error handling with custom `WhatsAppError`
### API Endpoints
#### Event Management
```
POST /events Create event (user becomes admin)
GET /events List user's events
GET /events/{event_id} Get event details
PATCH /events/{event_id} Update event (admin only)
DELETE /events/{event_id} Delete event (admin only)
```
#### Event Members
```
GET /events/{event_id}/members List members
POST /events/{event_id}/invite-member Invite by email (admin only)
PATCH /events/{event_id}/members/{user_id} Update role (admin only)
DELETE /events/{event_id}/members/{user_id} Remove member (admin only)
```
#### Guests (Event-Scoped)
```
POST /events/{event_id}/guests Add single guest
GET /events/{event_id}/guests List guests (with filters)
GET /events/{event_id}/guests/{guest_id} Get guest details
PATCH /events/{event_id}/guests/{guest_id} Update guest
DELETE /events/{event_id}/guests/{guest_id} Delete guest (admin only)
```
#### Bulk Operations
```
POST /events/{event_id}/guests/import Import multiple guests
POST /events/{event_id}/whatsapp Send message to guest
POST /events/{event_id}/whatsapp/broadcast Send to multiple guests
GET /events/{event_id}/stats Get event statistics
```
### Authorization
**All event-scoped endpoints enforce authorization:**
- User must be a member of the event
- Permissions based on role:
- **admin**: Full control (create, delete, manage members)
- **editor**: Add/edit guests, import
- **viewer**: View only, can send messages
**Implemented via:**
- `verify_event_access()` - Check membership
- `verify_event_admin()` - Check admin role
- `verify_event_editor()` - Check editor+ role
## Frontend Changes (React/Vite)
### New Components
#### 1. **EventList.jsx** - Event Discovery
- Shows all events user is member of
- Quick stats: total guests, confirmation rate
- Create/delete event actions
- Card-based responsive layout
#### 2. **EventForm.jsx** - Event Creation
- Modal form for new events
- Fields: name (required), date, location
- Automatically adds creator as admin
#### 3. **EventMembers.jsx** - Member Management
- Invite members by email
- Set member roles (admin/editor/viewer)
- Remove members
- Modal interface
### Updated Components
#### **App.jsx** - Main Navigation
- New page states: 'events', 'guests', 'guest-self-service'
- Event selection flow: List → Detail → Guests
- Modal overlays for forms
#### **api/api.js** - Event-Scoped Endpoints
- Reorganized into sections
- All guest operations now scoped by event
- New functions for events and members
- Backward compatibility where possible
### Updated API Functions (examples)
```javascript
// Events
getEvents() // List user's events
createEvent(event) // Create new event
getEventStats(eventId) // Get statistics
// Members
getEventMembers(eventId)
inviteEventMember(eventId, invite)
updateMemberRole(eventId, userId, role)
// Guests (now scoped)
getGuests(eventId, options) // List with filters
createGuest(eventId, guest) // Add single
bulkImportGuests(eventId, guests) // Bulk add
updateGuest(eventId, guestId, data) // Update
// WhatsApp
sendWhatsAppMessage(eventId, guestId, message)
broadcastWhatsAppMessage(eventId, request)
```
## Environment Configuration
### New Variables (.env)
```env
# WhatsApp Cloud API (required for messaging)
WHATSAPP_ACCESS_TOKEN=...
WHATSAPP_PHONE_NUMBER_ID=...
WHATSAPP_API_VERSION=v20.0
WHATSAPP_VERIFY_TOKEN=... (optional, for webhooks)
# Test user (temporary - implement real auth)
TEST_USER_EMAIL=test@example.com
```
See `.env.example` for full template.
## Migration Checklist
- [ ] Back up existing database
- [ ] Run `migrations.sql` to create new tables
- [ ] Update backend dependencies (if any new ones added)
- [ ] Update frontend packages (axios already included)
- [ ] Test authentication (currently uses TEST_USER_EMAIL)
- [ ] Configure WhatsApp credentials (optional)
- [ ] Update FRONTEND_URL in .env for CORS
- [ ] Test event creation workflow
- [ ] Test member invitation
- [ ] Test guest management
## Breaking Changes
### Database
- Old `guests` table still exists but unused
- Can be deleted after confirming data migration was successful:
```sql
DROP TABLE guests;
```
### APIs
Old endpoints **NO LONGER AVAILABLE**:
- `GET /guests/` → Use `GET /events/{event_id}/guests`
- `POST /guests/` → Use `POST /events/{event_id}/guests`
- `GET /guests/{id}` → Use `GET /events/{event_id}/guests/{id}`
### Frontend
- Old single-guest-list view replaced with event-first navigation
- Google import and duplicate manager need updates for event-scoped guests
## Authentication (TODO)
Current implementation uses `TEST_USER_EMAIL` from `.env`.
**Recommended approaches to implement:**
1. **JWT Tokens** - Extract user from Authorization header
2. **Session Cookies** - HTTP-only cookies with session ID
3. **OAuth2** - Google/GitHub integration
4. **API Keys** - For programmatic access
Update `get_current_user_id()` in `main.py` with your auth logic.
## WhatsApp Integration
### Setup Steps
1. Create Meta Business App: https://developers.facebook.com/
2. Add WhatsApp product
3. Create test phone number or configure production
4. Get credentials:
- `WHATSAPP_ACCESS_TOKEN` - Long-lived token
- `WHATSAPP_PHONE_NUMBER_ID` - Phone number sender ID
5. Add to `.env` and `.gitignore`
### Features
- **Send Text Messages**: Direct messages to guest phone (E.164 format)
- **Bulk Broadcast**: Send to multiple guests with optional filters
- **Phone Validation**: Automatic normalization (handles various formats)
- **Error Handling**: Detailed WhatsApp API non-200 errors
### Usage Example
```python
service = get_whatsapp_service()
result = await service.send_text_message(
to_phone="+972541234567",
message_text="Hello! Please confirm your attendance..."
)
```
## File Structure
```
backend/
├── main.py # FastAPI app with all routes
├── models.py # SQLAlchemy ORM models (UPDATED)
├── schemas.py # Pydantic request/response schemas (UPDATED)
├── crud.py # Database operations (COMPLETELY REWRITTEN)
├── authz.py # Authorization & permissions (NEW)
├── whatsapp.py # WhatsApp API client (NEW)
├── database.py # DB connection setup
├── migrations.sql # SQL schema with new tables (NEW)
└── .env.example # Environment template (UPDATED)
frontend/src/
├── components/
│ ├── EventList.jsx # List/manage events (NEW)
│ ├── EventForm.jsx # Create event modal (NEW)
│ ├── EventMembers.jsx # Manage members (NEW)
│ ├── GuestList.jsx # Guest list (needs update for event scope)
│ └── ...
├── api/
│ └── api.js # API client (UPDATED)
└── App.jsx # Main app (UPDATED for events)
```
## Performance Considerations
- **Indexes on guests_v2** for common queries:
- `event_id` - Filter by event
- `(event_id, status)` - Filter by status
- `(event_id, phone)` - Lookup by phone
- **Pagination**: List endpoints support skip/limit
- **Cascading Deletes**: Deleting event removes all guests and memberships
## Security Notes
1. **Authorization**: Every event endpoint checks membership
2. **Phone Numbers**: Validated/normalized before WhatsApp sends
3. **Secrets**: Store ACCESS_TOKEN in .env, never commit
4. **CORS**: Restricted to FRONTEND_URL (.env configuration)
5. **Roles**: Implement fine-grained permissions (admin/editor/viewer)
## Testing Recommendations
```bash
# Test event creation
psql -U wedding_admin -d wedding_guests -c "SELECT * FROM events;"
# Test member management
psql -U wedding_admin -d wedding_guests -c "SELECT * FROM event_members;"
# Test guest entries
psql -U wedding_admin -d wedding_guests -c "SELECT * FROM guests_v2 LIMIT 5;"
# Test API
curl http://localhost:8000/events
```
## Next Steps
1. **Implement Real Authentication** - Replace TEST_USER_EMAIL
2. **Add Google Import** - Update for event-scoped guests
3. **Implement Self-Service Guest Updates** - via token link
4. **Handle Webhooks** - WhatsApp status callbacks
5. **Add Email Notifications** - Event/RSVP confirmations
6. **Deploy Helm Charts** - Uses new schema structure
## Support
For issues or questions:
1. Check `.env` configuration
2. Review database indexes in `migrations.sql`
3. Check authorization checks in `authz.py`
4. Verify API response schemas in `schemas.py`