@tmlmobilidade/interfaces 20260326.1644.50 → 20260326.2139.30
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.
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import { Dates } from '@tmlmobilidade/dates';
|
|
2
|
+
//
|
|
3
|
+
// Time thresholds
|
|
4
|
+
const LAST_SEEN_WINDOW = 30 * 1000; // 30 seconds
|
|
5
|
+
const OPERATIONAL_WINDOW = 60 * 1000 * 10; // 10 minutes
|
|
6
|
+
const DELAY_THRESHOLDS = {
|
|
7
|
+
delayed: 5 * 60 * 1000, // 5 minutes after scheduled time
|
|
8
|
+
early: -1 * 60 * 1000, // 1 minute before scheduled time
|
|
9
|
+
};
|
|
2
10
|
/**
|
|
3
11
|
* Creates MongoDB aggregation pipeline stages to calculate and categorize delay statuses.
|
|
4
12
|
*
|
|
@@ -16,12 +24,6 @@ import { Dates } from '@tmlmobilidade/dates';
|
|
|
16
24
|
* @returns {Array} Array of MongoDB aggregation pipeline stages
|
|
17
25
|
*/
|
|
18
26
|
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
27
|
const pipeline = [
|
|
26
28
|
// Stage 1: Calculate delay differences in milliseconds
|
|
27
29
|
// Only compute if both scheduled and observed times exist
|
|
@@ -92,10 +94,10 @@ export function ridesPipelineDelayStatus({ filter } = {}) {
|
|
|
92
94
|
{ $project: { end_delay_diff: 0, start_delay_diff: 0 } },
|
|
93
95
|
];
|
|
94
96
|
// Stage 5: Filter by delay status if provided
|
|
95
|
-
if (filter
|
|
97
|
+
if (filter?.end_delay_status) {
|
|
96
98
|
pipeline.push({ $match: { end_delay_status: { $in: filter.end_delay_status } } });
|
|
97
99
|
}
|
|
98
|
-
if (filter
|
|
100
|
+
if (filter?.start_delay_status) {
|
|
99
101
|
pipeline.push({ $match: { start_delay_status: { $in: filter.start_delay_status } } });
|
|
100
102
|
}
|
|
101
103
|
return pipeline;
|
|
@@ -122,9 +124,6 @@ export function ridesPipelineDelayStatus({ filter } = {}) {
|
|
|
122
124
|
* @returns {Array} Array of MongoDB aggregation pipeline stages
|
|
123
125
|
*/
|
|
124
126
|
export function ridesPipelineOperationalStatus({ filter } = {}) {
|
|
125
|
-
//
|
|
126
|
-
// Time thresholds in milliseconds
|
|
127
|
-
const OPERATIONAL_WINDOW = 600000; // 10 minutes
|
|
128
127
|
const now = Dates.now('Europe/Lisbon').unix_timestamp;
|
|
129
128
|
const pipeline = [
|
|
130
129
|
// Stage 1: Add current timestamp to each document
|
|
@@ -191,7 +190,7 @@ export function ridesPipelineOperationalStatus({ filter } = {}) {
|
|
|
191
190
|
},
|
|
192
191
|
];
|
|
193
192
|
// Stage 5: Filter by operational status if provided
|
|
194
|
-
if (filter
|
|
193
|
+
if (filter?.operational_status) {
|
|
195
194
|
pipeline.push({ $match: { operational_status: { $in: filter.operational_status } } });
|
|
196
195
|
}
|
|
197
196
|
return pipeline;
|
|
@@ -217,9 +216,6 @@ export function ridesPipelineOperationalStatus({ filter } = {}) {
|
|
|
217
216
|
* @returns {Array} Array of MongoDB aggregation pipeline stages
|
|
218
217
|
*/
|
|
219
218
|
export function ridesPipelineSeenStatus({ filter } = {}) {
|
|
220
|
-
//
|
|
221
|
-
// Time thresholds in milliseconds
|
|
222
|
-
const SEEN_WINDOW = 30000; // 30 seconds
|
|
223
219
|
const now = Dates.now('Europe/Lisbon').unix_timestamp;
|
|
224
220
|
const pipeline = [
|
|
225
221
|
// Stage 1: Add current timestamp to each document
|
|
@@ -244,7 +240,7 @@ export function ridesPipelineSeenStatus({ filter } = {}) {
|
|
|
244
240
|
$switch: {
|
|
245
241
|
branches: [
|
|
246
242
|
{ case: { $eq: ['$seen_last_at', null] }, then: 'unseen' },
|
|
247
|
-
{ case: { $lte: ['$milliseconds_from_last_seen_to_now',
|
|
243
|
+
{ case: { $lte: ['$milliseconds_from_last_seen_to_now', LAST_SEEN_WINDOW] }, then: 'seen' },
|
|
248
244
|
],
|
|
249
245
|
default: 'gone',
|
|
250
246
|
},
|
|
@@ -261,7 +257,7 @@ export function ridesPipelineSeenStatus({ filter } = {}) {
|
|
|
261
257
|
},
|
|
262
258
|
];
|
|
263
259
|
// Stage 5: Filter by seen status if provided
|
|
264
|
-
if (filter
|
|
260
|
+
if (filter?.seen_status) {
|
|
265
261
|
pipeline.push({ $match: { seen_status: { $in: filter.seen_status } } });
|
|
266
262
|
}
|
|
267
263
|
return pipeline;
|
|
@@ -303,7 +299,16 @@ export function ridesBatchAggregationPipeline({ ...filter }) {
|
|
|
303
299
|
const driverMatch = filter.search.match(/d:([\d,]+)/);
|
|
304
300
|
// Remove v: and d: patterns from search string for ride ID matching
|
|
305
301
|
const searchWithoutSpecialFilters = filter.search.replace(/v:[\d,]+/g, '').replace(/d:[\d,]+/g, '').trim();
|
|
306
|
-
const keywords = searchWithoutSpecialFilters
|
|
302
|
+
const keywords = searchWithoutSpecialFilters
|
|
303
|
+
.split(/\s+/)
|
|
304
|
+
.filter(k => k.length > 0)
|
|
305
|
+
.map((v) => {
|
|
306
|
+
// Escape regex special chars EXCEPT %
|
|
307
|
+
let escaped = v.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
308
|
+
// Convert SQL wildcards to regex
|
|
309
|
+
escaped = escaped.replace(/%%/g, '.*');
|
|
310
|
+
return escaped;
|
|
311
|
+
});
|
|
307
312
|
if (keywords.length > 0) {
|
|
308
313
|
const pattern = keywords.map(k => `(?=.*${k})`).join('') + '.*';
|
|
309
314
|
pipeline.push({
|
|
@@ -322,10 +327,7 @@ export function ridesBatchAggregationPipeline({ ...filter }) {
|
|
|
322
327
|
}
|
|
323
328
|
if (driverMatch) {
|
|
324
329
|
const value = driverMatch[1];
|
|
325
|
-
const driverIDs = value
|
|
326
|
-
.split(',')
|
|
327
|
-
.map(id => id.trim())
|
|
328
|
-
.filter(id => id);
|
|
330
|
+
const driverIDs = value.split(',').map(id => id.trim()).filter(id => id);
|
|
329
331
|
if (driverIDs.length > 0) {
|
|
330
332
|
pipeline.push({ $match: { driver_ids: { $in: driverIDs } } });
|
|
331
333
|
}
|