Files
CapaKraken/samples/Dispov2/plan-org-unit-hierarchy.md
T

178 lines
5.3 KiB
Markdown

# Plan: Org Unit Hierarchy (Level 5 / 6 / 7)
**Date:** 2026-03-13
**Status:** Draft
**Depends on:** -
## Problem
The chargeability report groups resources by a 3-level organizational hierarchy:
```
Level 5: Content Production (department)
Level 6: CGI Content | CGI Technology | Creative Content Production | VFX (division)
Level 7: Art Direction | CGI Production | 3D | IT Development | ... (chapter/team)
```
Every resource must be mapped to an Org Unit Level 7. Level 7 rolls up to Level 6, which rolls up to Level 5. The names of org units can change over time, so they must be editable.
Planarchy already has a `Role` model, but roles represent skills/functions (e.g. "3D Artist"), not organizational placement. A person's org unit and their role are different dimensions.
## Current Data
### Level 5 → Level 6
| Level 5 | Level 6 |
|---|---|
| Content Production | CGI Content |
| Content Production | CGI Technology |
| Content Production | Creative Content Production |
| Content Production | VFX |
### Level 6 → Level 7
| Level 6 | Level 7 |
|---|---|
| CGI Content | Art Direction |
| CGI Content | Capability Development |
| CGI Content | CGI Production |
| CGI Content | Product Data Management |
| CGI Content | Program/Delivery Mgmt |
| CGI Technology | CGI Development |
| CGI Technology | IT Development |
| Creative Content Production | *(direct, no sub-teams)* |
| VFX | 2D & Art Direction |
| VFX | 3D |
| VFX | Program/Delivery Mgmt & Other |
## Schema
### New: `OrgUnit` model (self-referencing tree)
```prisma
model OrgUnit {
id String @id @default(cuid())
name String
shortName String? // optional abbreviation
level Int // 5, 6, or 7
parentId String?
parent OrgUnit? @relation("OrgUnitTree", fields: [parentId], references: [id])
children OrgUnit[] @relation("OrgUnitTree")
sortOrder Int @default(0)
isActive Boolean @default(true) // soft-delete for renamed/retired units
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
resources Resource[] // resources assigned to this org unit (level 7)
@@unique([parentId, name])
}
```
### Resource model extension
```prisma
model Resource {
// ... existing fields ...
orgUnitId String?
orgUnit OrgUnit? @relation(fields: [orgUnitId], references: [id])
}
```
Constraint: A resource should only be assigned to a Level 7 org unit. The UI enforces this; the schema allows any level for flexibility.
## Shared Types
```typescript
// packages/shared/src/types/org-unit.ts
interface OrgUnit {
id: string;
name: string;
shortName?: string;
level: number; // 5, 6, or 7
parentId?: string;
sortOrder: number;
isActive: boolean;
}
interface OrgUnitTree extends OrgUnit {
children: OrgUnitTree[];
}
```
## API
Location: `packages/api/src/router/org-unit.ts`
| Procedure | Access | Description |
|---|---|---|
| `list` | protected | Returns flat list, optionally filtered by level or parentId |
| `getTree` | protected | Returns nested tree structure for UI rendering |
| `create` | admin | Create org unit with parent reference |
| `update` | admin | Rename, re-parent, change sort order |
| `deactivate` | admin | Soft-delete (sets `isActive = false`) |
## UI
### Admin: Org Unit Management (`/admin/org-units`)
- Tree view showing L5 → L6 → L7 hierarchy
- Inline editing of names (since names can change)
- Add/remove units at each level
- Drag-and-drop reordering within a level
- Deactivate (not hard delete) to preserve historical data
### Resource: Org Unit Assignment
- `ResourceModal.tsx` gets cascading dropdowns:
1. Level 5 (pre-filtered or single value)
2. Level 6 (filtered by selected L5)
3. Level 7 (filtered by selected L6) — this is what gets stored on the resource
- Alternative: single tree picker showing full path
### Chargeability Report
The report groups by L6 → L7 (see `plan-chargeability-report.md`). The OrgUnit tree drives the row structure of the report.
## Seed Data
Seed the initial hierarchy from the Dispo Categories file:
```
Content Production (L5)
├── CGI Content (L6)
│ ├── Art Direction (L7)
│ ├── Capability Development (L7)
│ ├── CGI Production (L7)
│ ├── Product Data Management (L7)
│ └── Program/Delivery Mgmt (L7)
├── CGI Technology (L6)
│ ├── CGI Development (L7)
│ └── IT Development (L7)
├── Creative Content Production (L6)
│ └── Creative Content Production (L7)
└── VFX (L6)
├── 2D & Art Direction (L7)
├── 3D (L7)
└── Program/Delivery Mgmt & Other (L7)
```
## Migration
1. Create `OrgUnit` table and seed data
2. Add `orgUnitId` to Resource (nullable)
3. Admin assigns org units to existing resources
4. No automated backfill possible — org unit assignment is business knowledge
## Acceptance Criteria
- [ ] `OrgUnit` model with self-referencing parent/child tree
- [ ] Resource linked to OrgUnit (level 7)
- [ ] Admin UI: tree view with CRUD for all levels
- [ ] Resource modal: cascading L5 → L6 → L7 dropdowns
- [ ] Org unit names are editable without breaking historical references
- [ ] Seed data for the known hierarchy
- [ ] `getTree` API returns nested structure for UI