@tmlmobilidade/controllers 20260505.1315.54 → 20260505.2312.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/operation/hashed-trips/hashed-trips.d.ts +12 -0
- package/dist/operation/hashed-trips/hashed-trips.js +66 -0
- package/dist/operation/hashed-trips/index.d.ts +1 -0
- package/dist/operation/hashed-trips/index.js +1 -0
- package/dist/operation/index.d.ts +4 -0
- package/dist/operation/index.js +4 -0
- package/dist/operation/lines/batch.d.ts +2 -0
- package/dist/operation/lines/batch.js +118 -0
- package/dist/operation/lines/controller.d.ts +12 -0
- package/dist/operation/lines/controller.js +38 -0
- package/dist/operation/lines/index.d.ts +2 -0
- package/dist/operation/lines/index.js +2 -0
- package/dist/{rides → operation/rides}/index.d.ts +1 -0
- package/dist/{rides → operation/rides}/index.js +1 -0
- package/dist/operation/stops/batch.d.ts +2 -0
- package/dist/operation/stops/batch.js +119 -0
- package/dist/operation/stops/controller.d.ts +12 -0
- package/dist/operation/stops/controller.js +38 -0
- package/dist/operation/stops/index.d.ts +2 -0
- package/dist/operation/stops/index.js +2 -0
- package/package.json +2 -1
- /package/dist/{rides → operation/rides}/rides.d.ts +0 -0
- /package/dist/{rides → operation/rides}/rides.js +0 -0
- /package/dist/{rides → operation/rides}/watch.d.ts +0 -0
- /package/dist/{rides → operation/rides}/watch.js +0 -0
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type FastifyReply, type FastifyRequest } from '@tmlmobilidade/fastify';
|
|
2
|
+
import { type ActionsOf, type GetRidesBatchQuery, type HashedTrip, type Permission } from '@tmlmobilidade/types';
|
|
3
|
+
export declare class HashedTripsSharedController {
|
|
4
|
+
/**
|
|
5
|
+
* Gets a batch of HashedTrips built with an aggregation pipeline.
|
|
6
|
+
* @param request The Fastify request object.
|
|
7
|
+
* @param reply The Fastify reply object.
|
|
8
|
+
*/
|
|
9
|
+
static getBatch<S extends Permission['scope']>(request: FastifyRequest<{
|
|
10
|
+
Querystring: GetRidesBatchQuery;
|
|
11
|
+
}>, reply: FastifyReply<HashedTrip[]>, scope: S, action: ActionsOf<S>): Promise<never>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/* * */
|
|
2
|
+
import { HTTP_STATUS } from '@tmlmobilidade/consts';
|
|
3
|
+
import { hashedTrips, rides, ridesBatchAggregationPipeline } from '@tmlmobilidade/interfaces';
|
|
4
|
+
import { Logger } from '@tmlmobilidade/logger';
|
|
5
|
+
import { GetRidesBatchQuerySchema, PermissionCatalog } from '@tmlmobilidade/types';
|
|
6
|
+
/* * */
|
|
7
|
+
export class HashedTripsSharedController {
|
|
8
|
+
//
|
|
9
|
+
/**
|
|
10
|
+
* Gets a batch of HashedTrips built with an aggregation pipeline.
|
|
11
|
+
* @param request The Fastify request object.
|
|
12
|
+
* @param reply The Fastify reply object.
|
|
13
|
+
*/
|
|
14
|
+
static async getBatch(request, reply, scope, action) {
|
|
15
|
+
//
|
|
16
|
+
//
|
|
17
|
+
// Validate the request query parameters
|
|
18
|
+
const parsedQuery = GetRidesBatchQuerySchema.parse(request.query);
|
|
19
|
+
//
|
|
20
|
+
// Detect which agency_ids the user has access to,
|
|
21
|
+
// based on their permissions. If none, return an empty array.
|
|
22
|
+
const ridesPermission = PermissionCatalog.get(request.permissions, scope, action);
|
|
23
|
+
if (!ridesPermission['resources']?.agency_ids?.length)
|
|
24
|
+
return reply.send({ data: [], error: null, statusCode: HTTP_STATUS.OK });
|
|
25
|
+
const allowAllAgencies = ridesPermission['resources'].agency_ids.includes(PermissionCatalog.ALLOW_ALL_FLAG);
|
|
26
|
+
//
|
|
27
|
+
// Get the rides batch using native MongoDB cursor
|
|
28
|
+
// with batchSize to prevent memory issues
|
|
29
|
+
const pipeline = ridesBatchAggregationPipeline({
|
|
30
|
+
acceptance_status: parsedQuery.acceptance_status,
|
|
31
|
+
agency_ids: parsedQuery.agency_ids?.filter(id => allowAllAgencies || ridesPermission['resources'].agency_ids.includes(id)) ?? [],
|
|
32
|
+
analysis_ended_at_last_stop_grade: parsedQuery.analysis_ended_at_last_stop_grade,
|
|
33
|
+
analysis_expected_apex_validation_interval: parsedQuery.analysis_expected_apex_validation_interval,
|
|
34
|
+
analysis_simple_three_vehicle_events_grade: parsedQuery.analysis_simple_three_vehicle_events_grade,
|
|
35
|
+
analysis_transaction_sequentiality: parsedQuery.analysis_transaction_sequentiality,
|
|
36
|
+
date_end: parsedQuery.date_end,
|
|
37
|
+
date_start: parsedQuery.date_start,
|
|
38
|
+
delay_statuses: parsedQuery.delay_statuses,
|
|
39
|
+
line_ids: parsedQuery.line_ids,
|
|
40
|
+
operational_statuses: parsedQuery.operational_statuses,
|
|
41
|
+
search: parsedQuery.search,
|
|
42
|
+
seen_statuses: parsedQuery.seen_statuses,
|
|
43
|
+
stop_ids: parsedQuery.stop_ids,
|
|
44
|
+
});
|
|
45
|
+
//
|
|
46
|
+
// Limit the number of rides to 2000 and sort by start_time_scheduled
|
|
47
|
+
pipeline.push({ $limit: 2000 }, { $project: { hashed_trip_id: 1 } }, { $sort: { start_time_scheduled: 1 } });
|
|
48
|
+
//
|
|
49
|
+
// Fetch the rides batch from the database
|
|
50
|
+
const ridesBatch = await rides.aggregate(pipeline);
|
|
51
|
+
Logger.info(`HashedTripsSharedController.getBatch - ridesBatch count: ${ridesBatch?.length ?? 0}`);
|
|
52
|
+
//
|
|
53
|
+
// From the given batch of hashed_trip_ids,
|
|
54
|
+
// fetch the full HashedTrip documents with a single query.
|
|
55
|
+
const hashedTripIds = ridesBatch.map(ride => ride.hashed_trip_id);
|
|
56
|
+
const hashedTripsBatch = await hashedTrips.findMany({ _id: { $in: hashedTripIds } });
|
|
57
|
+
//
|
|
58
|
+
// Send the response
|
|
59
|
+
reply.send({
|
|
60
|
+
data: hashedTripsBatch ?? [],
|
|
61
|
+
error: null,
|
|
62
|
+
statusCode: HTTP_STATUS.OK,
|
|
63
|
+
});
|
|
64
|
+
//
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './hashed-trips.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './hashed-trips.js';
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/* * */
|
|
2
|
+
import { rides } from '@tmlmobilidade/interfaces';
|
|
3
|
+
import { Logger } from '@tmlmobilidade/logger';
|
|
4
|
+
/* * */
|
|
5
|
+
export async function getOperationalLinesBatch(query) {
|
|
6
|
+
//
|
|
7
|
+
//
|
|
8
|
+
// Use Rides as the baseline to fetch distinct hashed_trip_ids matching the query parameters.
|
|
9
|
+
// Rides are the glue between the different entities (Patterns, Lines, Stops, etc...) that compose an Operation,
|
|
10
|
+
// Stream the rides to build the Operation Lines batch on the fly, avoiding loading everything in memory at once.
|
|
11
|
+
const pipeline = [
|
|
12
|
+
{
|
|
13
|
+
$match: {
|
|
14
|
+
agency_id: { $in: query.agency_ids ?? [] },
|
|
15
|
+
start_time_scheduled: { $gte: query.date_start, $lte: query.date_end },
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
$sort: {
|
|
20
|
+
start_time_scheduled: -1, // newest first
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
$group: {
|
|
25
|
+
_id: '$hashed_trip_id',
|
|
26
|
+
agency_id: { $first: '$agency_id' },
|
|
27
|
+
hashed_trip_id: { $first: '$hashed_trip_id' },
|
|
28
|
+
line_id: { $first: '$line_id' },
|
|
29
|
+
operational_date: { $first: '$operational_date' },
|
|
30
|
+
plan_id: { $first: '$plan_id' },
|
|
31
|
+
start_time_scheduled: { $first: '$start_time_scheduled' },
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
$sort: {
|
|
36
|
+
start_time_scheduled: -1,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
$project: {
|
|
41
|
+
_id: 0,
|
|
42
|
+
agency_id: 1,
|
|
43
|
+
hashed_trip_id: 1,
|
|
44
|
+
line_id: 1,
|
|
45
|
+
operational_date: 1,
|
|
46
|
+
plan_id: 1,
|
|
47
|
+
start_time_scheduled: 1,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
$lookup: {
|
|
52
|
+
as: 'hashed_trip_doc',
|
|
53
|
+
foreignField: '_id',
|
|
54
|
+
from: 'hashed_trips',
|
|
55
|
+
localField: 'hashed_trip_id',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
$unwind: {
|
|
60
|
+
path: '$hashed_trip_doc',
|
|
61
|
+
preserveNullAndEmptyArrays: true,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
$sort: {
|
|
66
|
+
start_time_scheduled: -1,
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
$project: {
|
|
71
|
+
_id: 0,
|
|
72
|
+
agency_id: 1,
|
|
73
|
+
hashed_trip_doc: 1, // full joined document
|
|
74
|
+
operational_date: 1,
|
|
75
|
+
plan_id: 1,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
const ridesCollection = await rides.getCollection();
|
|
80
|
+
const pipelineResult = await ridesCollection
|
|
81
|
+
.aggregate(pipeline)
|
|
82
|
+
.toArray();
|
|
83
|
+
Logger.info(`OperationalLinesController.getBatch - pipeline result count: ${pipelineResult?.length ?? 0}`);
|
|
84
|
+
//
|
|
85
|
+
// Setup the final Map to keep track of the Operation Lines,
|
|
86
|
+
// using the line_id as the key to avoid duplicates,
|
|
87
|
+
// since multiple hashed_trip_ids can belong to the same line_id.
|
|
88
|
+
const operationalLinesMap = new Map();
|
|
89
|
+
pipelineResult.forEach((item) => {
|
|
90
|
+
// Initialize the line in the map if it doesn't exist yet
|
|
91
|
+
if (!operationalLinesMap.has(item.hashed_trip_doc.line_id)) {
|
|
92
|
+
operationalLinesMap.set(item.hashed_trip_doc.line_id, {
|
|
93
|
+
agency_id: item.agency_id,
|
|
94
|
+
hashed_trips: [],
|
|
95
|
+
last_operational_date: item.operational_date,
|
|
96
|
+
last_plan_id: item.plan_id,
|
|
97
|
+
line_id: item.hashed_trip_doc.line_id,
|
|
98
|
+
line_long_name: item.hashed_trip_doc.line_long_name,
|
|
99
|
+
line_short_name: item.hashed_trip_doc.line_short_name,
|
|
100
|
+
pattern_ids: [],
|
|
101
|
+
route_color: item.hashed_trip_doc.route_color,
|
|
102
|
+
route_ids: [],
|
|
103
|
+
stop_ids: [],
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
// Get the saved line from the map
|
|
107
|
+
const savedOperationalLine = operationalLinesMap.get(item.hashed_trip_doc.line_id);
|
|
108
|
+
// Update the object with the latest fields
|
|
109
|
+
savedOperationalLine.route_ids = Array.from(new Set([...savedOperationalLine.route_ids, item.hashed_trip_doc.route_id]));
|
|
110
|
+
savedOperationalLine.pattern_ids = Array.from(new Set([...savedOperationalLine.pattern_ids, item.hashed_trip_doc.pattern_id]));
|
|
111
|
+
savedOperationalLine.stop_ids = Array.from(new Set([...savedOperationalLine.stop_ids, ...(item.hashed_trip_doc.path.map(stop => stop.stop_id) ?? [])]));
|
|
112
|
+
savedOperationalLine.hashed_trips.push(item.hashed_trip_doc);
|
|
113
|
+
});
|
|
114
|
+
//
|
|
115
|
+
// Send the response
|
|
116
|
+
return Array.from(operationalLinesMap.values());
|
|
117
|
+
//
|
|
118
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type FastifyReply, type FastifyRequest } from '@tmlmobilidade/fastify';
|
|
2
|
+
import { type ActionsOf, type GetOperationalLinesBatchQuery, type OperationalLine, type Permission } from '@tmlmobilidade/types';
|
|
3
|
+
export declare class OperationalLinesSharedController {
|
|
4
|
+
/**
|
|
5
|
+
* Gets a batch of Operation Lines built with an aggregation pipeline.
|
|
6
|
+
* @param request The Fastify request object.
|
|
7
|
+
* @param reply The Fastify reply object.
|
|
8
|
+
*/
|
|
9
|
+
static getBatch<S extends Permission['scope']>(request: FastifyRequest<{
|
|
10
|
+
Querystring: GetOperationalLinesBatchQuery;
|
|
11
|
+
}>, reply: FastifyReply<OperationalLine[]>, scope: S, action: ActionsOf<S>): Promise<never>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/* * */
|
|
2
|
+
import { getOperationalLinesBatch } from './batch.js';
|
|
3
|
+
import { HTTP_STATUS } from '@tmlmobilidade/consts';
|
|
4
|
+
import { GetOperationalLinesBatchQuerySchema, PermissionCatalog } from '@tmlmobilidade/types';
|
|
5
|
+
/* * */
|
|
6
|
+
export class OperationalLinesSharedController {
|
|
7
|
+
//
|
|
8
|
+
/**
|
|
9
|
+
* Gets a batch of Operation Lines built with an aggregation pipeline.
|
|
10
|
+
* @param request The Fastify request object.
|
|
11
|
+
* @param reply The Fastify reply object.
|
|
12
|
+
*/
|
|
13
|
+
static async getBatch(request, reply, scope, action) {
|
|
14
|
+
//
|
|
15
|
+
const parsedQuery = GetOperationalLinesBatchQuerySchema.parse(request.query);
|
|
16
|
+
//
|
|
17
|
+
// Detect which agency_ids the user has access to,
|
|
18
|
+
// based on their permissions. If none, return an empty array.
|
|
19
|
+
const ridesPermission = PermissionCatalog.get(request.permissions, scope, action);
|
|
20
|
+
if (!ridesPermission['resources']?.agency_ids?.length)
|
|
21
|
+
return reply.send({ data: [], error: null, statusCode: HTTP_STATUS.OK });
|
|
22
|
+
const allowAllAgencies = ridesPermission['resources'].agency_ids.includes(PermissionCatalog.ALLOW_ALL_FLAG);
|
|
23
|
+
//
|
|
24
|
+
// Run the query
|
|
25
|
+
const result = await getOperationalLinesBatch({
|
|
26
|
+
...parsedQuery,
|
|
27
|
+
agency_ids: parsedQuery.agency_ids?.filter(id => allowAllAgencies || ridesPermission['resources'].agency_ids.includes(id)) ?? [],
|
|
28
|
+
});
|
|
29
|
+
//
|
|
30
|
+
// Send the response
|
|
31
|
+
reply.send({
|
|
32
|
+
data: result,
|
|
33
|
+
error: null,
|
|
34
|
+
statusCode: HTTP_STATUS.OK,
|
|
35
|
+
});
|
|
36
|
+
//
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/* * */
|
|
2
|
+
import { rides } from '@tmlmobilidade/interfaces';
|
|
3
|
+
import { Logger } from '@tmlmobilidade/logger';
|
|
4
|
+
/* * */
|
|
5
|
+
export async function getOperationalStopsBatch(query) {
|
|
6
|
+
//
|
|
7
|
+
//
|
|
8
|
+
// Use Rides as the baseline to fetch distinct hashed_trip_ids matching the query parameters.
|
|
9
|
+
// Rides are the glue between the different entities (Patterns, Lines, Stops, etc...) that compose an Operation,
|
|
10
|
+
// Stream the rides to build the Operation Stops batch on the fly, avoiding loading everything in memory at once.
|
|
11
|
+
const pipeline = [
|
|
12
|
+
{
|
|
13
|
+
$match: {
|
|
14
|
+
agency_id: { $in: query.agency_ids ?? [] },
|
|
15
|
+
start_time_scheduled: { $gte: query.date_start, $lte: query.date_end },
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
$sort: {
|
|
20
|
+
start_time_scheduled: -1, // newest first
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
$group: {
|
|
25
|
+
_id: '$hashed_trip_id',
|
|
26
|
+
agency_id: { $first: '$agency_id' },
|
|
27
|
+
hashed_trip_id: { $first: '$hashed_trip_id' },
|
|
28
|
+
line_id: { $first: '$line_id' },
|
|
29
|
+
operational_date: { $first: '$operational_date' },
|
|
30
|
+
plan_id: { $first: '$plan_id' },
|
|
31
|
+
start_time_scheduled: { $first: '$start_time_scheduled' },
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
$sort: {
|
|
36
|
+
start_time_scheduled: -1,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
$project: {
|
|
41
|
+
_id: 0,
|
|
42
|
+
agency_id: 1,
|
|
43
|
+
hashed_trip_id: 1,
|
|
44
|
+
line_id: 1,
|
|
45
|
+
operational_date: 1,
|
|
46
|
+
plan_id: 1,
|
|
47
|
+
start_time_scheduled: 1,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
$lookup: {
|
|
52
|
+
as: 'hashed_trip_doc',
|
|
53
|
+
foreignField: '_id',
|
|
54
|
+
from: 'hashed_trips',
|
|
55
|
+
localField: 'hashed_trip_id',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
$unwind: {
|
|
60
|
+
path: '$hashed_trip_doc',
|
|
61
|
+
preserveNullAndEmptyArrays: true,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
$sort: {
|
|
66
|
+
start_time_scheduled: -1,
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
$project: {
|
|
71
|
+
_id: 0,
|
|
72
|
+
agency_id: 1,
|
|
73
|
+
hashed_trip_doc: 1, // full joined document
|
|
74
|
+
operational_date: 1,
|
|
75
|
+
plan_id: 1,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
const ridesCollection = await rides.getCollection();
|
|
80
|
+
const pipelineResult = await ridesCollection
|
|
81
|
+
.aggregate(pipeline)
|
|
82
|
+
.toArray();
|
|
83
|
+
Logger.info(`OperationalStopsController.getBatch - pipeline result count: ${pipelineResult?.length ?? 0}`);
|
|
84
|
+
//
|
|
85
|
+
// Setup the final Map to keep track of the Operation Stops,
|
|
86
|
+
// using the stop_id as the key to avoid duplicates,
|
|
87
|
+
// since multiple hashed_trip_ids can belong to the same stop_id.
|
|
88
|
+
const operationalStopsMap = new Map();
|
|
89
|
+
pipelineResult.forEach((item) => {
|
|
90
|
+
item.hashed_trip_doc.path.forEach((waypoint) => {
|
|
91
|
+
// Initialize the stop in the map if it doesn't exist yet
|
|
92
|
+
if (!operationalStopsMap.has(waypoint.stop_id)) {
|
|
93
|
+
operationalStopsMap.set(waypoint.stop_id, {
|
|
94
|
+
agency_ids: [],
|
|
95
|
+
hashed_trips: [],
|
|
96
|
+
last_operational_date: item.operational_date,
|
|
97
|
+
last_plan_id: item.plan_id,
|
|
98
|
+
line_ids: [],
|
|
99
|
+
pattern_ids: [],
|
|
100
|
+
route_ids: [],
|
|
101
|
+
stop_id: waypoint.stop_id,
|
|
102
|
+
stop_name: waypoint.stop_name,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
// Get the saved stop from the map
|
|
106
|
+
const savedOperationalStop = operationalStopsMap.get(waypoint.stop_id);
|
|
107
|
+
// Update the object with the latest fields
|
|
108
|
+
savedOperationalStop.agency_ids = Array.from(new Set([...savedOperationalStop.agency_ids, item.agency_id]));
|
|
109
|
+
savedOperationalStop.line_ids = Array.from(new Set([...savedOperationalStop.line_ids, item.hashed_trip_doc.line_id]));
|
|
110
|
+
savedOperationalStop.route_ids = Array.from(new Set([...savedOperationalStop.route_ids, item.hashed_trip_doc.route_id]));
|
|
111
|
+
savedOperationalStop.pattern_ids = Array.from(new Set([...savedOperationalStop.pattern_ids, item.hashed_trip_doc.pattern_id]));
|
|
112
|
+
savedOperationalStop.hashed_trips.push(item.hashed_trip_doc);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
//
|
|
116
|
+
// Send the response
|
|
117
|
+
return Array.from(operationalStopsMap.values());
|
|
118
|
+
//
|
|
119
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type FastifyReply, type FastifyRequest } from '@tmlmobilidade/fastify';
|
|
2
|
+
import { type ActionsOf, type GetOperationalStopsBatchQuery, type OperationalStop, type Permission } from '@tmlmobilidade/types';
|
|
3
|
+
export declare class OperationalStopsSharedController {
|
|
4
|
+
/**
|
|
5
|
+
* Gets a batch of Operational Stops built with an aggregation pipeline.
|
|
6
|
+
* @param request The Fastify request object.
|
|
7
|
+
* @param reply The Fastify reply object.
|
|
8
|
+
*/
|
|
9
|
+
static getBatch<S extends Permission['scope']>(request: FastifyRequest<{
|
|
10
|
+
Querystring: GetOperationalStopsBatchQuery;
|
|
11
|
+
}>, reply: FastifyReply<OperationalStop[]>, scope: S, action: ActionsOf<S>): Promise<never>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/* * */
|
|
2
|
+
import { getOperationalStopsBatch } from './batch.js';
|
|
3
|
+
import { HTTP_STATUS } from '@tmlmobilidade/consts';
|
|
4
|
+
import { GetOperationalStopsBatchQuerySchema, PermissionCatalog } from '@tmlmobilidade/types';
|
|
5
|
+
/* * */
|
|
6
|
+
export class OperationalStopsSharedController {
|
|
7
|
+
//
|
|
8
|
+
/**
|
|
9
|
+
* Gets a batch of Operational Stops built with an aggregation pipeline.
|
|
10
|
+
* @param request The Fastify request object.
|
|
11
|
+
* @param reply The Fastify reply object.
|
|
12
|
+
*/
|
|
13
|
+
static async getBatch(request, reply, scope, action) {
|
|
14
|
+
//
|
|
15
|
+
const parsedQuery = GetOperationalStopsBatchQuerySchema.parse(request.query);
|
|
16
|
+
//
|
|
17
|
+
// Detect which agency_ids the user has access to,
|
|
18
|
+
// based on their permissions. If none, return an empty array.
|
|
19
|
+
const ridesPermission = PermissionCatalog.get(request.permissions, scope, action);
|
|
20
|
+
if (!ridesPermission['resources']?.agency_ids?.length)
|
|
21
|
+
return reply.send({ data: [], error: null, statusCode: HTTP_STATUS.OK });
|
|
22
|
+
const allowAllAgencies = ridesPermission['resources'].agency_ids.includes(PermissionCatalog.ALLOW_ALL_FLAG);
|
|
23
|
+
//
|
|
24
|
+
// Run the query
|
|
25
|
+
const result = await getOperationalStopsBatch({
|
|
26
|
+
...parsedQuery,
|
|
27
|
+
agency_ids: parsedQuery.agency_ids?.filter(id => allowAllAgencies || ridesPermission['resources'].agency_ids.includes(id)) ?? [],
|
|
28
|
+
});
|
|
29
|
+
//
|
|
30
|
+
// Send the response
|
|
31
|
+
reply.send({
|
|
32
|
+
data: result,
|
|
33
|
+
error: null,
|
|
34
|
+
statusCode: HTTP_STATUS.OK,
|
|
35
|
+
});
|
|
36
|
+
//
|
|
37
|
+
}
|
|
38
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tmlmobilidade/controllers",
|
|
3
|
-
"version": "20260505.
|
|
3
|
+
"version": "20260505.2312.1",
|
|
4
4
|
"author": {
|
|
5
5
|
"email": "iso@tmlmobilidade.pt",
|
|
6
6
|
"name": "TML-ISO"
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"@tmlmobilidade/consts": "*",
|
|
40
40
|
"@tmlmobilidade/fastify": "*",
|
|
41
41
|
"@tmlmobilidade/interfaces": "*",
|
|
42
|
+
"@tmlmobilidade/logger": "*",
|
|
42
43
|
"@tmlmobilidade/normalizers": "*",
|
|
43
44
|
"@tmlmobilidade/utils": "*"
|
|
44
45
|
},
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|