Appearance
Subscriptions & Plans
Subscriptions link a Member to a SubscriptionPlan and track billing periods, renewal behavior, and lifecycle status.
Subscription Plans
A SubscriptionPlan defines the terms of a membership offering:
| Field | Description |
|---|---|
Name | Display name (e.g., "Full Member") |
Code | Unique identifier (e.g., FULL) |
MonthlyPrice | Base monthly price |
QuarterlyPrice | Optional quarterly discount price |
AnnualPrice | Optional annual discount price |
IsActive | Whether new subscriptions can use this plan |
Benefits | List of PlanBenefit items describing what is included |
Billing Periods
| Code | Description |
|---|---|
monthly | Billed each month |
quarterly | Billed every 3 months |
annual | Billed once per year |
Subscription Lifecycle
Creation
Subscriptions are created during enrollment (POST /api/members/enroll) or directly via POST /api/members/{id}/subscriptions. The system computes StartedAt, EndsAt based on billing period, and stores the price at time of creation.
Statuses
| Status | Code | Meaning |
|---|---|---|
| Active | active | Subscription is current and valid |
| Expired | expired | End date has passed with no renewal |
| Canceled | canceled | Explicitly terminated by staff or member |
Renewal
Subscriptions with AutoRenew = true are processed nightly by ProcessAutoRenewalsJob. The job:
- Finds active subscriptions expiring within 24 hours with
AutoRenew = true - Creates a new subscription starting at the current end date
- Sends a renewal confirmation notification
- Updates the member status back to
activeif needed
Expiry Reminders
CheckExpiringSubscriptionsJob runs daily and sends renewal reminder emails to members whose subscriptions expire within the next 7 days.
Manual Operations
| Operation | Endpoint | Permission |
|---|---|---|
| View subscription | GET /api/members/{id}/subscriptions | subscriptions:read |
| Change plan | POST /api/members/{id}/subscriptions/{sid}/change-plan | subscriptions:change_plan |
| Renew | POST /api/members/{id}/subscriptions/{sid}/renew | subscriptions:renew |
| Cancel | POST /api/members/{id}/subscriptions/{sid}/cancel | subscriptions:cancel |
Plan Management
| Method | Path | Permission | Description |
|---|---|---|---|
GET | /api/plans | plans:read | List all plans |
POST | /api/plans | plans:write | Create a new plan |
GET | /api/plans/{id} | plans:read | Get plan details |
PUT | /api/plans/{id} | plans:write | Update plan |
DELETE | /api/plans/{id} | plans:delete | Deactivate plan |
Business Rules
- A plan cannot be deleted if it has active subscriptions — it can only be deactivated (new signups disabled).
- Price changes on a plan do not retroactively affect existing subscriptions. The price is captured at subscription creation time.
- Changing a subscription's plan (
change-plan) cancels the current subscription and creates a new one with the new plan, prorating when configured.
Frontend Routes
| Route | View | Permission |
|---|---|---|
/club/plans | PlansView | plans:read |
/club/plans/new | PlanCreateView | plans:write |
/club/plans/:id | PlanDetailView | plans:read |
/club/members/:id/subscription | MemberSubscriptionView | subscriptions:read |