@critical-path/core 0.17.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +28 -0
- package/dist/domain/index.d.ts +1 -0
- package/dist/domain/index.d.ts.map +1 -1
- package/dist/domain/index.js +1 -0
- package/dist/domain/index.js.map +1 -1
- package/dist/domain/workload.d.ts +10 -0
- package/dist/domain/workload.d.ts.map +1 -0
- package/dist/domain/workload.js +349 -0
- package/dist/domain/workload.js.map +1 -0
- package/dist/domain/workload.test.d.ts +2 -0
- package/dist/domain/workload.test.d.ts.map +1 -0
- package/dist/domain/workload.test.js +201 -0
- package/dist/domain/workload.test.js.map +1 -0
- package/dist/engine/index.d.ts +2 -1
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +13 -0
- package/dist/engine/index.js.map +1 -1
- package/dist/types/index.d.ts +37 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/domain/index.ts +1 -0
- package/src/domain/workload.test.ts +238 -0
- package/src/domain/workload.ts +403 -0
- package/src/engine/index.ts +25 -1
- package/src/types/index.ts +41 -0
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @critical-path/core
|
|
2
2
|
|
|
3
|
+
## 0.18.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- adf44f6: Add headless workload and capacity distribution engine for streamgraphs, stacked area charts, and team capacity planning. Features include contiguous calendar bucketing (`day`, `week`, `month`), multi-dimension grouping (`assignee`, `team`, `taskType`, `priority`, `status`), effort metric distribution (`scheduled`, `logged`, `remaining`, `blended`), tabular zero-filled series matrix for D3 stack layouts, and capacity/utilization thresholds.
|
|
8
|
+
|
|
3
9
|
## 0.17.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -36,6 +36,10 @@
|
|
|
36
36
|
- Multi-scale timeline synthesis: Macro bird's-eye phase rollups (`getTimelineLadder({ level: 'macro' })`), Standard Gantt view with topological CPM forward/backward passes and total float/slack, and Concrete grounding (attachments, deliverables, checklist items, daily effort histograms, and reality deltas).
|
|
37
37
|
- Single-task contextual drilldown via `getTaskLadder(taskId)`.
|
|
38
38
|
- Comprehensive CPM analysis via `calculateCriticalPath(projectId)` identifying project bottleneck tasks and critical path duration.
|
|
39
|
+
- **Headless Workload & Capacity Distribution (Streamgraphs & Capacity Planning)**:
|
|
40
|
+
- Time-series aggregations across customizable intervals (`day`, `week`, `month`) and dimensions (`assignee`, `team`, `taskType`, `priority`, `status`).
|
|
41
|
+
- Pluggable effort distribution metrics (`scheduled`, `logged`, `remaining`, `blended`) with contiguous, gap-free calendar buckets and zero-filled tabular series matrices ready for D3 (`d3.stack().offset(d3.stackOffsetWiggle)`).
|
|
42
|
+
- Dynamic capacity modeling per person and team, reporting bucket-level capacity thresholds and utilization ratios (`totalHours / totalCapacity`).
|
|
39
43
|
|
|
40
44
|
---
|
|
41
45
|
|
|
@@ -174,6 +178,30 @@ console.log('Curve Profile:', history?.curveProfile);
|
|
|
174
178
|
// 's_curve' | 'linear' | 'early_surge' | 'late_rush' | 'stalled'
|
|
175
179
|
```
|
|
176
180
|
|
|
181
|
+
### 7. Headless Workload & Capacity Distribution (Streamgraphs)
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
// Calculate weekly capacity and workload distribution across assignees
|
|
185
|
+
const workload = await engine.getWorkloadDistribution('proj_123', {
|
|
186
|
+
interval: 'week',
|
|
187
|
+
groupBy: 'assignee',
|
|
188
|
+
metric: 'blended'
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
console.log('Series Keys (Assignee IDs):', workload.seriesKeys);
|
|
192
|
+
console.log('Contiguous Weekly Buckets:', workload.buckets);
|
|
193
|
+
// Each bucket contains zero-filled numeric values for all seriesKeys:
|
|
194
|
+
// {
|
|
195
|
+
// date: '2026-09-01',
|
|
196
|
+
// timestamp: 1788220800000,
|
|
197
|
+
// values: { alice: 32, bob: 18, unassigned: 0 },
|
|
198
|
+
// capacity: { alice: 40, bob: 40 },
|
|
199
|
+
// totalHours: 50,
|
|
200
|
+
// totalCapacity: 80,
|
|
201
|
+
// utilizationRatio: 0.625
|
|
202
|
+
// }
|
|
203
|
+
```
|
|
204
|
+
|
|
177
205
|
---
|
|
178
206
|
|
|
179
207
|
## 🔌 Creating a Custom Plugin
|
package/dist/domain/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC"}
|
package/dist/domain/index.js
CHANGED
package/dist/domain/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Task, TimeEntry, User, Team, WorkloadDistribution, WorkloadDistributionOptions } from '../types/index.js';
|
|
2
|
+
export interface WorkloadContext {
|
|
3
|
+
tasks: Task[];
|
|
4
|
+
timeEntries?: TimeEntry[];
|
|
5
|
+
users?: User[];
|
|
6
|
+
teams?: Team[];
|
|
7
|
+
projectId?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function calculateWorkloadDistribution(context: WorkloadContext, options?: WorkloadDistributionOptions): WorkloadDistribution;
|
|
10
|
+
//# sourceMappingURL=workload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workload.d.ts","sourceRoot":"","sources":["../../src/domain/workload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,IAAI,EACJ,SAAS,EACT,IAAI,EACJ,IAAI,EAKJ,oBAAoB,EACpB,2BAA2B,EAC5B,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,WAAW,CAAC,EAAE,SAAS,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA+DD,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,eAAe,EACxB,OAAO,GAAE,2BAAgC,GACxC,oBAAoB,CA6TtB"}
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
function toDateString(d) {
|
|
2
|
+
return d.toISOString().split('T')[0];
|
|
3
|
+
}
|
|
4
|
+
function parseDateOnly(isoString) {
|
|
5
|
+
const parts = isoString.split('T')[0].split('-');
|
|
6
|
+
return new Date(Date.UTC(parseInt(parts[0], 10), parseInt(parts[1], 10) - 1, parseInt(parts[2], 10)));
|
|
7
|
+
}
|
|
8
|
+
function addDays(d, days) {
|
|
9
|
+
const res = new Date(d.getTime());
|
|
10
|
+
res.setUTCDate(res.getUTCDate() + days);
|
|
11
|
+
return res;
|
|
12
|
+
}
|
|
13
|
+
function startOfWeek(d) {
|
|
14
|
+
const date = new Date(d.getTime());
|
|
15
|
+
const day = date.getUTCDay();
|
|
16
|
+
// Monday is day 1, Sunday is day 0 -> shift Sunday to 7
|
|
17
|
+
const diff = date.getUTCDate() - day + (day === 0 ? -6 : 1);
|
|
18
|
+
return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), diff));
|
|
19
|
+
}
|
|
20
|
+
function startOfMonth(d) {
|
|
21
|
+
return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), 1));
|
|
22
|
+
}
|
|
23
|
+
function nextBucketDate(d, interval) {
|
|
24
|
+
if (interval === 'day') {
|
|
25
|
+
return addDays(d, 1);
|
|
26
|
+
}
|
|
27
|
+
if (interval === 'week') {
|
|
28
|
+
return addDays(d, 7);
|
|
29
|
+
}
|
|
30
|
+
// month: next month 1st
|
|
31
|
+
return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + 1, 1));
|
|
32
|
+
}
|
|
33
|
+
function getBucketKey(d, interval) {
|
|
34
|
+
if (interval === 'day') {
|
|
35
|
+
return toDateString(d);
|
|
36
|
+
}
|
|
37
|
+
if (interval === 'week') {
|
|
38
|
+
return toDateString(startOfWeek(d));
|
|
39
|
+
}
|
|
40
|
+
return toDateString(startOfMonth(d));
|
|
41
|
+
}
|
|
42
|
+
function getTaskDurationHours(task) {
|
|
43
|
+
if (typeof task.estimatedHours === 'number' && task.estimatedHours >= 0) {
|
|
44
|
+
return task.estimatedHours;
|
|
45
|
+
}
|
|
46
|
+
if (typeof task.estimatedDurationMinutes === 'number' && task.estimatedDurationMinutes >= 0) {
|
|
47
|
+
return task.estimatedDurationMinutes / 60;
|
|
48
|
+
}
|
|
49
|
+
if (typeof task.actualHours === 'number' && task.actualHours > 0) {
|
|
50
|
+
return task.actualHours;
|
|
51
|
+
}
|
|
52
|
+
return 1;
|
|
53
|
+
}
|
|
54
|
+
export function calculateWorkloadDistribution(context, options = {}) {
|
|
55
|
+
const { tasks, timeEntries = [], users = [], teams = [], projectId } = context;
|
|
56
|
+
const interval = options.interval || 'week';
|
|
57
|
+
const groupBy = options.groupBy || 'assignee';
|
|
58
|
+
const metric = options.metric || 'blended';
|
|
59
|
+
const defaultWeeklyCapacity = options.defaultWeeklyCapacityHours ?? 40;
|
|
60
|
+
// Build lookups for human-readable labels
|
|
61
|
+
const userMap = new Map(users.map((u) => [u.id, u]));
|
|
62
|
+
const teamMap = new Map(teams.map((t) => [t.id, t]));
|
|
63
|
+
// 1. Determine date range
|
|
64
|
+
let minDate = options.startDate ? parseDateOnly(options.startDate) : null;
|
|
65
|
+
let maxDate = options.endDate ? parseDateOnly(options.endDate) : null;
|
|
66
|
+
if (!minDate || !maxDate) {
|
|
67
|
+
const dates = [];
|
|
68
|
+
for (const t of tasks) {
|
|
69
|
+
if (t.plannedStartDate)
|
|
70
|
+
dates.push(parseDateOnly(t.plannedStartDate).getTime());
|
|
71
|
+
if (t.actualStartDate)
|
|
72
|
+
dates.push(parseDateOnly(t.actualStartDate).getTime());
|
|
73
|
+
if (t.dueDate)
|
|
74
|
+
dates.push(parseDateOnly(t.dueDate).getTime());
|
|
75
|
+
if (t.actualEndDate)
|
|
76
|
+
dates.push(parseDateOnly(t.actualEndDate).getTime());
|
|
77
|
+
if (t.createdAt)
|
|
78
|
+
dates.push(parseDateOnly(t.createdAt).getTime());
|
|
79
|
+
}
|
|
80
|
+
for (const te of timeEntries) {
|
|
81
|
+
if (te.loggedAt)
|
|
82
|
+
dates.push(parseDateOnly(te.loggedAt).getTime());
|
|
83
|
+
}
|
|
84
|
+
if (dates.length > 0) {
|
|
85
|
+
if (!minDate)
|
|
86
|
+
minDate = new Date(Math.min(...dates));
|
|
87
|
+
if (!maxDate)
|
|
88
|
+
maxDate = new Date(Math.max(...dates));
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
const now = new Date();
|
|
92
|
+
if (!minDate)
|
|
93
|
+
minDate = addDays(now, -7);
|
|
94
|
+
if (!maxDate)
|
|
95
|
+
maxDate = addDays(now, 28);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Ensure minDate <= maxDate
|
|
99
|
+
if (minDate > maxDate) {
|
|
100
|
+
maxDate = new Date(minDate.getTime());
|
|
101
|
+
}
|
|
102
|
+
// Align start to bucket boundary
|
|
103
|
+
let cursor = interval === 'week' ? startOfWeek(minDate) : interval === 'month' ? startOfMonth(minDate) : minDate;
|
|
104
|
+
const endLimit = interval === 'week' ? startOfWeek(maxDate) : interval === 'month' ? startOfMonth(maxDate) : maxDate;
|
|
105
|
+
const bucketList = [];
|
|
106
|
+
const bucketMap = new Map();
|
|
107
|
+
while (cursor <= endLimit || bucketList.length === 0) {
|
|
108
|
+
const dateStr = toDateString(cursor);
|
|
109
|
+
const nextDate = nextBucketDate(cursor, interval);
|
|
110
|
+
const b = {
|
|
111
|
+
date: dateStr,
|
|
112
|
+
startDate: new Date(cursor.getTime()),
|
|
113
|
+
endDate: nextDate,
|
|
114
|
+
timestamp: cursor.getTime(),
|
|
115
|
+
values: {}
|
|
116
|
+
};
|
|
117
|
+
bucketList.push(b);
|
|
118
|
+
bucketMap.set(dateStr, b);
|
|
119
|
+
cursor = nextDate;
|
|
120
|
+
}
|
|
121
|
+
const seriesKeySet = new Set();
|
|
122
|
+
const getDimensionKey = (task, timeEntry) => {
|
|
123
|
+
switch (groupBy) {
|
|
124
|
+
case 'assignee':
|
|
125
|
+
if (timeEntry?.userId)
|
|
126
|
+
return timeEntry.userId;
|
|
127
|
+
return task.assigneeId || 'unassigned';
|
|
128
|
+
case 'team':
|
|
129
|
+
return task.teamId || task.customFields?.teamId || 'unassigned';
|
|
130
|
+
case 'taskType':
|
|
131
|
+
return task.taskType || task.customFields?.type || 'standard';
|
|
132
|
+
case 'priority':
|
|
133
|
+
return task.priority || 'none';
|
|
134
|
+
case 'status':
|
|
135
|
+
return task.status || 'todo';
|
|
136
|
+
default:
|
|
137
|
+
return 'unassigned';
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
const addValue = (bucket, key, hours) => {
|
|
141
|
+
if (hours <= 0)
|
|
142
|
+
return;
|
|
143
|
+
seriesKeySet.add(key);
|
|
144
|
+
bucket.values[key] = (bucket.values[key] || 0) + hours;
|
|
145
|
+
};
|
|
146
|
+
const todayStr = toDateString(new Date());
|
|
147
|
+
const taskMap = new Map(tasks.map((t) => [t.id, t]));
|
|
148
|
+
// 2. Process Logged Hours from TimeEntries
|
|
149
|
+
if (metric === 'logged' || metric === 'blended') {
|
|
150
|
+
for (const entry of timeEntries) {
|
|
151
|
+
if (!entry.hours || entry.hours <= 0)
|
|
152
|
+
continue;
|
|
153
|
+
const entryDate = parseDateOnly(entry.loggedAt);
|
|
154
|
+
const bKey = getBucketKey(entryDate, interval);
|
|
155
|
+
const bucket = bucketMap.get(bKey);
|
|
156
|
+
if (bucket) {
|
|
157
|
+
const associatedTask = taskMap.get(entry.taskId) || {
|
|
158
|
+
id: entry.taskId,
|
|
159
|
+
projectId: projectId || '',
|
|
160
|
+
title: '',
|
|
161
|
+
status: 'in_progress',
|
|
162
|
+
priority: 'medium',
|
|
163
|
+
createdAt: entry.loggedAt,
|
|
164
|
+
updatedAt: entry.loggedAt
|
|
165
|
+
};
|
|
166
|
+
const dimKey = getDimensionKey(associatedTask, entry);
|
|
167
|
+
addValue(bucket, dimKey, entry.hours);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// 3. Process Scheduled / Remaining / Blended Hours from Tasks
|
|
172
|
+
if (metric === 'scheduled' || metric === 'remaining' || metric === 'blended') {
|
|
173
|
+
for (const task of tasks) {
|
|
174
|
+
const estimated = getTaskDurationHours(task);
|
|
175
|
+
const logged = task.loggedHours || 0;
|
|
176
|
+
let hoursToDistribute = 0;
|
|
177
|
+
if (metric === 'scheduled') {
|
|
178
|
+
hoursToDistribute = estimated;
|
|
179
|
+
}
|
|
180
|
+
else if (metric === 'remaining' || metric === 'blended') {
|
|
181
|
+
if (task.semanticStatus === 'completed' || task.semanticStatus === 'canceled') {
|
|
182
|
+
hoursToDistribute = 0;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
hoursToDistribute = Math.max(0, estimated - logged);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (hoursToDistribute <= 0)
|
|
189
|
+
continue;
|
|
190
|
+
const dimKey = getDimensionKey(task);
|
|
191
|
+
// Determine task date range
|
|
192
|
+
let taskStart = task.plannedStartDate
|
|
193
|
+
? parseDateOnly(task.plannedStartDate)
|
|
194
|
+
: task.actualStartDate
|
|
195
|
+
? parseDateOnly(task.actualStartDate)
|
|
196
|
+
: task.createdAt
|
|
197
|
+
? parseDateOnly(task.createdAt)
|
|
198
|
+
: minDate;
|
|
199
|
+
let taskEnd = task.dueDate
|
|
200
|
+
? parseDateOnly(task.dueDate)
|
|
201
|
+
: taskStart
|
|
202
|
+
? addDays(taskStart, Math.max(1, Math.ceil(hoursToDistribute / 8)))
|
|
203
|
+
: maxDate;
|
|
204
|
+
// In blended mode, uncompleted tasks' remaining hours start from today or planned start (whichever is later)
|
|
205
|
+
if (metric === 'blended') {
|
|
206
|
+
const today = parseDateOnly(todayStr);
|
|
207
|
+
if (taskStart < today) {
|
|
208
|
+
taskStart = today;
|
|
209
|
+
}
|
|
210
|
+
if (taskEnd < taskStart) {
|
|
211
|
+
taskEnd = addDays(taskStart, 1);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (taskEnd < taskStart) {
|
|
215
|
+
taskEnd = taskStart;
|
|
216
|
+
}
|
|
217
|
+
// Calculate days in task window
|
|
218
|
+
const msPerDay = 1000 * 60 * 60 * 24;
|
|
219
|
+
const totalDays = Math.max(1, Math.round((taskEnd.getTime() - taskStart.getTime()) / msPerDay) + 1);
|
|
220
|
+
const hoursPerDay = hoursToDistribute / totalDays;
|
|
221
|
+
// Distribute across overlapping buckets
|
|
222
|
+
for (const bucket of bucketList) {
|
|
223
|
+
const bucketLastDay = addDays(bucket.endDate, -1);
|
|
224
|
+
const overlapStart = new Date(Math.max(taskStart.getTime(), bucket.startDate.getTime()));
|
|
225
|
+
const overlapEnd = new Date(Math.min(taskEnd.getTime(), bucketLastDay.getTime()));
|
|
226
|
+
if (overlapStart <= overlapEnd) {
|
|
227
|
+
const overlapDays = Math.round((overlapEnd.getTime() - overlapStart.getTime()) / msPerDay) + 1;
|
|
228
|
+
const bucketEffort = overlapDays * hoursPerDay;
|
|
229
|
+
addValue(bucket, dimKey, bucketEffort);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
// Ensure all registered users are in series keys if grouping by assignee
|
|
235
|
+
if (groupBy === 'assignee' && users.length > 0) {
|
|
236
|
+
for (const u of users) {
|
|
237
|
+
seriesKeySet.add(u.id);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (groupBy === 'team' && teams.length > 0) {
|
|
241
|
+
for (const t of teams) {
|
|
242
|
+
seriesKeySet.add(t.id);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
const seriesKeys = Array.from(seriesKeySet).sort();
|
|
246
|
+
// Create human-readable series labels
|
|
247
|
+
const seriesLabels = {};
|
|
248
|
+
for (const key of seriesKeys) {
|
|
249
|
+
if (groupBy === 'assignee') {
|
|
250
|
+
const u = userMap.get(key);
|
|
251
|
+
seriesLabels[key] = u ? u.name : key === 'unassigned' ? 'Unassigned' : key;
|
|
252
|
+
}
|
|
253
|
+
else if (groupBy === 'team') {
|
|
254
|
+
const t = teamMap.get(key);
|
|
255
|
+
seriesLabels[key] = t ? t.name : key === 'unassigned' ? 'Unassigned' : key;
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
seriesLabels[key] = key.charAt(0).toUpperCase() + key.slice(1).replace(/_/g, ' ');
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
// 4. Calculate Capacity & Normalize Buckets
|
|
262
|
+
let totalDistributedHours = 0;
|
|
263
|
+
let sumCapacityAcrossBuckets = 0;
|
|
264
|
+
const buckets = bucketList.map((ib) => {
|
|
265
|
+
const values = {};
|
|
266
|
+
const capacity = {};
|
|
267
|
+
let bucketTotalHours = 0;
|
|
268
|
+
let bucketTotalCapacity = 0;
|
|
269
|
+
for (const key of seriesKeys) {
|
|
270
|
+
const rawHours = ib.values[key] || 0;
|
|
271
|
+
const roundedHours = Math.round(rawHours * 100) / 100;
|
|
272
|
+
values[key] = roundedHours;
|
|
273
|
+
bucketTotalHours += roundedHours;
|
|
274
|
+
// Capacity calculation
|
|
275
|
+
let weeklyCap = defaultWeeklyCapacity;
|
|
276
|
+
if (options.capacityOverrides && typeof options.capacityOverrides[key] === 'number') {
|
|
277
|
+
weeklyCap = options.capacityOverrides[key];
|
|
278
|
+
}
|
|
279
|
+
else if (groupBy === 'assignee') {
|
|
280
|
+
const u = userMap.get(key);
|
|
281
|
+
if (u?.weeklyCapacityHours)
|
|
282
|
+
weeklyCap = u.weeklyCapacityHours;
|
|
283
|
+
else if (key === 'unassigned')
|
|
284
|
+
weeklyCap = 0;
|
|
285
|
+
}
|
|
286
|
+
else if (groupBy === 'team') {
|
|
287
|
+
const t = teamMap.get(key);
|
|
288
|
+
if (t?.weeklyCapacityHours) {
|
|
289
|
+
weeklyCap = t.weeklyCapacityHours;
|
|
290
|
+
}
|
|
291
|
+
else if (t?.memberIds?.length) {
|
|
292
|
+
weeklyCap = t.memberIds.length * defaultWeeklyCapacity;
|
|
293
|
+
}
|
|
294
|
+
else if (key === 'unassigned') {
|
|
295
|
+
weeklyCap = 0;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
let bucketCap = 0;
|
|
299
|
+
if (interval === 'week') {
|
|
300
|
+
bucketCap = weeklyCap;
|
|
301
|
+
}
|
|
302
|
+
else if (interval === 'day') {
|
|
303
|
+
bucketCap = Math.round((weeklyCap / 5) * 100) / 100;
|
|
304
|
+
}
|
|
305
|
+
else if (interval === 'month') {
|
|
306
|
+
const daysInMonth = new Date(Date.UTC(ib.startDate.getUTCFullYear(), ib.startDate.getUTCMonth() + 1, 0)).getUTCDate();
|
|
307
|
+
bucketCap = Math.round((weeklyCap * (daysInMonth / 7)) * 100) / 100;
|
|
308
|
+
}
|
|
309
|
+
capacity[key] = bucketCap;
|
|
310
|
+
bucketTotalCapacity += bucketCap;
|
|
311
|
+
}
|
|
312
|
+
bucketTotalHours = Math.round(bucketTotalHours * 100) / 100;
|
|
313
|
+
bucketTotalCapacity = Math.round(bucketTotalCapacity * 100) / 100;
|
|
314
|
+
totalDistributedHours += bucketTotalHours;
|
|
315
|
+
sumCapacityAcrossBuckets += bucketTotalCapacity;
|
|
316
|
+
const utilizationRatio = bucketTotalCapacity > 0
|
|
317
|
+
? Math.round((bucketTotalHours / bucketTotalCapacity) * 1000) / 1000
|
|
318
|
+
: undefined;
|
|
319
|
+
return {
|
|
320
|
+
date: ib.date,
|
|
321
|
+
timestamp: ib.timestamp,
|
|
322
|
+
totalHours: bucketTotalHours,
|
|
323
|
+
values,
|
|
324
|
+
capacity,
|
|
325
|
+
totalCapacity: bucketTotalCapacity,
|
|
326
|
+
utilizationRatio
|
|
327
|
+
};
|
|
328
|
+
});
|
|
329
|
+
totalDistributedHours = Math.round(totalDistributedHours * 100) / 100;
|
|
330
|
+
sumCapacityAcrossBuckets = Math.round(sumCapacityAcrossBuckets * 100) / 100;
|
|
331
|
+
const averageUtilization = sumCapacityAcrossBuckets > 0
|
|
332
|
+
? Math.round((totalDistributedHours / sumCapacityAcrossBuckets) * 1000) / 1000
|
|
333
|
+
: undefined;
|
|
334
|
+
return {
|
|
335
|
+
projectId,
|
|
336
|
+
startDate: toDateString(minDate),
|
|
337
|
+
endDate: toDateString(maxDate),
|
|
338
|
+
interval,
|
|
339
|
+
groupBy,
|
|
340
|
+
metric,
|
|
341
|
+
seriesKeys,
|
|
342
|
+
seriesLabels,
|
|
343
|
+
buckets,
|
|
344
|
+
totalHours: totalDistributedHours,
|
|
345
|
+
totalCapacity: sumCapacityAcrossBuckets,
|
|
346
|
+
averageUtilization
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
//# sourceMappingURL=workload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workload.js","sourceRoot":"","sources":["../../src/domain/workload.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workload.test.d.ts","sourceRoot":"","sources":["../../src/domain/workload.test.ts"],"names":[],"mappings":""}
|