Orgs — models¶
Responsibilities¶
The orgs app models the organizational structure and membership layer of the system.
It is responsible for:
- the
Organizationtenant model - hierarchical parent/child org structure
- org-level settings inheritance
- branding and document identity configuration
- internal user membership in organizations
- customer user membership in customer organizations
- links between internal orgs and customer orgs
This app is the main multi-tenancy and role container for the backend.
It does not model user identity itself. That remains in accounts.
Instead, orgs answers questions like:
- which organization is the user acting in
- what role does the user have in that organization
- which customer organizations are linked to which internal organizations
- what branding/settings are effective for this org
Main models¶
Organization¶
Represents an organizational tenant and, optionally, a node in the org tree.
This is the central model of the app.
- Fields
- Core identity
nameslugorg_typeparentsettings
- Branding / legal identity
legal_namedisplay_name
- Address / contact
address_line1address_line2postal_codecitystate_regioncountryphoneemailwebsite
- Legal / registration
vat_numbercoc_number
- Branding assets
logologo_pdfbrand_primarybrand_textbrand_muted
- PDF/document options
pdf_footer_notepdf_show_legal_idspdf_show_contact_details
- Lifecycle
is_activecreated_at
- Audit/history
history
- Constraints
slugis uniqueparentis protected on delete- Tree behavior is managed via
MPTTModel - Relationships
- Optional parent organization via
parent - One-to-many child organizations via
children - One-to-many internal memberships via
memberships - One-to-many customer memberships via
customer_memberships - One-to-many outgoing customer links via
linked_customers - One-to-many incoming customer links via
linked_to_internal_orgs
Key derived behavior¶
effective_settings()¶
Combines inherited JSON settings from ancestors to the current org.
Rule: - parent settings form the base - child settings override matching keys
display_name_effective¶
Returns:
1. display_name
2. else legal_name
3. else name
logo_pdf_url¶
Returns the preferred branding file URL:
1. logo_pdf
2. else logo
address_single_line¶
Builds a one-line address string from the address fields.
effective_branding()¶
Builds a resolved branding/document payload using: - explicit org fields first - inherited settings as fallback - sensible defaults when neither exists
This makes Organization both a tenant model and a branding/document configuration source.
OrgMembership¶
Represents an internal user’s membership in an internal organization.
This is the main role-based authorization anchor used across the project.
- Fields
userorgroleis_activejoined_athistory- Constraints
- Unique per
(user, org) - Relationships
- Foreign key to
accounts.User - Foreign key to
Organization
Role values¶
owneradminmanagerengineerviewer
These roles are used by application logic to determine whether a user may: - manage members - manage invites - access organization-level functionality - act in administrative workflows
CustomerLink¶
Represents a relationship between an internal organization and a customer organization.
This allows the system to model customer-facing access without mixing internal and customer tenants directly.
- Fields
internal_orgcustomer_orgis_activecreated_at- Constraints
- Unique per
(internal_org, customer_org) - Relationships
- Foreign key to
Organizationasinternal_org - Foreign key to
Organizationascustomer_org
This model is the bridge that enables internal orgs to work with customer orgs in a controlled way.
CustomerMembership¶
Represents a customer user’s membership inside a customer organization.
This is intentionally separate from OrgMembership so internal roles and customer roles do not get mixed together.
- Fields
usercustomer_orgroleis_activejoined_at- Constraints
- Unique per
(user, customer_org) - Relationships
- Foreign key to
accounts.User - Foreign key to
Organizationascustomer_org
Role values¶
customer_admincustomer_user
This model is used for portal/customer-side access where internal staff roles should not apply.
Relationship overview¶
flowchart TD
User[User]
Organization[Organization]
OrgMembership[OrgMembership]
CustomerMembership[CustomerMembership]
CustomerLink[CustomerLink]
Organization -->|parent/children tree| Organization
User -->|1:N| OrgMembership
Organization -->|1:N| OrgMembership
User -->|1:N| CustomerMembership
Organization -->|1:N customer_org| CustomerMembership
Organization -->|internal_org| CustomerLink
Organization -->|customer_org| CustomerLink
Model boundaries and design notes¶
Why Organization is broader than a simple tenant table¶
Organization currently combines three concerns: • tenant identity • hierarchy/inheritance • branding/document configuration
That is acceptable in this system because branding and org identity are tightly linked in operational workflows such as: • PDF generation • customer-facing reports • organization settings screens
If these concerns become significantly more complex later, branding could be split into a dedicated model.
Why memberships are split into two models¶
The project distinguishes between: • internal workforce memberships • customer user memberships
That separation is important because: • role sets differ • permissions differ • workflows differ • mixing them would make authorization logic harder to reason about
So: • OrgMembership = internal tenant role • CustomerMembership = customer tenant role
Why CustomerLink exists separately¶
A customer org is still an Organization, but not every org should automatically be related to every other org.
CustomerLink makes the relationship explicit and manageable: • internal org can link to customer org • link can be activated/deactivated • downstream access can depend on that link