@tmlmobilidade/interfaces 20251027.1158.39 → 20251028.1557.20

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.
@@ -22,7 +22,7 @@ declare class AlertsRealtimeClass extends MongoCollectionClass<Alert, CreateAler
22
22
  active_period_start_date: number & {
23
23
  __brand: "UnixTimestamp";
24
24
  };
25
- cause: "ACCIDENT" | "CONSTRUCTION" | "DEMONSTRATION" | "HOLIDAY" | "MAINTENANCE" | "MEDICAL_EMERGENCY" | "OTHER_CAUSE" | "POLICE_ACTIVITY" | "STRIKE" | "TECHNICAL_PROBLEM" | "UNKNOWN_CAUSE" | "WEATHER";
25
+ cause: "ACCIDENT" | "CONSTRUCTION" | "DEMONSTRATION" | "HOLIDAY" | "MAINTENANCE" | "MEDICAL_EMERGENCY" | "OTHER_CAUSE" | "POLICE_ACTIVITY" | "STRIKE" | "TECHNICAL_PROBLEM" | "UNKNOWN_CAUSE" | "WEATHER" | "DRIVER_ABSENCE" | "DRIVER_ISSUE" | "HIGH_PASSENGER_LOAD" | "ROAD_INCIDENT" | "SYSTEM_FAILURE" | "TRAFFIC_JAM" | "VEHICLE_ISSUE";
26
26
  description: string;
27
27
  effect: "ACCESSIBILITY_ISSUE" | "ADDITIONAL_SERVICE" | "DETOUR" | "MODIFIED_SERVICE" | "NO_EFFECT" | "NO_SERVICE" | "OTHER_EFFECT" | "REDUCED_SERVICE" | "SIGNIFICANT_DELAYS" | "STOP_MOVED" | "UNKNOWN_EFFECT";
28
28
  modified_by: string;
@@ -57,7 +57,7 @@ declare class AlertsRealtimeClass extends MongoCollectionClass<Alert, CreateAler
57
57
  active_period_start_date: number & {
58
58
  __brand: "UnixTimestamp";
59
59
  };
60
- cause: "ACCIDENT" | "CONSTRUCTION" | "DEMONSTRATION" | "HOLIDAY" | "MAINTENANCE" | "MEDICAL_EMERGENCY" | "OTHER_CAUSE" | "POLICE_ACTIVITY" | "STRIKE" | "TECHNICAL_PROBLEM" | "UNKNOWN_CAUSE" | "WEATHER";
60
+ cause: "ACCIDENT" | "CONSTRUCTION" | "DEMONSTRATION" | "HOLIDAY" | "MAINTENANCE" | "MEDICAL_EMERGENCY" | "OTHER_CAUSE" | "POLICE_ACTIVITY" | "STRIKE" | "TECHNICAL_PROBLEM" | "UNKNOWN_CAUSE" | "WEATHER" | "DRIVER_ABSENCE" | "DRIVER_ISSUE" | "HIGH_PASSENGER_LOAD" | "ROAD_INCIDENT" | "SYSTEM_FAILURE" | "TRAFFIC_JAM" | "VEHICLE_ISSUE";
61
61
  description: string;
62
62
  effect: "ACCESSIBILITY_ISSUE" | "ADDITIONAL_SERVICE" | "DETOUR" | "MODIFIED_SERVICE" | "NO_EFFECT" | "NO_SERVICE" | "OTHER_EFFECT" | "REDUCED_SERVICE" | "SIGNIFICANT_DELAYS" | "STOP_MOVED" | "UNKNOWN_EFFECT";
63
63
  modified_by: string;
@@ -22,7 +22,7 @@ declare class AlertsClass extends MongoCollectionClass<Alert, CreateAlertDto, Up
22
22
  active_period_start_date: number & {
23
23
  __brand: "UnixTimestamp";
24
24
  };
25
- cause: "ACCIDENT" | "CONSTRUCTION" | "DEMONSTRATION" | "HOLIDAY" | "MAINTENANCE" | "MEDICAL_EMERGENCY" | "OTHER_CAUSE" | "POLICE_ACTIVITY" | "STRIKE" | "TECHNICAL_PROBLEM" | "UNKNOWN_CAUSE" | "WEATHER";
25
+ cause: "ACCIDENT" | "CONSTRUCTION" | "DEMONSTRATION" | "HOLIDAY" | "MAINTENANCE" | "MEDICAL_EMERGENCY" | "OTHER_CAUSE" | "POLICE_ACTIVITY" | "STRIKE" | "TECHNICAL_PROBLEM" | "UNKNOWN_CAUSE" | "WEATHER" | "DRIVER_ABSENCE" | "DRIVER_ISSUE" | "HIGH_PASSENGER_LOAD" | "ROAD_INCIDENT" | "SYSTEM_FAILURE" | "TRAFFIC_JAM" | "VEHICLE_ISSUE";
26
26
  description: string;
27
27
  effect: "ACCESSIBILITY_ISSUE" | "ADDITIONAL_SERVICE" | "DETOUR" | "MODIFIED_SERVICE" | "NO_EFFECT" | "NO_SERVICE" | "OTHER_EFFECT" | "REDUCED_SERVICE" | "SIGNIFICANT_DELAYS" | "STOP_MOVED" | "UNKNOWN_EFFECT";
28
28
  modified_by: string;
@@ -57,7 +57,7 @@ declare class AlertsClass extends MongoCollectionClass<Alert, CreateAlertDto, Up
57
57
  active_period_start_date: number & {
58
58
  __brand: "UnixTimestamp";
59
59
  };
60
- cause: "ACCIDENT" | "CONSTRUCTION" | "DEMONSTRATION" | "HOLIDAY" | "MAINTENANCE" | "MEDICAL_EMERGENCY" | "OTHER_CAUSE" | "POLICE_ACTIVITY" | "STRIKE" | "TECHNICAL_PROBLEM" | "UNKNOWN_CAUSE" | "WEATHER";
60
+ cause: "ACCIDENT" | "CONSTRUCTION" | "DEMONSTRATION" | "HOLIDAY" | "MAINTENANCE" | "MEDICAL_EMERGENCY" | "OTHER_CAUSE" | "POLICE_ACTIVITY" | "STRIKE" | "TECHNICAL_PROBLEM" | "UNKNOWN_CAUSE" | "WEATHER" | "DRIVER_ABSENCE" | "DRIVER_ISSUE" | "HIGH_PASSENGER_LOAD" | "ROAD_INCIDENT" | "SYSTEM_FAILURE" | "TRAFFIC_JAM" | "VEHICLE_ISSUE";
61
61
  description: string;
62
62
  effect: "ACCESSIBILITY_ISSUE" | "ADDITIONAL_SERVICE" | "DETOUR" | "MODIFIED_SERVICE" | "NO_EFFECT" | "NO_SERVICE" | "OTHER_EFFECT" | "REDUCED_SERVICE" | "SIGNIFICANT_DELAYS" | "STOP_MOVED" | "UNKNOWN_EFFECT";
63
63
  modified_by: string;
@@ -1,4 +1,5 @@
1
1
  export * from './hashed-shapes.js';
2
2
  export * from './hashed-trips.js';
3
+ export * from './pipelines.js';
3
4
  export * from './ride-acceptances.js';
4
5
  export * from './rides.js';
@@ -1,4 +1,5 @@
1
1
  export * from './hashed-shapes.js';
2
2
  export * from './hashed-trips.js';
3
+ export * from './pipelines.js';
3
4
  export * from './ride-acceptances.js';
4
5
  export * from './rides.js';
@@ -0,0 +1,109 @@
1
+ import { AggregationPipeline } from '../../aggregation-pipeline.js';
2
+ import { Ride, RideAcceptanceStatus, RideAnalysisGradeWithNone, RideDelayStatus, RideOperationalStatus, RideSeenStatus, UnixTimestamp } from '@tmlmobilidade/types';
3
+ /**
4
+ * Creates MongoDB aggregation pipeline stages to calculate and categorize delay statuses.
5
+ *
6
+ * This function generates three aggregation stages:
7
+ * 1. Calculates delay differences (in milliseconds) between scheduled and observed times
8
+ * 2. Categorizes delays into statuses: 'delayed', 'early', 'ontime', or 'none'
9
+ * 3. Removes intermediate calculation fields
10
+ *
11
+ * Delay thresholds:
12
+ * - Delayed: > 5 minutes (300000 ms)
13
+ * - Early: < -1 minute (-60000 ms)
14
+ * - On-time: between -1 minute and 5 minutes
15
+ * - None: missing scheduled or observed time data
16
+ *
17
+ * @returns {Array} Array of MongoDB aggregation pipeline stages
18
+ */
19
+ export declare function ridesPipelineDelayStatus({ filter }?: {
20
+ filter?: {
21
+ end_delay_status?: RideDelayStatus[];
22
+ start_delay_status?: RideDelayStatus[];
23
+ };
24
+ }): AggregationPipeline<Ride>;
25
+ /**
26
+ * Creates MongoDB aggregation pipeline stages to calculate and categorize operational statuses.
27
+ *
28
+ * This function generates four aggregation stages:
29
+ * 1. Adds the current timestamp (now) to each document
30
+ * 2. Calculates time differences from last seen and from start time
31
+ * 3. Categorizes operational status: 'scheduled', 'missed', 'running', or 'ended'
32
+ * 4. Removes intermediate calculation fields
33
+ *
34
+ * Operational status logic:
35
+ * - Scheduled: within 10 minutes of start time and never seen
36
+ * - Missed: more than 10 minutes after start time and never seen
37
+ * - Running: last seen within 10 minutes
38
+ * - Ended: default fallback (last seen more than 10 minutes ago)
39
+ *
40
+ * Time thresholds:
41
+ * - Operational window: 10 minutes (600000 ms)
42
+ *
43
+ * @param {number} now - Current timestamp in milliseconds
44
+ * @returns {Array} Array of MongoDB aggregation pipeline stages
45
+ */
46
+ export declare function ridesPipelineOperationalStatus({ filter }?: {
47
+ filter?: {
48
+ operational_status?: RideOperationalStatus[];
49
+ };
50
+ }): AggregationPipeline<Ride>;
51
+ /**
52
+ * Creates MongoDB aggregation pipeline stages to calculate and categorize seen statuses.
53
+ *
54
+ * This function generates three aggregation stages:
55
+ * 1. Adds the current timestamp (now) to each document
56
+ * 2. Calculates time difference from last seen to now
57
+ * 3. Categorizes seen status: 'gone', 'seen', or 'unseen'
58
+ * 4. Removes intermediate calculation fields
59
+ *
60
+ * Seen status logic:
61
+ * - Gone: last seen more than 30 seconds ago
62
+ * - Seen: last seen within 30 seconds
63
+ * - Unseen: no last seen time
64
+ *
65
+ * Time thresholds:
66
+ * - Seen window: 30 seconds (30000 ms)
67
+ *
68
+ * @param {number} now - Current timestamp in milliseconds
69
+ * @returns {Array} Array of MongoDB aggregation pipeline stages
70
+ */
71
+ export declare function ridesPipelineSeenStatus({ filter }?: {
72
+ filter?: {
73
+ seen_status?: RideSeenStatus[];
74
+ };
75
+ }): AggregationPipeline<Ride>;
76
+ interface RidesPipelineFilter {
77
+ acceptance_status?: ('none' | RideAcceptanceStatus)[];
78
+ agency_ids?: string[];
79
+ analysis_ended_at_last_stop_grade?: RideAnalysisGradeWithNone[];
80
+ analysis_expected_apex_validation_interval?: RideAnalysisGradeWithNone[];
81
+ analysis_simple_three_vehicle_events_grade?: RideAnalysisGradeWithNone[];
82
+ analysis_transaction_sequentiality?: RideAnalysisGradeWithNone[];
83
+ date_end: UnixTimestamp;
84
+ date_start: UnixTimestamp;
85
+ delay_statuses?: RideDelayStatus[];
86
+ line_ids?: string[];
87
+ operational_statuses?: RideOperationalStatus[];
88
+ search?: string;
89
+ seen_statuses?: RideSeenStatus[];
90
+ stop_ids?: string[];
91
+ }
92
+ /**
93
+ * Creates MongoDB aggregation pipeline stages to filter and process ride data.
94
+ *
95
+ * This function generates an aggregation pipeline that:
96
+ * 1. Filters rides by scheduled time range (date_start to date_end)
97
+ * 2. Optionally filters by line IDs and agency IDs
98
+ * 3. Optionally searches rides by ID using regex pattern matching
99
+ * 4. Adds acceptance status from ride_acceptances collection via lookup
100
+ * 5. Filters by analysis grades (ended_at_last_stop, expected_apex_validation_interval, simple_three_vehicle_events)
101
+ * 6. Filters by acceptance status (excluding 'none' if present)
102
+ * 7. Applies delay, operational, and seen status filters using dedicated pipeline functions
103
+ *
104
+ * @param {Object} params - Parameters object
105
+ * @param {RidesPipelineFilter} params.filter - Filter criteria for rides
106
+ * @returns {AggregationPipeline<Ride>} Array of MongoDB aggregation pipeline stages
107
+ */
108
+ export declare function ridesBatchAggregationPipeline({ ...filter }: RidesPipelineFilter): AggregationPipeline<Ride>;
109
+ export {};
@@ -0,0 +1,326 @@
1
+ import { Dates } from '@tmlmobilidade/utils';
2
+ /**
3
+ * Creates MongoDB aggregation pipeline stages to calculate and categorize delay statuses.
4
+ *
5
+ * This function generates three aggregation stages:
6
+ * 1. Calculates delay differences (in milliseconds) between scheduled and observed times
7
+ * 2. Categorizes delays into statuses: 'delayed', 'early', 'ontime', or 'none'
8
+ * 3. Removes intermediate calculation fields
9
+ *
10
+ * Delay thresholds:
11
+ * - Delayed: > 5 minutes (300000 ms)
12
+ * - Early: < -1 minute (-60000 ms)
13
+ * - On-time: between -1 minute and 5 minutes
14
+ * - None: missing scheduled or observed time data
15
+ *
16
+ * @returns {Array} Array of MongoDB aggregation pipeline stages
17
+ */
18
+ export function ridesPipelineDelayStatus({ filter } = {}) {
19
+ //
20
+ // Delay thresholds in milliseconds
21
+ const DELAY_THRESHOLDS = {
22
+ delayed: 300000, // 5 minutes after scheduled time
23
+ early: -60000, // 1 minute before scheduled time
24
+ };
25
+ const pipeline = [
26
+ // Stage 1: Calculate delay differences in milliseconds
27
+ // Only compute if both scheduled and observed times exist
28
+ {
29
+ $addFields: {
30
+ end_delay_diff: {
31
+ $cond: {
32
+ else: null,
33
+ if: { $and: [
34
+ { $ifNull: ['$end_time_scheduled', false] },
35
+ { $ifNull: ['$end_time_observed', false] },
36
+ ] },
37
+ then: { $subtract: ['$end_time_observed', '$end_time_scheduled'] },
38
+ },
39
+ },
40
+ start_delay_diff: {
41
+ $cond: {
42
+ else: null,
43
+ if: { $and: [
44
+ { $ifNull: ['$start_time_scheduled', false] },
45
+ { $ifNull: ['$start_time_observed', false] },
46
+ ] },
47
+ then: { $subtract: ['$start_time_observed', '$start_time_scheduled'] },
48
+ },
49
+ },
50
+ },
51
+ },
52
+ // Stage 2: Categorize delays into status strings
53
+ // Uses switch statement to classify based on delay thresholds
54
+ {
55
+ $addFields: {
56
+ end_delay_status: {
57
+ $switch: {
58
+ branches: [
59
+ // Delayed: > 5 minutes (300000 ms)
60
+ { case: { $gt: ['$end_delay_diff', DELAY_THRESHOLDS.delayed] }, then: 'delayed' },
61
+ // Early: < -1 minute (-60000 ms)
62
+ { case: { $lt: ['$end_delay_diff', DELAY_THRESHOLDS.early] }, then: 'early' },
63
+ // On-time: between -1 minute and 5 minutes
64
+ { case: { $and: [
65
+ { $gte: ['$end_delay_diff', DELAY_THRESHOLDS.early] },
66
+ { $lte: ['$end_delay_diff', DELAY_THRESHOLDS.delayed] },
67
+ ] }, then: 'ontime' },
68
+ ],
69
+ default: 'none',
70
+ },
71
+ },
72
+ start_delay_status: {
73
+ $switch: {
74
+ branches: [
75
+ // Delayed: > 5 minutes (300000 ms)
76
+ { case: { $gt: ['$start_delay_diff', DELAY_THRESHOLDS.delayed] }, then: 'delayed' },
77
+ // Early: < -1 minute (-60000 ms)
78
+ { case: { $lt: ['$start_delay_diff', DELAY_THRESHOLDS.early] }, then: 'early' },
79
+ // On-time: between -1 minute and 5 minutes
80
+ { case: { $and: [
81
+ { $gte: ['$start_delay_diff', DELAY_THRESHOLDS.early] },
82
+ { $lte: ['$start_delay_diff', DELAY_THRESHOLDS.delayed] },
83
+ ] }, then: 'ontime' },
84
+ ],
85
+ default: 'none',
86
+ },
87
+ },
88
+ },
89
+ },
90
+ // Stage 3: Remove intermediate calculation fields
91
+ // These fields were only used for status calculation and are not needed in final output
92
+ { $project: { end_delay_diff: 0, start_delay_diff: 0 } },
93
+ ];
94
+ // Stage 5: Filter by delay status if provided
95
+ if (filter && filter.end_delay_status && filter.end_delay_status.length > 0) {
96
+ pipeline.push({ $match: { end_delay_status: { $in: filter.end_delay_status } } });
97
+ }
98
+ if (filter && filter.start_delay_status && filter.start_delay_status.length > 0) {
99
+ pipeline.push({ $match: { start_delay_status: { $in: filter.start_delay_status } } });
100
+ }
101
+ return pipeline;
102
+ }
103
+ /**
104
+ * Creates MongoDB aggregation pipeline stages to calculate and categorize operational statuses.
105
+ *
106
+ * This function generates four aggregation stages:
107
+ * 1. Adds the current timestamp (now) to each document
108
+ * 2. Calculates time differences from last seen and from start time
109
+ * 3. Categorizes operational status: 'scheduled', 'missed', 'running', or 'ended'
110
+ * 4. Removes intermediate calculation fields
111
+ *
112
+ * Operational status logic:
113
+ * - Scheduled: within 10 minutes of start time and never seen
114
+ * - Missed: more than 10 minutes after start time and never seen
115
+ * - Running: last seen within 10 minutes
116
+ * - Ended: default fallback (last seen more than 10 minutes ago)
117
+ *
118
+ * Time thresholds:
119
+ * - Operational window: 10 minutes (600000 ms)
120
+ *
121
+ * @param {number} now - Current timestamp in milliseconds
122
+ * @returns {Array} Array of MongoDB aggregation pipeline stages
123
+ */
124
+ export function ridesPipelineOperationalStatus({ filter } = {}) {
125
+ //
126
+ // Time thresholds in milliseconds
127
+ const OPERATIONAL_WINDOW = 600000; // 10 minutes
128
+ const now = Dates.now('Europe/Lisbon').unix_timestamp;
129
+ const pipeline = [
130
+ // Stage 1: Add current timestamp to each document
131
+ { $addFields: { now } },
132
+ // Stage 2: Calculate time differences from last seen and from start time
133
+ // Only compute if the relevant fields exist
134
+ {
135
+ $addFields: {
136
+ milliseconds_from_last_seen_to_now: {
137
+ $cond: {
138
+ else: null,
139
+ if: { $ifNull: ['$seen_last_at', false] },
140
+ then: { $subtract: ['$now', '$seen_last_at'] },
141
+ },
142
+ },
143
+ milliseconds_from_start_to_now: { $subtract: ['$now', '$start_time_scheduled'] },
144
+ },
145
+ },
146
+ // Stage 3: Categorize operational status using switch statement
147
+ {
148
+ $addFields: {
149
+ operational_status: {
150
+ $switch: {
151
+ branches: [
152
+ // Scheduled: within 10 minutes of start time and never seen
153
+ {
154
+ case: {
155
+ $and: [
156
+ { $lte: ['$milliseconds_from_start_to_now', OPERATIONAL_WINDOW] },
157
+ { $or: [{ $eq: ['$seen_last_at', null] }, { $not: ['$seen_last_at'] }] },
158
+ ],
159
+ },
160
+ then: 'scheduled',
161
+ },
162
+ // Missed: more than 10 minutes after start time and never seen
163
+ {
164
+ case: {
165
+ $and: [
166
+ { $gt: ['$milliseconds_from_start_to_now', OPERATIONAL_WINDOW] },
167
+ { $or: [{ $eq: ['$seen_last_at', null] }, { $not: ['$seen_last_at'] }] },
168
+ ],
169
+ },
170
+ then: 'missed',
171
+ },
172
+ // Running: last seen within 10 minutes
173
+ {
174
+ case: { $lte: ['$milliseconds_from_last_seen_to_now', OPERATIONAL_WINDOW] },
175
+ then: 'running',
176
+ },
177
+ ],
178
+ default: 'ended',
179
+ },
180
+ },
181
+ },
182
+ },
183
+ // Stage 4: Remove intermediate calculation fields
184
+ // These fields were only used for status calculation and are not needed in final output
185
+ {
186
+ $project: {
187
+ milliseconds_from_last_seen_to_now: 0,
188
+ milliseconds_from_start_to_now: 0,
189
+ now: 0,
190
+ },
191
+ },
192
+ ];
193
+ // Stage 5: Filter by operational status if provided
194
+ if (filter && filter.operational_status && filter.operational_status.length > 0) {
195
+ pipeline.push({ $match: { operational_status: { $in: filter.operational_status } } });
196
+ }
197
+ return pipeline;
198
+ }
199
+ /**
200
+ * Creates MongoDB aggregation pipeline stages to calculate and categorize seen statuses.
201
+ *
202
+ * This function generates three aggregation stages:
203
+ * 1. Adds the current timestamp (now) to each document
204
+ * 2. Calculates time difference from last seen to now
205
+ * 3. Categorizes seen status: 'gone', 'seen', or 'unseen'
206
+ * 4. Removes intermediate calculation fields
207
+ *
208
+ * Seen status logic:
209
+ * - Gone: last seen more than 30 seconds ago
210
+ * - Seen: last seen within 30 seconds
211
+ * - Unseen: no last seen time
212
+ *
213
+ * Time thresholds:
214
+ * - Seen window: 30 seconds (30000 ms)
215
+ *
216
+ * @param {number} now - Current timestamp in milliseconds
217
+ * @returns {Array} Array of MongoDB aggregation pipeline stages
218
+ */
219
+ export function ridesPipelineSeenStatus({ filter } = {}) {
220
+ //
221
+ // Time thresholds in milliseconds
222
+ const SEEN_WINDOW = 30000; // 30 seconds
223
+ const now = Dates.now('Europe/Lisbon').unix_timestamp;
224
+ const pipeline = [
225
+ // Stage 1: Add current timestamp to each document
226
+ { $addFields: { now } },
227
+ // Stage 2: Calculate time difference from last seen to now
228
+ // Only compute if the last seen time exists
229
+ {
230
+ $addFields: {
231
+ milliseconds_from_last_seen_to_now: {
232
+ $cond: {
233
+ else: null,
234
+ if: { $ifNull: ['$seen_last_at', false] },
235
+ then: { $subtract: ['$now', '$seen_last_at'] },
236
+ },
237
+ },
238
+ },
239
+ },
240
+ // Stage 3: Categorize seen status using switch statement
241
+ {
242
+ $addFields: {
243
+ seen_status: {
244
+ $switch: {
245
+ branches: [
246
+ { case: { $eq: ['$seen_last_at', null] }, then: 'unseen' },
247
+ { case: { $lte: ['$milliseconds_from_last_seen_to_now', SEEN_WINDOW] }, then: 'seen' },
248
+ ],
249
+ default: 'gone',
250
+ },
251
+ },
252
+ },
253
+ },
254
+ // Stage 4: Remove intermediate calculation fields
255
+ // These fields were only used for status calculation and are not needed in final output
256
+ {
257
+ $project: {
258
+ milliseconds_from_last_seen_to_now: 0,
259
+ now: 0,
260
+ },
261
+ },
262
+ ];
263
+ // Stage 5: Filter by seen status if provided
264
+ if (filter && filter.seen_status && filter.seen_status.length > 0) {
265
+ pipeline.push({ $match: { seen_status: { $in: filter.seen_status } } });
266
+ }
267
+ return pipeline;
268
+ }
269
+ /**
270
+ * Creates MongoDB aggregation pipeline stages to filter and process ride data.
271
+ *
272
+ * This function generates an aggregation pipeline that:
273
+ * 1. Filters rides by scheduled time range (date_start to date_end)
274
+ * 2. Optionally filters by line IDs and agency IDs
275
+ * 3. Optionally searches rides by ID using regex pattern matching
276
+ * 4. Adds acceptance status from ride_acceptances collection via lookup
277
+ * 5. Filters by analysis grades (ended_at_last_stop, expected_apex_validation_interval, simple_three_vehicle_events)
278
+ * 6. Filters by acceptance status (excluding 'none' if present)
279
+ * 7. Applies delay, operational, and seen status filters using dedicated pipeline functions
280
+ *
281
+ * @param {Object} params - Parameters object
282
+ * @param {RidesPipelineFilter} params.filter - Filter criteria for rides
283
+ * @returns {AggregationPipeline<Ride>} Array of MongoDB aggregation pipeline stages
284
+ */
285
+ export function ridesBatchAggregationPipeline({ ...filter }) {
286
+ const pipeline = [];
287
+ // Stage 1: Filter by scheduled time range
288
+ pipeline.push({ $match: { start_time_scheduled: { $gte: filter.date_start, $lte: filter.date_end } } });
289
+ // Stage 2: Filter by line IDs if provided
290
+ if (filter.line_ids)
291
+ pipeline.push({ $match: { line_id: { $in: filter.line_ids.map(id => Number(id)) } } });
292
+ // Stage 3: Filter by agency IDs if provided
293
+ if (filter.agency_ids)
294
+ pipeline.push({ $match: { agency_id: { $in: filter.agency_ids } } });
295
+ // Stage 4: Search by ride ID if provided
296
+ // Uses regex pattern matching with case-insensitive option
297
+ if (filter.search) {
298
+ const keywords = filter.search.split(/\s+/).map(v => v.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
299
+ const pattern = keywords.map(k => `(?=.*${k})`).join('') + '.*';
300
+ pipeline.push({
301
+ $match: { _id: { $options: 'i', $regex: pattern } },
302
+ });
303
+ }
304
+ // Stage 5: Add acceptance status from ride_acceptances collection
305
+ // Lookup joins acceptance data, unwinds to flatten, adds status field, and removes intermediate data
306
+ pipeline.push({ $lookup: { as: 'acceptance', foreignField: 'ride_id', from: 'ride_acceptances', localField: '_id' } }, { $unwind: { path: '$acceptance', preserveNullAndEmptyArrays: true } }, { $addFields: { acceptance_status: { $ifNull: ['$acceptance.acceptance_status', null] } } }, { $project: { acceptance: 0 } });
307
+ // Stage 6: Filter by analysis grades
308
+ // Maps filter fields to their corresponding analysis paths in the document
309
+ const analysisFilters = [
310
+ { field: 'analysis_ended_at_last_stop_grade', path: 'analysis.ENDED_AT_LAST_STOP.grade' },
311
+ { field: 'analysis_expected_apex_validation_interval', path: 'analysis.EXPECTED_APEX_VALIDATION_INTERVAL.grade' },
312
+ { field: 'analysis_simple_three_vehicle_events_grade', path: 'analysis.SIMPLE_THREE_VEHICLE_EVENTS.grade' },
313
+ ];
314
+ analysisFilters.forEach(({ field, path }) => filter[field] && pipeline.push({ $match: { [path]: { $in: filter[field] } } }));
315
+ // Stage 7: Filter by acceptance status
316
+ // Only applies filter if acceptance_status is provided and doesn't include 'none'
317
+ if (filter.acceptance_status && filter.acceptance_status.length > 0 && !filter.acceptance_status.includes('none')) {
318
+ pipeline.push({ $match: { acceptance_status: { $exists: true } } }, { $match: { acceptance_status: { $in: filter.acceptance_status } } });
319
+ }
320
+ // Stage 8: Apply status filters using dedicated pipeline functions
321
+ // These functions add calculated status fields and filter by them
322
+ pipeline.push(...ridesPipelineDelayStatus({ filter: { end_delay_status: filter.delay_statuses?.map(status => status), start_delay_status: filter.delay_statuses?.map(status => status) } }));
323
+ pipeline.push(...ridesPipelineOperationalStatus({ filter: { operational_status: filter.operational_statuses?.map(status => status) } }));
324
+ pipeline.push(...ridesPipelineSeenStatus({ filter: { seen_status: filter.seen_statuses?.map(status => status) } }));
325
+ return pipeline;
326
+ }
@@ -26,13 +26,6 @@ declare class StopsClass extends MongoCollectionClass<Stop, CreateStopDto, Updat
26
26
  __brand: "UnixTimestamp";
27
27
  };
28
28
  name: string;
29
- is_locked: boolean;
30
- has_bench: "unknown" | "yes" | "no";
31
- has_network_map: "unknown" | "yes" | "no";
32
- has_schedules: "unknown" | "yes" | "no";
33
- has_shelter: "unknown" | "yes" | "no";
34
- has_stop_sign: "unknown" | "yes" | "no";
35
- municipality_id: string;
36
29
  comments: ({
37
30
  created_at: number & {
38
31
  __brand: "UnixTimestamp";
@@ -73,9 +66,16 @@ declare class StopsClass extends MongoCollectionClass<Stop, CreateStopDto, Updat
73
66
  created_by?: string | undefined;
74
67
  updated_by?: string | undefined;
75
68
  })[];
69
+ is_locked: boolean;
70
+ operational_status: "active" | "inactive" | "provisional" | "seasonal" | "voided";
71
+ has_bench: "unknown" | "yes" | "no";
72
+ has_network_map: "unknown" | "yes" | "no";
73
+ has_schedules: "unknown" | "yes" | "no";
74
+ has_shelter: "unknown" | "yes" | "no";
75
+ has_stop_sign: "unknown" | "yes" | "no";
76
+ municipality_id: string;
76
77
  is_archived: boolean;
77
78
  jurisdiction: "unknown" | "ip" | "municipality" | "other";
78
- operational_status: "active" | "inactive" | "provisional" | "seasonal" | "voided";
79
79
  district_id: string;
80
80
  latitude: number;
81
81
  longitude: number;
@@ -125,13 +125,6 @@ declare class StopsClass extends MongoCollectionClass<Stop, CreateStopDto, Updat
125
125
  __brand: "UnixTimestamp";
126
126
  };
127
127
  name: string;
128
- is_locked: boolean;
129
- has_bench: "unknown" | "yes" | "no";
130
- has_network_map: "unknown" | "yes" | "no";
131
- has_schedules: "unknown" | "yes" | "no";
132
- has_shelter: "unknown" | "yes" | "no";
133
- has_stop_sign: "unknown" | "yes" | "no";
134
- municipality_id: string;
135
128
  comments: ({
136
129
  created_at: number & {
137
130
  __brand: "UnixTimestamp";
@@ -172,9 +165,16 @@ declare class StopsClass extends MongoCollectionClass<Stop, CreateStopDto, Updat
172
165
  created_by?: string | undefined;
173
166
  updated_by?: string | undefined;
174
167
  })[];
168
+ is_locked: boolean;
169
+ operational_status: "active" | "inactive" | "provisional" | "seasonal" | "voided";
170
+ has_bench: "unknown" | "yes" | "no";
171
+ has_network_map: "unknown" | "yes" | "no";
172
+ has_schedules: "unknown" | "yes" | "no";
173
+ has_shelter: "unknown" | "yes" | "no";
174
+ has_stop_sign: "unknown" | "yes" | "no";
175
+ municipality_id: string;
175
176
  is_archived: boolean;
176
177
  jurisdiction: "unknown" | "ip" | "municipality" | "other";
177
- operational_status: "active" | "inactive" | "provisional" | "seasonal" | "voided";
178
178
  district_id: string;
179
179
  latitude: number;
180
180
  longitude: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tmlmobilidade/interfaces",
3
- "version": "20251027.1158.39",
3
+ "version": "20251028.1557.20",
4
4
  "author": "João de Vasconcelos & Jusi Monteiro",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "homepage": "https://github.com/tmlmobilidade/services#readme",