# Plan: Resource Model Extensions (EID Attributes) **Date:** 2026-03-13 **Status:** Draft **Depends on:** Country/SAH, OrgUnit hierarchy ## Problem The Dispo Categories file defines a rich set of EID (employee) attributes that CapaKraken's Resource model currently does not cover. These attributes are needed for chargeability reporting, resource filtering, and organizational grouping. ## Current Resource Model (relevant fields) ``` Resource { id, name, email, skills (JSONB), isActive, postalCode, federalState, portfolioUrl, roleId, aiSummary, fte, userId, ... } ``` ## Required New Attributes ### Attributes that need DB storage | Attribute | Type | Source | Notes | |---|---|---|---| | Enterprise ID | String | manual/import | ACN-style username (e.g. "a.kasperovich") | | Country | FK → Country | manual | See plan-country-sah-fte.md | | Metro City | FK → MetroCity | manual | See plan-country-sah-fte.md | | Org Unit (L7) | FK → OrgUnit | manual | See plan-org-unit-hierarchy.md | | Management Level Group | FK → ManagementLevel | manual | See below | | Management Level | derived from group | - | Sub-level within group | | FTE | Float | manual | Already exists, ensure 2+ decimal precision | | Resource Type | Enum | manual | Apprentice, Employee, Freelancer, Intern, Student | | Chg Responsibility | Boolean | manual | Default: true. Drives "Accenture" resource type derivation | | Rolled Off | Boolean | manual | Status flag, default: false | | Departed | Boolean | manual | Status flag, default: false | | Client Unit | FK → Client? or String | manual | Primary client assignment for reporting | ### Attributes that are derived (no DB input) | Attribute | Derivation Rule | |---|---| | Long-term absence | Derived from vacation/absence system (extended leave) | | Chapter | Derived from OrgUnit L7 → name | | Department | Derived from OrgUnit L6 → name | | MV Ressource Type (reporting) | Derived: see resource type derivation rules | ### Resource Type Derivation for Reporting The chargeability report uses a "MV Ressource Type" that differs from the stored Resource Type: | Reporting Type | Derivation Rule | |---|---| | Production Studios | `chgResponsibility = true` AND country is Germany | | Near&Offshore | Country is NOT Germany AND resource type is Employee/Freelancer | | Accenture | `chgResponsibility = false` (regardless of country) | | Long-term absence | Has active long-term absence flag | These are computed at query time, not stored. An admin UI can make the country→reporting-type mapping configurable. ## Management Level Model ### New: `ManagementLevelGroup` model ```prisma model ManagementLevelGroup { id String @id @default(cuid()) name String @unique // "Analyst", "Consultant", "Manager", etc. targetPercentage Float // Official chargeability target (e.g. 0.805) sortOrder Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt levels ManagementLevel[] resources Resource[] } ``` ### New: `ManagementLevel` model ```prisma model ManagementLevel { id String @id @default(cuid()) name String @unique // "10-Senior Analyst", "11-Analyst", etc. groupId String group ManagementLevelGroup @relation(fields: [groupId], references: [id]) resources Resource[] } ``` ### Seed Data | Group | Target % | Levels | |---|---|---| | Accenture Leadership | 36.5% | *(levels 1-4, names TBD)* | | Senior Manager | 54.6% | 5-Associate Director, 6-Senior Manager | | Manager | 74.7% | 7-Manager | | Consultant | 80.8% | 8-Associate Manager, 9-Team Lead/Consultant | | Analyst | 80.5% | 10-Senior Analyst, 11-Analyst | | Associate | 77.0% | 12-Associate, 13-New Associate | ## Schema Changes on Resource ```prisma model Resource { // ... existing fields ... enterpriseId String? @unique // ACN enterprise ID countryId String? // FK → Country country Country? @relation(...) metroCityId String? // FK → MetroCity metroCity MetroCity? @relation(...) orgUnitId String? // FK → OrgUnit (L7) orgUnit OrgUnit? @relation(...) managementLevelGroupId String? // FK → ManagementLevelGroup managementLevelGroup ManagementLevelGroup? @relation(...) managementLevelId String? // FK → ManagementLevel managementLevel ManagementLevel? @relation(...) resourceType ResourceType @default(EMPLOYEE) chgResponsibility Boolean @default(true) rolledOff Boolean @default(false) departed Boolean @default(false) clientUnitId String? // Primary client for reporting clientUnit Client? @relation("ResourceClientUnit", fields: [clientUnitId], references: [id]) } enum ResourceType { EMPLOYEE FREELANCER APPRENTICE INTERN STUDENT } ``` ## UI Changes ### Resource Modal Extensions Add to `ResourceModal.tsx`: | Field | UI Element | Notes | |---|---|---| | Enterprise ID | Text input | Optional, unique | | Country | Dropdown | Required for SAH | | Metro City | Dropdown (filtered by country) | Optional | | Org Unit | Cascading L5→L6→L7 picker | Stores L7 | | Management Level Group | Dropdown | Drives target % | | Management Level | Dropdown (filtered by group) | Specific level | | Resource Type | Dropdown (5 values) | Default: Employee | | Chg Responsibility | Toggle | Default: on | | Client Unit | Client picker | Primary client for reporting | | Rolled Off | Toggle | Status | | Departed | Toggle | Status | ### Admin: Management Level Management (`/admin/management-levels`) - Table of management level groups with target percentages - Nested levels within each group - Editable target % (changes over time) - Add/edit levels ### Resource List Enhancements - New columns: Enterprise ID, Country, Org Unit, Management Level, Client Unit - Filters for: Country, Org Unit (L6/L7), Management Level Group, Resource Type, Client Unit - Status filter: active / rolled off / departed ## LCR and UCR The Dispo file mentions LCR (Local Cost Rate) and UCR (Unit Cost Rate) but has no defined values yet. These are likely cost rates per resource used in budget calculations. Recommendation: Add placeholder fields now, define schema when values become available. ```prisma model Resource { // ... lcrCents Int? // Local Cost Rate in cents per hour ucrCents Int? // Unit Cost Rate in cents per hour } ``` Follows the integer-cents pattern from CLAUDE.md. ## Migration 1. Add new columns to Resource (all nullable initially) 2. Create ManagementLevelGroup + ManagementLevel tables with seed data 3. Add ResourceType enum 4. Admin populates existing resources via batch import or manual assignment ## Acceptance Criteria - [ ] Enterprise ID field on Resource (unique, optional) - [ ] Resource linked to Country, MetroCity, OrgUnit, ManagementLevel - [ ] ResourceType enum with 5 values - [ ] chgResponsibility, rolledOff, departed boolean flags - [ ] Client Unit FK for primary client assignment - [ ] ManagementLevelGroup with target percentages - [ ] ManagementLevel with group membership - [ ] Resource modal with all new fields - [ ] Resource list with new columns and filters - [ ] Management level admin UI - [ ] LCR/UCR placeholder fields (integer cents) - [ ] Reporting resource type derivation logic