chore(repo): initialize planarchy workspace

This commit is contained in:
2026-03-14 14:31:09 +01:00
commit dd55d0e78b
769 changed files with 166461 additions and 0 deletions
@@ -0,0 +1,158 @@
# Plan: Utilization Categories on Projects
**Date:** 2026-03-13
**Status:** Draft
**Depends on:** -
## Problem
The chargeability report categorizes all work into utilization buckets. Currently Planarchy projects have no utilization classification. Every project needs a utilization category so that hours booked against it flow into the correct reporting bucket.
## Utilization Categories
From the Dispo Categories file (adapted to ACN naming):
| Short | Name | Description |
|---|---|---|
| Chg | Chargeable | Billable client project work |
| BD | Business Development | Sales, proposals, presales activities |
| MD&I | Market Development and Initiative | R&D, innovation, market development |
| M&O | Management and Operations | Internal admin, management overhead |
| PD&R | Personal Development and Recruitment | Training, hiring, onboarding |
| Absence | Absence & Non Standard | Reduces Standard Available Hours: vacation, illness, non-standard leave |
Notes from the Dispo file:
- "Absent" and "Not available" are merged into "Absence & Non Standard"
- "Unassigned" hours are calculated automatically (SAH minus all categorized hours)
- Categories follow ACN naming convention
## Schema
### New: `UtilizationCategory` model
```prisma
model UtilizationCategory {
id String @id @default(cuid())
code String @unique // "Chg", "BD", "MD&I", etc.
name String // Full display name
description String? // Editable explanation
sortOrder Int @default(0)
isActive Boolean @default(true)
isDefault Boolean @default(false) // One category can be the default for new projects
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
projects Project[]
}
```
### Project model extension
```prisma
model Project {
// ... existing fields ...
utilizationCategoryId String?
utilizationCategory UtilizationCategory? @relation(fields: [utilizationCategoryId], references: [id])
}
```
Why on Project (not on Allocation/Assignment):
- The Dispo model maps categories to projects, not to individual time entries
- A project is either "Chargeable" or "Business Development" — the category is a project-level attribute
- Hours assigned to a project inherit the project's utilization category for reporting
## Shared Types
```typescript
// packages/shared/src/types/utilization-category.ts
interface UtilizationCategory {
id: string;
code: string; // "Chg", "BD", "MD&I", "M&O", "PD&R", "Absence"
name: string;
description?: string;
sortOrder: number;
isActive: boolean;
isDefault: boolean;
}
```
## API
Location: `packages/api/src/router/utilization-category.ts`
| Procedure | Access | Description |
|---|---|---|
| `list` | protected | Returns all active categories (sorted) |
| `getById` | protected | Single category |
| `create` | admin | Create new category |
| `update` | admin | Edit code, name, description, sort order |
| `deactivate` | admin | Soft-delete |
## UI
### Admin: Utilization Category Management (`/admin/utilization-categories`)
- Table listing all categories with code, name, description
- Inline editing of name and description
- Add new categories (for future extensibility)
- Reorder via sort order
- Mark one as default for new projects
### Project: Category Assignment
- `ProjectModal.tsx` gets a `UtilizationCategory` dropdown (required or defaults to "Chg")
- `ProjectWizard.tsx` Step 1 includes category selection
- Project list shows category badge
### Chargeability Report
Hours are bucketed by looking up `project.utilizationCategory.code`:
- `Chg` hours → chargeability numerator
- `BD` hours → business development column
- `MD&I` hours → market development column
- `M&O` hours → management overhead column
- `PD&R` hours → personal development column
- `Absence` hours → reduce SAH (already handled by vacation system, this is the project-side booking)
**Unassigned hours** = SAH - sum of all categorized hours (calculated, not stored)
## Absence Category and Vacation System
The "Absence & Non Standard" category overlaps with Phase 9 Vacation Pro. Relationship:
- Vacation/illness from the vacation system reduces SAH directly (date-based)
- An "Absence" project may additionally exist for booking non-standard absence hours
- The chargeability calculator deducts both: vacation days (from vacation system) and hours booked to Absence-category projects
This avoids double-counting: vacation days reduce available days in SAH, while Absence-project hours capture remaining non-standard time.
## Seed Data
```sql
INSERT INTO "UtilizationCategory" (code, name, description, "sortOrder", "isDefault") VALUES
('Chg', 'Chargeable', 'Billable client project work', 1, true),
('BD', 'Business Development', 'Sales, proposals, presales activities', 2, false),
('MD&I', 'Market Development and Initiative', 'R&D, innovation, market development', 3, false),
('M&O', 'Management and Operations', 'Internal admin, management overhead', 4, false),
('PD&R', 'Personal Development and Recruitment','Training, hiring, onboarding', 5, false),
('Absence', 'Absence & Non Standard', 'Vacation, illness, non-standard leave (reduces SAH)', 6, false);
```
## Migration
1. Create `UtilizationCategory` table with seed data
2. Add `utilizationCategoryId` to Project (nullable initially)
3. Default all existing projects to "Chg" (or let admin assign manually)
4. Make required once all projects are assigned
## Acceptance Criteria
- [ ] `UtilizationCategory` model with code, name, description
- [ ] Project linked to UtilizationCategory
- [ ] Admin UI for category CRUD (code, name, description editable)
- [ ] Project modal/wizard includes category dropdown
- [ ] Seed data for all 6 categories
- [ ] Chargeability report buckets hours by project category
- [ ] Unassigned hours computed as SAH minus all categorized hours