Skip to content

Events: Foundation — schema, models, enum, Admin CRUD #239

@danielhe4rt

Description

@danielhe4rt

Parent

#237

What to build

Create the foundational schema, models, and Filament Admin resources for the Events Participation module. This is the base layer that all other slices depend on.

Schema (7 tables via individual migrations):

  • events — id, tenant_id, event_type (enum: meetup/workshop/conference), active, slug, title, description, location, starts_at, ends_at, timestamps
  • events_enrollment_policies — event_id (unique FK), enrollment_method, check_in_method, capacity (nullable), has_waitlist, attendance_requirement, cancellation_deadline_hours, xp_reward_rsvp, xp_reward_checkin, xp_reward_attendance, application_form_schema (JSONB), timestamps
  • events_enrollments — id, event_id, user_id, status (enum), waitlist_position (nullable), application_data (JSONB), rejection_reason, enrolled_at, confirmed_at, checked_in_at, attended_at, cancelled_at, is_public, timestamps. UNIQUE(event_id, user_id)
  • events_enrollment_transitions — id, enrollment_id (FK), from_status, to_status, triggered_by, actor_user_id (nullable FK), reason (nullable), created_at
  • events_check_ins — id, enrollment_id (FK), method (enum), payload (JSONB), event_date (date), checked_in_at, timestamps
  • events_check_in_codes — id, event_id (FK), code, event_date (date), valid_from, valid_until, max_uses (nullable), uses_count (default 0), timestamps
  • events_qr_tokens — id, enrollment_id (FK), token (unique), expires_at (nullable), timestamps

Models:

  • EventModel, EventEnrollmentPolicy, EventEnrollment, EventEnrollmentTransition, EventCheckIn, EventCheckInCode, EventQrToken
  • All with proper relationships, casts (JSONB → array, dates → datetime, enums), and return type hints

Enums:

  • EventTypeEnum (meetup, workshop, conference)
  • EnrollmentStatusEnum (pending, confirmed, waitlisted, checked_in, attended, cancelled, rejected, no_show) with canTransitionTo(self $target): bool
  • EnrollmentMethodEnum (rsvp, rsvp_checkin, application)
  • CheckInMethodEnum (manual, numeric_code, qr_code)
  • AttendanceRequirementEnum (all_days, any_day, minimum_days)

Filament Admin:

  • Event resource with CRUD (create, list, edit, delete)
  • Inline Policy form (1:1 relationship) on event create/edit
  • Basic enrollments RelationManager (read-only for now)

Factories:

  • EventFactory, EventEnrollmentPolicyFactory, EventEnrollmentFactory, EventCheckInFactory, EventCheckInCodeFactory, EventQrTokenFactory

Key conventions:

  • declare(strict_types=1) in all files
  • Models are final class
  • Foreign keys use constrained() with appropriate cascades
  • Indexes on: status, event_date, event_id+user_id (composite unique), token
  • casts() method for JSONB and datetime fields
  • Mirror DB defaults in model $attributes
  • 1 migration per table (7 migrations total)
  • All migrations must have reversible down() methods
  • Run vendor/bin/pint --dirty --format agent after all PHP changes

Module structure:

  • Lives in app-modules/events/ following internachi/modular conventions
  • Namespace: He4rt\Events\*
  • Refer to app-modules/events/CONTEXT.md for domain glossary and state machine reference
  • Refer to app-modules/events/docs/adr/ for architectural decisions

Acceptance criteria

  • 7 migrations run successfully and create all tables with proper indexes and constraints
  • All models have correct relationships, casts, and PHPDoc return types
  • EnrollmentStatusEnum::canTransitionTo() correctly validates all allowed transitions per state machine in CONTEXT.md
  • Filament Admin can create an event with enrollment policy in a single form
  • Filament Admin can list events with type, date, and status
  • Factories can generate valid instances of all models
  • All tests pass: php artisan test --compact --filter=Events
  • Pint passes: vendor/bin/pint --dirty --format agent

Blocked by

None — can start immediately

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestready-for-agentFully specified, ready for an AFK agent

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions