grm-shared-library 1.1.243 → 1.1.245

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.
Files changed (69) hide show
  1. package/dist/cjs/modules/gis/dtos/locate-counties.dto.js +38 -0
  2. package/dist/cjs/modules/gis/dtos/locate-counties.dto.js.map +1 -0
  3. package/dist/cjs/modules/gis/index.js +3 -0
  4. package/dist/cjs/modules/gis/index.js.map +1 -1
  5. package/dist/cjs/modules/gis/interfaces/county-locate.js +3 -0
  6. package/dist/cjs/modules/gis/interfaces/county-locate.js.map +1 -0
  7. package/dist/cjs/modules/gis/interfaces/zone-analytics.js +3 -0
  8. package/dist/cjs/modules/gis/interfaces/zone-analytics.js.map +1 -0
  9. package/dist/cjs/modules/incident/dtos/analytics/incident-dashboard-analytics-query.dto.js +102 -0
  10. package/dist/cjs/modules/incident/dtos/analytics/incident-dashboard-analytics-query.dto.js.map +1 -0
  11. package/dist/cjs/modules/incident/dtos/analytics/index.js +1 -0
  12. package/dist/cjs/modules/incident/dtos/analytics/index.js.map +1 -1
  13. package/dist/cjs/modules/incident/index.js +1 -0
  14. package/dist/cjs/modules/incident/index.js.map +1 -1
  15. package/dist/cjs/modules/incident/intefaces/incident-dashboard-analytics.js +17 -0
  16. package/dist/cjs/modules/incident/intefaces/incident-dashboard-analytics.js.map +1 -0
  17. package/dist/cjs/modules/organization/dtos/organization-analytics-query.dto.js +58 -0
  18. package/dist/cjs/modules/organization/dtos/organization-analytics-query.dto.js.map +1 -0
  19. package/dist/cjs/modules/organization/index.js +2 -0
  20. package/dist/cjs/modules/organization/index.js.map +1 -1
  21. package/dist/cjs/modules/organization/interfaces/organization-analytics.js +15 -0
  22. package/dist/cjs/modules/organization/interfaces/organization-analytics.js.map +1 -0
  23. package/dist/cjs/modules/permission/data/permissions.data.js +3 -1
  24. package/dist/cjs/modules/permission/data/permissions.data.js.map +1 -1
  25. package/dist/cjs/modules/permission/enums/permission-actions.enum.js +12 -0
  26. package/dist/cjs/modules/permission/enums/permission-actions.enum.js.map +1 -1
  27. package/dist/cjs/modules/role/data/roles.data.js +10 -0
  28. package/dist/cjs/modules/role/data/roles.data.js.map +1 -1
  29. package/dist/esm/modules/gis/dtos/locate-counties.dto.js +34 -0
  30. package/dist/esm/modules/gis/dtos/locate-counties.dto.js.map +1 -0
  31. package/dist/esm/modules/gis/index.js +3 -0
  32. package/dist/esm/modules/gis/index.js.map +1 -1
  33. package/dist/esm/modules/gis/interfaces/county-locate.js +2 -0
  34. package/dist/esm/modules/gis/interfaces/county-locate.js.map +1 -0
  35. package/dist/esm/modules/gis/interfaces/zone-analytics.js +2 -0
  36. package/dist/esm/modules/gis/interfaces/zone-analytics.js.map +1 -0
  37. package/dist/esm/modules/incident/dtos/analytics/incident-dashboard-analytics-query.dto.js +98 -0
  38. package/dist/esm/modules/incident/dtos/analytics/incident-dashboard-analytics-query.dto.js.map +1 -0
  39. package/dist/esm/modules/incident/dtos/analytics/index.js +1 -0
  40. package/dist/esm/modules/incident/dtos/analytics/index.js.map +1 -1
  41. package/dist/esm/modules/incident/index.js +1 -0
  42. package/dist/esm/modules/incident/index.js.map +1 -1
  43. package/dist/esm/modules/incident/intefaces/incident-dashboard-analytics.js +16 -0
  44. package/dist/esm/modules/incident/intefaces/incident-dashboard-analytics.js.map +1 -0
  45. package/dist/esm/modules/organization/dtos/organization-analytics-query.dto.js +54 -0
  46. package/dist/esm/modules/organization/dtos/organization-analytics-query.dto.js.map +1 -0
  47. package/dist/esm/modules/organization/index.js +2 -0
  48. package/dist/esm/modules/organization/index.js.map +1 -1
  49. package/dist/esm/modules/organization/interfaces/organization-analytics.js +14 -0
  50. package/dist/esm/modules/organization/interfaces/organization-analytics.js.map +1 -0
  51. package/dist/esm/modules/permission/data/permissions.data.js +3 -1
  52. package/dist/esm/modules/permission/data/permissions.data.js.map +1 -1
  53. package/dist/esm/modules/permission/enums/permission-actions.enum.js +12 -0
  54. package/dist/esm/modules/permission/enums/permission-actions.enum.js.map +1 -1
  55. package/dist/esm/modules/role/data/roles.data.js +10 -0
  56. package/dist/esm/modules/role/data/roles.data.js.map +1 -1
  57. package/dist/types/modules/gis/dtos/locate-counties.dto.d.ts +10 -0
  58. package/dist/types/modules/gis/index.d.ts +3 -0
  59. package/dist/types/modules/gis/interfaces/county-locate.d.ts +37 -0
  60. package/dist/types/modules/gis/interfaces/zone-analytics.d.ts +143 -0
  61. package/dist/types/modules/incident/dtos/analytics/incident-dashboard-analytics-query.dto.d.ts +27 -0
  62. package/dist/types/modules/incident/dtos/analytics/index.d.ts +1 -0
  63. package/dist/types/modules/incident/index.d.ts +1 -0
  64. package/dist/types/modules/incident/intefaces/incident-dashboard-analytics.d.ts +297 -0
  65. package/dist/types/modules/organization/dtos/organization-analytics-query.dto.d.ts +17 -0
  66. package/dist/types/modules/organization/index.d.ts +2 -0
  67. package/dist/types/modules/organization/interfaces/organization-analytics.d.ts +189 -0
  68. package/dist/types/modules/permission/enums/permission-actions.enum.d.ts +2 -0
  69. package/package.json +1 -1
