150 lines
4.7 KiB
Markdown
150 lines
4.7 KiB
Markdown
# Plan: Client Model with WBS Hierarchy
|
|
|
|
**Date:** 2026-03-13
|
|
**Status:** Draft
|
|
**Depends on:** -
|
|
|
|
## Problem
|
|
|
|
Projects need to be linked to clients for chargeability reporting, budget tracking, and organizational grouping. The Dispo Categories file defines a two-level client hierarchy:
|
|
|
|
- **WBS Master Client** — the parent organization (e.g. "BMW", "VOLKSWAGEN")
|
|
- **WBS Client Name** — the legal entity (e.g. "BMW AG", "Dr. Ing. h.c. F. Porsche AG")
|
|
|
|
Currently Planarchy has no Client model. Projects exist independently without client attribution.
|
|
|
|
## Data
|
|
|
|
35 WBS Master Clients with their legal sub-entities. Examples:
|
|
|
|
| WBS Master Client | WBS Client Names |
|
|
|---|---|
|
|
| BMW | BMW AG |
|
|
| VOLKSWAGEN | Audi Business Innovation GmbH, Dr. Ing. h.c. F. Porsche AG, MAN Truck & Bus SE, Volkswagen AG |
|
|
| DAIMLER | antoni garage GmbH & Co. KG, Mercedes-Benz AG |
|
|
| EXOR-STELLANTIS | AUTOMOBILES PEUGEOT, FCA Italy S.p.A., Ferrari S.p.A, MASERATI SPA A SOCIO UNICO |
|
|
|
|
## Schema
|
|
|
|
### New: `Client` model (self-referencing for parent/child)
|
|
|
|
```prisma
|
|
model Client {
|
|
id String @id @default(cuid())
|
|
name String // Display name
|
|
code String? @unique // Optional short code (e.g. "BMW", "VW")
|
|
parentId String?
|
|
parent Client? @relation("ClientTree", fields: [parentId], references: [id])
|
|
children Client[] @relation("ClientTree")
|
|
isActive Boolean @default(true)
|
|
sortOrder Int @default(0)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
projects Project[]
|
|
|
|
@@unique([parentId, name])
|
|
}
|
|
```
|
|
|
|
Design choice: self-referencing tree instead of separate `MasterClient` + `ClientEntity` tables. This supports:
|
|
- Two levels today (Master → Entity)
|
|
- Potential deeper nesting in the future
|
|
- Simple queries via `parentId IS NULL` for top-level clients
|
|
|
|
### Project model extension
|
|
|
|
```prisma
|
|
model Project {
|
|
// ... existing fields ...
|
|
|
|
clientId String?
|
|
client Client? @relation(fields: [clientId], references: [id])
|
|
}
|
|
```
|
|
|
|
A project links to a WBS Client Name (child level). The master client is derived via `client.parent`.
|
|
|
|
## Shared Types
|
|
|
|
```typescript
|
|
// packages/shared/src/types/client.ts
|
|
|
|
interface Client {
|
|
id: string;
|
|
name: string;
|
|
code?: string;
|
|
parentId?: string;
|
|
isActive: boolean;
|
|
sortOrder: number;
|
|
}
|
|
|
|
interface ClientWithChildren extends Client {
|
|
children: Client[];
|
|
}
|
|
|
|
interface ClientTree extends Client {
|
|
children: ClientTree[];
|
|
}
|
|
```
|
|
|
|
## API
|
|
|
|
Location: `packages/api/src/router/client.ts`
|
|
|
|
| Procedure | Access | Description |
|
|
|---|---|---|
|
|
| `list` | protected | Flat list, optionally filtered by parentId |
|
|
| `getTree` | protected | Nested tree for UI |
|
|
| `getById` | protected | Single client with parent/children |
|
|
| `create` | manager | Create client (top-level or child) |
|
|
| `update` | manager | Edit name, code, re-parent |
|
|
| `deactivate` | manager | Soft-delete |
|
|
|
|
Manager-level access (not just admin) since project managers typically need to manage client relationships.
|
|
|
|
## UI
|
|
|
|
### Client Management (`/clients` or `/admin/clients`)
|
|
|
|
- Tree view showing Master Clients → WBS Client Names
|
|
- CRUD at both levels
|
|
- Search/filter for quick lookup
|
|
- Badge showing number of linked projects per client
|
|
|
|
### Project: Client Assignment
|
|
|
|
- `ProjectModal.tsx` gets a cascading or searchable client picker:
|
|
1. Select or search Master Client
|
|
2. Select WBS Client Name under that master
|
|
- `ProjectWizard.tsx` Step 1 includes client selection
|
|
- Project list shows client name column
|
|
|
|
### Client Unit (Resource Attribute)
|
|
|
|
The chargeability report also has a "Client Unit" dimension on resources (BMW, Daimler, Porsche, etc.). This represents which client a resource is primarily assigned to. This is separate from project-client linking:
|
|
|
|
- **Project.clientId** → which client owns this project (WBS billing entity)
|
|
- **Resource client unit** → which client group the resource primarily serves (for reporting)
|
|
|
|
Resource client unit can be derived from the resource's primary assignments or set manually. This is covered in the resource extensions plan, not here.
|
|
|
|
## Seed Data
|
|
|
|
Seed the 35 master clients and their sub-entities from the Dispo Categories file. See `MandatoryDispoCategories_V3.xlsx` → `Project-Attr` sheet, rows 5-40.
|
|
|
|
## Migration
|
|
|
|
1. Create `Client` table with seed data (35 masters + ~50 sub-entities)
|
|
2. Add `clientId` to Project (nullable)
|
|
3. Admin links existing projects to clients
|
|
|
|
## Acceptance Criteria
|
|
|
|
- [ ] `Client` model with self-referencing parent/child tree
|
|
- [ ] Project linked to Client (WBS Client Name level)
|
|
- [ ] Client management UI with tree view
|
|
- [ ] Project modal/wizard includes client picker
|
|
- [ ] Seed data for all 35 master clients and sub-entities
|
|
- [ ] `getTree` API returns nested structure
|