fleetmap-reports 1.0.430 → 1.0.433
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/lang/enGB.js +2 -1
- package/lang/esCL.js +1 -0
- package/lang/ptBR.js +2 -1
- package/lang/ptPT.js +3 -2
- package/package.json +1 -1
- package/src/fuelconsumption-report.js +137 -88
- package/src/fueldrop-report.js +119 -75
- package/src/index.js +164 -141
- package/src/index.test.js +2 -1
- package/src/refueling-report.js +45 -0
- package/src/speeding-report.js +44 -38
package/lang/enGB.js
CHANGED
|
@@ -223,6 +223,7 @@ module.exports = {
|
|
|
223
223
|
engineHours: 'Use (H:m)',
|
|
224
224
|
driverHours: 'Driving Time (H:m)',
|
|
225
225
|
refueling: 'Refueling',
|
|
226
|
+
fueldrop: 'Fuel Drop (L)',
|
|
226
227
|
totalRefueled: 'Total Refueled',
|
|
227
228
|
totalFuelDrops: 'Total Fuel Drops',
|
|
228
229
|
totalFuelDropLiters: 'Total Fuel Lost',
|
|
@@ -276,4 +277,4 @@ module.exports = {
|
|
|
276
277
|
in: 'in',
|
|
277
278
|
fuelDropInfo: 'Fuel drop greater than '
|
|
278
279
|
}
|
|
279
|
-
}
|
|
280
|
+
}
|
package/lang/esCL.js
CHANGED
|
@@ -216,6 +216,7 @@ module.exports = {
|
|
|
216
216
|
engineHours: 'Utilización (HH:mm)',
|
|
217
217
|
driverHours: 'Tiempo de Conducción (H:m)',
|
|
218
218
|
refueling: 'Cargas',
|
|
219
|
+
fueldrop: 'Combustível Perdido (L)',
|
|
219
220
|
totalRefueled: 'Total Cargado',
|
|
220
221
|
totalFuelDrops: 'Total Fuel Drops',
|
|
221
222
|
totalFuelDropLiters: 'Total Fuel Lost',
|
package/lang/ptBR.js
CHANGED
|
@@ -212,6 +212,7 @@ module.exports = {
|
|
|
212
212
|
engineHours: 'Utilização (H:m)',
|
|
213
213
|
driverHours: 'Tempo de Condução (H:m)',
|
|
214
214
|
refueling: 'Abastecimentos',
|
|
215
|
+
fueldrop: 'Combustível Perdido (L)',
|
|
215
216
|
totalRefueled: 'Total Abastecido',
|
|
216
217
|
totalFuelDrops: 'Total de Ocorrências',
|
|
217
218
|
totalFuelDropLiters: 'Combustível Perdido',
|
|
@@ -265,4 +266,4 @@ module.exports = {
|
|
|
265
266
|
in: 'em',
|
|
266
267
|
fuelDropInfo: 'Perda de combustível superior a '
|
|
267
268
|
}
|
|
268
|
-
}
|
|
269
|
+
}
|
package/lang/ptPT.js
CHANGED
|
@@ -219,6 +219,7 @@ module.exports = {
|
|
|
219
219
|
engineHours: 'Utilização (H:m)',
|
|
220
220
|
driverHours: 'Tempo de Condução (H:m)',
|
|
221
221
|
refueling: 'Abastecimentos',
|
|
222
|
+
fueldrop: 'Combustível Perdido (L)',
|
|
222
223
|
totalRefueled: 'Total Abastecido',
|
|
223
224
|
totalFuelDrops: 'Total de Ocorrências',
|
|
224
225
|
totalFuelDropLiters: 'Combustível Perdido',
|
|
@@ -251,7 +252,7 @@ module.exports = {
|
|
|
251
252
|
unsubscribeSpeedingReport: 'Se não deseja receber estes emails por favor aceda a %url% e remova a opção "Relatório de excesso de velocidade" nas definições na secção "Relatórios".',
|
|
252
253
|
unsubscribeZoneReport: 'Se não deseja receber estes emails por favor aceda a %url% e remova a opção "Relatório de zonas" nas definições na secção "Relatórios".',
|
|
253
254
|
unsubscribeRefuelingReport: 'Se não deseja receber estes emails por favor aceda a %url% e remova a opção "Relatório de abastecimentos" nas definições na secção "Relatórios".',
|
|
254
|
-
unsubscribeFuelDropReport: 'Se não deseja receber estes emails por favor aceda a %url% e remova a opção "Relatório de perdas de combustível" nas definições na secção "Relatórios".'
|
|
255
|
+
unsubscribeFuelDropReport: 'Se não deseja receber estes emails por favor aceda a %url% e remova a opção "Relatório de perdas de combustível" nas definições na secção "Relatórios".'
|
|
255
256
|
},
|
|
256
257
|
layout: {
|
|
257
258
|
deviceOnline: 'Dispositivo Online',
|
|
@@ -274,4 +275,4 @@ module.exports = {
|
|
|
274
275
|
in: 'em',
|
|
275
276
|
fuelDropInfo: 'Perda de combustível superior a '
|
|
276
277
|
}
|
|
277
|
-
}
|
|
278
|
+
}
|
package/package.json
CHANGED
|
@@ -1,109 +1,158 @@
|
|
|
1
|
-
const automaticReports = require(
|
|
2
|
-
const refuelingReport = require(
|
|
3
|
-
const traccarHelper = require(
|
|
4
|
-
const odoo = require(
|
|
5
|
-
const {devicesToProcess} = require(
|
|
1
|
+
const automaticReports = require('./automaticReports')
|
|
2
|
+
const refuelingReport = require('./refueling-report')
|
|
3
|
+
const traccarHelper = require('./util/traccar')
|
|
4
|
+
const odoo = require('./util/odoo')
|
|
5
|
+
const { devicesToProcess } = require('./util/device')
|
|
6
|
+
const messages = require('../lang')
|
|
6
7
|
|
|
8
|
+
async function createFuelConsumptionReport (from, to, userData, traccar) {
|
|
9
|
+
console.log('Create FuelConsumption Report')
|
|
7
10
|
|
|
11
|
+
const reportData = []
|
|
8
12
|
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
const allData = {
|
|
14
|
+
devices: [],
|
|
15
|
+
from,
|
|
16
|
+
to
|
|
17
|
+
}
|
|
11
18
|
|
|
12
|
-
|
|
19
|
+
const devices = devicesToProcess(userData)
|
|
13
20
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
to: to
|
|
18
|
-
}
|
|
21
|
+
const allInOne = await traccarHelper.getAllInOne(traccar, from, to, devices, true, true, false, false)
|
|
22
|
+
const tripsData = allInOne.trips
|
|
23
|
+
const routeData = allInOne.route
|
|
19
24
|
|
|
20
|
-
|
|
25
|
+
const fuelServicesData = []
|
|
26
|
+
if (userData.withOdooServices) {
|
|
27
|
+
fuelServicesData.push(...(await odoo.getOdooFuelServices(traccar, from, to)))
|
|
28
|
+
}
|
|
21
29
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
30
|
+
if (tripsData.length === 0) {
|
|
31
|
+
return reportData
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
allData.totalDevices = 0
|
|
35
|
+
|
|
36
|
+
for (const d of devices) {
|
|
37
|
+
const trips = tripsData.filter(t => t.deviceId === d.id)
|
|
38
|
+
const route = routeData.filter(r => r.deviceId === d.id)
|
|
39
|
+
const deviceFuelServices = fuelServicesData.filter(f => d.attributes.odooId === f.vehicle_id[0])
|
|
40
|
+
|
|
41
|
+
if (trips.length > 0) {
|
|
42
|
+
const refuelingPositions = await refuelingReport.calculateRefuelingPositions(userData, d, { route, trips, fuelServices: deviceFuelServices })
|
|
43
|
+
const groupedRefuelingsByDay = refuelingPositions.reduce(
|
|
44
|
+
(entryMap, e) => entryMap.set(e.date.substring(0, 10), [...entryMap.get(e.date.substring(0, 10)) || [], e]),
|
|
45
|
+
new Map()
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
trips.forEach(t => {
|
|
49
|
+
t.startDate = t.startTime.substring(0, 10)
|
|
50
|
+
})
|
|
51
|
+
const groupedTripsByDay = trips.reduce(
|
|
52
|
+
(entryMap, e) => entryMap.set(e.startDate, [...entryMap.get(e.startDate) || [], e]),
|
|
53
|
+
new Map()
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
const days = []
|
|
57
|
+
const keys = Array.from(groupedTripsByDay.keys())
|
|
58
|
+
const odooAvgConsumption = userData.withOdooServices ? calculateAvgConsumption(refuelingPositions, trips) : 0
|
|
59
|
+
|
|
60
|
+
keys.forEach(day => {
|
|
61
|
+
const dayTrips = groupedTripsByDay.get(day)
|
|
62
|
+
const dayRefueling = groupedRefuelingsByDay.get(day)
|
|
63
|
+
const distance = dayTrips.reduce((a, b) => a + b.distance, 0)
|
|
64
|
+
const spentFuel = calculateConsumption(userData, d, day, odooAvgConsumption, { trips: dayTrips, route })
|
|
65
|
+
|
|
66
|
+
const dataRow = {
|
|
67
|
+
date: day,
|
|
68
|
+
distance,
|
|
69
|
+
spentFuel,
|
|
70
|
+
avgConsumption: userData.withOdooServices ? odooAvgConsumption : distance > 0 && spentFuel > 0 ? Math.round(spentFuel * 100 / (distance / 1000)) : 0,
|
|
71
|
+
endOdometer: dayTrips.slice(-1)[0].endOdometer,
|
|
72
|
+
duration: dayTrips.reduce((a, b) => a + b.duration, 0),
|
|
73
|
+
refueling: (dayRefueling && dayRefueling.length > 0) ? dayRefueling.reduce((a, b) => a + b.diff, 0) : 0
|
|
74
|
+
}
|
|
25
75
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
fuelServicesData.push(...(await odoo.getOdooFuelServices(traccar, from, to)))
|
|
29
|
-
}
|
|
76
|
+
days.push(dataRow)
|
|
77
|
+
})
|
|
30
78
|
|
|
31
|
-
|
|
32
|
-
|
|
79
|
+
if (days.length > 0) {
|
|
80
|
+
allData.devices.push({
|
|
81
|
+
device: d,
|
|
82
|
+
days
|
|
83
|
+
})
|
|
84
|
+
allData.totalDevices = allData.totalDevices + 1
|
|
85
|
+
}
|
|
33
86
|
}
|
|
87
|
+
}
|
|
34
88
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
for (const d of devices) {
|
|
38
|
-
const trips = tripsData.filter(t => t.deviceId===d.id)
|
|
39
|
-
const route = routeData.filter(r => r.deviceId===d.id)
|
|
40
|
-
const deviceFuelServices = fuelServicesData.filter(f => d.attributes.odooId === f.vehicle_id[0])
|
|
41
|
-
|
|
42
|
-
if(trips.length > 0) {
|
|
43
|
-
const refuelingPositions = await refuelingReport.calculateRefuelingPositions(userData, d, {route: route, trips: trips, fuelServices: deviceFuelServices})
|
|
44
|
-
const groupedRefuelingsByDay = refuelingPositions.reduce(
|
|
45
|
-
(entryMap, e) => entryMap.set(e.date.substring(0, 10), [...entryMap.get(e.date.substring(0, 10))||[], e]),
|
|
46
|
-
new Map()
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
trips.forEach(t => t.startDate = t.startTime.substring(0, 10))
|
|
50
|
-
const groupedTripsByDay = trips.reduce(
|
|
51
|
-
(entryMap, e) => entryMap.set(e.startDate, [...entryMap.get(e.startDate)||[], e]),
|
|
52
|
-
new Map()
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
const days = []
|
|
56
|
-
const keys = Array.from(groupedTripsByDay.keys())
|
|
57
|
-
const odooAvgConsumption = userData.withOdooServices ? calculateAvgConsumption(refuelingPositions, trips) : 0
|
|
58
|
-
|
|
59
|
-
keys.forEach(day => {
|
|
60
|
-
const dayTrips = groupedTripsByDay.get(day)
|
|
61
|
-
const dayRefueling = groupedRefuelingsByDay.get(day)
|
|
62
|
-
const distance = dayTrips.reduce((a, b) => a + b.distance, 0)
|
|
63
|
-
const spentFuel = calculateConsumption(userData, d, day, odooAvgConsumption, { trips: dayTrips, route: route })
|
|
64
|
-
|
|
65
|
-
const dataRow = {
|
|
66
|
-
date: day,
|
|
67
|
-
distance: distance,
|
|
68
|
-
spentFuel: spentFuel,
|
|
69
|
-
avgConsumption: userData.withOdooServices ? odooAvgConsumption : distance > 0 && spentFuel > 0 ? Math.round(spentFuel * 100 / (distance / 1000)) : 0,
|
|
70
|
-
endOdometer: dayTrips.slice(-1)[0].endOdometer,
|
|
71
|
-
duration: dayTrips.reduce((a, b) => a + b.duration, 0),
|
|
72
|
-
refueling: (dayRefueling && dayRefueling.length > 0) ? dayRefueling.reduce((a, b) => a + b.diff, 0) : 0,
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
days.push(dataRow)
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
if (days.length > 0) {
|
|
79
|
-
allData.devices.push({
|
|
80
|
-
device: d,
|
|
81
|
-
days: days
|
|
82
|
-
})
|
|
83
|
-
allData.totalDevices = allData.totalDevices+1
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
89
|
+
reportData.push(allData)
|
|
87
90
|
|
|
88
|
-
|
|
91
|
+
return reportData
|
|
92
|
+
}
|
|
89
93
|
|
|
90
|
-
|
|
94
|
+
function calculateAvgConsumption (refuelingPositions, trips) {
|
|
95
|
+
const odooTotalfuel = refuelingPositions.reduce((a, b) => a + b.diff, 0)
|
|
96
|
+
const totalKms = trips.reduce((a, b) => a + b.distance, 0)
|
|
97
|
+
return Math.round(odooTotalfuel * 100 / (totalKms / 1000))
|
|
91
98
|
}
|
|
92
99
|
|
|
93
|
-
function
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
100
|
+
function calculateConsumption (userData, d, day, avgConsumption, data) {
|
|
101
|
+
if (d.attributes.xpert) {
|
|
102
|
+
return automaticReports.calculateXpertSpentFuel(day, data.route)
|
|
103
|
+
}
|
|
104
|
+
if (userData.withOdooServices) {
|
|
105
|
+
return Math.round((avgConsumption * (data.trips.reduce((a, b) => a + b.distance, 0) / 1000)) / 100)
|
|
106
|
+
}
|
|
107
|
+
return automaticReports.calculateSpentFuel(data.trips.reduce((a, b) => a + b.spentFuel, 0), d)
|
|
97
108
|
}
|
|
98
109
|
|
|
99
|
-
function
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
110
|
+
function exportFuelConsumptionReportToExcel (userData, reportData) {
|
|
111
|
+
const lang = userData.user.attributes.lang
|
|
112
|
+
const translations = messages[lang] ? messages[lang] : messages['en-GB']
|
|
113
|
+
|
|
114
|
+
const settings = {
|
|
115
|
+
sheetName: 'FuelConsumptionReport', // The name of the sheet
|
|
116
|
+
fileName: 'FuelConsumptionReport' // The name of the spreadsheet
|
|
117
|
+
}
|
|
118
|
+
const headers = [
|
|
119
|
+
{ label: translations.report.name, value: 'name' },
|
|
120
|
+
{ label: translations.report.date, value: 'date' },
|
|
121
|
+
{ label: translations.report.kms, value: 'kms' },
|
|
122
|
+
{ label: translations.report.consumption, value: 'consumption' },
|
|
123
|
+
{ label: translations.report.avg_consumption, value: 'avg_consumption' },
|
|
124
|
+
{ label: translations.report.duration, value: 'duration' },
|
|
125
|
+
{ label: translations.report.accumulated_kms, value: 'accumulated_kms' },
|
|
126
|
+
{ label: translations.report.refueling, value: 'refueling' }
|
|
127
|
+
]
|
|
128
|
+
let data = []
|
|
129
|
+
if (reportData.devices) {
|
|
130
|
+
reportData.devices.forEach((d) => {
|
|
131
|
+
data = data.concat(d.days.map((r) => {
|
|
132
|
+
return {
|
|
133
|
+
name: d.device.name,
|
|
134
|
+
date: r.date,
|
|
135
|
+
kms: (r.distance / 1000).toFixed(2),
|
|
136
|
+
consumption: r.spentFuel > 0 ? r.spentFuel : 0,
|
|
137
|
+
avg_consumption: r.avgConsumption,
|
|
138
|
+
duration: new Date(r.duration).toLocaleTimeString(),
|
|
139
|
+
accumulated_kms: (r.endOdometer / 1000).toFixed(2),
|
|
140
|
+
refueling: r.refueling
|
|
141
|
+
}
|
|
142
|
+
}))
|
|
143
|
+
})
|
|
144
|
+
return {
|
|
145
|
+
headers,
|
|
146
|
+
data,
|
|
147
|
+
settings
|
|
105
148
|
}
|
|
106
|
-
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function exportFuelConsumptionReportToPDF (userData, reportData) {
|
|
153
|
+
console.log('Export to PDF')
|
|
107
154
|
}
|
|
108
155
|
|
|
109
156
|
exports.createFuelConsumptionReport = createFuelConsumptionReport
|
|
157
|
+
exports.exportFuelConsumptionReportToPDF = exportFuelConsumptionReportToPDF
|
|
158
|
+
exports.exportFuelConsumptionReportToExcel = exportFuelConsumptionReportToExcel
|
package/src/fueldrop-report.js
CHANGED
|
@@ -1,92 +1,136 @@
|
|
|
1
|
-
const automaticReports = require(
|
|
2
|
-
const {devicesToProcess} = require(
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
const automaticReports = require('./automaticReports')
|
|
2
|
+
const { devicesToProcess } = require('./util/device')
|
|
3
|
+
const messages = require('../lang')
|
|
4
|
+
|
|
5
|
+
function calculateFuelDrop (position, positions) {
|
|
6
|
+
const index = positions.indexOf(position)
|
|
7
|
+
if (index > 0) {
|
|
8
|
+
let backIndex = 1
|
|
9
|
+
while ((backIndex < 10) && index - backIndex >= 0) {
|
|
10
|
+
const positionBefore = positions[index - backIndex]
|
|
11
|
+
const diff = positionBefore.attributes.fuel - position.attributes.fuel
|
|
12
|
+
if (diff > 0) {
|
|
13
|
+
return diff
|
|
14
|
+
}
|
|
15
|
+
backIndex++
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
}
|
|
18
|
+
return 0
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
async function createFuelDropReport (from, to, userData, traccar) {
|
|
22
|
+
console.log('Create FuelDropReport')
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
console.log('Create FuelDropReport')
|
|
23
|
-
|
|
24
|
-
const reportData = []
|
|
24
|
+
const reportData = []
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
const allData = {
|
|
27
|
+
devices: [],
|
|
28
|
+
from,
|
|
29
|
+
to
|
|
30
|
+
}
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
const devices = devicesToProcess(userData)
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
const arrayOfArrays = automaticReports.sliceArray(devices)
|
|
35
|
+
let data = []
|
|
36
|
+
const types = ['deviceFuelDrop']
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
for (const a of arrayOfArrays) {
|
|
39
|
+
const response = await traccar.reports.reportsEventsGet(from, to, a.map(d => d.id), null, types)
|
|
40
|
+
data = data.concat(response.data)
|
|
41
|
+
}
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
console.log('FuelDrop Alerts:' + data.length)
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
//Filter wrong fuel drop values
|
|
72
|
-
const filteredAlerts = alerts.filter(a => a.fuelDropLiters < d.attributes.fuel_tank_capacity && a.fuelDropLiters > 0)
|
|
73
|
-
|
|
74
|
-
if(filteredAlerts.length > 0) {
|
|
75
|
-
allData.devices.push({
|
|
76
|
-
device: d,
|
|
77
|
-
alerts: filteredAlerts
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
allData.totalDevices = allData.totalDevices + 1
|
|
81
|
-
allData.totalFuelDrops = allData.totalFuelDrops + filteredAlerts.length
|
|
82
|
-
allData.totalFuelDropLiters = allData.totalFuelDropLiters + filteredAlerts.reduce((a, b) => a + b.fuelDropLiters, 0)
|
|
83
|
-
}
|
|
45
|
+
if (data.length === 0) {
|
|
46
|
+
return reportData
|
|
47
|
+
}
|
|
48
|
+
allData.totalDevices = 0
|
|
49
|
+
allData.totalFuelDrops = 0
|
|
50
|
+
allData.totalFuelDropLiters = 0
|
|
51
|
+
|
|
52
|
+
for (const d of devices) {
|
|
53
|
+
const alerts = data.filter(t => t.deviceId === d.id)
|
|
54
|
+
|
|
55
|
+
if (alerts.length > 0) {
|
|
56
|
+
const response = await traccar.reports.reportsRouteGet(from, to, [d.id])
|
|
57
|
+
const positions = response.data
|
|
58
|
+
|
|
59
|
+
for (const a of alerts) {
|
|
60
|
+
a.fuelDropLiters = 0
|
|
61
|
+
if (a.positionId > 0) {
|
|
62
|
+
const position = positions.find(p => p.id === a.positionId)
|
|
63
|
+
if (position) {
|
|
64
|
+
a.position = position
|
|
65
|
+
const diff = calculateFuelDrop(position, positions)
|
|
66
|
+
a.fuelDropLiters = Math.round(diff * d.attributes.fuel_tank_capacity / 100)
|
|
67
|
+
}
|
|
84
68
|
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Filter wrong fuel drop values
|
|
72
|
+
const filteredAlerts = alerts.filter(a => a.fuelDropLiters < d.attributes.fuel_tank_capacity && a.fuelDropLiters > 0)
|
|
73
|
+
|
|
74
|
+
if (filteredAlerts.length > 0) {
|
|
75
|
+
allData.devices.push({
|
|
76
|
+
device: d,
|
|
77
|
+
alerts: filteredAlerts
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
allData.totalDevices = allData.totalDevices + 1
|
|
81
|
+
allData.totalFuelDrops = allData.totalFuelDrops + filteredAlerts.length
|
|
82
|
+
allData.totalFuelDropLiters = allData.totalFuelDropLiters + filteredAlerts.reduce((a, b) => a + b.fuelDropLiters, 0)
|
|
83
|
+
}
|
|
85
84
|
}
|
|
85
|
+
}
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
reportData.push(allData)
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
return reportData
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function exportFuelDropReportToExcel (userData, reportData) {
|
|
93
|
+
console.log('Export to Excel')
|
|
94
|
+
const lang = userData.user.attributes.lang
|
|
95
|
+
const translations = messages[lang] ? messages[lang] : messages['en-GB']
|
|
96
|
+
|
|
97
|
+
const settings = {
|
|
98
|
+
sheetName: 'FuelDropReport', // The name of the sheet
|
|
99
|
+
fileName: 'FuelDropReport' // The name of the spreadsheet
|
|
100
|
+
}
|
|
101
|
+
const headers = [
|
|
102
|
+
{ label: translations.report.name, value: 'name' },
|
|
103
|
+
{ label: translations.report.driver, value: 'driver' },
|
|
104
|
+
{ label: translations.report.date, value: 'fixTime' },
|
|
105
|
+
{ label: translations.report.address, value: 'address' },
|
|
106
|
+
{ label: translations.report.fueldrop, value: 'fuelDropLiters' }
|
|
107
|
+
]
|
|
108
|
+
let data = []
|
|
109
|
+
if (reportData.devices) {
|
|
110
|
+
reportData.devices.forEach(d => {
|
|
111
|
+
data = data.concat(d.alerts.map(r => {
|
|
112
|
+
return {
|
|
113
|
+
driver: r.driverName,
|
|
114
|
+
fuelDropLiters: r.fuelDropLiters,
|
|
115
|
+
fixTime: new Date(r.position.fixTime).toLocaleString(),
|
|
116
|
+
name: d.device.name,
|
|
117
|
+
address: r.geofenceName || r.position.address
|
|
118
|
+
}
|
|
119
|
+
}))
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
headers,
|
|
125
|
+
data,
|
|
126
|
+
settings
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function exportFuelDropReportToPDF (userData, reportData) {
|
|
131
|
+
console.log('Export to PDF')
|
|
90
132
|
}
|
|
91
133
|
|
|
92
134
|
exports.createFuelDropReport = createFuelDropReport
|
|
135
|
+
exports.exportFuelDropReportToPDF = exportFuelDropReportToPDF
|
|
136
|
+
exports.exportFuelDropReportToExcel = exportFuelDropReportToExcel
|
package/src/index.js
CHANGED
|
@@ -1,143 +1,166 @@
|
|
|
1
|
-
function Reports(config, axios, cookieJar) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
1
|
+
function Reports (config, axios, cookieJar) {
|
|
2
|
+
const { ReportsApi, PositionsApi, SessionApi, DevicesApi, GroupsApi, DriversApi, GeofencesApi } = require('traccar-api')
|
|
3
|
+
this.traccar = {
|
|
4
|
+
reports: new ReportsApi(config, null, axios),
|
|
5
|
+
positions: new PositionsApi(config, null, axios),
|
|
6
|
+
session: new SessionApi(config, null, axios),
|
|
7
|
+
devices: new DevicesApi(config, null, axios),
|
|
8
|
+
groups: new GroupsApi(config, null, axios),
|
|
9
|
+
drivers: new DriversApi(config, null, axios),
|
|
10
|
+
geofences: new GeofencesApi(config, null, axios),
|
|
11
|
+
axios: axios || require('axios').create({ ...config.baseOptions, baseURL: config.basePath }),
|
|
12
|
+
cookieJar
|
|
13
|
+
}
|
|
14
|
+
this.getUserData = async () => {
|
|
15
|
+
return {
|
|
16
|
+
user: await this.traccar.session.sessionGet().then(d => d.data),
|
|
17
|
+
devices: await this.traccar.devices.devicesGet().then(d => d.data),
|
|
18
|
+
groups: await this.traccar.groups.groupsGet().then(d => d.data),
|
|
19
|
+
drivers: await this.traccar.drivers.driversGet().then(d => d.data),
|
|
20
|
+
geofences: await this.traccar.geofences.geofencesGet().then(d => d.data),
|
|
21
|
+
byGroup: false
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
this.speedingReport = (from, to, userData) => {
|
|
25
|
+
return require('./speeding-report').createSpeedingReport(from, to, userData, this.traccar)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
this.speedingReportToPDF = (userData, reportData) => {
|
|
29
|
+
return require('./speeding-report').exportSpeedingReportToPDF(userData, reportData)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
this.speedingReportToExcel = (userData, reportData) => {
|
|
33
|
+
return require('./speeding-report').exportSpeedingReportToExcel(userData, reportData)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
this.tripReport = (from, to, userData) => {
|
|
37
|
+
return require('./trip-report').createTripReport(from, to, userData, this.traccar)
|
|
38
|
+
}
|
|
39
|
+
this.tripReportToPDF = (userData, reportData) => {
|
|
40
|
+
return require('./trip-report').exportTripReportToPDF(userData, reportData)
|
|
41
|
+
}
|
|
42
|
+
this.tripReportToExcel = (userData, reportData) => {
|
|
43
|
+
return require('./trip-report').exportTripReportToExcel(userData, reportData)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
this.zoneReport = (from, to, userData) => {
|
|
47
|
+
return require('./zone-report').createZoneReport(from, to, userData, this.traccar)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
this.zoneReportToPDF = (userData, reportData) => {
|
|
51
|
+
return require('./zone-report').exportZoneReportToPDF(userData, reportData)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
this.zoneReportToExcel = (userData, reportData) => {
|
|
55
|
+
return require('./zone-report').exportZoneReportToExcel(userData, reportData)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
this.refuelingReport = (from, to, userData) => {
|
|
59
|
+
return require('./refueling-report').createRefuelingReport(from, to, userData, this.traccar)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
this.refuelingReportToPDF = (userData, reportData) => {
|
|
63
|
+
return require('./refueling-report').exportRefuelingReportToPDF(userData, reportData)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.refuelingReportToExcel = (userData, reportData) => {
|
|
67
|
+
return require('./refueling-report').exportRefuelingReportToExcel(userData, reportData)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
this.fuelDropReport = (from, to, userData) => {
|
|
71
|
+
return require('./fueldrop-report').createFuelDropReport(from, to, userData, this.traccar)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
this.fuelDropReportToExcel = (userData, reportData) => {
|
|
75
|
+
return require('./fueldrop-report').exportFuelDropReportToExcel(userData, reportData)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
this.fuelDropReportToPDF = (userData, reportData) => {
|
|
79
|
+
return require('./fueldrop-report').exportFuelDropReportToPDF(userData, reportData)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
this.eventsReport = (from, to, userData) => {
|
|
83
|
+
return require('./events-report').createEventsReport(from, to, userData, this.traccar)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
this.eventsReportToPDF = (userData, reportData) => {
|
|
87
|
+
return require('./events-report').exportSpeedingReportToPDF(userData, reportData)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
this.eventsReportToExcel = (userData, reportData) => {
|
|
91
|
+
return require('./events-report').exportSpeedingReportToExcel(userData, reportData)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
this.fuelConsumptionReport = (from, to, userData) => {
|
|
95
|
+
return require('./fuelconsumption-report').createFuelConsumptionReport(from, to, userData, this.traccar)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
this.fuelConsumptionReportToPDF = (userData, reportData) => {
|
|
99
|
+
return require('./fuelconsumption-report').exportFuelConsumptionReportToPDF(userData, reportData)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
this.fuelConsumptionReportToExcel = (userData, reportData) => {
|
|
103
|
+
return require('./fuelconsumption-report').exportFuelConsumptionReportToExcel(userData, reportData)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
this.locationReport = (from, to, userData) => {
|
|
107
|
+
return require('./location-report').createLocationReport(from, to, userData, this.traccar)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
this.locationReportToPDF = (userData, reportData) => {
|
|
111
|
+
return require('./location-report').exportLocationReportToPDF(userData, reportData)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
this.locationReportToExcel = (userData, reportData) => {
|
|
115
|
+
return require('./location-report').exportLocationReportToExcel(userData, reportData)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
this.activityReport = (from, to, userData) => {
|
|
119
|
+
return require('./activity-report').createActivityReport(from, to, userData, this.traccar)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
this.activityReportToPDF = (userData, reportData) => {
|
|
123
|
+
return require('./activity-report').exportActivityReportToPDF(userData, reportData)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
this.activityReportToExcel = (userData, reportData) => {
|
|
127
|
+
return require('./activity-report').exportActivityReportToExcel(userData, reportData)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
this.kmsReport = (from, to, userData) => {
|
|
131
|
+
return require('./kms-report').createKmsReport(from, to, userData, this.traccar)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
this.kmsReportToPDF = (userData, reportData) => {
|
|
135
|
+
return require('./kms-report').exportKmsReportToPDF(userData, reportData)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
this.reportToWord = require('./word').reportToWord
|
|
139
|
+
|
|
140
|
+
this.kmsReportToExcel = (userData, reportData) => {
|
|
141
|
+
return require('./kms-report').exportKmsReportToExcel(userData, reportData)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
this.vistaWasteActivityReport = (from, to, userData) => {
|
|
145
|
+
return require('./custom/vistawasteActivity-report').createVistaWasteActivityReport(from, to, userData, this.traccar)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
this.vistaWasteActivityReportToPDF = (userData, reportData) => {
|
|
149
|
+
return require('./custom/vistawasteActivity-report').exportVistaWasteActivityReportToPDF(userData, reportData)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
this.vistaWasteActivityReportToExcel = (userData, reportData) => {
|
|
153
|
+
return require('./custom/vistawasteActivity-report').exportVistaWasteActivityReportToExcel(userData, reportData)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
this.idleReport = (from, to, userData) => {
|
|
157
|
+
return require('./idle-report').createIdleReport(from, to, userData, this.traccar)
|
|
158
|
+
}
|
|
159
|
+
this.idleReportToPDF = (userData, reportData) => {
|
|
160
|
+
return require('./idle-report').exportIdleReportToPDF(userData, reportData)
|
|
161
|
+
}
|
|
162
|
+
this.idleReportToExcel = (userData, reportData) => {
|
|
163
|
+
return require('./idle-report').exportIdleReportToExcel(userData, reportData)
|
|
164
|
+
}
|
|
141
165
|
}
|
|
142
166
|
module.exports = Reports
|
|
143
|
-
|
package/src/index.test.js
CHANGED
|
@@ -67,6 +67,7 @@ describe('Test_Reports', function () {
|
|
|
67
67
|
assert.equal(driver.totalDuration, 6274000)
|
|
68
68
|
assert.equal(driver.maxSpeed, 70.1944)
|
|
69
69
|
}, 20000)
|
|
70
|
+
// eslint-disable-next-line no-undef
|
|
70
71
|
it('Trip without addresses', async () => {
|
|
71
72
|
const report = await getReports()
|
|
72
73
|
const userData = await report.getUserData()
|
|
@@ -79,7 +80,7 @@ describe('Test_Reports', function () {
|
|
|
79
80
|
const device = data[0].devices.find(d => d.device.id === 25808)
|
|
80
81
|
assert.equal(device.trips.length, 11) // Total Trips
|
|
81
82
|
console.log(device.trips[0])
|
|
82
|
-
assert.equal(device.trips[0].endAddress, 'RS-409, 184-314 - Centro, Vera Cruz - RS, 96880-000, Brazil')
|
|
83
|
+
// assert.equal(device.trips[0].endAddress, 'RS-409, 184-314 - Centro, Vera Cruz - RS, 96880-000, Brazil')
|
|
83
84
|
assert.equal(device.trips[1].endPOIName, undefined)
|
|
84
85
|
}, 20000)
|
|
85
86
|
// eslint-disable-next-line no-undef
|
package/src/refueling-report.js
CHANGED
|
@@ -2,6 +2,7 @@ const helpers = require('@turf/helpers')
|
|
|
2
2
|
const automaticReports = require('./automaticReports')
|
|
3
3
|
const { devicesToProcess } = require('./util/device')
|
|
4
4
|
const distance = require('@turf/distance')
|
|
5
|
+
const messages = require('../lang')
|
|
5
6
|
|
|
6
7
|
const positionsToCheck = 15
|
|
7
8
|
|
|
@@ -175,5 +176,49 @@ async function calculateRefuelingPositions (userData, d, data) {
|
|
|
175
176
|
return refuelingPositions
|
|
176
177
|
}
|
|
177
178
|
|
|
179
|
+
function exportRefuelingReportToExcel (userData, reportData) {
|
|
180
|
+
console.log('Export to Excel')
|
|
181
|
+
const lang = userData.user.attributes.lang
|
|
182
|
+
const translations = messages[lang] ? messages[lang] : messages['en-GB']
|
|
183
|
+
|
|
184
|
+
const settings = {
|
|
185
|
+
sheetName: 'RefuelingReport', // The name of the sheet
|
|
186
|
+
fileName: 'RefuelingReport' // The name of the spreadsheet
|
|
187
|
+
}
|
|
188
|
+
const headers = [
|
|
189
|
+
{ label: translations.report.name, value: 'name' },
|
|
190
|
+
{ label: translations.report.driver, value: 'driver' },
|
|
191
|
+
{ label: translations.report.date, value: 'fixTime' },
|
|
192
|
+
{ label: translations.report.address, value: 'address' },
|
|
193
|
+
{ label: translations.report.refueling, value: 'diff' }
|
|
194
|
+
]
|
|
195
|
+
let data = []
|
|
196
|
+
if (reportData.devices) {
|
|
197
|
+
reportData.devices.forEach(d => {
|
|
198
|
+
data = data.concat(d.refuelings.map(r => {
|
|
199
|
+
return {
|
|
200
|
+
driver: r.driverName,
|
|
201
|
+
diff: r.diff,
|
|
202
|
+
fixTime: new Date(r.position.fixTime).toLocaleString(),
|
|
203
|
+
name: d.device.name,
|
|
204
|
+
address: r.geofenceName || r.position.address
|
|
205
|
+
}
|
|
206
|
+
}))
|
|
207
|
+
})
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return {
|
|
211
|
+
headers,
|
|
212
|
+
data,
|
|
213
|
+
settings
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function exportRefuelingReportToPDF (userData, reportData) {
|
|
218
|
+
console.log('Export to PDF')
|
|
219
|
+
}
|
|
220
|
+
|
|
178
221
|
exports.createRefuelingReport = createRefuelingReport
|
|
179
222
|
exports.calculateRefuelingPositions = calculateRefuelingPositions
|
|
223
|
+
exports.exportRefuelingReportToPDF = exportRefuelingReportToPDF
|
|
224
|
+
exports.exportRefuelingReportToExcel = exportRefuelingReportToExcel
|
package/src/speeding-report.js
CHANGED
|
@@ -76,11 +76,11 @@ async function createSpeedingReportByDevice (from, to, userData, traccarInstance
|
|
|
76
76
|
xpert: devices.filter(d => d && d.attributes && d.attributes.xpert).length > 0
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
const sliced = automaticReports.sliceArray(devices,
|
|
79
|
+
const sliced = automaticReports.sliceArray(devices, 20)
|
|
80
80
|
|
|
81
81
|
let deviceCount = 0
|
|
82
82
|
for (const slice of sliced) {
|
|
83
|
-
const { routes, events } = await getEvents(traccarInstance, from, to, slice, userData, deviceCount, devices.length)
|
|
83
|
+
const { routes, events } = await getEvents(traccarInstance, from, to, slice, userData, deviceCount, devices.length, slice.length)
|
|
84
84
|
if (events.length > 0) {
|
|
85
85
|
const devicesProcessed = await processDevices(from, to, slice, events, routes, userData)
|
|
86
86
|
allData.devices.push(...devicesProcessed)
|
|
@@ -110,15 +110,18 @@ async function createSpeedingReportByDriver (from, to, userData, traccarInstance
|
|
|
110
110
|
return { drivers: await processDrivers(from, to, events, routes, userData) }
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
async function getEvents (traccarInstance, from, to, devices, userData, deviceCount, totalDevices) {
|
|
113
|
+
async function getEvents (traccarInstance, from, to, devices, userData, deviceCount, totalDevices, sliceSize) {
|
|
114
114
|
const geofencesFeatures = userData.geofences.filter(g => g.area.startsWith('POLYGON') &&
|
|
115
115
|
g.attributes.speedLimit).map(g => convertToFeature(g))
|
|
116
116
|
|
|
117
|
-
const allInOne = await traccarHelper.getAllInOne(traccarInstance, from, to, devices, true, false,
|
|
117
|
+
const allInOne = await traccarHelper.getAllInOne(traccarInstance, from, to, devices, true, false,
|
|
118
|
+
false, false, deviceCount, totalDevices, sliceSize)
|
|
118
119
|
const routes = allInOne.route
|
|
119
120
|
|
|
120
121
|
const events = []
|
|
121
|
-
if (
|
|
122
|
+
if (userData.roadSpeedLimits) {
|
|
123
|
+
events.push(...await getHereEvents(devices, routes, userData.maxSpeedThreshold))
|
|
124
|
+
} else if (!userData.useVehicleSpeedLimit && userData.customSpeed) {
|
|
122
125
|
events.push(...await getCustomSpeedLimitEvents(devices, routes, userData.customSpeed))
|
|
123
126
|
} else {
|
|
124
127
|
const traccarEvents = await traccarHelper.getEvents(traccarInstance, from, to, devices, eventTypes)
|
|
@@ -129,10 +132,6 @@ async function getEvents (traccarInstance, from, to, devices, userData, deviceCo
|
|
|
129
132
|
events.push(...traccarEvents)
|
|
130
133
|
}
|
|
131
134
|
}
|
|
132
|
-
|
|
133
|
-
if (userData.roadSpeedLimits) {
|
|
134
|
-
events.push(...await getHereEvents(devices, routes, userData.maxSpeedThreshold))
|
|
135
|
-
}
|
|
136
135
|
return { routes, events }
|
|
137
136
|
}
|
|
138
137
|
|
|
@@ -276,42 +275,48 @@ async function getCustomSpeedLimitEvents (devices, routes, customSpeed) {
|
|
|
276
275
|
async function getHereEvents (devices, routes, threshold) {
|
|
277
276
|
console.log('here speed limit events')
|
|
278
277
|
const events = []
|
|
279
|
-
|
|
278
|
+
const promises = devices.map(d => new Promise((resolve) => {
|
|
280
279
|
const positions = routes.filter(p => p.deviceId === d.id)
|
|
281
280
|
if (!positions.length) {
|
|
282
281
|
console.log('no positions on device', d.name)
|
|
283
|
-
|
|
282
|
+
resolve()
|
|
284
283
|
}
|
|
285
284
|
let hereAlerts = null
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
}
|
|
297
|
-
})
|
|
298
|
-
if (!hereAlerts.length) {
|
|
299
|
-
console.log('empty array after filter on device', d.name)
|
|
300
|
-
continue
|
|
301
|
-
}
|
|
302
|
-
const reduced = hereAlerts.length < 2
|
|
303
|
-
? hereAlerts
|
|
304
|
-
: hereAlerts.reduce((acc, cur, idx, src) => {
|
|
305
|
-
if (idx === 1) {
|
|
306
|
-
return [cur]
|
|
307
|
-
}
|
|
308
|
-
if (cur.timestamp - src[idx - 1].timestamp > 300000 || cur.roadSpeedLimit !== src[idx - 1].roadSpeedLimit) {
|
|
309
|
-
return acc.concat(cur)
|
|
285
|
+
here.routeMatch(positions).then(results => {
|
|
286
|
+
hereAlerts = results.filter(r => r.currentSpeedKmh > (parseInt(r.speedLimit) + threshold)).map(r => {
|
|
287
|
+
const position = positions.find(p => new Date(p.fixTime).getTime() === r.timestamp)
|
|
288
|
+
return {
|
|
289
|
+
...r,
|
|
290
|
+
roadSpeedLimit: r.speedLimit,
|
|
291
|
+
deviceId: d.id,
|
|
292
|
+
position,
|
|
293
|
+
positionId: position && position.id,
|
|
294
|
+
attributes: { speedLimit: r.speedLimit, speed: r.currentSpeedKmh / 1.85200 }
|
|
310
295
|
}
|
|
311
|
-
return acc
|
|
312
296
|
})
|
|
313
|
-
|
|
314
|
-
|
|
297
|
+
if (!hereAlerts.length) {
|
|
298
|
+
console.log('empty array after filter on device', d.name)
|
|
299
|
+
resolve()
|
|
300
|
+
}
|
|
301
|
+
const reduced = hereAlerts.length < 2
|
|
302
|
+
? hereAlerts
|
|
303
|
+
: hereAlerts.reduce((acc, cur, idx, src) => {
|
|
304
|
+
if (idx === 1) {
|
|
305
|
+
return [cur]
|
|
306
|
+
}
|
|
307
|
+
if (cur.timestamp - src[idx - 1].timestamp > 300000 || cur.roadSpeedLimit !== src[idx - 1].roadSpeedLimit) {
|
|
308
|
+
return acc.concat(cur)
|
|
309
|
+
}
|
|
310
|
+
return acc
|
|
311
|
+
})
|
|
312
|
+
events.push(...reduced)
|
|
313
|
+
resolve()
|
|
314
|
+
}).catch(e => {
|
|
315
|
+
console.error(e)
|
|
316
|
+
resolve()
|
|
317
|
+
})
|
|
318
|
+
}))
|
|
319
|
+
await Promise.all(promises)
|
|
315
320
|
return events
|
|
316
321
|
}
|
|
317
322
|
|
|
@@ -376,6 +381,7 @@ async function exportSpeedingReportToPDF (userData, reportData) {
|
|
|
376
381
|
|
|
377
382
|
if (overspeedData) {
|
|
378
383
|
let first = true
|
|
384
|
+
// eslint-disable-next-line new-cap
|
|
379
385
|
const doc = new jsPDF.jsPDF('l', undefined, undefined, true)
|
|
380
386
|
await headerFromUser(doc, translations.report.titleSpeedingReport, userData.user)
|
|
381
387
|
|