Appearance
Event Planning Backend Implementation
Backend implementation for event creation and management API endpoints.
Architecture
Events are managed through a layered architecture:
Client Request → Controller → Service → Repository → Database
↓ ↓
Policy TransactionLayers
- Controller (
apps/server/app/controllers/events_controller.ts) - HTTP request handling, response formatting - Service (
apps/server/app/services/event_service.ts) - Business logic and validation - Repository (
apps/server/app/repositories/event_repository.ts) - Data access with transaction support - Policy (
apps/server/app/policies/event_policy.ts) - Authorization rules - DTO (
apps/server/app/dtos/event.ts) - Response serialization
Data Models
The event planning feature uses the following core models:
- Event - Core event entity with organization ownership, status tracking, and flexible metadata for categories, guest counts, and budgets
- Address - Polymorphic location data that can belong to Event, Vendor, or EventPersonnel entities
- EventPlan - Event planning drafts and versions
- EventBlock - Modular event components with polymorphic containers
For complete schema details, field definitions, metadata structure, and relationships, see:
Business Logic
Event Ownership & Organization Scope
- Event ownership: Events belong to organizations, not individual users
- All queries must be scoped to the active organization
- Cross-organization access is prevented at the application layer
- Collaborator access: Organization members can be added as EventCollaborators (future)
- Personnel management: EventPersonnel are text entries (future)
Address Handling
- Polymorphic relationship: Events can have one associated address
- Transaction-safe: Address creation/updates happen within event transactions
- Optional: Addresses are not required for event creation
For details on other event planning entities (EventPlan, EventBlock, Tasks, Vendors, Permissions), see the Event Planning Data Models documentation. These features are planned for future implementation.
API Endpoints
All event endpoints are nested under organization routes and require authentication.
Available Operations
- POST
/organizations/:organizationId/events- Create a new event with metadata and optional address - PATCH
/organizations/:organizationId/events/:id- Update existing event (supports partial updates with metadata deep-merging) - GET
/organizations/:organizationId/events/:id- Retrieve event details
For complete API documentation including request/response formats, metadata schemas, validation rules, deep-merge behavior, and usage examples, see:
Authorization
Authorization is handled by the EventPolicy class, which enforces organization-based access control.
Authorization Rules
All event operations check organization membership:
- Create Event - User must be a member of the target organization
- View Event - User must be a member of the organization that owns the event
- Update Event - User must be a member of the organization that owns the event
Organization Access Verification
Organization membership is verified by the OrganizationAuthorizationService:
Response Serialization
Event responses use a two-level DTO pattern:
- Minimal DTO: Used for list views (id, name, description, organizationId)
- Detailed DTO: Extends minimal with timestamps (createdAt, updatedAt)
Implementation: apps/server/app/dtos/event.ts
Validation
Validation Strategy
- Required fields: Only
nameis required for event creation - Optional fields: description, targetDate, status, metadata, address
- Metadata validation: Supports category, guestCount, budgetRange with nested validation
- Address validation: Requires
city, optional street address, state, postal code, country - Custom validators: Currency codes (ISO 4217), country codes (ISO 3166-1 alpha-2), postal codes
Default Values
status: BACKLOGeventType: ONE_OFFmetadata.budgetRange.currency: CAD (when budgetRange is provided)
For complete validation schemas and field constraints, see:
apps/server/app/validators/schemas/event.ts- Events API Reference
Error Handling
The implementation uses the neverthrow Result pattern for explicit error handling.
Result Pattern
typescript
// Service layer returns Result
const result = await eventService.createEvent(organizationId, data)
// Controller handles both success and error cases
return result.match(
(event) => response.created({ data: new EventDto(event).minimal }),
(error) => {
// Handle validation errors
if (error instanceof errors.E_VALIDATION_ERROR) {
return response.badRequest({ errors: error.messages })
}
// Handle other errors
return response.internalServerError({ message: 'Failed to create event' })
}
)Error Types
- E_VALIDATION_ERROR - VineJS validation failures
- Error - Database errors, not found errors, etc.
Future Enhancements
The following features are planned but not yet implemented:
- Role-based permissions (currently organization membership check only)
- Event deletion endpoint
- Event listing with pagination and filtering
- Event search functionality
- Recurring event instance management
- And More..
For the current implementation status, see the actual code in:
apps/server/app/controllers/events_controller.tsapps/server/app/services/event_service.tsapps/server/app/repositories/event_repository.tsapps/server/app/policies/event_policy.ts