Skip to content

Member Management

Phase 2 of Club Wilo implements the full member lifecycle — from enrollment through cancellation — including subscription plans, promotions, referrals, and background automation.

Member Lifecycle

A member passes through a defined set of statuses:

StatusCodeDescription
ActiveactiveMember has an active subscription
Payment Pendingpayment_pendingSubscription expired, payment awaited
SuspendedsuspendedManually suspended by staff or automated (unpaid)
CanceledcanceledMembership terminated

Status Transitions

                  ┌─────────────────┐
                  │   enrollment    │
                  └────────┬────────┘

                       ┌────────┐
                ┌─────►│ ACTIVE │◄────────────────────┐
                │      └───┬────┘                     │
                │          │ expiry / no auto-renew    │
                │          ▼                           │
                │  ┌─────────────────┐                 │
                │  │ PAYMENT_PENDING │                 │ renew
                │  └───────┬─────────┘                 │
                │          │ manual suspend             │
                │  payment ▼ / auto-suspend             │
                │     ┌───────────┐                    │
                │     │ SUSPENDED │────────────────────┘
                │     └─────┬─────┘
                │           │ terminate
                │           ▼
                │      ┌──────────┐
                └──────│ CANCELED │
                       └──────────┘

Enrollment Flow

A new member is enrolled via POST /api/members/enroll which atomically:

  1. Creates the Member entity
  2. Creates an initial Subscription linked to a SubscriptionPlan
  3. Applies any promotion or referral discount to the first month
  4. Generates a ReferralCode for the new member
  5. Publishes MemberCreatedEvent (integration event via outbox)
  6. Sends a welcome notification

Status History

Every status change is recorded in MemberStatusHistory with:

  • Previous and new status
  • Actor (who made the change)
  • Optional reason

This provides a full audit trail accessible at /api/members/{id}/status-history.

Key Entities

EntityPurpose
MemberCore aggregate root — personal data, status, member number
SubscriptionActive subscription with plan, billing period, dates
SubscriptionPlanPlan definition — price, benefits, billing options
MemberStatusHistoryImmutable log of all status changes
ReferralCodeUnique code generated at enrollment, used to invite others
ReferralRecord of a successful referral (referrer → referee)
PromotionDiscount rule (percentage or fixed amount) with conditions
PromotionUsageTracks per-member usage of a promotion
UserPreferencesMember notification and app preferences

API Endpoints

Member CRUD

MethodPathPermissionDescription
GET/api/membersmembers:readList members (paginated, filterable)
POST/api/members/enrollenrollment:writeEnroll a new member
GET/api/members/{id}members:readGet member details
PUT/api/members/{id}members:writeUpdate member data
DELETE/api/members/{id}members:writeSoft-delete member

Status Management

MethodPathPermissionDescription
POST/api/members/{id}/activatemembers:status:writeActivate member
POST/api/members/{id}/suspendmembers:status:writeSuspend member
POST/api/members/{id}/cancelmembers:status:writeCancel membership
GET/api/members/{id}/status-historymembers:status_history:readView status history

Self-Service

MethodPathPermissionDescription
GET/api/users/me/subscriptionmembers:subscription:readView own subscription
GET/api/users/me/preferencespreferences:readView own preferences
PUT/api/users/me/preferencespreferences:writeUpdate own preferences

Export

MethodPathPermissionDescription
GET/api/members/exportmembers:exportExport to CSV/XLSX

Frontend Routes

RouteViewPermission
/clubClubDashboardViewmembers:read
/club/membersMembersViewmembers:read
/club/members/newMemberCreateViewmembers:write
/club/members/:idMemberDetailViewmembers:read
/club/members/:id/subscriptionMemberSubscriptionViewsubscriptions:read
/club/members/:id/historyMemberHistoryViewmembers:read