@@ -0,0 +1,297 @@
1
+ /**
2
+ * The incident analytics of the admin's Dashboard: the incidents (or grievances) raised
3
+ * over a period, where they stand now, how quickly they were answered and resolved, what
4
+ * kind they were, when and where they happened - computed by clarion-incident, with the
5
+ * county of each place from clarion-gis.
6
+ *
7
+ * Incidents belong to the period they were RAISED in and are shown as they stand now.
8
+ * "Open now" is every open incident in scope, whatever the period. Durations come from
9
+ * each incident's timeline (its actions). Geography follows GIS practice: places are
10
+ * aggregated - to counties (a choropleth, normalised by area) and to an equal-area
11
+ * hexagonal grid (density, and Getis-Ord Gi* hot spots) - and an incident's own position
12
+ * is never returned. Counts, rates and durations only - never a reporter, a description
13
+ * or an address.
14
+ */
15
+ /** How the period is cut into points. Chosen by the service from the length of the period. */
16
+ export type IncidentAnalyticsBucket = 'hour' | 'day' | 'week' | 'month';
17
+ export interface IncidentAnalyticsRange {
18
+ /** Inclusive, ISO 8601. For "forever", the first incident in scope. */
19
+ from: string;
20
+ /** Exclusive, ISO 8601. */
21
+ to: string;
22
+ bucket: IncidentAnalyticsBucket;
23
+ /** IANA time zone the buckets and the hour-of-week grid are cut in. */
24
+ timeZone: string;
25
+ }
26
+ /** Whose incidents, as the service decided from the caller. */
27
+ export interface IncidentAnalyticsScope {
28
+ /** Null: every organization (a Super-Admin's platform view). */
29
+ organizationId: number | null;
30
+ /** Null: every control centre of the organization. */
31
+ controlCentreId: number | null;
32
+ platform: boolean;
33
+ }
34
+ /** The filters applied, as the service understood them; null when not filtered on. */
35
+ export interface IncidentAnalyticsFilters {
36
+ incidentClass: string | null;
37
+ priority: string | null;
38
+ emergencyType: string | null;
39
+ channel: string | null;
40
+ typeId: number | null;
41
+ categoryId: number | null;
42
+ }
43
+ /** A count by a key, largest first unless the section says otherwise. */
44
+ export interface IncidentAnalyticsCount<K extends string = string> {
45
+ key: K;
46
+ count: number;
47
+ }
48
+ /** Median and 90th percentile of one duration, in seconds; null when nothing was measured. */
49
+ export interface IncidentAnalyticsDuration {
50
+ samples: number;
51
+ medianSeconds: number | null;
52
+ p90Seconds: number | null;
53
+ }
54
+ /** The incidents raised in the period, as they stand now. */
55
+ export interface IncidentAnalyticsTotals {
56
+ raised: number;
57
+ /** The previous period of the same length; null for "forever". */
58
+ previousRaised: number | null;
59
+ /** Raised as an emergency or a panic alert (SOS). */
60
+ emergencies: number;
61
+ /** Answered: an action by anybody but the reporter (a status change, an assignment, an edit, a dispatch). */
62
+ responded: number;
63
+ /** Reached Resolved or Closed, at any time since. */
64
+ resolved: number;
65
+ closed: number;
66
+ /** Ended Unresolved. */
67
+ unresolved: number;
68
+ /** Still open now: Received, In-Progress, In-Review, On-Hold, Escalated or Appealed. */
69
+ stillOpen: number;
70
+ /** Escalated, appealed, put on hold or reopened (back to work after being resolved or closed) at least once. */
71
+ escalated: number;
72
+ appealed: number;
73
+ heldOnHold: number;
74
+ reopened: number;
75
+ /** With somebody assigned now. */
76
+ assigned: number;
77
+ anonymous: number;
78
+ sensitive: number;
79
+ /** resolved / raised, as a percentage; and the same for the previous period (null for "forever"). */
80
+ resolutionRate: number | null;
81
+ previousResolutionRate: number | null;
82
+ }
83
+ /** Every open incident in scope NOW, whenever it was raised. */
84
+ export interface IncidentAnalyticsOpenNow {
85
+ open: number;
86
+ unassigned: number;
87
+ byStatus: IncidentAnalyticsCount[];
88
+ byPriority: IncidentAnalyticsCount[];
89
+ /** How long they have been open: UNDER_1H, 1H_4H, 4H_24H, 1D_3D, 3D_7D, 7D_30D, OVER_30D - every band, in that order. */
90
+ ageBands: IncidentAnalyticsCount[];
91
+ /** When the oldest one was raised; null with none open. */
92
+ oldestRaisedAt: string | null;
93
+ }
94
+ export interface IncidentAnalyticsTimes {
95
+ /** From raised to the first action by anybody but the reporter. */
96
+ toFirstResponse: IncidentAnalyticsDuration;
97
+ /** From raised to somebody being assigned. */
98
+ toAssignment: IncidentAnalyticsDuration;
99
+ /** From raised to Resolved or Closed, whichever came first. */
100
+ toResolution: IncidentAnalyticsDuration;
101
+ /** From raised to Closed. */
102
+ toClosure: IncidentAnalyticsDuration;
103
+ /** The previous period's medians, for the change; null for "forever" or nothing measured. */
104
+ previousMedianSecondsToFirstResponse: number | null;
105
+ previousMedianSecondsToResolution: number | null;
106
+ /** How long the resolved ones took, in the same bands as `IncidentAnalyticsOpenNow.ageBands`. */
107
+ resolutionBands: IncidentAnalyticsCount[];
108
+ }
109
+ export interface IncidentAnalyticsBreakdowns {
110
+ /** Every status, in the order an incident lives through them, zero counts included. */
111
+ byStatus: IncidentAnalyticsCount[];
112
+ /** Critical, High, Medium, Low - every priority, in that order. */
113
+ byPriority: IncidentAnalyticsCount[];
114
+ /** emergency, panic, non-emergency. */
115
+ byEmergencyType: IncidentAnalyticsCount[];
116
+ /** How it reached the platform: App, Web, Phone, Chat... */
117
+ byChannel: IncidentAnalyticsCount[];
118
+ /** What raised it: MANUAL (a person), SAFETY_CHECK, FOLLOW_ME. */
119
+ byOrigin: IncidentAnalyticsCount[];
120
+ /** Incident or Grievance. */
121
+ byClass: IncidentAnalyticsCount[];
122
+ /** The reporter's entitlement when raised: PREMIUM, TRIAL, FREE, NOT_APPLICABLE. */
123
+ byEntitlementTier: IncidentAnalyticsCount[];
124
+ /** Whether it was sent to the control room (REACHED) or kept from it (NOT_SENT: a free user, or opted out). */
125
+ byControlRoom: IncidentAnalyticsCount[];
126
+ /** Third-party partner routing: NOT_ROUTED, ROUTED, ... */
127
+ byPartnerRouting: IncidentAnalyticsCount[];
128
+ }
129
+ export interface IncidentAnalyticsTimelinePoint {
130
+ /** Start of the bucket, ISO 8601. */
131
+ at: string;
132
+ raised: number;
133
+ emergencies: number;
134
+ /** Of those raised in the bucket: resolved since, and still open now. */
135
+ resolved: number;
136
+ open: number;
137
+ medianSecondsToFirstResponse: number | null;
138
+ }
139
+ export interface IncidentAnalyticsHourOfWeek {
140
+ /** 0 = Monday ... 6 = Sunday, in the period's time zone. */
141
+ day: number;
142
+ hour: number;
143
+ raised: number;
144
+ }
145
+ export interface IncidentAnalyticsTypeRow {
146
+ /** Null: raised without a type. */
147
+ typeId: number | null;
148
+ name: string;
149
+ categoryId: number | null;
150
+ categoryName: string | null;
151
+ raised: number;
152
+ previousRaised: number | null;
153
+ emergencies: number;
154
+ resolved: number;
155
+ resolutionRate: number | null;
156
+ medianSecondsToFirstResponse: number | null;
157
+ medianSecondsToResolution: number | null;
158
+ }
159
+ export interface IncidentAnalyticsCategoryRow {
160
+ categoryId: number | null;
161
+ name: string;
162
+ raised: number;
163
+ resolved: number;
164
+ resolutionRate: number | null;
165
+ medianSecondsToResolution: number | null;
166
+ }
167
+ /** A control centre in scope (named by the admin from its own list). */
168
+ export interface IncidentAnalyticsControlCentreRow {
169
+ controlCentreId: number;
170
+ organizationId: number;
171
+ raised: number;
172
+ /** Open now, whenever raised. */
173
+ open: number;
174
+ resolved: number;
175
+ resolutionRate: number | null;
176
+ escalated: number;
177
+ medianSecondsToFirstResponse: number | null;
178
+ medianSecondsToResolution: number | null;
179
+ }
180
+ /** Platform view only: one row per organization. */
181
+ export interface IncidentAnalyticsOrganizationRow {
182
+ organizationId: number;
183
+ raised: number;
184
+ previousRaised: number | null;
185
+ emergencies: number;
186
+ open: number;
187
+ resolutionRate: number | null;
188
+ medianSecondsToFirstResponse: number | null;
189
+ }
190
+ /** How many of the period's incidents could be placed. */
191
+ export interface IncidentAnalyticsGeoQuality {
192
+ raised: number;
193
+ /** With a usable position. */
194
+ located: number;
195
+ withoutLocation: number;
196
+ /** Located, but in no county of the boundary data (another country, the sea, a test device). */
197
+ outsideMappedArea: number;
198
+ /** False when clarion-gis could not be asked: no county figures this time. */
199
+ countiesAvailable: boolean;
200
+ }
201
+ /** One county: the period's incidents in it, normalised by its area. */
202
+ export interface IncidentAnalyticsCountyRow {
203
+ code: number;
204
+ name: string;
205
+ countryIso: string;
206
+ areaKm2: number;
207
+ incidents: number;
208
+ /** Null for "forever". */
209
+ previousIncidents: number | null;
210
+ /** Of the located incidents in mapped counties, as a percentage. */
211
+ share: number | null;
212
+ /** Incidents per 1,000 km² - what a choropleth should show: raw counts favour big counties. */
213
+ perThousandKm2: number;
214
+ emergencies: number;
215
+ resolved: number;
216
+ medianSecondsToFirstResponse: number | null;
217
+ }
218
+ /** Statistical significance of a hexagon's clustering (Getis-Ord Gi*). */
219
+ export interface IncidentAnalyticsGiStar {
220
+ /** The Gi* z-score: high and positive, more incidents around here than chance would put. */
221
+ z: number;
222
+ /** Two-tailed p-value. */
223
+ p: number;
224
+ /** Hot spot at this confidence after the false-discovery-rate correction: 99, 95, 90 - or 0, not significant. */
225
+ confidence: 0 | 90 | 95 | 99;
226
+ }
227
+ /** One hexagon of the equal-area grid with incidents in it. */
228
+ export interface IncidentAnalyticsHexCell {
229
+ /** Axial grid coordinates, "q:r". */
230
+ id: string;
231
+ centre: {
232
+ lat: number;
233
+ lng: number;
234
+ };
235
+ /** The six corners, [lat, lng], for drawing it. */
236
+ vertices: Array<[number, number]>;
237
+ incidents: number;
238
+ emergencies: number;
239
+ /** Null when hot spots were not computed (too few incidents). */
240
+ gi: IncidentAnalyticsGiStar | null;
241
+ }
242
+ /** How the hot-spot analysis was run, and what it found. */
243
+ export interface IncidentAnalyticsHotSpots {
244
+ /** Whether it ran; it needs at least `minimumIncidents` placed incidents. */
245
+ available: boolean;
246
+ /** Why not, when it did not. */
247
+ reason: string | null;
248
+ method: 'Getis-Ord Gi*';
249
+ /** Each hexagon with its six neighbours (first-order contiguity, the hexagon itself included). */
250
+ neighbourhood: string;
251
+ /** Benjamini-Hochberg false-discovery-rate correction across the hexagons tested. */
252
+ fdrCorrected: boolean;
253
+ minimumIncidents: number;
254
+ /** Hexagons in the study area (the incidents' convex hull, one ring wider), empty ones included. */
255
+ studyAreaCells: number;
256
+ hot99: number;
257
+ hot95: number;
258
+ hot90: number;
259
+ }
260
+ export interface IncidentAnalyticsGeography {
261
+ quality: IncidentAnalyticsGeoQuality;
262
+ /** Side of the hexagons, in km on the ground: chosen from the spread of the incidents, never under 1 km. */
263
+ hexSideKm: number | null;
264
+ /** The hexagons with incidents, most first; capped (see `hexesTruncated`). */
265
+ hexes: IncidentAnalyticsHexCell[];
266
+ hexesTruncated: boolean;
267
+ hotSpots: IncidentAnalyticsHotSpots;
268
+ /** Every county of the countries the incidents fall in, zero counts included, most incidents first. */
269
+ counties: IncidentAnalyticsCountyRow[];
270
+ /** The placed incidents' extent, for framing a map; null with none. */
271
+ bounds: {
272
+ south: number;
273
+ west: number;
274
+ north: number;
275
+ east: number;
276
+ } | null;
277
+ }
278
+ export interface IncidentDashboardAnalytics {
279
+ generatedAt: string;
280
+ range: IncidentAnalyticsRange;
281
+ scope: IncidentAnalyticsScope;
282
+ filters: IncidentAnalyticsFilters;
283
+ totals: IncidentAnalyticsTotals;
284
+ openNow: IncidentAnalyticsOpenNow;
285
+ times: IncidentAnalyticsTimes;
286
+ breakdowns: IncidentAnalyticsBreakdowns;
287
+ timeline: IncidentAnalyticsTimelinePoint[];
288
+ /** Raised by weekday and hour; only cells with incidents. */
289
+ hourOfWeek: IncidentAnalyticsHourOfWeek[];
290
+ /** The types raised, most first; capped at 50. */
291
+ types: IncidentAnalyticsTypeRow[];
292
+ categories: IncidentAnalyticsCategoryRow[];
293
+ controlCentres: IncidentAnalyticsControlCentreRow[];
294
+ /** Platform view only; null otherwise. */
295
+ byOrganization: IncidentAnalyticsOrganizationRow[] | null;
296
+ geography: IncidentAnalyticsGeography;
297
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The period an Organization analytics read covers (both halves: organizations and
3
+ * zones), and optionally one control centre. Both ends optional: no `from` is
4
+ * "forever", no `to` is now.
5
+ */
6
+ export declare class OrganizationAnalyticsQueryDto {
7
+ from?: string;
8
+ to?: string;
9
+ timeZone?: string;
10
+ /** Super-Admin only: one organization's figures instead of every organization's. Ignored for anybody else. */
11
+ organizationId?: number;
12
+ /**
13
+ * One control centre's figures. Within the caller's own organization (a Super-Admin's
14
+ * pick of one); control-centre staff see their own centre whatever this says.
15
+ */
16
+ controlCentreId?: number;
17
+ }
@@ -1,8 +1,10 @@
1
1
  export * from './dtos/create-organization.dto';
2
2
  export * from './dtos/update-organization.dto';
3
3
  export * from './dtos/organization-sla.dto';
4
+ export * from './dtos/organization-analytics-query.dto';
4
5
  export * from './interfaces/organization';
5
6
  export * from './interfaces/organization-sla';
6
7
  export * from './interfaces/organization-created-event';
8
+ export * from './interfaces/organization-analytics';
7
9
  export * from './enums/org-status.enum';
8
10
  export * from './enums/org-type.enum';
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Organization analytics, the organization half (the admin's Organization Analytics):
3
+ * the organizations, their control centres, the response units they have set up and
4
+ * what those can respond to, and the responders who crew them - computed by
5
+ * clarion-organization. The other half, the zones the control centres cover, is
6
+ * ZoneAnalytics (clarion-gis); both answer the same query.
7
+ *
8
+ * The structure - organizations, control centres, units, responders - is as it stands
9
+ * NOW. What the period adds: what was created in it, and the responders' duty in it.
10
+ * Counts, rates and durations only - never a phone number, an address, a person or a
11
+ * typed reason.
12
+ */
13
+ /** How the period is cut into points. Chosen by the service from the length of the period. */
14
+ export type OrganizationAnalyticsBucket = 'hour' | 'day' | 'week' | 'month';
15
+ export interface OrganizationAnalyticsRange {
16
+ /** Inclusive, ISO 8601. For "forever", the start of the data in scope. */
17
+ from: string;
18
+ /** Exclusive, ISO 8601. */
19
+ to: string;
20
+ bucket: OrganizationAnalyticsBucket;
21
+ /** IANA time zone the buckets (and the hour-of-week grid) are cut in. */
22
+ timeZone: string;
23
+ }
24
+ /** Whose figures these are, as the service decided from the caller. */
25
+ export interface OrganizationAnalyticsScope {
26
+ /** Null: every organization (a Super-Admin's platform view). */
27
+ organizationId: number | null;
28
+ /** Null: every control centre of the organization. */
29
+ controlCentreId: number | null;
30
+ platform: boolean;
31
+ }
32
+ /** A count by a key (a status, a type, a country), largest first unless the section says otherwise. */
33
+ export interface OrganizationAnalyticsCount<K extends string = string> {
34
+ key: K;
35
+ count: number;
36
+ }
37
+ /** Median and 90th percentile of one duration, in seconds; null when nothing was measured. */
38
+ export interface OrganizationAnalyticsDuration {
39
+ samples: number;
40
+ medianSeconds: number | null;
41
+ p90Seconds: number | null;
42
+ }
43
+ /** The organizations in scope: every one for the platform, otherwise the caller's own. */
44
+ export interface OrganizationAnalyticsOrganizations {
45
+ total: number;
46
+ /** Created in the period, and in the previous period of the same length (null for "forever"). */
47
+ created: number;
48
+ previousCreated: number | null;
49
+ byStatus: OrganizationAnalyticsCount[];
50
+ /** ISO 3166-1 alpha-2. */
51
+ byCountry: OrganizationAnalyticsCount[];
52
+ /** The organization type it was registered with (Private, Public, ...). */
53
+ byType: OrganizationAnalyticsCount[];
54
+ /** The app (brand) it belongs to. */
55
+ byApp: OrganizationAnalyticsCount[];
56
+ /** Whether it handles incidents or grievances. */
57
+ byIncidentClass: OrganizationAnalyticsCount[];
58
+ }
59
+ export interface OrganizationAnalyticsControlCentres {
60
+ total: number;
61
+ active: number;
62
+ created: number;
63
+ previousCreated: number | null;
64
+ byStatus: OrganizationAnalyticsCount[];
65
+ /** Control centres with at least one unit in service, and with none. */
66
+ withUnits: number;
67
+ withoutUnits: number;
68
+ /** Control centres with at least one responder assigned to one of their units. */
69
+ withResponders: number;
70
+ /**
71
+ * For each capability (MEDICAL_RESPONSE, ...): the active control centres with no
72
+ * unit in service able to answer it. Every capability, zero counts included.
73
+ */
74
+ capabilityGaps: OrganizationAnalyticsCount[];
75
+ }
76
+ export interface OrganizationAnalyticsUnits {
77
+ total: number;
78
+ /** In service (`isActive`) and switched off. */
79
+ active: number;
80
+ inactive: number;
81
+ created: number;
82
+ previousCreated: number | null;
83
+ /** Vehicle, Person, Team. */
84
+ byType: OrganizationAnalyticsCount[];
85
+ /** What kind of each: the vehicle type (Ambulance, Security, ...), the person's category, or Team. */
86
+ byKind: OrganizationAnalyticsCount[];
87
+ /** As each was last set: a vehicle's status, a person's or a team's. */
88
+ byStatus: OrganizationAnalyticsCount[];
89
+ /**
90
+ * Units in service able to answer each capability - as configured on the unit, or
91
+ * as its type implies when nothing is configured. A unit can count under several.
92
+ * Every capability, zero counts included.
93
+ */
94
+ byCapability: OrganizationAnalyticsCount[];
95
+ /** Units whose capabilities were set on the unit rather than implied by its type. */
96
+ configuredCapabilities: number;
97
+ /** Units in service that answer nothing: none configured and none implied (a team, a volunteer). */
98
+ withoutCapability: number;
99
+ }
100
+ /** The responder app's people: who crews which unit, and their duty. */
101
+ export interface OrganizationAnalyticsResponders {
102
+ /** Responder-to-unit assignments, the people behind them, and the units that have any. */
103
+ memberships: number;
104
+ responders: number;
105
+ unitsWithResponders: number;
106
+ /** Units in service with no responder assigned. */
107
+ unitsWithoutResponders: number;
108
+ /** On duty now: responders, and the units they are on duty with. */
109
+ onDutyNow: number;
110
+ unitsOnDutyNow: number;
111
+ /** Duty sessions started in the period, and in the previous period (null for "forever"). */
112
+ sessions: number;
113
+ previousSessions: number | null;
114
+ /** Different responders who were on duty at any time in the period. */
115
+ respondersOnDuty: number;
116
+ /** Hours on duty within the period, every session counted for the part of it inside the period. */
117
+ dutyHours: number;
118
+ /** Length of the sessions started in the period that have ended. */
119
+ sessionLength: OrganizationAnalyticsDuration;
120
+ /** Why the period's ended sessions ended. */
121
+ endReasons: OrganizationAnalyticsCount[];
122
+ }
123
+ export interface OrganizationAnalyticsTimelinePoint {
124
+ /** Start of the bucket, ISO 8601. */
125
+ at: string;
126
+ organizations: number;
127
+ controlCentres: number;
128
+ units: number;
129
+ /** Duty sessions started, and hours on duty within the bucket. */
130
+ dutySessions: number;
131
+ dutyHours: number;
132
+ }
133
+ export interface OrganizationAnalyticsHourOfWeek {
134
+ /** 0 = Monday ... 6 = Sunday, in the period's time zone. */
135
+ day: number;
136
+ hour: number;
137
+ /** Duty sessions started in that hour. */
138
+ sessions: number;
139
+ }
140
+ /** A control centre in scope, as it stands now, and its responders' duty in the period. */
141
+ export interface OrganizationAnalyticsControlCentreRow {
142
+ controlCentreId: number;
143
+ organizationId: number;
144
+ name: string;
145
+ status: string;
146
+ createdAt: string;
147
+ units: number;
148
+ activeUnits: number;
149
+ responders: number;
150
+ onDutyNow: number;
151
+ dutyHours: number;
152
+ /** The capabilities its units in service can answer between them. */
153
+ capabilities: string[];
154
+ }
155
+ /** An organization in scope (the platform's every one, otherwise the caller's own). */
156
+ export interface OrganizationAnalyticsOrganizationRow {
157
+ organizationId: number;
158
+ name: string;
159
+ countryCode: string | null;
160
+ type: string | null;
161
+ appId: string | null;
162
+ incidentClass: string | null;
163
+ status: string;
164
+ createdAt: string;
165
+ controlCentres: number;
166
+ activeControlCentres: number;
167
+ units: number;
168
+ activeUnits: number;
169
+ responders: number;
170
+ onDutyNow: number;
171
+ dutyHours: number;
172
+ }
173
+ export interface OrganizationAnalytics {
174
+ generatedAt: string;
175
+ range: OrganizationAnalyticsRange;
176
+ scope: OrganizationAnalyticsScope;
177
+ organizations: OrganizationAnalyticsOrganizations;
178
+ controlCentres: OrganizationAnalyticsControlCentres;
179
+ units: OrganizationAnalyticsUnits;
180
+ responders: OrganizationAnalyticsResponders;
181
+ timeline: OrganizationAnalyticsTimelinePoint[];
182
+ /** Duty sessions started, by weekday and hour; only cells with sessions. */
183
+ dutyHourOfWeek: OrganizationAnalyticsHourOfWeek[];
184
+ /** The control centres in scope, most units first; capped (see `controlCentreRowsTruncated`). */
185
+ controlCentreRows: OrganizationAnalyticsControlCentreRow[];
186
+ controlCentreRowsTruncated: boolean;
187
+ /** The organizations in scope: one row for an organization's own staff. */
188
+ organizationRows: OrganizationAnalyticsOrganizationRow[];
189
+ }
@@ -3,6 +3,7 @@ export declare enum PermissionActions {
3
3
  READ_ORGANIZATION = "read:organization",
4
4
  UPDATE_ORGANIZATION = "update:organization",
5
5
  DELETE_ORGANIZATION = "delete:organization",
6
+ READ_ORGANIZATION_ANALYTICS = "read:organization-analytics",
6
7
  CREATE_PARTNER = "create:partner",
7
8
  READ_PARTNER = "read:partner",
8
9
  UPDATE_PARTNER = "update:partner",
@@ -74,6 +75,7 @@ export declare enum PermissionActions {
74
75
  READ_INCIDENT = "read:incident",
75
76
  UPDATE_INCIDENT = "update:incident",
76
77
  DELETE_INCIDENT = "delete:incident",
78
+ READ_INCIDENT_ANALYTICS = "read:incident-analytics",
77
79
  READ_CHAT_ANALYTICS = "read:chat-analytics",
78
80
  CREATE_INCIDENT_CATEGORY_TYPE = "create:incident-category-type",
79
81
  READ_INCIDENT_CATEGORY_TYPE = "read:incident-category-type",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grm-shared-library",
3
- "version": "1.1.243",
3
+ "version": "1.1.245",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/esm/index.js",
6
6
  "types": "dist/types/index.d.ts",