Club Management
En bref
Club Management is the operational layer for individual clubs as OrgNodes inside their federation tenant — registration under the right district, full profile with venue and 13 facility flags, board composition with multilingual role matching, annual affiliation lifecycle, member roster, aggregated statistics dashboard, threaded club-to-club messaging, versioned document vault, searchable public directory and safeguarding officer tracking with append-only history.
Comment ça fonctionne
A Club is an OrgNode anchored to its district through district_id. Its profile carries name, logo, venue, founding year, contact details, level (recreational, regional, national, international), a closed ClubFacility enum with 13 facility flags (indoor, outdoor, bar, parking, accessibility, etc.) and a free-text description capped at 5 000 characters. Board composition is structured — president, secretary, treasurer and additional roles — with multilingual token matching so has_president/has_secretary/has_treasurer flags work correctly across French, Swedish, German and English titles.
Affiliation runs as a yearly lifecycle: registered → affiliated → renewed/expired with days_until_expiry surfaced for renewal reminders. The member roster is the canonical list of users tied to the club; license issuance (F03) and competition entries (F04) all key off it. GET /clubs/{id}/statistics aggregates everything an operator wants to see on the club dashboard — member count, board completeness, affiliation status, hosted competitions split by status with first/last host date, published results — and every query goes through Beanie's typed query builder so user input cannot inject Mongo operators.
Club-to-club communication uses ClubMessage: messages are threaded (the root message's thread_id equals its own id, replies inherit the thread and auto-prefix Re:), cross-tenant sends are blocked with 403, and mark-read by the sender returns 400. Attachments are stored as metadata. The directory adds city/level/facility filters; facility uses MongoDB $all semantics so ?facility=indoor&facility=bar ANDs the conditions, backed by dedicated indexes on (level,1), (facilities,1) and (venue.city,1).
ClubDocument is a versioned document store with a closed category enum (statutes, bylaws, insurance, permit, financial_statement, meeting_minutes, policy, other), valid_from/valid_to validation, soft-delete, an expiring?days=N sweep and route ordering that places /documents/expiring before /documents/{document_id} to avoid collision. Safeguarding officer tracking embeds SafeguardingOfficer (user_id, contact, term, BackgroundCheck link, training status, contact_visible_publicly) on the club, with an append-only safeguarding_history; replacing the officer archives the previous one with end_reason=replaced and ended_at=now, and DELETE requires an end_reason in the body.
Capacités clés
- Register and operate a club as an OrgNode under its district with full profile and venue data.
- Manage board composition with multilingual role matching and dashboard completeness signals.
- Track affiliation status, renewal cycle and days-to-expiry for proactive reminders.
- Send and reply to threaded club-to-club messages with hard cross-tenant isolation.
- Publish to a searchable directory filterable by city, level and AND-combined facility flags.
- Store club documents with versioning, validity dates, soft-delete and expiring sweeps.
- Designate a safeguarding officer with background-check link and full append-only history.
En pratique
On a Sunday afternoon the secretary of a mid-sized SBF club opens the club admin. The dashboard shows 87 members, board complete, affiliation expiring in 41 days. She clicks Documents, sees that the liability insurance expires in 14 days from the expiring sweep, uploads the renewed policy as a new version of the existing ClubDocument, marks valid_to to next year, and the expiring counter drops to zero.
She switches to Messages, opens a thread with a neighbouring club about a friendly tournament, and replies — the system auto-prefixes Re: and inherits the thread. Before logging off she replaces the outgoing safeguarding officer: the previous embedded record is archived to safeguarding_history with end_reason=replaced, the new officer is created with a fresh BackgroundCheck link, and the audit row is written.
Fonctionnalités de ce sous-système
10| ID | Status | Fonctionnalités |
|---|---|---|
| F01.06.01 | Livré | Club registration as OrgNode under district in the OrgNode hierarchy ✅ PL-F0106a |
| F01.06.02 | Livré | Club profile (name, logo, venue, contact, founding year) ✅ PL-F0106a |
| F01.06.03 | Livré | Club board/officers management (president, secretary, treasurer, etc.) ✅ PL-F0106a |
| F01.06.04 | Livré | Club affiliation status and annual renewal ✅ PL-F0106a |
| F01.06.05 | Livré | Club member roster management ✅ PL-F0106a |
| F01.06.06 | Livré | Club statistics (members, competitions hosted, results) — GET /clubs/{id}/statistics aggregerar medlemmar/styrelse/anslutning/värdskap/resultat med tenant-scopad, typad Beanie-query ✅ PL-F0106b |
| F01.06.07 | Livré | Club-to-club communication — trådad meddelandetjänst (ClubMessage) med cross-tenant-block, reply/mark-read/direction-filter ✅ PL-F0106b |
| F01.06.08 | Livré | Club search/directory (by district, facilities, level) — city/level/facility ($all) filter + nya index (level,1), (facilities,1), (venue.city,1) ✅ PL-F0106b |
| F01.06.09 | Livré | Club document management (statutes, insurance, permits) — ClubDocument med sluten kategori-enum, versionskedja, verify/expiring-sweep, soft-delete ✅ PL-F0106b |
| F01.06.10 | Livré | Safeguarding officer designation and tracking — embedded SafeguardingOfficer + append-only safeguarding_history, 6 endpoints, BackgroundCheck-länk ✅ PL-F0106b |
Sous-systèmes liés
Parties prenantes qui ont besoin de ce sous-système
Apparaît dans 3 analyses de parties prenantes