@tmlmobilidade/export-data 20260121.2332.4 → 20260123.1211.24
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.js +11 -28
- package/dist/prompts/export-types.js +1 -5
- package/dist/prompts/validation-group-fields.d.ts +2 -0
- package/dist/prompts/validation-group-fields.js +22 -0
- package/dist/tasks/apex-validations/validations-aggregated.d.ts +18 -0
- package/dist/tasks/apex-validations/{validations-by-stop-by-pattern.js → validations-aggregated.js} +48 -12
- package/dist/types.d.ts +1 -5
- package/dist/types.js +1 -5
- package/package.json +1 -1
- package/dist/tasks/apex-validations/validations-by-line.d.ts +0 -2
- package/dist/tasks/apex-validations/validations-by-line.js +0 -85
- package/dist/tasks/apex-validations/validations-by-pattern.d.ts +0 -5
- package/dist/tasks/apex-validations/validations-by-pattern.js +0 -87
- package/dist/tasks/apex-validations/validations-by-stop-by-pattern.d.ts +0 -5
- package/dist/tasks/apex-validations/validations-by-stop-by-trip.d.ts +0 -5
- package/dist/tasks/apex-validations/validations-by-stop-by-trip.js +0 -88
- package/dist/tasks/apex-validations/validations-by-stop.d.ts +0 -5
- package/dist/tasks/apex-validations/validations-by-stop.js +0 -87
package/dist/index.js
CHANGED
|
@@ -9,11 +9,8 @@ import { promptFilterByStopIds } from './prompts/filter-stop-ids.js';
|
|
|
9
9
|
import { promptFilterTypes } from './prompts/filter-types.js';
|
|
10
10
|
import { promptFilterByVehicleIds } from './prompts/filter-vehicle-ids.js';
|
|
11
11
|
import { promptHashedShapeIds } from './prompts/hashedshape-ids.js';
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { exportValidationsByStopByPattern } from './tasks/apex-validations/validations-by-stop-by-pattern.js';
|
|
15
|
-
import { exportValidationsByStopByTrip } from './tasks/apex-validations/validations-by-stop-by-trip.js';
|
|
16
|
-
import { exportValidationsByStop } from './tasks/apex-validations/validations-by-stop.js';
|
|
12
|
+
import { promptValidationGroupFields } from './prompts/validation-group-fields.js';
|
|
13
|
+
import { exportValidationsAggregated } from './tasks/apex-validations/validations-aggregated.js';
|
|
17
14
|
import { exportValidationsRaw } from './tasks/apex-validations/validations-raw.js';
|
|
18
15
|
import { exportHashedShapesGeoJSON } from './tasks/hashed-shapes/hashed-shapes-geojson.js';
|
|
19
16
|
import { exportRidesRaw } from './tasks/rides/rides-raw.js';
|
|
@@ -53,6 +50,12 @@ import { ASCII_CM_SHORT } from '@tmlmobilidade/consts';
|
|
|
53
50
|
hashedShapeIds = await promptHashedShapeIds();
|
|
54
51
|
}
|
|
55
52
|
//
|
|
53
|
+
// For validations-aggregated export, prompt for group fields
|
|
54
|
+
let validationGroupFields = [];
|
|
55
|
+
if (exportTypes.includes('validations-aggregated')) {
|
|
56
|
+
validationGroupFields = await promptValidationGroupFields();
|
|
57
|
+
}
|
|
58
|
+
//
|
|
56
59
|
// Skip filters and dates if all selected export types don't require them
|
|
57
60
|
if (!shouldSkipFilters) {
|
|
58
61
|
const filterTypes = await promptFilterTypes();
|
|
@@ -79,29 +82,9 @@ import { ASCII_CM_SHORT } from '@tmlmobilidade/consts';
|
|
|
79
82
|
title: exportTypeLabels['validations-raw'],
|
|
80
83
|
},
|
|
81
84
|
{
|
|
82
|
-
enabled: exportTypes.includes('validations-
|
|
83
|
-
task: async (message) => await
|
|
84
|
-
title: exportTypeLabels['validations-
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
enabled: exportTypes.includes('validations-by-stop-by-pattern'),
|
|
88
|
-
task: async (message) => await exportValidationsByStopByPattern({ context, message }),
|
|
89
|
-
title: exportTypeLabels['validations-by-stop-by-pattern'],
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
enabled: exportTypes.includes('validations-by-stop'),
|
|
93
|
-
task: async (message) => await exportValidationsByStop({ context, message }),
|
|
94
|
-
title: exportTypeLabels['validations-by-stop'],
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
enabled: exportTypes.includes('validations-by-pattern'),
|
|
98
|
-
task: async (message) => await exportValidationsByPattern({ context, message }),
|
|
99
|
-
title: exportTypeLabels['validations-by-pattern'],
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
enabled: exportTypes.includes('validations-by-line'),
|
|
103
|
-
task: async (message) => await exportValidationsByLine({ context, message }),
|
|
104
|
-
title: exportTypeLabels['validations-by-line'],
|
|
85
|
+
enabled: exportTypes.includes('validations-aggregated'),
|
|
86
|
+
task: async (message) => await exportValidationsAggregated({ context, groupFields: validationGroupFields, message }),
|
|
87
|
+
title: exportTypeLabels['validations-aggregated'],
|
|
105
88
|
},
|
|
106
89
|
{
|
|
107
90
|
enabled: exportTypes.includes('rides-raw'),
|
|
@@ -9,11 +9,7 @@ export async function promptExportTypes() {
|
|
|
9
9
|
options: {
|
|
10
10
|
'1. Validações APEX': [
|
|
11
11
|
{ label: exportTypeLabels['validations-raw'], value: 'validations-raw' },
|
|
12
|
-
{ label: exportTypeLabels['validations-
|
|
13
|
-
{ label: exportTypeLabels['validations-by-stop-by-pattern'], value: 'validations-by-stop-by-pattern' },
|
|
14
|
-
{ label: exportTypeLabels['validations-by-stop'], value: 'validations-by-stop' },
|
|
15
|
-
{ label: exportTypeLabels['validations-by-pattern'], value: 'validations-by-pattern' },
|
|
16
|
-
{ label: exportTypeLabels['validations-by-line'], value: 'validations-by-line' },
|
|
12
|
+
{ label: exportTypeLabels['validations-aggregated'], value: 'validations-aggregated' },
|
|
17
13
|
],
|
|
18
14
|
'2. Rides': [
|
|
19
15
|
{ label: exportTypeLabels['rides-raw'], value: 'rides-raw' },
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/* * */
|
|
2
|
+
import { validationGroupFieldLabels, validationGroupFields } from '../tasks/apex-validations/validations-aggregated.js';
|
|
3
|
+
import { cancel, isCancel, multiselect } from '@clack/prompts';
|
|
4
|
+
/* * */
|
|
5
|
+
export async function promptValidationGroupFields() {
|
|
6
|
+
//
|
|
7
|
+
const values = await multiselect({
|
|
8
|
+
message: 'Escolhe os campos para agrupar as validações (a data é sempre incluída):',
|
|
9
|
+
options: validationGroupFields.map(field => ({
|
|
10
|
+
label: validationGroupFieldLabels[field],
|
|
11
|
+
value: field,
|
|
12
|
+
})),
|
|
13
|
+
required: true,
|
|
14
|
+
});
|
|
15
|
+
if (isCancel(values)) {
|
|
16
|
+
cancel('Operação cancelada pelo utilizador.');
|
|
17
|
+
process.exit(0);
|
|
18
|
+
}
|
|
19
|
+
if (!values)
|
|
20
|
+
return [];
|
|
21
|
+
return values;
|
|
22
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type TaskProps } from '../../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Available fields for grouping validations.
|
|
4
|
+
* 'date' is always included by default.
|
|
5
|
+
*/
|
|
6
|
+
export declare const validationGroupFields: readonly ["line_id", "pattern_id", "product_id", "trip_id", "stop_id", "agency_id", "vehicle_id"];
|
|
7
|
+
export type ValidationGroupField = typeof validationGroupFields[number];
|
|
8
|
+
export declare const validationGroupFieldLabels: Record<ValidationGroupField, string>;
|
|
9
|
+
interface ValidationAggregatedTaskProps extends TaskProps {
|
|
10
|
+
groupFields: ValidationGroupField[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Export Validations aggregated by user-selected fields.
|
|
14
|
+
* Always groups by date, plus any additional fields selected by the user.
|
|
15
|
+
* The 'validations' count is always included.
|
|
16
|
+
*/
|
|
17
|
+
export declare function exportValidationsAggregated({ context, groupFields, message }: ValidationAggregatedTaskProps): Promise<void>;
|
|
18
|
+
export {};
|
package/dist/tasks/apex-validations/{validations-by-stop-by-pattern.js → validations-aggregated.js}
RENAMED
|
@@ -4,13 +4,30 @@ import { simplifiedApexValidations } from '@tmlmobilidade/interfaces';
|
|
|
4
4
|
import { CsvWriter } from '@tmlmobilidade/writers';
|
|
5
5
|
import fs from 'node:fs';
|
|
6
6
|
/* * */
|
|
7
|
-
const TASK_ID = 'validations-by-stop-by-pattern';
|
|
8
7
|
/**
|
|
9
|
-
*
|
|
8
|
+
* Available fields for grouping validations.
|
|
9
|
+
* 'date' is always included by default.
|
|
10
10
|
*/
|
|
11
|
-
export
|
|
11
|
+
export const validationGroupFields = ['line_id', 'pattern_id', 'product_id', 'trip_id', 'stop_id', 'agency_id', 'vehicle_id'];
|
|
12
|
+
export const validationGroupFieldLabels = {
|
|
13
|
+
agency_id: 'Operador (agency_id)',
|
|
14
|
+
line_id: 'Linha (line_id)',
|
|
15
|
+
pattern_id: 'Pattern (pattern_id)',
|
|
16
|
+
product_id: 'Tipo de passe (product_id)',
|
|
17
|
+
stop_id: 'Paragem (stop_id)',
|
|
18
|
+
trip_id: 'Viagem (trip_id)',
|
|
19
|
+
vehicle_id: 'Veículo (vehicle_id)',
|
|
20
|
+
};
|
|
21
|
+
/* * */
|
|
22
|
+
/**
|
|
23
|
+
* Export Validations aggregated by user-selected fields.
|
|
24
|
+
* Always groups by date, plus any additional fields selected by the user.
|
|
25
|
+
* The 'validations' count is always included.
|
|
26
|
+
*/
|
|
27
|
+
export async function exportValidationsAggregated({ context, groupFields, message }) {
|
|
12
28
|
//
|
|
13
|
-
|
|
29
|
+
const fieldsList = ['date', ...groupFields].join(', ');
|
|
30
|
+
message(`A iniciar a exportação de Validações APEX agrupadas por: ${fieldsList}...`);
|
|
14
31
|
//
|
|
15
32
|
// Prepare the filter params
|
|
16
33
|
const filterQuery = {
|
|
@@ -51,7 +68,9 @@ export async function exportValidationsByStopByPattern({ context, message }) {
|
|
|
51
68
|
message(`A preparar a pasta para guardar os resultados...`);
|
|
52
69
|
if (!fs.existsSync(context.output))
|
|
53
70
|
fs.mkdirSync(context.output, { recursive: true });
|
|
54
|
-
|
|
71
|
+
// Build filename based on selected fields
|
|
72
|
+
const fieldsSlug = groupFields.length > 0 ? `by-${groupFields.join('-')}` : 'by-date';
|
|
73
|
+
const csvWriter = new CsvWriter('output', `${context.output}/validations-${fieldsSlug}-${context.dates.start}-${context.dates.end}.csv`, { batch_size: 100000, logs: false });
|
|
55
74
|
//
|
|
56
75
|
// Export the data
|
|
57
76
|
let counter = 0;
|
|
@@ -64,25 +83,42 @@ export async function exportValidationsByStopByPattern({ context, message }) {
|
|
|
64
83
|
const operationalDate = Dates
|
|
65
84
|
.fromUnixTimestamp(document.created_at)
|
|
66
85
|
.operational_date;
|
|
67
|
-
|
|
86
|
+
// Build the key from date + all selected group fields
|
|
87
|
+
const keyParts = [operationalDate, ...groupFields.map(field => String(document[field]))];
|
|
88
|
+
const resultKey = keyParts.join(':');
|
|
68
89
|
//
|
|
69
90
|
// Update the result with the current document
|
|
70
91
|
if (!result[resultKey]) {
|
|
71
|
-
result
|
|
92
|
+
// Initialize the result object with date first, then selected fields in order
|
|
93
|
+
const resultObj = {
|
|
72
94
|
date: operationalDate,
|
|
73
|
-
pattern_id: document.pattern_id,
|
|
74
|
-
stop_id: document.stop_id,
|
|
75
|
-
validations: 0,
|
|
76
95
|
};
|
|
96
|
+
// Add each selected group field
|
|
97
|
+
for (const field of groupFields) {
|
|
98
|
+
resultObj[field] = document[field];
|
|
99
|
+
}
|
|
100
|
+
// Always add validations count at the end
|
|
101
|
+
resultObj.validations = 0;
|
|
102
|
+
result[resultKey] = resultObj;
|
|
77
103
|
}
|
|
78
|
-
result[resultKey].validations
|
|
104
|
+
result[resultKey].validations = result[resultKey].validations + 1;
|
|
79
105
|
if (counter % 1000 === 0)
|
|
80
106
|
message(`Processados ${counter} documentos até agora...`);
|
|
81
107
|
counter++;
|
|
82
108
|
//
|
|
83
109
|
}
|
|
84
110
|
message(`A escrever os resultados no ficheiro CSV...`);
|
|
85
|
-
|
|
111
|
+
// Write results in batches to avoid stack overflow with large datasets
|
|
112
|
+
const WRITE_BATCH_SIZE = 10000;
|
|
113
|
+
const resultKeys = Object.keys(result);
|
|
114
|
+
const totalResults = resultKeys.length;
|
|
115
|
+
for (let i = 0; i < totalResults; i += WRITE_BATCH_SIZE) {
|
|
116
|
+
const batch = resultKeys.slice(i, i + WRITE_BATCH_SIZE).map(key => result[key]);
|
|
117
|
+
await csvWriter.write(batch);
|
|
118
|
+
if (i % 50000 === 0 && i > 0) {
|
|
119
|
+
message(`Escritos ${i} de ${totalResults} resultados...`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
86
122
|
await csvWriter.flush();
|
|
87
123
|
//
|
|
88
124
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -3,11 +3,7 @@ export declare const exportTypeLabels: {
|
|
|
3
3
|
readonly 'hashed-shapes-geojson': "4.0. HashedShapes para GeoJSON";
|
|
4
4
|
readonly 'rides-raw': "2.0. Rides em bruto (SLAs)";
|
|
5
5
|
readonly 'sams-raw': "5.0. SAMs em bruto (Sequencialidade)";
|
|
6
|
-
readonly 'validations-
|
|
7
|
-
readonly 'validations-by-pattern': "1.4. Validações por Pattern ID";
|
|
8
|
-
readonly 'validations-by-stop': "1.3. Validações por Stop ID";
|
|
9
|
-
readonly 'validations-by-stop-by-pattern': "1.2. Validações por Stop ID, por Pattern ID";
|
|
10
|
-
readonly 'validations-by-stop-by-trip': "1.1. Validações por Stop ID, por Trip ID";
|
|
6
|
+
readonly 'validations-aggregated': "1.1. Validações agregadas (escolher campos)";
|
|
11
7
|
readonly 'validations-raw': "1.0. Validações em bruto";
|
|
12
8
|
readonly 'vehicle-events-raw': "3.0. Vehicle Events em bruto";
|
|
13
9
|
};
|
package/dist/types.js
CHANGED
|
@@ -4,11 +4,7 @@ export const exportTypeLabels = {
|
|
|
4
4
|
'hashed-shapes-geojson': '4.0. HashedShapes para GeoJSON',
|
|
5
5
|
'rides-raw': '2.0. Rides em bruto (SLAs)',
|
|
6
6
|
'sams-raw': '5.0. SAMs em bruto (Sequencialidade)',
|
|
7
|
-
'validations-
|
|
8
|
-
'validations-by-pattern': '1.4. Validações por Pattern ID',
|
|
9
|
-
'validations-by-stop': '1.3. Validações por Stop ID',
|
|
10
|
-
'validations-by-stop-by-pattern': '1.2. Validações por Stop ID, por Pattern ID',
|
|
11
|
-
'validations-by-stop-by-trip': '1.1. Validações por Stop ID, por Trip ID',
|
|
7
|
+
'validations-aggregated': '1.1. Validações agregadas (escolher campos)',
|
|
12
8
|
'validations-raw': '1.0. Validações em bruto',
|
|
13
9
|
'vehicle-events-raw': '3.0. Vehicle Events em bruto',
|
|
14
10
|
};
|
package/package.json
CHANGED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
/* * */
|
|
2
|
-
import { Dates } from '@tmlmobilidade/dates';
|
|
3
|
-
import { simplifiedApexValidations } from '@tmlmobilidade/interfaces';
|
|
4
|
-
import { CsvWriter } from '@tmlmobilidade/writers';
|
|
5
|
-
import fs from 'node:fs';
|
|
6
|
-
/* * */
|
|
7
|
-
const TASK_ID = 'validations-by-line';
|
|
8
|
-
/* * */
|
|
9
|
-
export async function exportValidationsByLine({ context, message }) {
|
|
10
|
-
//
|
|
11
|
-
message('A iniciar a exportação de Validações APEX por Linha...');
|
|
12
|
-
//
|
|
13
|
-
// Prepare the filter params
|
|
14
|
-
const filterQuery = {
|
|
15
|
-
is_passenger: true,
|
|
16
|
-
};
|
|
17
|
-
filterQuery.created_at = {
|
|
18
|
-
$gte: Dates
|
|
19
|
-
.fromOperationalDate(context.dates.start, 'Europe/Lisbon')
|
|
20
|
-
.set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
|
|
21
|
-
.unix_timestamp,
|
|
22
|
-
$lt: Dates
|
|
23
|
-
.fromOperationalDate(context.dates.end, 'Europe/Lisbon')
|
|
24
|
-
.set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
|
|
25
|
-
.unix_timestamp,
|
|
26
|
-
};
|
|
27
|
-
if (context.filters.agency_ids.length) {
|
|
28
|
-
filterQuery.agency_id = { $in: context.filters.agency_ids };
|
|
29
|
-
}
|
|
30
|
-
if (context.filters.line_ids.length) {
|
|
31
|
-
filterQuery.line_id = { $in: context.filters.line_ids };
|
|
32
|
-
}
|
|
33
|
-
if (context.filters.pattern_ids.length) {
|
|
34
|
-
filterQuery.pattern_id = { $in: context.filters.pattern_ids };
|
|
35
|
-
}
|
|
36
|
-
if (context.filters.stop_ids.length) {
|
|
37
|
-
filterQuery.stop_id = { $in: context.filters.stop_ids };
|
|
38
|
-
}
|
|
39
|
-
if (context.filters.vehicle_ids.length) {
|
|
40
|
-
filterQuery.vehicle_id = { $in: context.filters.vehicle_ids };
|
|
41
|
-
}
|
|
42
|
-
//
|
|
43
|
-
// Setup a database stream to export data
|
|
44
|
-
message(`A iniciar ligação à base de dados...`);
|
|
45
|
-
const simplifiedApexValidationsCollection = await simplifiedApexValidations.getCollection();
|
|
46
|
-
const stream = simplifiedApexValidationsCollection.find(filterQuery).stream();
|
|
47
|
-
//
|
|
48
|
-
// Prepare the output directory and CSV writer
|
|
49
|
-
message(`A preparar a pasta para guardar os resultados...`);
|
|
50
|
-
if (!fs.existsSync(context.output))
|
|
51
|
-
fs.mkdirSync(context.output, { recursive: true });
|
|
52
|
-
const csvWriter = new CsvWriter('output', `${context.output}/${TASK_ID}-${context.dates.start}-${context.dates.end}.csv`, { batch_size: 100000, logs: false });
|
|
53
|
-
//
|
|
54
|
-
// Export the data
|
|
55
|
-
let counter = 0;
|
|
56
|
-
message(`A aguardar o resultado da pesquisa...`);
|
|
57
|
-
const result = {};
|
|
58
|
-
for await (const doc of stream) {
|
|
59
|
-
const document = doc;
|
|
60
|
-
//
|
|
61
|
-
// Prepare the result key
|
|
62
|
-
const operationalDate = Dates
|
|
63
|
-
.fromUnixTimestamp(document.created_at)
|
|
64
|
-
.operational_date;
|
|
65
|
-
const resultKey = `${operationalDate}:${document.line_id}`;
|
|
66
|
-
//
|
|
67
|
-
// Update the result with the current document
|
|
68
|
-
if (!result[resultKey]) {
|
|
69
|
-
result[resultKey] = {
|
|
70
|
-
date: operationalDate,
|
|
71
|
-
line_id: document.line_id,
|
|
72
|
-
validations: 0,
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
result[resultKey].validations += 1;
|
|
76
|
-
if (counter % 1000 === 0)
|
|
77
|
-
message(`Processados ${counter} documentos até agora...`);
|
|
78
|
-
counter++;
|
|
79
|
-
//
|
|
80
|
-
}
|
|
81
|
-
message(`A escrever os resultados no ficheiro CSV...`);
|
|
82
|
-
await csvWriter.write(Object.values(result));
|
|
83
|
-
await csvWriter.flush();
|
|
84
|
-
//
|
|
85
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/* * */
|
|
2
|
-
import { Dates } from '@tmlmobilidade/dates';
|
|
3
|
-
import { simplifiedApexValidations } from '@tmlmobilidade/interfaces';
|
|
4
|
-
import { CsvWriter } from '@tmlmobilidade/writers';
|
|
5
|
-
import fs from 'node:fs';
|
|
6
|
-
/* * */
|
|
7
|
-
const TASK_ID = 'validations-by-pattern';
|
|
8
|
-
/**
|
|
9
|
-
* Export Validations By Pattern data applying the given filters.
|
|
10
|
-
*/
|
|
11
|
-
export async function exportValidationsByPattern({ context, message }) {
|
|
12
|
-
//
|
|
13
|
-
message('A iniciar a exportação de Validações APEX por Pattern...');
|
|
14
|
-
//
|
|
15
|
-
// Prepare the filter params
|
|
16
|
-
const filterQuery = {
|
|
17
|
-
is_passenger: true,
|
|
18
|
-
};
|
|
19
|
-
filterQuery.created_at = {
|
|
20
|
-
$gte: Dates
|
|
21
|
-
.fromOperationalDate(context.dates.start, 'Europe/Lisbon')
|
|
22
|
-
.set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
|
|
23
|
-
.unix_timestamp,
|
|
24
|
-
$lt: Dates
|
|
25
|
-
.fromOperationalDate(context.dates.end, 'Europe/Lisbon')
|
|
26
|
-
.set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
|
|
27
|
-
.unix_timestamp,
|
|
28
|
-
};
|
|
29
|
-
if (context.filters.agency_ids.length) {
|
|
30
|
-
filterQuery.agency_id = { $in: context.filters.agency_ids };
|
|
31
|
-
}
|
|
32
|
-
if (context.filters.line_ids.length) {
|
|
33
|
-
filterQuery.line_id = { $in: context.filters.line_ids };
|
|
34
|
-
}
|
|
35
|
-
if (context.filters.pattern_ids.length) {
|
|
36
|
-
filterQuery.pattern_id = { $in: context.filters.pattern_ids };
|
|
37
|
-
}
|
|
38
|
-
if (context.filters.stop_ids.length) {
|
|
39
|
-
filterQuery.stop_id = { $in: context.filters.stop_ids };
|
|
40
|
-
}
|
|
41
|
-
if (context.filters.vehicle_ids.length) {
|
|
42
|
-
filterQuery.vehicle_id = { $in: context.filters.vehicle_ids };
|
|
43
|
-
}
|
|
44
|
-
//
|
|
45
|
-
// Setup a database stream to export data
|
|
46
|
-
message(`A iniciar ligação à base de dados...`);
|
|
47
|
-
const simplifiedApexValidationsCollection = await simplifiedApexValidations.getCollection();
|
|
48
|
-
const stream = simplifiedApexValidationsCollection.find(filterQuery).stream();
|
|
49
|
-
//
|
|
50
|
-
// Prepare the output directory and CSV writer
|
|
51
|
-
message(`A preparar a pasta para guardar os resultados...`);
|
|
52
|
-
if (!fs.existsSync(context.output))
|
|
53
|
-
fs.mkdirSync(context.output, { recursive: true });
|
|
54
|
-
const csvWriter = new CsvWriter('output', `${context.output}/${TASK_ID}-${context.dates.start}-${context.dates.end}.csv`, { batch_size: 100000, logs: false });
|
|
55
|
-
//
|
|
56
|
-
// Export the data
|
|
57
|
-
let counter = 0;
|
|
58
|
-
message(`A aguardar o resultado da pesquisa...`);
|
|
59
|
-
const result = {};
|
|
60
|
-
for await (const doc of stream) {
|
|
61
|
-
const document = doc;
|
|
62
|
-
//
|
|
63
|
-
// Prepare the result key
|
|
64
|
-
const operationalDate = Dates
|
|
65
|
-
.fromUnixTimestamp(document.created_at)
|
|
66
|
-
.operational_date;
|
|
67
|
-
const resultKey = `${operationalDate}:${document.pattern_id}`;
|
|
68
|
-
//
|
|
69
|
-
// Update the result with the current document
|
|
70
|
-
if (!result[resultKey]) {
|
|
71
|
-
result[resultKey] = {
|
|
72
|
-
date: operationalDate,
|
|
73
|
-
pattern_id: document.pattern_id,
|
|
74
|
-
validations: 0,
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
result[resultKey].validations += 1;
|
|
78
|
-
if (counter % 1000 === 0)
|
|
79
|
-
message(`Processados ${counter} documentos até agora...`);
|
|
80
|
-
counter++;
|
|
81
|
-
//
|
|
82
|
-
}
|
|
83
|
-
message(`A escrever os resultados no ficheiro CSV...`);
|
|
84
|
-
await csvWriter.write(Object.values(result));
|
|
85
|
-
await csvWriter.flush();
|
|
86
|
-
//
|
|
87
|
-
}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/* * */
|
|
2
|
-
import { Dates } from '@tmlmobilidade/dates';
|
|
3
|
-
import { simplifiedApexValidations } from '@tmlmobilidade/interfaces';
|
|
4
|
-
import { CsvWriter } from '@tmlmobilidade/writers';
|
|
5
|
-
import fs from 'node:fs';
|
|
6
|
-
/* * */
|
|
7
|
-
const TASK_ID = 'validations-by-stop-by-trip';
|
|
8
|
-
/**
|
|
9
|
-
* Export Validations By Stop By Trip data applying the given filters.
|
|
10
|
-
*/
|
|
11
|
-
export async function exportValidationsByStopByTrip({ context, message }) {
|
|
12
|
-
//
|
|
13
|
-
message('A iniciar a exportação de Validações APEX por Paragem e por Viagem...');
|
|
14
|
-
//
|
|
15
|
-
// Prepare the filter params
|
|
16
|
-
const filterQuery = {
|
|
17
|
-
is_passenger: true,
|
|
18
|
-
};
|
|
19
|
-
filterQuery.created_at = {
|
|
20
|
-
$gte: Dates
|
|
21
|
-
.fromOperationalDate(context.dates.start, 'Europe/Lisbon')
|
|
22
|
-
.set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
|
|
23
|
-
.unix_timestamp,
|
|
24
|
-
$lt: Dates
|
|
25
|
-
.fromOperationalDate(context.dates.end, 'Europe/Lisbon')
|
|
26
|
-
.set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
|
|
27
|
-
.unix_timestamp,
|
|
28
|
-
};
|
|
29
|
-
if (context.filters.agency_ids.length) {
|
|
30
|
-
filterQuery.agency_id = { $in: context.filters.agency_ids };
|
|
31
|
-
}
|
|
32
|
-
if (context.filters.line_ids.length) {
|
|
33
|
-
filterQuery.line_id = { $in: context.filters.line_ids };
|
|
34
|
-
}
|
|
35
|
-
if (context.filters.pattern_ids.length) {
|
|
36
|
-
filterQuery.pattern_id = { $in: context.filters.pattern_ids };
|
|
37
|
-
}
|
|
38
|
-
if (context.filters.stop_ids.length) {
|
|
39
|
-
filterQuery.stop_id = { $in: context.filters.stop_ids };
|
|
40
|
-
}
|
|
41
|
-
if (context.filters.vehicle_ids.length) {
|
|
42
|
-
filterQuery.vehicle_id = { $in: context.filters.vehicle_ids };
|
|
43
|
-
}
|
|
44
|
-
//
|
|
45
|
-
// Setup a database stream to export data
|
|
46
|
-
message(`A iniciar ligação à base de dados...`);
|
|
47
|
-
const simplifiedApexValidationsCollection = await simplifiedApexValidations.getCollection();
|
|
48
|
-
const stream = simplifiedApexValidationsCollection.find(filterQuery).stream();
|
|
49
|
-
//
|
|
50
|
-
// Prepare the output directory and CSV writer
|
|
51
|
-
message(`A preparar a pasta para guardar os resultados...`);
|
|
52
|
-
if (!fs.existsSync(context.output))
|
|
53
|
-
fs.mkdirSync(context.output, { recursive: true });
|
|
54
|
-
const csvWriter = new CsvWriter('output', `${context.output}/${TASK_ID}-${context.dates.start}-${context.dates.end}.csv`, { batch_size: 100000, logs: false });
|
|
55
|
-
//
|
|
56
|
-
// Export the data
|
|
57
|
-
let counter = 0;
|
|
58
|
-
message(`A aguardar o resultado da pesquisa...`);
|
|
59
|
-
const result = {};
|
|
60
|
-
for await (const doc of stream) {
|
|
61
|
-
const document = doc;
|
|
62
|
-
//
|
|
63
|
-
// Prepare the result key
|
|
64
|
-
const operationalDate = Dates
|
|
65
|
-
.fromUnixTimestamp(document.created_at)
|
|
66
|
-
.operational_date;
|
|
67
|
-
const resultKey = `${operationalDate}:${document.stop_id}:${document.trip_id}`;
|
|
68
|
-
//
|
|
69
|
-
// Update the result with the current document
|
|
70
|
-
if (!result[resultKey]) {
|
|
71
|
-
result[resultKey] = {
|
|
72
|
-
date: operationalDate,
|
|
73
|
-
stop_id: document.stop_id,
|
|
74
|
-
trip_id: document.trip_id,
|
|
75
|
-
validations: 0,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
result[resultKey].validations += 1;
|
|
79
|
-
if (counter % 1000 === 0)
|
|
80
|
-
message(`Processados ${counter} documentos até agora...`);
|
|
81
|
-
counter++;
|
|
82
|
-
//
|
|
83
|
-
}
|
|
84
|
-
message(`A escrever os resultados no ficheiro CSV...`);
|
|
85
|
-
await csvWriter.write(Object.values(result));
|
|
86
|
-
await csvWriter.flush();
|
|
87
|
-
//
|
|
88
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/* * */
|
|
2
|
-
import { Dates } from '@tmlmobilidade/dates';
|
|
3
|
-
import { simplifiedApexValidations } from '@tmlmobilidade/interfaces';
|
|
4
|
-
import { CsvWriter } from '@tmlmobilidade/writers';
|
|
5
|
-
import fs from 'node:fs';
|
|
6
|
-
/* * */
|
|
7
|
-
const TASK_ID = 'validations-by-stop';
|
|
8
|
-
/**
|
|
9
|
-
* Export Validations By Stop data applying the given filters.
|
|
10
|
-
*/
|
|
11
|
-
export async function exportValidationsByStop({ context, message }) {
|
|
12
|
-
//
|
|
13
|
-
message('A iniciar a exportação de Validações APEX por Paragem...');
|
|
14
|
-
//
|
|
15
|
-
// Prepare the filter params
|
|
16
|
-
const filterQuery = {
|
|
17
|
-
is_passenger: true,
|
|
18
|
-
};
|
|
19
|
-
filterQuery.created_at = {
|
|
20
|
-
$gte: Dates
|
|
21
|
-
.fromOperationalDate(context.dates.start, 'Europe/Lisbon')
|
|
22
|
-
.set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
|
|
23
|
-
.unix_timestamp,
|
|
24
|
-
$lt: Dates
|
|
25
|
-
.fromOperationalDate(context.dates.end, 'Europe/Lisbon')
|
|
26
|
-
.set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
|
|
27
|
-
.unix_timestamp,
|
|
28
|
-
};
|
|
29
|
-
if (context.filters.agency_ids.length) {
|
|
30
|
-
filterQuery.agency_id = { $in: context.filters.agency_ids };
|
|
31
|
-
}
|
|
32
|
-
if (context.filters.line_ids.length) {
|
|
33
|
-
filterQuery.line_id = { $in: context.filters.line_ids };
|
|
34
|
-
}
|
|
35
|
-
if (context.filters.pattern_ids.length) {
|
|
36
|
-
filterQuery.pattern_id = { $in: context.filters.pattern_ids };
|
|
37
|
-
}
|
|
38
|
-
if (context.filters.stop_ids.length) {
|
|
39
|
-
filterQuery.stop_id = { $in: context.filters.stop_ids };
|
|
40
|
-
}
|
|
41
|
-
if (context.filters.vehicle_ids.length) {
|
|
42
|
-
filterQuery.vehicle_id = { $in: context.filters.vehicle_ids };
|
|
43
|
-
}
|
|
44
|
-
//
|
|
45
|
-
// Setup a database stream to export data
|
|
46
|
-
message(`A iniciar ligação à base de dados...`);
|
|
47
|
-
const simplifiedApexValidationsCollection = await simplifiedApexValidations.getCollection();
|
|
48
|
-
const stream = simplifiedApexValidationsCollection.find(filterQuery).stream();
|
|
49
|
-
//
|
|
50
|
-
// Prepare the output directory and CSV writer
|
|
51
|
-
message(`A preparar a pasta para guardar os resultados...`);
|
|
52
|
-
if (!fs.existsSync(context.output))
|
|
53
|
-
fs.mkdirSync(context.output, { recursive: true });
|
|
54
|
-
const csvWriter = new CsvWriter('output', `${context.output}/${TASK_ID}-${context.dates.start}-${context.dates.end}.csv`, { batch_size: 100000, logs: false });
|
|
55
|
-
//
|
|
56
|
-
// Export the data
|
|
57
|
-
let counter = 0;
|
|
58
|
-
message(`A aguardar o resultado da pesquisa...`);
|
|
59
|
-
const result = {};
|
|
60
|
-
for await (const doc of stream) {
|
|
61
|
-
const document = doc;
|
|
62
|
-
//
|
|
63
|
-
// Prepare the result key
|
|
64
|
-
const operationalDate = Dates
|
|
65
|
-
.fromUnixTimestamp(document.created_at)
|
|
66
|
-
.operational_date;
|
|
67
|
-
const resultKey = `${operationalDate}:${document.stop_id}`;
|
|
68
|
-
//
|
|
69
|
-
// Update the result with the current document
|
|
70
|
-
if (!result[resultKey]) {
|
|
71
|
-
result[resultKey] = {
|
|
72
|
-
date: operationalDate,
|
|
73
|
-
stop_id: document.stop_id,
|
|
74
|
-
validations: 0,
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
result[resultKey].validations += 1;
|
|
78
|
-
if (counter % 1000 === 0)
|
|
79
|
-
message(`Processados ${counter} documentos até agora...`);
|
|
80
|
-
counter++;
|
|
81
|
-
//
|
|
82
|
-
}
|
|
83
|
-
message(`A escrever os resultados no ficheiro CSV...`);
|
|
84
|
-
await csvWriter.write(Object.values(result));
|
|
85
|
-
await csvWriter.flush();
|
|
86
|
-
//
|
|
87
|
-
}
|