@goxtechnologies/connectwise-psa-mcp 1.1.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/data/connectwise_api.db +0 -0
- package/data/manage.json +298179 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +116 -0
- package/dist/index.js.map +1 -0
- package/dist/operations/analytics-extended.d.ts +6 -0
- package/dist/operations/analytics-extended.d.ts.map +1 -0
- package/dist/operations/analytics-extended.js +825 -0
- package/dist/operations/analytics-extended.js.map +1 -0
- package/dist/operations/analytics-msp-assets.d.ts +3 -0
- package/dist/operations/analytics-msp-assets.d.ts.map +1 -0
- package/dist/operations/analytics-msp-assets.js +180 -0
- package/dist/operations/analytics-msp-assets.js.map +1 -0
- package/dist/operations/analytics-msp-clients.d.ts +3 -0
- package/dist/operations/analytics-msp-clients.d.ts.map +1 -0
- package/dist/operations/analytics-msp-clients.js +198 -0
- package/dist/operations/analytics-msp-clients.js.map +1 -0
- package/dist/operations/analytics-msp-comms.d.ts +3 -0
- package/dist/operations/analytics-msp-comms.d.ts.map +1 -0
- package/dist/operations/analytics-msp-comms.js +127 -0
- package/dist/operations/analytics-msp-comms.js.map +1 -0
- package/dist/operations/analytics-msp-contracts.d.ts +3 -0
- package/dist/operations/analytics-msp-contracts.d.ts.map +1 -0
- package/dist/operations/analytics-msp-contracts.js +91 -0
- package/dist/operations/analytics-msp-contracts.js.map +1 -0
- package/dist/operations/analytics-msp-financial.d.ts +3 -0
- package/dist/operations/analytics-msp-financial.d.ts.map +1 -0
- package/dist/operations/analytics-msp-financial.js +300 -0
- package/dist/operations/analytics-msp-financial.js.map +1 -0
- package/dist/operations/analytics-msp-procurement.d.ts +3 -0
- package/dist/operations/analytics-msp-procurement.d.ts.map +1 -0
- package/dist/operations/analytics-msp-procurement.js +78 -0
- package/dist/operations/analytics-msp-procurement.js.map +1 -0
- package/dist/operations/analytics-msp-projects.d.ts +3 -0
- package/dist/operations/analytics-msp-projects.d.ts.map +1 -0
- package/dist/operations/analytics-msp-projects.js +190 -0
- package/dist/operations/analytics-msp-projects.js.map +1 -0
- package/dist/operations/analytics-msp-sales.d.ts +3 -0
- package/dist/operations/analytics-msp-sales.d.ts.map +1 -0
- package/dist/operations/analytics-msp-sales.js +99 -0
- package/dist/operations/analytics-msp-sales.js.map +1 -0
- package/dist/operations/analytics-msp-schedule.d.ts +3 -0
- package/dist/operations/analytics-msp-schedule.d.ts.map +1 -0
- package/dist/operations/analytics-msp-schedule.js +339 -0
- package/dist/operations/analytics-msp-schedule.js.map +1 -0
- package/dist/operations/analytics-msp-team.d.ts +3 -0
- package/dist/operations/analytics-msp-team.d.ts.map +1 -0
- package/dist/operations/analytics-msp-team.js +195 -0
- package/dist/operations/analytics-msp-team.js.map +1 -0
- package/dist/operations/analytics-msp-tickets.d.ts +3 -0
- package/dist/operations/analytics-msp-tickets.d.ts.map +1 -0
- package/dist/operations/analytics-msp-tickets.js +578 -0
- package/dist/operations/analytics-msp-tickets.js.map +1 -0
- package/dist/operations/analytics-msp-time.d.ts +3 -0
- package/dist/operations/analytics-msp-time.d.ts.map +1 -0
- package/dist/operations/analytics-msp-time.js +485 -0
- package/dist/operations/analytics-msp-time.js.map +1 -0
- package/dist/operations/analytics-msp-utils.d.ts +49 -0
- package/dist/operations/analytics-msp-utils.d.ts.map +1 -0
- package/dist/operations/analytics-msp-utils.js +157 -0
- package/dist/operations/analytics-msp-utils.js.map +1 -0
- package/dist/operations/analytics.d.ts +9 -0
- package/dist/operations/analytics.d.ts.map +1 -0
- package/dist/operations/analytics.js +742 -0
- package/dist/operations/analytics.js.map +1 -0
- package/dist/operations/executor.d.ts +10 -0
- package/dist/operations/executor.d.ts.map +1 -0
- package/dist/operations/executor.js +243 -0
- package/dist/operations/executor.js.map +1 -0
- package/dist/operations/registry.d.ts +16 -0
- package/dist/operations/registry.d.ts.map +1 -0
- package/dist/operations/registry.js +847 -0
- package/dist/operations/registry.js.map +1 -0
- package/dist/services/api-database.d.ts +38 -0
- package/dist/services/api-database.d.ts.map +1 -0
- package/dist/services/api-database.js +191 -0
- package/dist/services/api-database.js.map +1 -0
- package/dist/services/cache.d.ts +12 -0
- package/dist/services/cache.d.ts.map +1 -0
- package/dist/services/cache.js +32 -0
- package/dist/services/cache.js.map +1 -0
- package/dist/services/connectwise-api.d.ts +43 -0
- package/dist/services/connectwise-api.d.ts.map +1 -0
- package/dist/services/connectwise-api.js +198 -0
- package/dist/services/connectwise-api.js.map +1 -0
- package/dist/services/db-builder.d.ts +11 -0
- package/dist/services/db-builder.d.ts.map +1 -0
- package/dist/services/db-builder.js +237 -0
- package/dist/services/db-builder.js.map +1 -0
- package/dist/services/fast-memory.d.ts +39 -0
- package/dist/services/fast-memory.d.ts.map +1 -0
- package/dist/services/fast-memory.js +147 -0
- package/dist/services/fast-memory.js.map +1 -0
- package/dist/services/load-env.d.ts +15 -0
- package/dist/services/load-env.d.ts.map +1 -0
- package/dist/services/load-env.js +59 -0
- package/dist/services/load-env.js.map +1 -0
- package/dist/tools/batch.d.ts +9 -0
- package/dist/tools/batch.d.ts.map +1 -0
- package/dist/tools/batch.js +159 -0
- package/dist/tools/batch.js.map +1 -0
- package/dist/tools/composite.d.ts +9 -0
- package/dist/tools/composite.d.ts.map +1 -0
- package/dist/tools/composite.js +353 -0
- package/dist/tools/composite.js.map +1 -0
- package/dist/tools/discovery.d.ts +9 -0
- package/dist/tools/discovery.d.ts.map +1 -0
- package/dist/tools/discovery.js +245 -0
- package/dist/tools/discovery.js.map +1 -0
- package/dist/tools/execution.d.ts +9 -0
- package/dist/tools/execution.d.ts.map +1 -0
- package/dist/tools/execution.js +130 -0
- package/dist/tools/execution.js.map +1 -0
- package/dist/tools/memory.d.ts +9 -0
- package/dist/tools/memory.d.ts.map +1 -0
- package/dist/tools/memory.js +152 -0
- package/dist/tools/memory.js.map +1 -0
- package/dist/tools/operations.d.ts +9 -0
- package/dist/tools/operations.d.ts.map +1 -0
- package/dist/tools/operations.js +214 -0
- package/dist/tools/operations.js.map +1 -0
- package/dist/tools/pagination.d.ts +9 -0
- package/dist/tools/pagination.d.ts.map +1 -0
- package/dist/tools/pagination.js +133 -0
- package/dist/tools/pagination.js.map +1 -0
- package/dist/tools/validation.d.ts +9 -0
- package/dist/tools/validation.d.ts.map +1 -0
- package/dist/tools/validation.js +705 -0
- package/dist/tools/validation.js.map +1 -0
- package/dist/types/index.d.ts +145 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/operations.d.ts +30 -0
- package/dist/types/operations.d.ts.map +1 -0
- package/dist/types/operations.js +3 -0
- package/dist/types/operations.js.map +1 -0
- package/dist/utils/conditions.d.ts +20 -0
- package/dist/utils/conditions.d.ts.map +1 -0
- package/dist/utils/conditions.js +78 -0
- package/dist/utils/conditions.js.map +1 -0
- package/dist/utils/formatters.d.ts +35 -0
- package/dist/utils/formatters.d.ts.map +1 -0
- package/dist/utils/formatters.js +337 -0
- package/dist/utils/formatters.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
// ConnectWise PSA MCP Server — MSP Analytics: Time & Labor Handlers (8 handlers)
|
|
2
|
+
// This module was the original motivation for the MSP analytics project:
|
|
3
|
+
// the AI was making arithmetic errors when summing hours manually across daily
|
|
4
|
+
// time entries. All aggregation is done server-side in typed code.
|
|
5
|
+
import { getAPI } from '../services/connectwise-api.js';
|
|
6
|
+
import { num, nested, daysAgo, today, round2, dateRange, groupByDate, groupByField, sum, pct, hoursDisplay, mdTable, weekdaysBetween, } from './analytics-msp-utils.js';
|
|
7
|
+
export const mspTimeHandlers = {};
|
|
8
|
+
function reg(name, handler) { mspTimeHandlers[name] = handler; }
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Internal helpers (file-local)
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
/** Returns true when the billableOption value represents a billable entry. */
|
|
13
|
+
function isBillable(entry) {
|
|
14
|
+
return String(entry['billableOption'] ?? '').toLowerCase().includes('billable');
|
|
15
|
+
}
|
|
16
|
+
/** Extracts the YYYY-MM-DD date string from a timeStart or similar ISO field. */
|
|
17
|
+
function dateOf(entry, field = 'timeStart') {
|
|
18
|
+
return String(entry[field] ?? '').substring(0, 10);
|
|
19
|
+
}
|
|
20
|
+
/** Returns the chargeToType string, normalised to lower-case for comparisons. */
|
|
21
|
+
function chargeType(entry) {
|
|
22
|
+
return String(entry['chargeToType'] ?? '').toLowerCase();
|
|
23
|
+
}
|
|
24
|
+
/** Parses an ISO timestamp string into a Date, returning null on failure. */
|
|
25
|
+
function parseDate(iso) {
|
|
26
|
+
if (!iso)
|
|
27
|
+
return null;
|
|
28
|
+
const d = new Date(String(iso));
|
|
29
|
+
return Number.isNaN(d.getTime()) ? null : d;
|
|
30
|
+
}
|
|
31
|
+
/** Returns the number of minutes between two ISO timestamp strings. */
|
|
32
|
+
function minutesBetween(a, b) {
|
|
33
|
+
const da = parseDate(a);
|
|
34
|
+
const db = parseDate(b);
|
|
35
|
+
if (!da || !db)
|
|
36
|
+
return 0;
|
|
37
|
+
return (db.getTime() - da.getTime()) / 60000;
|
|
38
|
+
}
|
|
39
|
+
/** Formats a minute duration as "Xh Ym". */
|
|
40
|
+
function fmtMinutes(mins) {
|
|
41
|
+
const h = Math.floor(mins / 60);
|
|
42
|
+
const m = Math.round(mins % 60);
|
|
43
|
+
return h > 0 ? `${h}h ${m}m` : `${m}m`;
|
|
44
|
+
}
|
|
45
|
+
// ===========================================================================
|
|
46
|
+
// HANDLER 1 — member_daily_totals
|
|
47
|
+
// THE most critical handler: avoids manual arithmetic errors when summing daily
|
|
48
|
+
// time entries. Groups by calendar date, computes billable/non-billable splits
|
|
49
|
+
// and a breakdown by chargeToType (tickets, projects, charge codes, activities).
|
|
50
|
+
// ===========================================================================
|
|
51
|
+
reg('member_daily_totals', async (params) => {
|
|
52
|
+
const api = getAPI();
|
|
53
|
+
const id = String(params['identifier'] ?? '').trim();
|
|
54
|
+
if (!id)
|
|
55
|
+
return 'Error: `identifier` parameter is required.';
|
|
56
|
+
const start = String(params['start_date'] ?? daysAgo(7));
|
|
57
|
+
const end = String(params['end_date'] ?? today());
|
|
58
|
+
const conditions = `member/identifier='${id}' AND timeStart>=[${start}] AND timeStart<[${end}]`;
|
|
59
|
+
const fields = 'id,actualHours,billableOption,chargeToType,chargeToId,timeStart,timeEnd';
|
|
60
|
+
const result = await api.paginatedFetch('/time/entries', conditions, fields, 1000);
|
|
61
|
+
if (result.items.length === 0) {
|
|
62
|
+
return `No time entries found for **${id}** between ${start.substring(0, 10)} and ${end.substring(0, 10)}.`;
|
|
63
|
+
}
|
|
64
|
+
// --- group by calendar date -----------------------------------------------
|
|
65
|
+
const byDate = groupByDate(result.items, 'timeStart');
|
|
66
|
+
const sortedDates = [...byDate.keys()].sort();
|
|
67
|
+
// --- accumulators for TOTALS row ------------------------------------------
|
|
68
|
+
let grandTotal = 0;
|
|
69
|
+
let grandBillable = 0;
|
|
70
|
+
let grandNonBill = 0;
|
|
71
|
+
let grandTickets = 0;
|
|
72
|
+
let grandProjects = 0;
|
|
73
|
+
let grandCodes = 0;
|
|
74
|
+
let grandActivity = 0;
|
|
75
|
+
const rows = [];
|
|
76
|
+
for (const date of sortedDates) {
|
|
77
|
+
const entries = byDate.get(date) ?? [];
|
|
78
|
+
const total = round2(sum(entries, 'actualHours'));
|
|
79
|
+
const billable = round2(entries.filter(isBillable).reduce((acc, e) => acc + num(e['actualHours']), 0));
|
|
80
|
+
const nonBill = round2(total - billable);
|
|
81
|
+
// chargeToType breakdown — ConnectWise uses: ServiceTicket, ProjectTicket,
|
|
82
|
+
// ChargeCode, Activity (exact casing may vary — match case-insensitively)
|
|
83
|
+
const tickets = round2(entries.filter(e => chargeType(e) === 'serviceticket').reduce((acc, e) => acc + num(e['actualHours']), 0));
|
|
84
|
+
const projects = round2(entries.filter(e => chargeType(e) === 'projectticket').reduce((acc, e) => acc + num(e['actualHours']), 0));
|
|
85
|
+
const codes = round2(entries.filter(e => chargeType(e) === 'chargecode').reduce((acc, e) => acc + num(e['actualHours']), 0));
|
|
86
|
+
const activity = round2(entries.filter(e => chargeType(e) === 'activity').reduce((acc, e) => acc + num(e['actualHours']), 0));
|
|
87
|
+
grandTotal += total;
|
|
88
|
+
grandBillable += billable;
|
|
89
|
+
grandNonBill += nonBill;
|
|
90
|
+
grandTickets += tickets;
|
|
91
|
+
grandProjects += projects;
|
|
92
|
+
grandCodes += codes;
|
|
93
|
+
grandActivity += activity;
|
|
94
|
+
rows.push([date, hoursDisplay(total), hoursDisplay(billable), hoursDisplay(nonBill), hoursDisplay(tickets), hoursDisplay(projects), hoursDisplay(codes), hoursDisplay(activity)]);
|
|
95
|
+
}
|
|
96
|
+
// TOTALS row
|
|
97
|
+
rows.push([
|
|
98
|
+
'**TOTALS**',
|
|
99
|
+
`**${hoursDisplay(round2(grandTotal))}**`,
|
|
100
|
+
`**${hoursDisplay(round2(grandBillable))}**`,
|
|
101
|
+
`**${hoursDisplay(round2(grandNonBill))}**`,
|
|
102
|
+
`**${hoursDisplay(round2(grandTickets))}**`,
|
|
103
|
+
`**${hoursDisplay(round2(grandProjects))}**`,
|
|
104
|
+
`**${hoursDisplay(round2(grandCodes))}**`,
|
|
105
|
+
`**${hoursDisplay(round2(grandActivity))}**`,
|
|
106
|
+
]);
|
|
107
|
+
const headers = ['Date', 'Total', 'Billable', 'Non-Bill', 'Tickets', 'Projects', 'Charge Codes', 'Activities'];
|
|
108
|
+
const billPct = pct(grandBillable, grandTotal);
|
|
109
|
+
return [
|
|
110
|
+
`## Daily Time Totals — ${id}`,
|
|
111
|
+
`**Period:** ${start.substring(0, 10)} to ${end.substring(0, 10)} | **Entries:** ${result.items.length} | **Billable:** ${billPct}`,
|
|
112
|
+
'',
|
|
113
|
+
mdTable(headers, rows),
|
|
114
|
+
].join('\n');
|
|
115
|
+
});
|
|
116
|
+
// ===========================================================================
|
|
117
|
+
// HANDLER 2 — member_utilization
|
|
118
|
+
// Computes utilization as billable hours vs available working hours over N days.
|
|
119
|
+
// ===========================================================================
|
|
120
|
+
reg('member_utilization', async (params) => {
|
|
121
|
+
const api = getAPI();
|
|
122
|
+
const id = String(params['identifier'] ?? '').trim();
|
|
123
|
+
const days = num(params['days'], 30);
|
|
124
|
+
const { start, end } = dateRange(days);
|
|
125
|
+
const baseConditions = `timeStart>=[${start}] AND timeStart<[${end}]`;
|
|
126
|
+
const conditions = id ? `member/identifier='${id}' AND ${baseConditions}` : baseConditions;
|
|
127
|
+
const fields = 'id,actualHours,billableOption,timeStart';
|
|
128
|
+
const result = await api.paginatedFetch('/time/entries', conditions, fields, 2000);
|
|
129
|
+
if (result.items.length === 0) {
|
|
130
|
+
const who = id || 'any member';
|
|
131
|
+
return `No time entries found for **${who}** in the last ${days} days.`;
|
|
132
|
+
}
|
|
133
|
+
const totalHours = round2(result.items.reduce((acc, e) => acc + num(e['actualHours']), 0));
|
|
134
|
+
const billableHours = round2(result.items.filter(isBillable).reduce((acc, e) => acc + num(e['actualHours']), 0));
|
|
135
|
+
const nonBillable = round2(totalHours - billableHours);
|
|
136
|
+
// Available = days * 8h/day * 5/7 (Mon–Fri weighting)
|
|
137
|
+
const availableHours = round2(days * 8 * 5 / 7);
|
|
138
|
+
const utilization = round2((billableHours / availableHours) * 100);
|
|
139
|
+
const billableRatio = pct(billableHours, totalHours);
|
|
140
|
+
// Days with entries (unique dates)
|
|
141
|
+
const activeDays = new Set(result.items.map(e => dateOf(e))).size;
|
|
142
|
+
const avgPerDay = activeDays > 0 ? round2(totalHours / activeDays) : 0;
|
|
143
|
+
const who = id ? `**${id}**` : 'All Members';
|
|
144
|
+
return [
|
|
145
|
+
`## Utilization — ${who} (last ${days} days)`,
|
|
146
|
+
'',
|
|
147
|
+
`| Metric | Value |`,
|
|
148
|
+
`|--------|-------|`,
|
|
149
|
+
`| Total Hours Logged | ${hoursDisplay(totalHours)} |`,
|
|
150
|
+
`| Billable Hours | ${hoursDisplay(billableHours)} |`,
|
|
151
|
+
`| Non-Billable Hours | ${hoursDisplay(nonBillable)} |`,
|
|
152
|
+
`| Available Working Hours | ${hoursDisplay(availableHours)} |`,
|
|
153
|
+
`| **Utilization** | **${utilization}%** |`,
|
|
154
|
+
`| Billable Ratio | ${billableRatio} |`,
|
|
155
|
+
`| Active Days | ${activeDays} |`,
|
|
156
|
+
`| Avg Hours / Active Day | ${hoursDisplay(avgPerDay)} |`,
|
|
157
|
+
`| Time Entries | ${result.items.length} |`,
|
|
158
|
+
].join('\n');
|
|
159
|
+
});
|
|
160
|
+
// ===========================================================================
|
|
161
|
+
// HANDLER 3 — team_utilization_comparison
|
|
162
|
+
// Fetches all active members and their time entries, ranks by utilization.
|
|
163
|
+
// ===========================================================================
|
|
164
|
+
reg('team_utilization_comparison', async (params) => {
|
|
165
|
+
const api = getAPI();
|
|
166
|
+
const days = num(params['days'], 30);
|
|
167
|
+
const { start, end } = dateRange(days);
|
|
168
|
+
const [membersResult, entriesResult] = await Promise.all([
|
|
169
|
+
api.paginatedFetch('/system/members', 'inactiveFlag=false', 'id,identifier,firstName,lastName', 500),
|
|
170
|
+
api.paginatedFetch('/time/entries', `timeStart>=[${start}] AND timeStart<[${end}]`, 'id,actualHours,billableOption,member/identifier', 5000),
|
|
171
|
+
]);
|
|
172
|
+
if (membersResult.items.length === 0)
|
|
173
|
+
return 'No active members found.';
|
|
174
|
+
// Build a map: identifier -> { name, total, billable }
|
|
175
|
+
const memberMap = new Map();
|
|
176
|
+
for (const m of membersResult.items) {
|
|
177
|
+
const ident = String(m['identifier'] ?? '');
|
|
178
|
+
const name = `${String(m['firstName'] ?? '')} ${String(m['lastName'] ?? '')}`.trim() || ident;
|
|
179
|
+
memberMap.set(ident, { name, total: 0, billable: 0 });
|
|
180
|
+
}
|
|
181
|
+
for (const e of entriesResult.items) {
|
|
182
|
+
const ident = nested(e, 'member', 'identifier');
|
|
183
|
+
let slot = memberMap.get(ident);
|
|
184
|
+
if (!slot) {
|
|
185
|
+
slot = { name: ident, total: 0, billable: 0 };
|
|
186
|
+
memberMap.set(ident, slot);
|
|
187
|
+
}
|
|
188
|
+
slot.total += num(e['actualHours']);
|
|
189
|
+
if (isBillable(e))
|
|
190
|
+
slot.billable += num(e['actualHours']);
|
|
191
|
+
}
|
|
192
|
+
const availableHours = round2(days * 8 * 5 / 7);
|
|
193
|
+
const ranked = [...memberMap.entries()].map(([ident, d]) => ({
|
|
194
|
+
ident,
|
|
195
|
+
name: d.name,
|
|
196
|
+
total: round2(d.total),
|
|
197
|
+
billable: round2(d.billable),
|
|
198
|
+
util: round2((d.billable / availableHours) * 100),
|
|
199
|
+
})).sort((a, b) => b.util - a.util);
|
|
200
|
+
const rows = ranked.map((r, i) => [
|
|
201
|
+
String(i + 1),
|
|
202
|
+
r.name,
|
|
203
|
+
r.ident,
|
|
204
|
+
hoursDisplay(r.total),
|
|
205
|
+
hoursDisplay(r.billable),
|
|
206
|
+
`${r.util}%`,
|
|
207
|
+
pct(r.billable, r.total),
|
|
208
|
+
]);
|
|
209
|
+
const headers = ['#', 'Name', 'Identifier', 'Total', 'Billable', 'Utilization', 'Bill Ratio'];
|
|
210
|
+
return [
|
|
211
|
+
`## Team Utilization Comparison (last ${days} days)`,
|
|
212
|
+
`**Available Hours / Member:** ${hoursDisplay(availableHours)} | **Members:** ${membersResult.items.length} | **Time Entries:** ${entriesResult.items.length}`,
|
|
213
|
+
'',
|
|
214
|
+
mdTable(headers, rows),
|
|
215
|
+
].join('\n');
|
|
216
|
+
});
|
|
217
|
+
// ===========================================================================
|
|
218
|
+
// HANDLER 4 — timesheet_completeness
|
|
219
|
+
// Compares logged hours against expected 8h per weekday per member.
|
|
220
|
+
// ===========================================================================
|
|
221
|
+
reg('timesheet_completeness', async (params) => {
|
|
222
|
+
const api = getAPI();
|
|
223
|
+
const start = String(params['start_date'] ?? daysAgo(7)).substring(0, 10);
|
|
224
|
+
const end = String(params['end_date'] ?? new Date().toISOString().split('T')[0]);
|
|
225
|
+
const conditions = `timeStart>=[${start}T00:00:00Z] AND timeStart<[${end}T23:59:59Z]`;
|
|
226
|
+
const fields = 'id,actualHours,member/identifier,timeStart';
|
|
227
|
+
const result = await api.paginatedFetch('/time/entries', conditions, fields, 5000);
|
|
228
|
+
if (result.items.length === 0) {
|
|
229
|
+
return `No time entries found between ${start} and ${end}.`;
|
|
230
|
+
}
|
|
231
|
+
// Build: member -> date -> hours
|
|
232
|
+
const map = new Map();
|
|
233
|
+
for (const e of result.items) {
|
|
234
|
+
const ident = nested(e, 'member', 'identifier');
|
|
235
|
+
const date = dateOf(e);
|
|
236
|
+
if (!map.has(ident))
|
|
237
|
+
map.set(ident, new Map());
|
|
238
|
+
const byDate = map.get(ident);
|
|
239
|
+
byDate.set(date, (byDate.get(date) ?? 0) + num(e['actualHours']));
|
|
240
|
+
}
|
|
241
|
+
const weekdays = weekdaysBetween(start, end);
|
|
242
|
+
const rows = [];
|
|
243
|
+
for (const [ident, byDate] of [...map.entries()].sort()) {
|
|
244
|
+
for (const date of weekdays) {
|
|
245
|
+
const logged = round2(byDate.get(date) ?? 0);
|
|
246
|
+
const expected = 8;
|
|
247
|
+
const delta = round2(logged - expected);
|
|
248
|
+
const flag = delta < -2 ? ' !' : '';
|
|
249
|
+
rows.push([ident, date, `${expected}h`, hoursDisplay(logged), `${delta >= 0 ? '+' : ''}${hoursDisplay(delta)}${flag}`]);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (rows.length === 0)
|
|
253
|
+
return `No weekday completeness data for ${start} – ${end}.`;
|
|
254
|
+
const headers = ['Member', 'Date', 'Expected', 'Logged', 'Delta'];
|
|
255
|
+
return [
|
|
256
|
+
`## Timesheet Completeness — ${start} to ${end}`,
|
|
257
|
+
`**Weekdays in period:** ${weekdays.length} | **Members:** ${map.size}`,
|
|
258
|
+
'',
|
|
259
|
+
mdTable(headers, rows),
|
|
260
|
+
].join('\n');
|
|
261
|
+
});
|
|
262
|
+
// ===========================================================================
|
|
263
|
+
// HANDLER 5 — overtime_detection
|
|
264
|
+
// Flags any day >8h or any week >40h per member.
|
|
265
|
+
// ===========================================================================
|
|
266
|
+
reg('overtime_detection', async (params) => {
|
|
267
|
+
const api = getAPI();
|
|
268
|
+
const days = num(params['days'], 14);
|
|
269
|
+
const { start, end } = dateRange(days);
|
|
270
|
+
const conditions = `timeStart>=[${start}] AND timeStart<[${end}]`;
|
|
271
|
+
const fields = 'id,actualHours,member/identifier,timeStart';
|
|
272
|
+
const result = await api.paginatedFetch('/time/entries', conditions, fields, 5000);
|
|
273
|
+
if (result.items.length === 0)
|
|
274
|
+
return `No time entries in the last ${days} days.`;
|
|
275
|
+
// Build member -> date -> hours AND member -> week-start -> hours
|
|
276
|
+
const byMemberDate = new Map();
|
|
277
|
+
const byMemberWeek = new Map();
|
|
278
|
+
for (const e of result.items) {
|
|
279
|
+
const ident = nested(e, 'member', 'identifier');
|
|
280
|
+
const date = dateOf(e);
|
|
281
|
+
const h = num(e['actualHours']);
|
|
282
|
+
// ISO week start (Monday)
|
|
283
|
+
const d = new Date(date + 'T00:00:00Z');
|
|
284
|
+
const dow = d.getUTCDay();
|
|
285
|
+
const diff = dow === 0 ? -6 : 1 - dow;
|
|
286
|
+
d.setUTCDate(d.getUTCDate() + diff);
|
|
287
|
+
const week = d.toISOString().split('T')[0];
|
|
288
|
+
if (!byMemberDate.has(ident))
|
|
289
|
+
byMemberDate.set(ident, new Map());
|
|
290
|
+
const dm = byMemberDate.get(ident);
|
|
291
|
+
dm.set(date, (dm.get(date) ?? 0) + h);
|
|
292
|
+
if (!byMemberWeek.has(ident))
|
|
293
|
+
byMemberWeek.set(ident, new Map());
|
|
294
|
+
const wm = byMemberWeek.get(ident);
|
|
295
|
+
wm.set(week, (wm.get(week) ?? 0) + h);
|
|
296
|
+
}
|
|
297
|
+
const flags = [];
|
|
298
|
+
for (const [ident, dm] of byMemberDate.entries()) {
|
|
299
|
+
for (const [date, h] of dm.entries()) {
|
|
300
|
+
if (h > 8) {
|
|
301
|
+
flags.push([ident, 'Daily OT', date, hoursDisplay(round2(h)), `+${hoursDisplay(round2(h - 8))}`]);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
for (const [ident, wm] of byMemberWeek.entries()) {
|
|
306
|
+
for (const [week, h] of wm.entries()) {
|
|
307
|
+
if (h > 40) {
|
|
308
|
+
flags.push([ident, 'Weekly OT', `w/o ${week}`, hoursDisplay(round2(h)), `+${hoursDisplay(round2(h - 40))}`]);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
if (flags.length === 0) {
|
|
313
|
+
return `No overtime detected in the last ${days} days. (No day >8h, no week >40h.)`;
|
|
314
|
+
}
|
|
315
|
+
flags.sort((a, b) => a[0].localeCompare(b[0]) || a[2].localeCompare(b[2]));
|
|
316
|
+
const headers = ['Member', 'Type', 'Period', 'Hours', 'Overage'];
|
|
317
|
+
return [
|
|
318
|
+
`## Overtime Detection (last ${days} days)`,
|
|
319
|
+
`**Flags:** ${flags.length}`,
|
|
320
|
+
'',
|
|
321
|
+
mdTable(headers, flags),
|
|
322
|
+
].join('\n');
|
|
323
|
+
});
|
|
324
|
+
// ===========================================================================
|
|
325
|
+
// HANDLER 6 — unbilled_wip_report
|
|
326
|
+
// Lists billable but uninvoiced time grouped by company. Estimates revenue
|
|
327
|
+
// using the hourlyRate field when available.
|
|
328
|
+
// ===========================================================================
|
|
329
|
+
reg('unbilled_wip_report', async (_params) => {
|
|
330
|
+
const api = getAPI();
|
|
331
|
+
const conditions = "billableOption='Billable' AND invoiceFlag=false";
|
|
332
|
+
const fields = 'id,actualHours,hourlyRate,company/name,member/identifier';
|
|
333
|
+
const result = await api.paginatedFetch('/time/entries', conditions, fields, 2000);
|
|
334
|
+
if (result.items.length === 0)
|
|
335
|
+
return 'No unbilled billable time entries found. WIP is clean.';
|
|
336
|
+
// Aggregate by company
|
|
337
|
+
const byCompany = new Map();
|
|
338
|
+
for (const e of result.items) {
|
|
339
|
+
const company = nested(e, 'company', 'name');
|
|
340
|
+
const hours = num(e['actualHours']);
|
|
341
|
+
const rate = num(e['hourlyRate']);
|
|
342
|
+
const rev = rate > 0 ? hours * rate : 0;
|
|
343
|
+
let slot = byCompany.get(company);
|
|
344
|
+
if (!slot) {
|
|
345
|
+
slot = { hours: 0, revenue: 0, entries: 0, hasRate: false };
|
|
346
|
+
byCompany.set(company, slot);
|
|
347
|
+
}
|
|
348
|
+
slot.hours += hours;
|
|
349
|
+
slot.revenue += rev;
|
|
350
|
+
slot.entries++;
|
|
351
|
+
if (rate > 0)
|
|
352
|
+
slot.hasRate = true;
|
|
353
|
+
}
|
|
354
|
+
const sorted = [...byCompany.entries()].sort((a, b) => b[1].hours - a[1].hours);
|
|
355
|
+
const totalHours = round2(sorted.reduce((acc, [, d]) => acc + d.hours, 0));
|
|
356
|
+
const totalRevenue = round2(sorted.reduce((acc, [, d]) => acc + d.revenue, 0));
|
|
357
|
+
const totalEntries = sorted.reduce((acc, [, d]) => acc + d.entries, 0);
|
|
358
|
+
const rows = sorted.map(([company, d]) => [
|
|
359
|
+
company,
|
|
360
|
+
hoursDisplay(round2(d.hours)),
|
|
361
|
+
String(d.entries),
|
|
362
|
+
d.hasRate ? `$${round2(d.revenue).toFixed(2)}` : 'N/A',
|
|
363
|
+
]);
|
|
364
|
+
const headers = ['Company', 'Hours', 'Entries', 'Est. Revenue'];
|
|
365
|
+
return [
|
|
366
|
+
`## Unbilled WIP Report`,
|
|
367
|
+
`**Total Unbilled:** ${hoursDisplay(totalHours)} across ${totalEntries} entries | **Est. Revenue:** $${totalRevenue.toFixed(2)}`,
|
|
368
|
+
'',
|
|
369
|
+
mdTable(headers, rows),
|
|
370
|
+
'',
|
|
371
|
+
'_Est. Revenue is 0 / N/A where hourlyRate is not set on the time entry._',
|
|
372
|
+
].join('\n');
|
|
373
|
+
});
|
|
374
|
+
// ===========================================================================
|
|
375
|
+
// HANDLER 7 — charge_code_summary
|
|
376
|
+
// Groups time entries where chargeToType='ChargeCode' by chargeToId.
|
|
377
|
+
// Optional: scoped to a specific member.
|
|
378
|
+
// ===========================================================================
|
|
379
|
+
reg('charge_code_summary', async (params) => {
|
|
380
|
+
const api = getAPI();
|
|
381
|
+
const days = num(params['days'], 30);
|
|
382
|
+
const id = String(params['identifier'] ?? '').trim();
|
|
383
|
+
const { start, end } = dateRange(days);
|
|
384
|
+
let conditions = `chargeToType='ChargeCode' AND timeStart>=[${start}] AND timeStart<[${end}]`;
|
|
385
|
+
if (id)
|
|
386
|
+
conditions = `member/identifier='${id}' AND ${conditions}`;
|
|
387
|
+
const fields = 'id,actualHours,chargeToId,member/identifier';
|
|
388
|
+
const result = await api.paginatedFetch('/time/entries', conditions, fields, 2000);
|
|
389
|
+
if (result.items.length === 0) {
|
|
390
|
+
const who = id ? ` for **${id}**` : '';
|
|
391
|
+
return `No charge-code time entries found${who} in the last ${days} days.`;
|
|
392
|
+
}
|
|
393
|
+
const totalHours = result.items.reduce((acc, e) => acc + num(e['actualHours']), 0);
|
|
394
|
+
// Group by chargeToId
|
|
395
|
+
const byCode = groupByField(result.items, 'chargeToId');
|
|
396
|
+
const sorted = [...byCode.entries()].sort((a, b) => sum(b[1], 'actualHours') - sum(a[1], 'actualHours'));
|
|
397
|
+
const rows = sorted.map(([code, entries]) => {
|
|
398
|
+
const h = round2(sum(entries, 'actualHours'));
|
|
399
|
+
return [code, hoursDisplay(h), pct(h, totalHours), String(entries.length)];
|
|
400
|
+
});
|
|
401
|
+
const headers = ['Charge Code ID', 'Hours', '% of Total', 'Entries'];
|
|
402
|
+
const who = id ? ` — ${id}` : '';
|
|
403
|
+
return [
|
|
404
|
+
`## Charge Code Summary${who} (last ${days} days)`,
|
|
405
|
+
`**Total Hours:** ${hoursDisplay(round2(totalHours))} | **Entries:** ${result.items.length} | **Unique Codes:** ${byCode.size}`,
|
|
406
|
+
'',
|
|
407
|
+
mdTable(headers, rows),
|
|
408
|
+
].join('\n');
|
|
409
|
+
});
|
|
410
|
+
// ===========================================================================
|
|
411
|
+
// HANDLER 8 — time_entry_gap_analysis
|
|
412
|
+
// Finds gaps >30 minutes between consecutive time entries for a member on a
|
|
413
|
+
// given date. Useful for identifying unlogged work or scheduling holes.
|
|
414
|
+
// ===========================================================================
|
|
415
|
+
reg('time_entry_gap_analysis', async (params) => {
|
|
416
|
+
const api = getAPI();
|
|
417
|
+
const id = String(params['identifier'] ?? '').trim();
|
|
418
|
+
const date = String(params['date'] ?? '').trim();
|
|
419
|
+
if (!id)
|
|
420
|
+
return 'Error: `identifier` parameter is required.';
|
|
421
|
+
if (!date)
|
|
422
|
+
return 'Error: `date` parameter is required (YYYY-MM-DD).';
|
|
423
|
+
const conditions = `member/identifier='${id}' AND timeStart>=[${date}T00:00:00Z] AND timeStart<[${date}T23:59:59Z]`;
|
|
424
|
+
const fields = 'id,actualHours,timeStart,timeEnd,chargeToType,chargeToId';
|
|
425
|
+
const result = await api.paginatedFetch('/time/entries', conditions, fields, 500);
|
|
426
|
+
if (result.items.length === 0) {
|
|
427
|
+
return `No time entries found for **${id}** on ${date}.`;
|
|
428
|
+
}
|
|
429
|
+
// Sort by timeStart ascending
|
|
430
|
+
const sorted = [...result.items].sort((a, b) => {
|
|
431
|
+
const da = parseDate(a['timeStart']);
|
|
432
|
+
const db = parseDate(b['timeStart']);
|
|
433
|
+
if (!da || !db)
|
|
434
|
+
return 0;
|
|
435
|
+
return da.getTime() - db.getTime();
|
|
436
|
+
});
|
|
437
|
+
const THRESHOLD_MINS = 30;
|
|
438
|
+
const gaps = [];
|
|
439
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
440
|
+
const prev = sorted[i - 1];
|
|
441
|
+
const curr = sorted[i];
|
|
442
|
+
const prevEnd = String(prev['timeEnd'] ?? '');
|
|
443
|
+
const currStart = String(curr['timeStart'] ?? '');
|
|
444
|
+
if (!prevEnd || !currStart)
|
|
445
|
+
continue;
|
|
446
|
+
const gapMins = minutesBetween(prevEnd, currStart);
|
|
447
|
+
if (gapMins > THRESHOLD_MINS) {
|
|
448
|
+
gaps.push([
|
|
449
|
+
prevEnd.substring(11, 16),
|
|
450
|
+
currStart.substring(11, 16),
|
|
451
|
+
fmtMinutes(round2(gapMins)),
|
|
452
|
+
]);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
// Also show the full day schedule for context
|
|
456
|
+
const scheduleRows = sorted.map(e => [
|
|
457
|
+
String(e['timeStart'] ?? '').substring(11, 16),
|
|
458
|
+
String(e['timeEnd'] ?? '').substring(11, 16),
|
|
459
|
+
hoursDisplay(num(e['actualHours'])),
|
|
460
|
+
String(e['chargeToType'] ?? 'N/A'),
|
|
461
|
+
String(e['chargeToId'] ?? 'N/A'),
|
|
462
|
+
]);
|
|
463
|
+
const dayStart = String(sorted[0]?.['timeStart'] ?? '').substring(11, 16);
|
|
464
|
+
const dayEnd = String(sorted[sorted.length - 1]?.['timeEnd'] ?? '').substring(11, 16);
|
|
465
|
+
const totalHours = round2(sum(sorted, 'actualHours'));
|
|
466
|
+
const scheduleSection = [
|
|
467
|
+
`### Time Entries on ${date}`,
|
|
468
|
+
mdTable(['Start', 'End', 'Hours', 'Type', 'Charge To'], scheduleRows),
|
|
469
|
+
];
|
|
470
|
+
const gapSection = gaps.length === 0
|
|
471
|
+
? [`### Gaps > ${THRESHOLD_MINS} min`, '_No gaps larger than 30 minutes detected._']
|
|
472
|
+
: [
|
|
473
|
+
`### Gaps > ${THRESHOLD_MINS} min (${gaps.length} found)`,
|
|
474
|
+
mdTable(['Gap Start', 'Gap End', 'Duration'], gaps),
|
|
475
|
+
];
|
|
476
|
+
return [
|
|
477
|
+
`## Time Entry Gap Analysis — ${id} on ${date}`,
|
|
478
|
+
`**Day:** ${dayStart} – ${dayEnd} | **Total Hours:** ${hoursDisplay(totalHours)} | **Entries:** ${sorted.length}`,
|
|
479
|
+
'',
|
|
480
|
+
...scheduleSection,
|
|
481
|
+
'',
|
|
482
|
+
...gapSection,
|
|
483
|
+
].join('\n');
|
|
484
|
+
});
|
|
485
|
+
//# sourceMappingURL=analytics-msp-time.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics-msp-time.js","sourceRoot":"","sources":["../../src/operations/analytics-msp-time.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export type CWObj = Record<string, unknown>;
|
|
2
|
+
export type Params = Record<string, unknown>;
|
|
3
|
+
export type MspHandler = (params: Params) => Promise<string>;
|
|
4
|
+
export declare function num(v: unknown, fallback?: number): number;
|
|
5
|
+
export declare function nested(obj: CWObj, field: string, sub: string): string;
|
|
6
|
+
export declare function daysSince(iso: string): number;
|
|
7
|
+
export declare function daysAgo(n: number): string;
|
|
8
|
+
export declare function today(): string;
|
|
9
|
+
export declare function round2(n: number): number;
|
|
10
|
+
/** Returns ISO date strings for the start (N days ago) and end (today). */
|
|
11
|
+
export declare function dateRange(days: number): {
|
|
12
|
+
start: string;
|
|
13
|
+
end: string;
|
|
14
|
+
};
|
|
15
|
+
/** Groups entries by the YYYY-MM-DD portion of a date field. */
|
|
16
|
+
export declare function groupByDate(entries: CWObj[], dateField: string): Map<string, CWObj[]>;
|
|
17
|
+
/** Groups entries by a field value. Supports nested paths like 'member/identifier'. */
|
|
18
|
+
export declare function groupByField(entries: CWObj[], field: string): Map<string, CWObj[]>;
|
|
19
|
+
export declare function sum(items: CWObj[], field: string): number;
|
|
20
|
+
export declare function avg(items: CWObj[], field: string): number;
|
|
21
|
+
export declare function median(items: CWObj[], field: string): number;
|
|
22
|
+
export declare function percentile(items: CWObj[], field: string, p: number): number;
|
|
23
|
+
export declare function pct(a: number, b: number): string;
|
|
24
|
+
export declare function hoursDisplay(h: number): string;
|
|
25
|
+
export declare function currencyDisplay(n: number): string;
|
|
26
|
+
export declare function daysDisplay(d: number): string;
|
|
27
|
+
/** Builds a full markdown table string from header names and data rows. */
|
|
28
|
+
export declare function mdTable(headers: string[], rows: string[][]): string;
|
|
29
|
+
/** Returns the ISO date string (YYYY-MM-DD) for the Monday of the week containing dateStr. */
|
|
30
|
+
export declare function weekStart(dateStr: string): string;
|
|
31
|
+
/** Returns all weekday (Mon–Fri) date strings in [start, end] (inclusive, YYYY-MM-DD). */
|
|
32
|
+
export declare function weekdaysBetween(start: string, end: string): string[];
|
|
33
|
+
/**
|
|
34
|
+
* Wrap an MSP analytics handler with error handling and truncation disclosure.
|
|
35
|
+
* Catches unhandled errors and returns user-friendly messages.
|
|
36
|
+
*/
|
|
37
|
+
export declare function safeHandler(name: string, fn: MspHandler): MspHandler;
|
|
38
|
+
/**
|
|
39
|
+
* Build a truncation warning if a paginated result was capped.
|
|
40
|
+
*/
|
|
41
|
+
export declare function truncationWarning(result: {
|
|
42
|
+
items: unknown[];
|
|
43
|
+
truncated?: boolean;
|
|
44
|
+
}, label?: string): string;
|
|
45
|
+
/**
|
|
46
|
+
* Build a warning for Promise.allSettled failures.
|
|
47
|
+
*/
|
|
48
|
+
export declare function settledWarning(results: PromiseSettledResult<unknown>[], label?: string): string;
|
|
49
|
+
//# sourceMappingURL=analytics-msp-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics-msp-utils.d.ts","sourceRoot":"","sources":["../../src/operations/analytics-msp-utils.ts"],"names":[],"mappings":"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"}
|