Skip to main content

organizations app

The structural backbone. Every other app's data is scoped through this app's models.

Models (9)

  • Organization — tenant root; fields: name, slug, type, is_active, primary_color, accepts_account_requests
  • Region — optional grouping of chapters within an org; states_covered as text
  • Chapter — concrete chapter; FK to org + nullable region; fields: name, designation, university, city, state, founded_date, status (active / inactive / suspended)
  • Membership — joins User to Chapter; fields: role (member / officer / president / advisor), status (pnm / pledge / undergrad / associate / alumni / inactive / disaffiliated), joined_at
  • OrganizationAdmin — promotes a User to org admin; fields: title, is_active
  • RegionalAdmin — promotes a User to regional admin; fields: role (director / coordinator / advisor), title, is_active
  • ProfileCompletenessConfig — per-org rules for what counts toward member profile completeness score
  • StorageConfig — per-org S3 / MinIO config (encrypted credentials)
  • OrganizationConsentTemplate — per-org legal templates (membership agreement, code of conduct, photo release, etc.)

Key endpoints

URLPurpose
GET /api/organizations/List orgs (platform admin sees all; others see own)
GET /api/organizations/<id>/Org detail
PATCH /api/organizations/<id>/Update org (name, branding, etc.)
POST /api/organizations/<id>/admins/Invite an org admin
GET /api/organizations/<id>/regions/List regions
POST /api/organizations/<id>/regions/Create a region
GET /api/organizations/<id>/chapters/List chapters
POST /api/organizations/<id>/chapters/Create a chapter
GET /api/chapters/<id>/members/Roster
POST /api/chapters/<id>/members/Add a member
PATCH /api/memberships/<id>/Update role / status

Permissions

  • IsNationalAdmin — org-wide CRUD
  • IsRegionalAdmin — region-scoped reads + chapter management within region
  • IsChapterOfficer — chapter-scoped membership management
  • IsChapterMember — read-only on own chapter

Background tasks

  • generate_org_snapshots — periodic stats snapshot for retention analytics
  • recalculate_membership_stats — fires on bulk membership changes

Signals

  • post_save on Membership — creates the related MemberProfile and onboarding records

Notable patterns

Membership statuses control platform access

Membership.PLATFORM_ACCESS_STATUSES is the gate — only users with at least one membership in an "access" status can sign in. Statuses excluded from access:

  • pnm (Prospective New Member — pre-bid)
  • disaffiliated (terminated)
  • inactive (paused)

One Membership per (User, Chapter)

DB constraint: unique_together = ("user", "chapter"). Transferring a member to another chapter creates a new Membership with the prior one moved to inactive.

Sole-admin protection

_validate_org_admin_deactivation blocks deactivating the last active org admin. Returns 409 Conflict with code: "last_admin".

Org-level branding

Organization.primary_color (HSL string, nullable). When set, the frontend injects it as the --primary CSS var, overriding the platform default #334155.

Per-org module licensing

Lives on the OrganizationModule model in apps/organizations/models.py. Foreign-key on Organization, one row per module.

Code paths

  • Models: backend/apps/organizations/models.py
  • Views: backend/apps/organizations/views.py
  • Permissions referenced: backend/apps/common/permissions.py
  • Middleware that scopes queries: backend/apps/common/middleware.py