grm-shared-library 1.1.241 → 1.1.243

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 (95) hide show
  1. package/dist/cjs/index.js +1 -0
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/modules/dispatch/index.js +1 -0
  4. package/dist/cjs/modules/dispatch/index.js.map +1 -1
  5. package/dist/cjs/modules/dispatch/interfaces/dispatch-analytics.js +3 -0
  6. package/dist/cjs/modules/dispatch/interfaces/dispatch-analytics.js.map +1 -0
  7. package/dist/cjs/modules/permission/data/permissions.data.js +9 -0
  8. package/dist/cjs/modules/permission/data/permissions.data.js.map +1 -1
  9. package/dist/cjs/modules/permission/enums/permission-actions.enum.js +21 -0
  10. package/dist/cjs/modules/permission/enums/permission-actions.enum.js.map +1 -1
  11. package/dist/cjs/modules/permission/enums/permissions-module.enum.js +1 -0
  12. package/dist/cjs/modules/permission/enums/permissions-module.enum.js.map +1 -1
  13. package/dist/cjs/modules/responder/constants/responder.const.js +124 -0
  14. package/dist/cjs/modules/responder/constants/responder.const.js.map +1 -0
  15. package/dist/cjs/modules/responder/dtos/responder.dto.js +582 -0
  16. package/dist/cjs/modules/responder/dtos/responder.dto.js.map +1 -0
  17. package/dist/cjs/modules/responder/enums/responder.enums.js +142 -0
  18. package/dist/cjs/modules/responder/enums/responder.enums.js.map +1 -0
  19. package/dist/cjs/modules/responder/index.js +29 -0
  20. package/dist/cjs/modules/responder/index.js.map +1 -0
  21. package/dist/cjs/modules/responder/interfaces/responder-dispatch.js +3 -0
  22. package/dist/cjs/modules/responder/interfaces/responder-dispatch.js.map +1 -0
  23. package/dist/cjs/modules/responder/interfaces/responder-policy.js +3 -0
  24. package/dist/cjs/modules/responder/interfaces/responder-policy.js.map +1 -0
  25. package/dist/cjs/modules/responder/interfaces/responder.js +3 -0
  26. package/dist/cjs/modules/responder/interfaces/responder.js.map +1 -0
  27. package/dist/cjs/modules/responder/utils/responder.util.js +65 -0
  28. package/dist/cjs/modules/responder/utils/responder.util.js.map +1 -0
  29. package/dist/cjs/modules/role/data/roles.data.js +30 -4
  30. package/dist/cjs/modules/role/data/roles.data.js.map +1 -1
  31. package/dist/cjs/modules/tracking/dtos/units-analytics-query.dto.js +58 -0
  32. package/dist/cjs/modules/tracking/dtos/units-analytics-query.dto.js.map +1 -0
  33. package/dist/cjs/modules/tracking/enums/tracking-provider-code.enum.js +8 -0
  34. package/dist/cjs/modules/tracking/enums/tracking-provider-code.enum.js.map +1 -1
  35. package/dist/cjs/modules/tracking/index.js +3 -0
  36. package/dist/cjs/modules/tracking/index.js.map +1 -1
  37. package/dist/cjs/modules/tracking/interfaces/tracking-analytics.js +14 -0
  38. package/dist/cjs/modules/tracking/interfaces/tracking-analytics.js.map +1 -0
  39. package/dist/esm/index.js +1 -0
  40. package/dist/esm/index.js.map +1 -1
  41. package/dist/esm/modules/dispatch/index.js +1 -0
  42. package/dist/esm/modules/dispatch/index.js.map +1 -1
  43. package/dist/esm/modules/dispatch/interfaces/dispatch-analytics.js +2 -0
  44. package/dist/esm/modules/dispatch/interfaces/dispatch-analytics.js.map +1 -0
  45. package/dist/esm/modules/permission/data/permissions.data.js +9 -0
  46. package/dist/esm/modules/permission/data/permissions.data.js.map +1 -1
  47. package/dist/esm/modules/permission/enums/permission-actions.enum.js +21 -0
  48. package/dist/esm/modules/permission/enums/permission-actions.enum.js.map +1 -1
  49. package/dist/esm/modules/permission/enums/permissions-module.enum.js +1 -0
  50. package/dist/esm/modules/permission/enums/permissions-module.enum.js.map +1 -1
  51. package/dist/esm/modules/responder/constants/responder.const.js +121 -0
  52. package/dist/esm/modules/responder/constants/responder.const.js.map +1 -0
  53. package/dist/esm/modules/responder/dtos/responder.dto.js +560 -0
  54. package/dist/esm/modules/responder/dtos/responder.dto.js.map +1 -0
  55. package/dist/esm/modules/responder/enums/responder.enums.js +139 -0
  56. package/dist/esm/modules/responder/enums/responder.enums.js.map +1 -0
  57. package/dist/esm/modules/responder/index.js +13 -0
  58. package/dist/esm/modules/responder/index.js.map +1 -0
  59. package/dist/esm/modules/responder/interfaces/responder-dispatch.js +2 -0
  60. package/dist/esm/modules/responder/interfaces/responder-dispatch.js.map +1 -0
  61. package/dist/esm/modules/responder/interfaces/responder-policy.js +2 -0
  62. package/dist/esm/modules/responder/interfaces/responder-policy.js.map +1 -0
  63. package/dist/esm/modules/responder/interfaces/responder.js +2 -0
  64. package/dist/esm/modules/responder/interfaces/responder.js.map +1 -0
  65. package/dist/esm/modules/responder/utils/responder.util.js +59 -0
  66. package/dist/esm/modules/responder/utils/responder.util.js.map +1 -0
  67. package/dist/esm/modules/role/data/roles.data.js +29 -3
  68. package/dist/esm/modules/role/data/roles.data.js.map +1 -1
  69. package/dist/esm/modules/tracking/dtos/units-analytics-query.dto.js +54 -0
  70. package/dist/esm/modules/tracking/dtos/units-analytics-query.dto.js.map +1 -0
  71. package/dist/esm/modules/tracking/enums/tracking-provider-code.enum.js +8 -0
  72. package/dist/esm/modules/tracking/enums/tracking-provider-code.enum.js.map +1 -1
  73. package/dist/esm/modules/tracking/index.js +3 -0
  74. package/dist/esm/modules/tracking/index.js.map +1 -1
  75. package/dist/esm/modules/tracking/interfaces/tracking-analytics.js +13 -0
  76. package/dist/esm/modules/tracking/interfaces/tracking-analytics.js.map +1 -0
  77. package/dist/types/index.d.ts +1 -0
  78. package/dist/types/modules/dispatch/index.d.ts +1 -0
  79. package/dist/types/modules/dispatch/interfaces/dispatch-analytics.d.ts +158 -0
  80. package/dist/types/modules/permission/enums/permission-actions.enum.d.ts +4 -0
  81. package/dist/types/modules/permission/enums/permissions-module.enum.d.ts +2 -1
  82. package/dist/types/modules/responder/constants/responder.const.d.ts +67 -0
  83. package/dist/types/modules/responder/dtos/responder.dto.d.ts +144 -0
  84. package/dist/types/modules/responder/enums/responder.enums.d.ts +128 -0
  85. package/dist/types/modules/responder/index.d.ts +7 -0
  86. package/dist/types/modules/responder/interfaces/responder-dispatch.d.ts +144 -0
  87. package/dist/types/modules/responder/interfaces/responder-policy.d.ts +55 -0
  88. package/dist/types/modules/responder/interfaces/responder.d.ts +113 -0
  89. package/dist/types/modules/responder/utils/responder.util.d.ts +24 -0
  90. package/dist/types/modules/role/data/roles.data.d.ts +7 -0
  91. package/dist/types/modules/tracking/dtos/units-analytics-query.dto.d.ts +17 -0
  92. package/dist/types/modules/tracking/enums/tracking-provider-code.enum.d.ts +9 -1
  93. package/dist/types/modules/tracking/index.d.ts +2 -0
  94. package/dist/types/modules/tracking/interfaces/tracking-analytics.d.ts +192 -0
  95. package/package.json +1 -1
