Multi-Chapter Membership Service
Component Detail
Description
Business logic layer for managing many-to-many relationships between contacts and chapters. Enforces the maximum of 5 simultaneous chapter affiliations, handles assignment and removal transactions, and provides the complete affiliation set for a given contact across the organization.
multi-chapter-membership-service
Summaries
This service enforces a core business rule — that no contact may belong to more than five chapters simultaneously — protecting the integrity of the organization's membership structure. By centralizing this constraint in a dedicated service layer, the business eliminates the risk of inconsistent enforcement across different parts of the application, which could lead to contacts appearing in conflicting reports or coordinators receiving inaccurate affiliation data. Clean, enforced membership boundaries also directly support compliance and audit readiness, reducing operational risk and making the platform more trustworthy for chapter leadership making staffing and engagement decisions.
The Multi-Chapter Membership Service is a medium-complexity component spanning both mobile and backend execution contexts, which means it requires coordinated delivery and testing across two runtime environments. Its single dependency on the Contact Chapter Repository means that repository must be production-ready before integration work begins — this is a sequencing constraint that should be reflected in the sprint plan. The five-chapter maximum validation logic must be covered by unit and integration tests, including edge cases such as concurrent assignment attempts. Deployment considerations include ensuring the same validation logic behaves consistently on both mobile (offline-capable) and backend (authoritative) paths to avoid race conditions.
This service class sits between the Cubit state layer and the Contact Chapter Repository, encapsulating all business logic for contact-chapter many-to-many relationships. The addContactToChapter() method must call validateMaxAffiliations() before delegating to the repository's insert operation — this guard is the primary enforcement point for the 5-chapter rule. The service is consumed by ChapterMembershipCubit on mobile and may also be invoked server-side for bulk operations or API-driven imports. All methods return Futures, so callers must handle async errors including constraint violations, which should be surfaced as typed exceptions rather than raw Supabase errors.
Consider whether validateMaxAffiliations() should use a database-level count query (via countChaptersForContact) to avoid TOCTOU race conditions in concurrent environments.
Responsibilities
- Add a contact to a chapter, enforcing the 5-chapter maximum
- Remove a contact from a chapter
- Retrieve all chapter affiliations for a contact
- Validate that a contact is not already assigned to the same chapter
Interfaces
addContactToChapter(String contactId, String chapterId)
removeContactFromChapter(String contactId, String chapterId)
getChaptersForContact(String contactId) → Future<List<ContactChapter>>
getContactsForChapter(String chapterId) → Future<List<ContactChapter>>
validateMaxAffiliations(String contactId) → Future<bool>
isContactInChapter(String contactId, String chapterId) → Future<bool>
Relationships
Dependents (2)
Components that depend on this component
Related Data Entities (2)
Data entities managed by this component