Add personio-headcount skill (migrated from plugin)
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
# Data Schemas
|
||||
|
||||
## Snapshot Structure
|
||||
|
||||
```json
|
||||
{
|
||||
"last_refreshed": "2026-03-04T19:00:00Z",
|
||||
"total_records": 755,
|
||||
"summary": {
|
||||
"ACTIVE": 177,
|
||||
"INACTIVE": 574,
|
||||
"ONBOARDING": 1,
|
||||
"LEAVE": 3
|
||||
},
|
||||
"employees": [
|
||||
{
|
||||
"personio_id": "35653993",
|
||||
"status": "ONBOARDING",
|
||||
"team_id": "417186",
|
||||
"department_id": "1291054",
|
||||
"office_id": "501083",
|
||||
"start_date": "2026-05-01",
|
||||
"end_date": null
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Team Mapping Structure
|
||||
|
||||
Maps Personio team IDs to human-readable names:
|
||||
|
||||
```json
|
||||
{
|
||||
"total_teams": 65,
|
||||
"teams": [
|
||||
{
|
||||
"team_id": "4400959",
|
||||
"team_name": "AI & Automation",
|
||||
"active_headcount": 6,
|
||||
"total_records": 7
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Department Mapping Structure
|
||||
|
||||
Groups teams under departments with real names from `department-mapping.csv`:
|
||||
|
||||
```json
|
||||
{
|
||||
"total_departments": 19,
|
||||
"departments": [
|
||||
{
|
||||
"department_id": "1291054",
|
||||
"department_name": "Finance & Business Navigation",
|
||||
"active_headcount": 11,
|
||||
"total_records": 45,
|
||||
"team_ids": ["417186", "417184", "3442693", "3443053", "572110"],
|
||||
"teams": ["Data", "Finance & Administration", "M&A", "Pricing", "Rev Ops"]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Office Mapping Structure
|
||||
|
||||
```json
|
||||
{
|
||||
"total_offices": 8,
|
||||
"offices": [
|
||||
{
|
||||
"office_id": "501083",
|
||||
"active_headcount": 120,
|
||||
"total_records": 500
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## MCP Tool Reference
|
||||
|
||||
**Tool:** `Call_Personio_Get_Employees_` (full ID: `mcp__n8n-personio__Call_Personio_Get_Employees_`)
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|--------|---------|--------------------------------------|
|
||||
| limit | number | 50 | Records per page (use 50 for balance)|
|
||||
| cursor | string | "" | Pagination cursor from previous page |
|
||||
|
||||
Pass parameters as a JSON string in the `input` field:
|
||||
- First page: `{"limit": 50}`
|
||||
- Subsequent pages: `{"limit": 50, "cursor": "<nextCursor>"}`
|
||||
|
||||
## Employee Record Fields (from API)
|
||||
|
||||
Each employee record from the MCP tool contains:
|
||||
- `id` → store as `personio_id`
|
||||
- `status` → ACTIVE, INACTIVE, ONBOARDING, or LEAVE
|
||||
- `team_id` → Personio team ID (look up name in team_mapping.json)
|
||||
- `department_id` → Personio department ID
|
||||
- `office_id` → Personio office ID
|
||||
- `start_date` → employment start
|
||||
- `end_date` → contract end date (null if ongoing)
|
||||
- `first_name`, `last_name`, `email` → **NEVER STORE THESE** — strip before saving
|
||||
|
||||
## Incremental Refresh (Delta Update)
|
||||
|
||||
1. Read existing snapshot
|
||||
2. Fetch all pages from Personio (no "modified since" filter available)
|
||||
3. Compare each employee by `personio_id`:
|
||||
- ID exists → update the record (status, team_id, etc. may have changed)
|
||||
- ID is new → add it
|
||||
- ID in snapshot but not in fresh data → keep (historical)
|
||||
4. Recalculate summary counts
|
||||
5. Update `last_refreshed` timestamp
|
||||
6. Rebuild team_mapping.json counts
|
||||
7. Save all files
|
||||
|
||||
## PDF Report Contents
|
||||
|
||||
The PDF report has 6 pages:
|
||||
|
||||
1. **Cover page** — KPI cards (active, onboarding, on leave, inactive)
|
||||
2. **Headcount by Team** — all active teams ranked by headcount with percentages
|
||||
3. **Headcount by Department** — departments with team listings
|
||||
4. **New Joiners** — monthly breakdown since Jan 2025, with team attribution
|
||||
5. **Departures** — monthly breakdown since Jan 2025, with team attribution
|
||||
6. **Net Workforce Movement** — joiners vs leavers with cumulative net change
|
||||
|
||||
### XML Escaping
|
||||
|
||||
The report uses `xml_escape()` for special characters in names (e.g., "M&A" → "M&A").
|
||||
This is required because reportlab's Paragraph class uses an XML parser internally.
|
||||
Reference in New Issue
Block a user