@@ -0,0 +1,158 @@
1
+ import { UnitsAnalyticsCount, UnitsAnalyticsDuration, UnitsAnalyticsRange, UnitsAnalyticsScope } from '../../tracking/interfaces/tracking-analytics';
2
+ /**
3
+ * Units & Tracking analytics, the dispatch half: the response units sent to emergencies
4
+ * and what became of each - computed by clarion-incident, for the same query as
5
+ * TrackingAnalytics.
6
+ *
7
+ * Dispatches are counted by when they were made (`dispatchedAt`) and shown as they stand
8
+ * now: a dispatch made in the period and completed after it counts as completed. Times
9
+ * are measured between the timestamps a dispatch records. Emergencies are the period's
10
+ * incidents (not grievances) that reached the control room. Counts, rates and durations
11
+ * only - never a dispatcher, a crew's phone number, a reason someone typed or a note.
12
+ */
13
+ export interface DispatchAnalyticsTotals {
14
+ dispatches: number;
15
+ /** The previous period of the same length; null for "forever". */
16
+ previousDispatches: number | null;
17
+ /** Emergencies a unit was sent to in the period. */
18
+ incidentsDispatched: number;
19
+ /** Emergencies raised in the period (reaching the control room), and those a unit was ever sent to. */
20
+ emergencies: number;
21
+ emergenciesDispatched: number;
22
+ /** emergenciesDispatched / emergencies, as a percentage. */
23
+ dispatchRate: number | null;
24
+ unitsDispatched: number;
25
+ dispatchers: number;
26
+ /** Dispatches per emergency dispatched in the period. */
27
+ unitsPerIncident: number | null;
28
+ }
29
+ export interface DispatchAnalyticsOutcomes {
30
+ /** Still out: dispatched, acknowledged, en route or on scene. */
31
+ active: number;
32
+ completed: number;
33
+ /** Stood down (CANCELLED) - and of those, refused by the responder. */
34
+ cancelled: number;
35
+ rejected: number;
36
+ /** Reached the scene. */
37
+ reachedScene: number;
38
+ /** Completed, as a percentage of the dispatches no longer out. */
39
+ completionRate: number | null;
40
+ /** Every status, in the order a dispatch lives through them, zero counts included. */
41
+ byStatus: UnitsAnalyticsCount[];
42
+ /** How the arrival was recorded (responder, control centre, inferred from tracking). */
43
+ arrivalBySource: UnitsAnalyticsCount[];
44
+ /** Who recorded each dispatch's latest status. */
45
+ statusBySource: UnitsAnalyticsCount[];
46
+ }
47
+ export interface DispatchAnalyticsTimes {
48
+ /** From an emergency being raised to its first unit being sent (the period's emergencies). */
49
+ toFirstDispatch: UnitsAnalyticsDuration;
50
+ /** From the unit being sent to it acknowledging, setting off, arriving and being done. */
51
+ toAcknowledge: UnitsAnalyticsDuration;
52
+ toEnRoute: UnitsAnalyticsDuration;
53
+ toOnScene: UnitsAnalyticsDuration;
54
+ /** From arriving to being done. */
55
+ onScene: UnitsAnalyticsDuration;
56
+ toComplete: UnitsAnalyticsDuration;
57
+ }
58
+ export interface DispatchAnalyticsRecommendation {
59
+ /** Dispatches made with a recommendation on screen. */
60
+ recommended: number;
61
+ /** ...that sent the recommended unit. */
62
+ followed: number;
63
+ /** ...that sent another unit, and of those, with a reason given. */
64
+ overridden: number;
65
+ overriddenWithReason: number;
66
+ /** Dispatches made when no unit was recommended. */
67
+ withoutRecommendation: number;
68
+ /** followed / recommended, as a percentage. */
69
+ followRate: number | null;
70
+ /** The sent unit as the recommendation saw it: how its capabilities matched, its availability, how fresh its position was. */
71
+ capabilityMatch: UnitsAnalyticsCount[];
72
+ availability: UnitsAnalyticsCount[];
73
+ locationFreshness: UnitsAnalyticsCount[];
74
+ /** Straight-line distance from the unit to the emergency when it was sent. */
75
+ distance: {
76
+ samples: number;
77
+ medianMetres: number | null;
78
+ p90Metres: number | null;
79
+ };
80
+ }
81
+ /** The dispatch message (SMS) to the crew. */
82
+ export interface DispatchAnalyticsNotification {
83
+ sent: number;
84
+ failed: number;
85
+ /** Could not be sent at all: no phone number, not configured, ... */
86
+ notPossible: number;
87
+ pending: number;
88
+ failures: UnitsAnalyticsCount[];
89
+ /** sent / (sent + failed), as a percentage. */
90
+ deliveryRate: number | null;
91
+ /** From the message being requested to the provider's answer. */
92
+ toResult: UnitsAnalyticsDuration;
93
+ /** Dispatches whose message was sent more than once. */
94
+ resent: number;
95
+ }
96
+ export interface DispatchAnalyticsTimelinePoint {
97
+ /** Start of the bucket, ISO 8601. */
98
+ at: string;
99
+ dispatches: number;
100
+ completed: number;
101
+ cancelled: number;
102
+ }
103
+ export interface DispatchAnalyticsUnitRow {
104
+ responseUnitId: number;
105
+ organizationId: number;
106
+ /** As it was named when last sent. */
107
+ name: string;
108
+ responseUnitType: string | null;
109
+ dispatches: number;
110
+ completed: number;
111
+ cancelled: number;
112
+ rejected: number;
113
+ medianSecondsToAcknowledge: number | null;
114
+ medianSecondsToOnScene: number | null;
115
+ lastDispatchedAt: string;
116
+ }
117
+ export interface DispatchAnalyticsTypeRow {
118
+ responseUnitType: string;
119
+ dispatches: number;
120
+ completed: number;
121
+ medianSecondsToOnScene: number | null;
122
+ }
123
+ export interface DispatchAnalyticsHourOfWeek {
124
+ /** 0 = Monday ... 6 = Sunday, in the period's time zone. */
125
+ day: number;
126
+ hour: number;
127
+ dispatches: number;
128
+ }
129
+ /** Platform view only: one row per organization. */
130
+ export interface DispatchAnalyticsOrganizationRow {
131
+ organizationId: number;
132
+ dispatches: number;
133
+ emergencies: number;
134
+ emergenciesDispatched: number;
135
+ completed: number;
136
+ medianSecondsToOnScene: number | null;
137
+ }
138
+ export interface DispatchAnalytics {
139
+ generatedAt: string;
140
+ range: UnitsAnalyticsRange;
141
+ scope: UnitsAnalyticsScope;
142
+ totals: DispatchAnalyticsTotals;
143
+ outcomes: DispatchAnalyticsOutcomes;
144
+ times: DispatchAnalyticsTimes;
145
+ recommendation: DispatchAnalyticsRecommendation;
146
+ notification: DispatchAnalyticsNotification;
147
+ timeline: DispatchAnalyticsTimelinePoint[];
148
+ byUnitType: DispatchAnalyticsTypeRow[];
149
+ /** The dispatched emergencies by their emergency type. */
150
+ byEmergencyType: UnitsAnalyticsCount[];
151
+ /** Dispatches by weekday and hour; only cells with dispatches. */
152
+ hourOfWeek: DispatchAnalyticsHourOfWeek[];
153
+ /** Units sent in the period, most dispatches first; capped (see `unitsTruncated`). */
154
+ units: DispatchAnalyticsUnitRow[];
155
+ unitsTruncated: boolean;
156
+ /** Platform view only; null otherwise. */
157
+ byOrganization: DispatchAnalyticsOrganizationRow[] | null;
158
+ }
@@ -94,6 +94,7 @@ export declare enum PermissionActions {
94
94
  READ_TRACKING_POSITION = "read:tracking-position",
95
95
  READ_TRACKING_HISTORY = "read:tracking-history",
96
96
  READ_TRACKING_OPERATIONS = "read:tracking-operations",
97
+ READ_TRACKING_ANALYTICS = "read:tracking-analytics",
97
98
  MANAGE_TRACKING_OPERATIONS = "manage:tracking-operations",
98
99
  READ_RESPONSE_UNIT_DISPATCH = "read:response-unit-dispatch",
99
100
  CREATE_RESPONSE_UNIT_DISPATCH = "create:response-unit-dispatch",
@@ -215,6 +216,9 @@ export declare enum PermissionActions {
215
216
  READ_INCIDENT_SLA_POLICY = "read:incident-sla-policy",
216
217
  MANAGE_INCIDENT_SLA_POLICY = "manage:incident-sla-policy",
217
218
  READ_INCIDENT_SLA_ANALYTICS = "read:incident-sla-analytics",
219
+ USE_RESPONDER_APP = "use:responder-app",
220
+ RESPOND_RESPONSE_UNIT_DISPATCH = "respond:response-unit-dispatch",
221
+ REPORT_RESPONDER_POSITION = "report:responder-position",
218
222
  /**
219
223
  * @deprecated Split into the connection / message / screened-message /
220
224
  * analytics actions above, which the gateway now requires instead. Still
@@ -16,5 +16,6 @@ export declare enum PermissionsModule {
16
16
  ALERT_INTAKE = "Alert Intake",
17
17
  SAFETY = "Safety",
18
18
  PLACES = "Places",
19
- INCIDENT_SLA = "Incident SLA"
19
+ INCIDENT_SLA = "Incident SLA",
20
+ RESPONDER = "Responder"
20
21
  }
@@ -0,0 +1,67 @@
1
+ import { ResponseUnitDispatchStatus } from '../../dispatch/enums/response-unit-dispatch-status.enum';
2
+ import { ResponderPolicy } from '../interfaces/responder-policy';
3
+ /**
4
+ * The moves a responder may make on their own unit's dispatch - a strict
5
+ * subset of RESPONSE_UNIT_DISPATCH_TRANSITIONS.
6
+ *
7
+ * - Standing a unit down (CANCELLED) stays the control room's decision.
8
+ * - Declining (REJECTED) is only possible before the unit is moving, as for
9
+ * the control room.
10
+ * - COMPLETED only from ON_SCENE: a responder who never arrived did not
11
+ * complete anything; the control room stands the unit down instead.
12
+ * - EN_ROUTE straight from DISPATCHED is allowed: "I'm on my way" is an
13
+ * acknowledgement too, and making the responder tap twice while driving off
14
+ * helps nobody.
15
+ */
16
+ export declare const RESPONDER_DISPATCH_TRANSITIONS: Readonly<Record<ResponseUnitDispatchStatus, readonly ResponseUnitDispatchStatus[]>>;
17
+ /** Every status a responder may ever set. */
18
+ export declare const RESPONDER_SETTABLE_DISPATCH_STATUSES: readonly ResponseUnitDispatchStatus[];
19
+ export declare const RESPONDER_FIELD_LIMITS: {
20
+ readonly statusReason: 500;
21
+ readonly dutyEndReason: 300;
22
+ readonly reportSummary: 4000;
23
+ readonly reportActionsTaken: 4000;
24
+ readonly reportPersonsContacted: 2000;
25
+ readonly reportHandoverTo: 500;
26
+ readonly reportFollowUpNotes: 2000;
27
+ readonly reportRemarks: 2000;
28
+ readonly reportChecklistItems: 50;
29
+ readonly reportChecklistItemId: 64;
30
+ readonly reportChecklistItemLabel: 200;
31
+ readonly reportAttachments: 50;
32
+ /** Positions per POST /responder/positions. The app sends smaller batches; this bounds a backlog. */
33
+ readonly positionBatchSize: 100;
34
+ readonly dispatchPageSize: 50;
35
+ };
36
+ /**
37
+ * A position older than this is still stored in the history but never moves
38
+ * the unit's current position (the projector's out-of-order rule) - and the
39
+ * ingestion refuses anything older than the backlog window outright.
40
+ */
41
+ export declare const RESPONDER_POSITION_LIMITS: {
42
+ /** Samples older than this are refused (an offline backlog is kept this long). */
43
+ readonly maxSampleAgeSeconds: number;
44
+ /** Samples further in the future than this (clock skew) are refused. */
45
+ readonly maxFutureSkewSeconds: 120;
46
+ /** Worse than this is refused: it would put the unit in the wrong street. */
47
+ readonly maxAccuracyMetres: 1000;
48
+ };
49
+ /**
50
+ * The defaults every organization starts from. An organization may override any
51
+ * part through `organizations.responderPolicy` (validated by ResponderPolicyDto);
52
+ * clarion-organization merges the override over these and serves the result in
53
+ * the responder profile, and clarion-incident enforces the dispatch and report
54
+ * parts server-side. The app only ever READS the policy - a client cannot relax
55
+ * it.
56
+ */
57
+ export declare const DEFAULT_RESPONDER_POLICY: ResponderPolicy;
58
+ /**
59
+ * Cluster-internal routes. Not proxied by the gateway; callers carry the
60
+ * internal service token and no user context.
61
+ */
62
+ export declare const RESPONDER_INTERNAL_PATHS: {
63
+ /** clarion-organization: a user's units, active duty and effective policy. */
64
+ readonly userUnits: (userId: number) => string;
65
+ /** clarion-organization: who is on duty with a unit right now. */
66
+ readonly unitOnDuty: (responseUnitId: number) => string;
67
+ };
@@ -0,0 +1,144 @@
1
+ import { ResponseUnitDispatchStatus } from '../../dispatch/enums/response-unit-dispatch-status.enum';
2
+ import { ResponderArrivalMethod, ResponderDispatchListState, ResponderReportField, ResponderReportOutcome } from '../enums/responder.enums';
3
+ /** `POST /responder/duty` - go on duty with one of the caller's units. */
4
+ export declare class StartResponderDutyDto {
5
+ responseUnitId: number;
6
+ }
7
+ /** `POST /responder/duty/end` - go off duty. Idempotent: ending no duty is not an error. */
8
+ export declare class EndResponderDutyDto {
9
+ reason?: string;
10
+ }
11
+ /** `POST /response-units/:id/responders/:userId/end-duty` - the control room ends someone's duty. */
12
+ export declare class EndResponderDutyByControlCentreDto extends EndResponderDutyDto {
13
+ }
14
+ /** `POST /response-units/:id/responders` - link a Responder account to a unit. */
15
+ export declare class AddResponseUnitResponderDto {
16
+ userId: number;
17
+ }
18
+ /** `GET /responder/dispatches`. Newest first. */
19
+ export declare class ResponderDispatchListQueryDto {
20
+ state?: ResponderDispatchListState;
21
+ page?: number;
22
+ limit?: number;
23
+ /** `123` or `#123`: only that incident's dispatches. */
24
+ search?: string;
25
+ }
26
+ /** A position fix the phone took, sent as evidence with an action. */
27
+ export declare class ResponderLocationFixDto {
28
+ latitude: number;
29
+ longitude: number;
30
+ accuracyMetres?: number;
31
+ /** When the phone took the fix (ISO 8601). */
32
+ recordedAt: string;
33
+ }
34
+ /**
35
+ * `POST /responder/dispatches/:dispatchId/status` - acknowledge, set off,
36
+ * arrive, complete or decline.
37
+ *
38
+ * Idempotent by target: asking for the status the dispatch already has returns
39
+ * it unchanged (HTTP 200) instead of a conflict, so a retry after a lost
40
+ * response is safe. `clientActionId` is recorded with the change for the audit.
41
+ */
42
+ export declare class RespondToDispatchDto {
43
+ status: ResponseUnitDispatchStatus;
44
+ clientActionId: string;
45
+ /** Why - required to decline, and for a manual arrival, when policy says so. */
46
+ reason?: string;
47
+ /** The phone's position when the action was taken, when it has one. */
48
+ location?: ResponderLocationFixDto;
49
+ /** ON_SCENE only: how the arrival was established. Defaults to GPS when a location is sent. */
50
+ arrivalMethod?: ResponderArrivalMethod;
51
+ }
52
+ export declare class ResponderChecklistAnswerDto {
53
+ itemId: string;
54
+ checked: boolean;
55
+ }
56
+ /**
57
+ * `POST /responder/dispatches/:dispatchId/report` - submit, or amend, the
58
+ * response report. The first submission is idempotent on `clientReportId`; an
59
+ * amendment must name the `expectedVersion` it was edited from.
60
+ */
61
+ export declare class SubmitResponderReportDto {
62
+ clientReportId: string;
63
+ /** Absent for the first submission; the version being amended otherwise. */
64
+ expectedVersion?: number;
65
+ summary: string;
66
+ actionsTaken?: string;
67
+ outcome: ResponderReportOutcome;
68
+ personsContacted?: string;
69
+ handoverTo?: string;
70
+ followUpRequired: boolean;
71
+ followUpNotes?: string;
72
+ remarks?: string;
73
+ checklist?: ResponderChecklistAnswerDto[];
74
+ /** DMS file ids (images, documents, videos) to attach to the incident with this report. */
75
+ attachmentIds?: number[];
76
+ }
77
+ export declare class ResponderPositionSampleDto {
78
+ latitude: number;
79
+ longitude: number;
80
+ accuracyMetres?: number;
81
+ altitudeMetres?: number;
82
+ /** Metres per second, as the phone reports it. */
83
+ speedMetresPerSecond?: number;
84
+ headingDegrees?: number;
85
+ /** When the phone took the fix (ISO 8601) - never the upload time. */
86
+ recordedAt: string;
87
+ /** The OS flagged it as a mock location. Kept and flagged, never used for arrival. */
88
+ isMocked?: boolean;
89
+ }
90
+ /**
91
+ * `POST /responder/positions` - positions of the unit the caller is on duty
92
+ * with. The server decides the unit from the caller's active duty session;
93
+ * the client never names one.
94
+ */
95
+ export declare class ReportResponderPositionsDto {
96
+ samples: ResponderPositionSampleDto[];
97
+ }
98
+ export declare class ResponderLocationPolicyDto {
99
+ onDutyIntervalSeconds?: number;
100
+ activeIntervalSeconds?: number;
101
+ distanceFilterMetres?: number;
102
+ maxAccuracyMetres?: number;
103
+ staleAfterSeconds?: number;
104
+ }
105
+ export declare class ResponderArrivalPolicyDto {
106
+ radiusMetres?: number;
107
+ allowManualConfirmation?: boolean;
108
+ manualReasonRequired?: boolean;
109
+ }
110
+ export declare class ResponderDispatchPolicyDto {
111
+ allowDecline?: boolean;
112
+ declineReasonRequired?: boolean;
113
+ }
114
+ export declare class ResponderChecklistItemDto {
115
+ id: string;
116
+ label: string;
117
+ required: boolean;
118
+ }
119
+ export declare class ResponderReportPolicyDto {
120
+ requiredToComplete?: boolean;
121
+ requiredFields?: ResponderReportField[];
122
+ checklist?: ResponderChecklistItemDto[];
123
+ minPhotos?: number;
124
+ }
125
+ export declare class ResponderEvidencePolicyDto {
126
+ allowPhotos?: boolean;
127
+ allowDocuments?: boolean;
128
+ allowVideo?: boolean;
129
+ maxImageMegabytes?: number;
130
+ maxDocumentMegabytes?: number;
131
+ maxVideoMegabytes?: number;
132
+ }
133
+ export declare class ResponderReporterContactPolicyDto {
134
+ visible?: boolean;
135
+ }
136
+ /** An organization's override of DEFAULT_RESPONDER_POLICY; every part optional. */
137
+ export declare class ResponderPolicyDto {
138
+ location?: ResponderLocationPolicyDto;
139
+ arrival?: ResponderArrivalPolicyDto;
140
+ dispatch?: ResponderDispatchPolicyDto;
141
+ report?: ResponderReportPolicyDto;
142
+ evidence?: ResponderEvidencePolicyDto;
143
+ reporterContact?: ResponderReporterContactPolicyDto;
144
+ }
@@ -0,0 +1,128 @@
1
+ /**
2
+ * The responder app: field personnel (role `Responder`) who staff a response
3
+ * unit, go on duty with it, receive its dispatches on their phone and report
4
+ * progress, arrival, position and the outcome back to the control room.
5
+ *
6
+ * A responder is linked to the units they may staff by an explicit membership
7
+ * (clarion-organization, managed by whoever holds update:response-unit). There
8
+ * is deliberately no implicit link by phone number: a crew phone typed into a
9
+ * unit form is not proof that an app account belongs to that crew.
10
+ */
11
+ /** Whether a responder is currently on duty with one of their units. */
12
+ export declare enum ResponderDutyStatus {
13
+ ON_DUTY = "ON_DUTY",
14
+ OFF_DUTY = "OFF_DUTY"
15
+ }
16
+ /** A duty session's own lifecycle. One session is ACTIVE per responder at most. */
17
+ export declare enum ResponderDutySessionStatus {
18
+ ACTIVE = "ACTIVE",
19
+ ENDED = "ENDED"
20
+ }
21
+ /** Why a duty session ended. */
22
+ export declare enum ResponderDutyEndReason {
23
+ /** The responder went off duty in the app. */
24
+ RESPONDER = "RESPONDER",
25
+ /** The control room ended it (update:response-unit). */
26
+ CONTROL_CENTRE = "CONTROL_CENTRE",
27
+ /** The responder was removed from the unit while on duty with it. */
28
+ MEMBERSHIP_REMOVED = "MEMBERSHIP_REMOVED",
29
+ /** The unit was deactivated or deleted while the responder was on duty with it. */
30
+ UNIT_DEACTIVATED = "UNIT_DEACTIVATED"
31
+ }
32
+ /** How an arrival on scene was established by the responder. */
33
+ export declare enum ResponderArrivalMethod {
34
+ /** The phone's position was within the organization's arrival radius. */
35
+ GPS = "GPS",
36
+ /** The responder confirmed it by hand (with a reason, when policy asks for one). */
37
+ MANUAL = "MANUAL"
38
+ }
39
+ /** How a response ended, as the responder reports it. */
40
+ export declare enum ResponderReportOutcome {
41
+ RESOLVED_ON_SCENE = "RESOLVED_ON_SCENE",
42
+ HANDED_OVER = "HANDED_OVER",
43
+ REFERRED = "REFERRED",
44
+ NO_ACTION_REQUIRED = "NO_ACTION_REQUIRED",
45
+ FALSE_ALARM = "FALSE_ALARM",
46
+ UNABLE_TO_LOCATE = "UNABLE_TO_LOCATE",
47
+ OTHER = "OTHER"
48
+ }
49
+ /** The free-text fields of a responder report a policy may make mandatory. */
50
+ export declare enum ResponderReportField {
51
+ SUMMARY = "summary",
52
+ ACTIONS_TAKEN = "actionsTaken",
53
+ PERSONS_CONTACTED = "personsContacted",
54
+ HANDOVER_TO = "handoverTo",
55
+ REMARKS = "remarks"
56
+ }
57
+ /** Which dispatches `GET /responder/dispatches` lists. */
58
+ export declare enum ResponderDispatchListState {
59
+ /** DISPATCHED, ACKNOWLEDGED, EN_ROUTE, ON_SCENE. */
60
+ ACTIVE = "ACTIVE",
61
+ /** COMPLETED, CANCELLED, REJECTED. */
62
+ HISTORY = "HISTORY",
63
+ ALL = "ALL"
64
+ }
65
+ /** How a unit's live position reaches clarion-response-tracking. */
66
+ export declare enum ResponderTrackingMode {
67
+ /** The on-duty responder's phone reports the unit's position. */
68
+ PHONE = "PHONE",
69
+ /** The unit has an enabled hardware tracker binding; the phone stays quiet so the two never compete. */
70
+ UNIT_DEVICE = "UNIT_DEVICE",
71
+ /** The caller is not on duty, so no position is accepted. */
72
+ NOT_ON_DUTY = "NOT_ON_DUTY"
73
+ }
74
+ /**
75
+ * `data.action` of the pushes clarion-notification sends a responder's phone.
76
+ * Every one carries `dispatchId`, `incidentId` and `route`; none carries the
77
+ * reporter's name, number, address or the incident description, because a
78
+ * push is shown on a lock screen.
79
+ */
80
+ export declare enum ResponderPushAction {
81
+ /** A unit the responder is on duty with was dispatched. */
82
+ DISPATCH_ASSIGNED = "RESPONDER_DISPATCH_ASSIGNED",
83
+ /** The control room stood the unit down (CANCELLED). */
84
+ DISPATCH_STOOD_DOWN = "RESPONDER_DISPATCH_STOOD_DOWN",
85
+ /** Any other status change made by somebody else (control room, lifecycle, tracking). */
86
+ DISPATCH_UPDATED = "RESPONDER_DISPATCH_UPDATED"
87
+ }
88
+ /**
89
+ * Machine-readable refusals of the responder endpoints, in the error body's
90
+ * `code` (the same `{statusCode, code, message, ...details}` envelope the
91
+ * dispatch endpoints use).
92
+ */
93
+ export declare enum ResponderErrorCode {
94
+ /** The caller does not hold the Responder role. */
95
+ NOT_A_RESPONDER = "RESPONDER_NOT_A_RESPONDER",
96
+ /** The responder account has no control centre, so nothing can be scoped. */
97
+ NO_CONTROL_CENTRE = "RESPONDER_NO_CONTROL_CENTRE",
98
+ UNIT_NOT_FOUND = "RESPONDER_UNIT_NOT_FOUND",
99
+ /** The caller is not a member of that unit. */
100
+ NOT_A_UNIT_MEMBER = "RESPONDER_NOT_A_UNIT_MEMBER",
101
+ UNIT_INACTIVE = "RESPONDER_UNIT_INACTIVE",
102
+ /** Already on duty with ANOTHER unit; end that duty first. `details.activeDuty` names it. */
103
+ ALREADY_ON_DUTY = "RESPONDER_ALREADY_ON_DUTY",
104
+ NOT_ON_DUTY = "RESPONDER_NOT_ON_DUTY",
105
+ /** Membership: the user is not a Responder of the unit's organization and control centre. */
106
+ USER_NOT_ELIGIBLE = "RESPONDER_USER_NOT_ELIGIBLE",
107
+ ALREADY_A_MEMBER = "RESPONDER_ALREADY_A_MEMBER",
108
+ MEMBERSHIP_NOT_FOUND = "RESPONDER_MEMBERSHIP_NOT_FOUND",
109
+ /** The dispatch does not exist or is not for one of the caller's units (never says which). */
110
+ DISPATCH_NOT_FOUND = "RESPONDER_DISPATCH_NOT_FOUND",
111
+ /** The move is not one a responder may make from the current status. `details.currentStatus`. */
112
+ INVALID_STATUS_TRANSITION = "RESPONDER_INVALID_STATUS_TRANSITION",
113
+ REASON_REQUIRED = "RESPONDER_REASON_REQUIRED",
114
+ DECLINE_NOT_ALLOWED = "RESPONDER_DECLINE_NOT_ALLOWED",
115
+ MANUAL_ARRIVAL_NOT_ALLOWED = "RESPONDER_MANUAL_ARRIVAL_NOT_ALLOWED",
116
+ /** Completing needs the response report first (organization policy). */
117
+ REPORT_REQUIRED = "RESPONDER_REPORT_REQUIRED",
118
+ /** A report can only be written once the unit reached the scene. */
119
+ REPORT_NOT_ALLOWED = "RESPONDER_REPORT_NOT_ALLOWED",
120
+ /** The report changed since the version the client edited. `details.currentVersion`. */
121
+ REPORT_VERSION_CONFLICT = "RESPONDER_REPORT_VERSION_CONFLICT",
122
+ /** The incident is closed or archived, so its reports can no longer be amended. */
123
+ REPORT_LOCKED = "RESPONDER_REPORT_LOCKED",
124
+ /** A required report field or checklist item is missing. `details.missing`. */
125
+ REPORT_INCOMPLETE = "RESPONDER_REPORT_INCOMPLETE",
126
+ /** An attachment id is not a file the caller may link. */
127
+ ATTACHMENT_NOT_READABLE = "RESPONDER_ATTACHMENT_NOT_READABLE"
128
+ }
@@ -0,0 +1,7 @@
1
+ export * from './enums/responder.enums';
2
+ export * from './interfaces/responder-policy';
3
+ export * from './interfaces/responder';
4
+ export * from './interfaces/responder-dispatch';
5
+ export * from './constants/responder.const';
6
+ export * from './dtos/responder.dto';
7
+ export * from './utils/responder.util';
@@ -0,0 +1,144 @@
1
+ import { ResponseUnitDispatchStatus } from '../../dispatch/enums/response-unit-dispatch-status.enum';
2
+ import { ResponseUnitDispatchTransitionSource } from '../../dispatch/enums/response-unit-dispatch-transition-source.enum';
3
+ import { ResponderArrivalMethod, ResponderReportOutcome, ResponderTrackingMode } from '../enums/responder.enums';
4
+ /** The incident as a dispatched responder sees it. */
5
+ export interface ResponderIncidentSummary {
6
+ id: number;
7
+ /** `#<id>` - the reference the control room quotes. */
8
+ reference: string;
9
+ class: string;
10
+ emergencyType: string | null;
11
+ status: string;
12
+ priority: string;
13
+ categoryName: string | null;
14
+ typeName: string | null;
15
+ description: string | null;
16
+ /** Null when the incident has no usable coordinates. */
17
+ location: {
18
+ latitude: number;
19
+ longitude: number;
20
+ } | null;
21
+ physicalAddress: string | null;
22
+ isAnonymous: boolean;
23
+ /** Null when anonymous, or when the organization hides reporter contact from responders. */
24
+ reporter: {
25
+ name: string | null;
26
+ phoneNumber: string | null;
27
+ } | null;
28
+ /** The incident chat, when it has one. */
29
+ conversationId: string | null;
30
+ organizationId: number;
31
+ controlCentreId: number | null;
32
+ createdAt: string;
33
+ updatedAt: string;
34
+ }
35
+ /** Whether the responder's report exists, without its body. */
36
+ export interface ResponderReportState {
37
+ submitted: boolean;
38
+ reportId: number | null;
39
+ version: number | null;
40
+ submittedAt: string | null;
41
+ }
42
+ /** One dispatch of one of the responder's units, with its incident. */
43
+ export interface ResponderDispatch {
44
+ id: number;
45
+ reference: string;
46
+ incidentId: number;
47
+ responseUnitId: number;
48
+ responseUnitName: string;
49
+ responseUnitType: string | null;
50
+ status: ResponseUnitDispatchStatus;
51
+ statusChangedAt: string;
52
+ statusSource: ResponseUnitDispatchTransitionSource;
53
+ statusReason: string | null;
54
+ dispatchedAt: string;
55
+ acknowledgedAt: string | null;
56
+ enRouteAt: string | null;
57
+ onSceneAt: string | null;
58
+ completedAt: string | null;
59
+ cancelledAt: string | null;
60
+ rejectedAt: string | null;
61
+ arrivalSource: string | null;
62
+ /** What the dispatcher wrote when sending the unit. */
63
+ notes: string | null;
64
+ /** Distance from the unit to the incident at dispatch time. */
65
+ distanceMetres: number | null;
66
+ /** The statuses THIS caller may set next, already filtered by policy. */
67
+ allowedStatuses: ResponseUnitDispatchStatus[];
68
+ report: ResponderReportState;
69
+ incident: ResponderIncidentSummary;
70
+ }
71
+ /** Another unit sent to the same incident. */
72
+ export interface ResponderCoResponder {
73
+ dispatchId: number;
74
+ responseUnitId: number;
75
+ responseUnitName: string;
76
+ responseUnitType: string | null;
77
+ status: ResponseUnitDispatchStatus;
78
+ dispatchedAt: string;
79
+ }
80
+ /** `GET /responder/dispatches/:dispatchId`. */
81
+ export interface ResponderDispatchDetail extends ResponderDispatch {
82
+ otherUnits: ResponderCoResponder[];
83
+ /** What the responder recorded when arriving, if they did. */
84
+ arrivalEvidence: ResponderArrivalEvidence | null;
85
+ }
86
+ /** What a responder's arrival rested on - stored with the dispatch for the audit. */
87
+ export interface ResponderArrivalEvidence {
88
+ method: ResponderArrivalMethod;
89
+ latitude: number | null;
90
+ longitude: number | null;
91
+ accuracyMetres: number | null;
92
+ /** Distance from the fix to the incident, computed by the server. */
93
+ distanceMetres: number | null;
94
+ recordedAt: string | null;
95
+ reason: string | null;
96
+ }
97
+ export interface ResponderDispatchPage {
98
+ data: ResponderDispatch[];
99
+ meta: {
100
+ total: number;
101
+ page: number;
102
+ limit: number;
103
+ totalPages: number;
104
+ hasNextPage: boolean;
105
+ hasPreviousPage: boolean;
106
+ };
107
+ }
108
+ /** `GET|POST /responder/dispatches/:dispatchId/report`. */
109
+ export interface ResponderDispatchReport {
110
+ id: number;
111
+ reference: string;
112
+ dispatchId: number;
113
+ incidentId: number;
114
+ responseUnitId: number;
115
+ submittedByUserId: number;
116
+ /** Starts at 1; every amendment adds one. */
117
+ version: number;
118
+ summary: string;
119
+ actionsTaken: string | null;
120
+ outcome: ResponderReportOutcome;
121
+ personsContacted: string | null;
122
+ handoverTo: string | null;
123
+ followUpRequired: boolean;
124
+ followUpNotes: string | null;
125
+ remarks: string | null;
126
+ checklist: {
127
+ itemId: string;
128
+ checked: boolean;
129
+ }[];
130
+ attachmentIds: number[];
131
+ submittedAt: string;
132
+ updatedAt: string;
133
+ /** Whether the caller may still amend it (submitter, incident not closed). */
134
+ amendable: boolean;
135
+ }
136
+ /** `POST /responder/positions`. */
137
+ export interface ResponderPositionBatchResult {
138
+ accepted: number;
139
+ rejected: number;
140
+ /** Why individual samples were refused (`TOO_OLD`, `IN_FUTURE`, `INACCURATE`, `INVALID`). */
141
+ rejectedReasons: Record<string, number>;
142
+ responseUnitId: number | null;
143
+ trackingMode: ResponderTrackingMode;
144
+ }