Departments
Organizational units for user grouping and permission management
Overview
Departments are organizational units within a tenant that allow administrators to group users and control their access to features and applications. This provides a hierarchical permission system where tenant-level features can be selectively granted to different departments.
Purpose
The departments feature enables:
- Feature Management: Control which features and apps are available to users based on their department membership
- User Organization: Group users into logical units for better management
- Permission Inheritance: Create a permission hierarchy: Tenant → Department → User
- Dashboard Customization: Dashboard cards and sections are conditionally rendered based on department permissions
Hierarchical Structure
The system supports a flexible permission hierarchy:
- Tenant Level: The tenant has a set of enabled features and installed apps
- Department Level: Departments can be assigned a subset of the tenant's features
- User Level: Users inherit features from their department(s)
Feature Assignment
Features and apps are stored as a JSON array in the features field:
- Standard features:
["locations", "calendar", "files", "knowledge"] - Apps:
["online-join", "starting-line"] - Null/empty: Inherits all tenant features
Note: Apps and features are stored as plain strings without prefixes.
Database Schema
Department Model
model Department {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenantId String
name String
description String?
features String? @db.NVarChar(max) // JSON array
createdByUserId String
lastModifiedByUserId String
departmentTenantUsers DepartmentTenantUser[]
locationDepartments LocationDepartment[]
}DepartmentTenantUser Model
model DepartmentTenantUser {
id String @id @default(cuid())
departmentId String
tenantUserId String
@@unique([departmentId, tenantUserId])
}Routes
Main Routes
/app/{tenant}/settings/departments- List all departments/app/{tenant}/settings/departments/new- Create new department/app/{tenant}/settings/departments/{id}- Edit department details
Feature Filtering Logic
Central Function
Get user's effective features with proper typing:
const effectiveFeatures = await getUserEffectiveFeatures({
tenantId,
userId
});
// Returns:
{
features: AppFeature[]; // Typed array of features
apps: AppType[]; // Typed array of apps
raw: string[]; // Combined list for backward compatibility
}Dashboard Integration
The dashboard conditionally renders cards based on enabled features:
// Dashboard loader
const effectiveFeatures = await getUserEffectiveFeatures({ tenantId, userId });
const stats = await getTenantFeatureStats(tenant, t, effectiveFeatures.raw);
// Component helpers
const isFeatureEnabled = (feature: string): boolean => {
return enabledFeatures.includes(feature);
};Multiple Department Membership
When a user belongs to multiple departments:
- Features from all departments are combined (union)
- If any department has no custom features, user gets all tenant features
- The most permissive access wins
User Experience
For Administrators
- Navigate to Settings → Departments
- Create a new department or edit existing
- Assign users to the department
- Select which features/apps the department can access
- Save changes
For End Users
- Users are assigned to departments by administrators
- When users log in, their available features are filtered based on:
- If no department: Access all tenant features
- If in department(s) with no custom features: Access all tenant features
- If in department(s) with custom features: Access only assigned features
- The UI automatically adjusts to show only permitted features/apps
Components
DepartmentForm
Form for creating/editing departments with:
- Name and description fields
- User selection with InputAutocomplete
- Feature selection with checkboxes
- Separate sections for features and apps
Example Use Cases
1. Sales Department
- Features:
["locations", "providers", "starting-line"] - Users see only Locations, Providers features, and Starting Line app
2. HR Department
- Features:
["calendar", "knowledge", "online-join"] - Users see Calendar, Knowledge features, and Online Join app
3. Executive Department
- Features:
[](empty) - Users see all tenant features (full access)
Best Practices
Feature Assignment
- Default Behavior: Leave features empty to grant all tenant features
- Restrictive Access: Only assign specific features when limiting access
- No Prefixing: Apps and features are stored as plain strings
- Order Preservation: Features and apps maintain their original order
User Management
- Bulk Assignment: Use the dual table selector for managing multiple users
- Department Hierarchy: Create departments that reflect organizational structure
- Feature Groups: Consider creating departments for common feature sets
Performance Considerations
- Caching: User department features are cached during session
- Eager Loading: Department relations are loaded efficiently
- Filtering: Feature filtering happens server-side before rendering
Troubleshooting
Common Issues
- Features Not Showing: Check if user is properly assigned to department
- All Features Visible: Department might have no custom features (inheriting all)
- No Features Visible: User might not be in any department with the tenant
Debugging
Check department assignments:
SELECT d.name, dtu.*
FROM DepartmentTenantUser dtu
JOIN Department d ON d.id = dtu.departmentId
WHERE dtu.tenantUserId = 'USER_ID'Check feature assignments:
SELECT name, features
FROM Department
WHERE tenantId = 'TENANT_ID'Integration Points
- Dashboard: Conditional rendering of feature cards
- Navigation: Sidebar menu items filtered by permissions
- Apps: App visibility controlled by department features
- Locations: Department-based location access (partial)

