Aller au contenu principal
Petanque Life

Club Membership

F03.02 17 fonctionnalités Plateforme+

En bref

Club Membership manages the relationship between players and clubs independently of federation licenses, with a separate lifecycle, billing model, and category catalogue. It supports configurable membership categories per tenant, a strict single license-club constraint with optional support memberships in other clubs, family grouping with discounts, automated renewal reminders, per-club member directories with privacy controls, and competition-entry validation against the player's actual license club.

Comment ça fonctionne

Club membership is modelled separately from licensing because the two have distinct lifecycles and purposes — a player can be a paying member of several clubs but can hold competition rights through only one. The membership flow starts when a player submits an application to a club; the club then accepts or rejects through a workflow that records activated_at, expired_at, and full status-transition history. Each tenant configures its own MembershipCategory catalogue (full, associate, honorary, youth, family, support, etc.) and per-category membership fees, which are decoupled from license fees and billed by the club rather than the federation.

The license-club constraint is enforced at the system level: every player has exactly one ClubMembership flagged as is_license_club=true, and any category whose grants_competition_rights flag is set may only be assigned to that license-club membership. All other club memberships must use support categories. This lets a player play competitions for Club A while paying social membership at Club B without any conflict in license assignment. A dedicated player-summary endpoint exposes the full picture (license club + support clubs) for both admin and member-facing UIs.

Family grouping is handled through a FamilyGroup model: when two or more members from the same household join, the second and subsequent memberships receive a configurable family discount. A family-overview endpoint surfaces all members and their categories for billing and renewal. Renewal reminders run as a bulk job per club with a max_reminders threshold and per-player reminder count tracking, so members don't get spammed and clubs see who has been notified how many times. Membership cards are generated digitally and the per-club member directory respects privacy controls configured by both the club and individual members.

Finally, club-bound competition enforcement validates that players entering a competition under a specific club are actually license-club members of that club — using the per-player club mapping resolved at entry time — preventing accidental or fraudulent club affiliation in entry lists.

Capacités clés

  • Membership application and acceptance/rejection workflow with full status history
  • Configurable membership categories and per-category fees per tenant
  • Single license-club constraint with optional support memberships in other clubs
  • Family grouping with automatic discounts for second and subsequent members
  • Automated bulk renewal reminders with per-player reminder count tracking
  • Per-club member directory with privacy controls
  • Club-bound competition entry validation against the player's license club

En pratique

A Swedish family of four signs up at BK Boule Stockholm. The parent registers first with a Full membership; the system creates a FamilyGroup, then applies a 25 percent family discount to the spouse's Full membership and to both children's Youth memberships. The club secretary accepts all four applications in one batch; activated_at timestamps are written and digital member cards are pushed.

Six months later the system runs the renewal-reminder job, which sees three of the four are renewed and the fourth has received only one of the three configured reminders, so a second reminder email goes out — but no new emails to the renewed members. When the parent registers as a support member at a second club, the system blocks the second club from assigning a Full category and offers only support categories instead.

Fonctionnalités de ce sous-système

17
ID Status Fonctionnalités
F03.02.01 Livré Membership application (player applies to join club) — PL-F0302a ✅ PL-F0302a
F03.02.02 Livré Club acceptance/rejection workflow — PL-F0302a ✅ PL-F0302a
F03.02.03 Livré Membership categories — configurable per tenant (full, associate, honorary, youth, family, support, etc.) — PL-F0302a ✅ PL-F0302a
F03.02.04 Livré Membership fee management per category — PL-F0302a ✅ PL-F0302a
F03.02.05 Livré Membership card generation — PL-F0302a ✅ PL-F0302a
F03.02.06 Livré Member directory per club (with privacy controls) — PL-F0302a ✅ PL-F0302a
F03.02.07 Livré Membership start/end dates and status tracking — status transition history, auto-expire endpoint, activated_at/expired_at timestamps — PL-F0302b ✅ PL-F0302b
F03.02.08 Livré License club vs support membership — player has exactly one license club (competition rights) but can be support member in other clubs (no competition rights). System enforces single license club constraint. Categories with grants_competition_rights require is_license_club=true. Player summary endpoint. — PL-F0302b ✅ PL-F0302b
F03.02.09 Livré Family membership grouping — FamilyGroup model, family discount for 2nd+ member, family membership overview endpoint — PL-F0302b ✅ PL-F0302b
F03.02.10 Livré Automatic membership renewal reminders — bulk reminder endpoint with max_reminders threshold, per-club filtering, reminder count tracking — PL-F0302b ✅ PL-F0302b
F03.02.11 Livré Club-bound competition enforcement — enhanced validation with expected club_id, per-player club mapping, club name resolution — PL-F0302b ✅ PL-F0302b
F03.02.12 Livré ClubInquiry inbox — shared inbox for prospect/visitor inquiries, status-FSM new/assigned/awaiting_reply/responded/converted/closed_no_response/spam, indices för (tenant_id, club_id, status) + (tenant_id, assigned_to, status) + (follow_up_due) — PL-T222 ✅ PL-T222
F03.02.13 Livré InquiryAssignment — event-log per (re-)assignment, role-gated på role:club_secretary / role:membership_secretary, dispatchar inquiry.assigned-notification via F09.02 — PL-T222 ✅ PL-T222
F03.02.14 Livré InquiryResponseTemplate — Jinja-style {{contact.name}}-substitution, per (club_id, inquiry_type, language)-default, okända variabler collapsar till tomt — PL-T222 ✅ PL-T222
F03.02.15 Livré Inquiry follow-up reminder — 5-dagars default-SLA, inquiry_follow_up_tick (1 h-cron), single-fire via follow_up_reminder_sent_at-marker — PL-T222 ✅ PL-T222
F03.02.16 Livré Convert-to-member — skapar ClubMember från inquiry, sätter inquiry.converted_to_member_id + status=converted, 409 vid email-kollision — PL-T222 ✅ PL-T222
F03.02.17 Livré Public CMS inquiry-form-endpoint — POST /public/clubs/{id}/inquiries med rate-limit 10/h per IP, honeypot-fält website (left:-9999px), 5-min dedup på (email, subject), email lower-normaliserad — PL-T222 ✅ PL-T222