-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathresourceAnalysisValidator.js
More file actions
128 lines (108 loc) · 5.94 KB
/
resourceAnalysisValidator.js
File metadata and controls
128 lines (108 loc) · 5.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// resourceAnalysisValidator.js
export default {
validateResponse(response) {
if (!response.Entities || !response.Users || !response.Categories) {
throw new Error('Missing one of the main objects: Entities, Users, or Categories.');
}
const isIntervals = response.Intervals !== undefined;
const userCapacities = {};
response.Entities.forEach(entity => {
if (!entity.Id || !entity.Name) {
throw new Error('Each entity must have an "Id" and "Name".');
}
if (!['project', 'service'].includes(entity.EntityType)) {
throw new Error('EntityType must be either "project" or "service".');
}
if (entity.EntitySubType && !['waterfall', 'agile'].includes(entity.EntitySubType)) {
throw new Error(`EntitySubType must be either "waterfall" or "agile" if specified. Found: ${entity.EntitySubType} at ${entity.Name}`);
}
entity.WorkItems.forEach(workItem => {
if (!workItem.Id || !workItem.Name) {
throw new Error(`Each work item must have an "Id" and "Name".'. Found: ${workItem.Id} and ${workItem.Name}`);
}
workItem.AssignedEfforts.forEach(effort => {
if (!isIntervals && !effort.TotalUserWorkItemEffort) {
throw new Error(`All users per work item must have "TotalUserWorkItemEffort". Found: ${effort.UserId} at ${workItem.Name}`);
}
if (isIntervals) {
if (effort.Intervals.length !== response.Intervals.length) {
throw new Error(`All AssignedEfforts per work item must have the same number of Intervals as the main Intervals object. Found: ${effort.UserId} at ${workItem.Name}`);
}
effort.Intervals.forEach(interval => {
const key = `${effort.UserId}_${interval.IntervalId}`;
if (interval.Capacity === undefined) {
throw new Error(`Missing capacity for user ${effort.UserId} at interval ${interval.IntervalId}`);
}
if (userCapacities[key] === undefined) {
userCapacities[key] = interval.Capacity;
} else if (userCapacities[key] !== interval.Capacity) {
throw new Error(`Inconsistency found: User ${effort.UserId} has capacities ${userCapacities[key]} and ${interval.Capacity} for IntervalId ${interval.IntervalId} across different work items. Difference found in work item with Id ${workItem.Id} and Name "${workItem.Name}".`);
}
});
}
});
});
});
// Validate Users
const seenIds = new Set();
const duplicateIds = [];
response.Users.forEach(user => {
if (!user.Id || !user.Name) {
throw new Error(`Each user must have an "Id" and "Name". Found: ${user.Id} and ${user.Name}`);
}
if (seenIds.has(user.Id)) {
duplicateIds.push(user.Id);
} else {
seenIds.add(user.Id);
}
});
if (duplicateIds.length > 0) {
throw new Error(`Duplicate IDs detected: ${duplicateIds.join(", ")}`);
}
// Validate Intervals
if (isIntervals) {
response.Intervals.forEach(interval => {
if (!interval.IntervalId || !interval.IntervalName) {
throw new Error(`Each interval must have an "IntervalId" and "IntervalName". Found: ${interval.IntervalId} and ${interval.IntervalName}`);
}
});
}
// Validate Categories
response.Categories.forEach(category => {
if (!category.Id || !category.Name) {
throw new Error(`Each category must have an "Id" and "Name". Found: ${category.Id} and ${category.Name}`);
}
});
},
validateRequest(request) {
// Check if analysisMode is present and valid
if (!request.analysisMode || (request.analysisMode !== 'intervals' && request.analysisMode !== 'totals')) {
throw new Error('Invalid analysisMode: must be either "intervals" or "totals".');
}
// Validate intervals if analysisMode is intervals
if (request.analysisMode === 'intervals') {
if (!request.intervals) {
throw new Error(`Missing intervals object for analysisMode: ${JSON.stringify(request)}`);
}
if (!request.intervals.startDate || typeof request.intervals.startDate !== 'string') {
throw new Error(`Invalid or missing startDate in intervals: ${JSON.stringify(request)}`);
}
if (!request.intervals.intervalType || typeof request.intervals.intervalType !== 'string') {
throw new Error(`Invalid or missing intervalType in intervals: ${JSON.stringify(request)}`);
}
if (!['day', 'week', 'month', 'quarter'].includes(request.intervals.intervalType)) {
throw new Error(`Invalid intervalType: ${request.intervals.intervalType}. Must be one of: day, week, month, quarter.`);
}
if (!request.intervals.noOfIntervals || typeof request.intervals.noOfIntervals !== 'number') {
throw new Error(`Invalid or missing noOfIntervals in intervals: ${JSON.stringify(request)}`);
}
}
if (request.filter) {
['project', 'service', 'user'].forEach(filterKey => {
if (request.filter[filterKey] && typeof request.filter[filterKey] !== 'object') {
throw new Error(`Filter for ${filterKey} should be an object with valid query parameters.`);
}
});
}
}
};