fleetmap-reports 1.0.287 → 1.0.288
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/.idea/codeStyles/codeStyleConfig.xml +5 -0
- package/.idea/jsLibraryMappings.xml +6 -0
- package/.idea/modules.xml +1 -1
- package/.idea/vcs.xml +1 -1
- package/{.idea/fleetmap-reports.iml → fleetmap-reports.iml} +1 -2
- package/lang/enGB.js +2 -12
- package/lang/esCL.js +1 -10
- package/lang/index.js +1 -4
- package/lang/ptBR.js +1 -11
- package/lang/ptPT.js +1 -11
- package/package.json +1 -2
- package/src/activity-report.js +206 -542
- package/src/automaticReports.js +1 -1
- package/src/events-report.js +21 -25
- package/src/here.js +1 -1
- package/src/index.js +2 -12
- package/src/index.test.js +27 -60
- package/src/kms-report.js +103 -409
- package/src/location-report.js +18 -22
- package/src/refueling-report.js +1 -11
- package/src/reportStyle.js +0 -26
- package/src/speeding-report.js +180 -232
- package/src/trip-report.js +159 -152
- package/src/util/driver.js +13 -5
- package/src/util/utils.js +1 -67
- package/src/zone-report.js +23 -22
- package/.idea/aws.xml +0 -17
- package/.idea/runConfigurations.xml +0 -10
- package/.idea/shelf/Uncommitted_changes_before_Update_at_13_01_2022,_12_06_[Changes]/shelved.patch +0 -111
- package/.idea/shelf/Uncommitted_changes_before_Update_at_13_01_2022__12_06__Changes_.xml +0 -4
- package/.idea/workspace.xml +0 -515
- package/src/idle-report.js +0 -285
- package/src/tests/index.js +0 -22
- package/src/util/pdfDocument.js +0 -58
- package/src/util/traccar.js +0 -72
- package/src/util/trips.js +0 -76
package/src/trip-report.js
CHANGED
|
@@ -1,151 +1,158 @@
|
|
|
1
|
-
const automaticReports = require("./automaticReports")
|
|
2
|
-
const messages = require('../lang')
|
|
3
|
-
const jsPDF = require('jspdf')
|
|
4
|
-
const {convertMS
|
|
5
|
-
require('jspdf-autotable')
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const {getStyle} = require("./reportStyle")
|
|
10
|
-
const traccar = require("./util/traccar")
|
|
11
|
-
const trips = require("./util/trips");
|
|
12
|
-
const {isInsideTimetable, addNearestPOIs} = require("./util/trips");
|
|
13
|
-
|
|
1
|
+
const automaticReports = require("./automaticReports");
|
|
2
|
+
const messages = require('../lang');
|
|
3
|
+
const jsPDF = require('jspdf');
|
|
4
|
+
const {convertMS} = require("./util/utils");
|
|
5
|
+
const autotable = require('jspdf-autotable');
|
|
6
|
+
const {coordsDistance} = require("./util/utils");
|
|
7
|
+
const reportStyle = require("./reportStyle")
|
|
8
|
+
const drivers = require("./util/driver");
|
|
14
9
|
|
|
15
10
|
let traccarInstance
|
|
16
|
-
let userData
|
|
17
11
|
|
|
18
12
|
const fileName = 'TripReport'
|
|
19
13
|
|
|
20
|
-
async function createTripReport(from, to,
|
|
14
|
+
async function createTripReport(from, to, userData, traccar) {
|
|
21
15
|
console.log('Create TripReport')
|
|
22
|
-
|
|
16
|
+
|
|
23
17
|
traccarInstance = traccar
|
|
24
18
|
const reportData = []
|
|
25
19
|
|
|
26
|
-
if
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
reportData.push(report)
|
|
20
|
+
if(userData.byDriver){
|
|
21
|
+
const allData = await createTripReportByDriver(from, to, userData)
|
|
22
|
+
reportData.push(allData)
|
|
30
23
|
}
|
|
31
|
-
else if
|
|
24
|
+
else if(userData.byGroup){
|
|
32
25
|
console.log("ByGroup")
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
26
|
+
for (const g of userData.groups) {
|
|
27
|
+
const devices = userData.devices.filter(d => d.groupId === g.id)
|
|
28
|
+
console.log(g.name + ' devices:' + devices.length)
|
|
29
|
+
if(devices.length > 0) {
|
|
30
|
+
const groupData = {
|
|
31
|
+
devices: [],
|
|
32
|
+
group: g,
|
|
33
|
+
xpert: devices.filter(d => d.attributes.xpert).length > 0
|
|
34
|
+
}
|
|
40
35
|
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
const response = await traccarInstance.reports.reportsTripsGet(from, to, null, [g.id])
|
|
37
|
+
const data = response.data
|
|
43
38
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const allData = {
|
|
47
|
-
devices: [],
|
|
48
|
-
xpert: devices.filter(d => d.attributes.xpert).length > 0
|
|
49
|
-
}
|
|
39
|
+
const stopsResponse = await traccarInstance.reports.reportsStopsGet(from, to, null, [g.id])
|
|
40
|
+
const stopsData = stopsResponse.data
|
|
50
41
|
|
|
51
|
-
|
|
42
|
+
devices.sort((a, b) => (a.name > b.name) ? 1 : -1)
|
|
52
43
|
|
|
53
|
-
|
|
54
|
-
const data = await traccar.getTrips(traccarInstance, from, to, devicesToSlice)
|
|
55
|
-
const stopsData = await traccar.getStops(traccarInstance, from, to, devicesToSlice)
|
|
44
|
+
if (data.length > 0) {
|
|
56
45
|
|
|
57
|
-
|
|
46
|
+
console.log('Trips:' + data.length)
|
|
47
|
+
groupData.devices = processDevices(from, to, devices, data, stopsData)
|
|
58
48
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
49
|
+
reportData.push(groupData)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
62
53
|
}
|
|
63
54
|
|
|
64
|
-
|
|
65
|
-
|
|
55
|
+
const groupIds = userData.groups.map(g => g.id)
|
|
56
|
+
const withoutGroupDevices = userData.byGroup ? userData.devices.filter(d => !groupIds.includes(d.groupId)) : userData.devices
|
|
66
57
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
console.log(g.name + ' devices:' + devices.length)
|
|
72
|
-
if(devices.length > 0) {
|
|
73
|
-
const groupData = {
|
|
74
|
-
devices: [],
|
|
75
|
-
group: g,
|
|
76
|
-
xpert: devices.filter(d => d.attributes.xpert).length > 0
|
|
77
|
-
}
|
|
58
|
+
const allData = {
|
|
59
|
+
devices: [],
|
|
60
|
+
xpert: withoutGroupDevices.filter(d => d.attributes.xpert).length > 0
|
|
61
|
+
}
|
|
78
62
|
|
|
79
|
-
|
|
80
|
-
|
|
63
|
+
withoutGroupDevices.sort((a, b) => (a.name > b.name) ? 1 : -1)
|
|
64
|
+
const devicesToSlice = withoutGroupDevices.slice()
|
|
81
65
|
|
|
82
|
-
|
|
83
|
-
|
|
66
|
+
const arrayOfArrays = automaticReports.sliceArray(devicesToSlice)
|
|
67
|
+
let data = []
|
|
68
|
+
let stopsData = []
|
|
69
|
+
for (const a of arrayOfArrays) {
|
|
70
|
+
const response = await traccarInstance.reports.reportsTripsGet(from, to, a.map(d => d.id))
|
|
71
|
+
data = data.concat(response.data)
|
|
84
72
|
|
|
85
|
-
|
|
73
|
+
const stopsResponse = await traccarInstance.reports.reportsStopsGet(from, to, a.map(d => d.id))
|
|
74
|
+
stopsData = stopsResponse.data
|
|
75
|
+
}
|
|
86
76
|
|
|
87
|
-
|
|
88
|
-
console.log('Trips:' + tripsData.length)
|
|
89
|
-
groupData.devices = processDevices(from, to, devices, tripsData, stopsData, userData)
|
|
77
|
+
console.log('Trips:' + data.length)
|
|
90
78
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
79
|
+
if (data.length === 0) {
|
|
80
|
+
return reportData
|
|
94
81
|
}
|
|
95
82
|
|
|
96
|
-
|
|
97
|
-
const withoutGroupDevices = userData.devices.filter(d => !groupIds.includes(d.groupId))
|
|
83
|
+
allData.devices = processDevices(from, to, withoutGroupDevices, data, stopsData, userData)
|
|
98
84
|
|
|
99
|
-
const allData = await createTripReportByDevice(from, to, withoutGroupDevices)
|
|
100
85
|
reportData.push(allData)
|
|
101
86
|
|
|
102
87
|
return reportData
|
|
103
88
|
}
|
|
104
89
|
|
|
105
|
-
async function createTripReportByDriver(from, to){
|
|
106
|
-
|
|
107
|
-
|
|
90
|
+
async function createTripReportByDriver(from, to, userData){
|
|
91
|
+
|
|
92
|
+
const deviceIds = await drivers.devicesByDriver(traccarInstance, from, to, userData.drivers, userData.devices)
|
|
93
|
+
console.log(deviceIds.length)
|
|
94
|
+
|
|
95
|
+
let tripsData = []
|
|
96
|
+
if(deviceIds.length > 0) {
|
|
97
|
+
const response = await traccarInstance.reports.reportsTripsGet(from, to, deviceIds)
|
|
98
|
+
tripsData = response.data
|
|
99
|
+
}
|
|
108
100
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return { drivers:[] }
|
|
101
|
+
const allData = {
|
|
102
|
+
drivers: []
|
|
112
103
|
}
|
|
113
104
|
|
|
114
|
-
|
|
105
|
+
allData.drivers = processDrivers(from, to, userData.drivers, tripsData)
|
|
115
106
|
|
|
116
|
-
return
|
|
107
|
+
return allData
|
|
117
108
|
}
|
|
118
109
|
|
|
119
|
-
function processDevices(from, to, devices, data, stopsData) {
|
|
110
|
+
function processDevices(from, to, devices, data, stopsData, userData) {
|
|
120
111
|
const devicesResult = []
|
|
121
112
|
|
|
122
113
|
devices.forEach(d => {
|
|
123
|
-
const trips = data.filter(t => t.deviceId === d.id
|
|
124
|
-
&& (userData.allWeek || !userData.weekDays || isInsideTimetable(t, userData)))
|
|
114
|
+
const trips = data.filter(t => t.deviceId === d.id)
|
|
125
115
|
const stops = stopsData.filter(s => s.deviceId === d.id)
|
|
126
116
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
trips.forEach(trip => {
|
|
117
|
+
trips.forEach(t => {
|
|
118
|
+
t.totalKms = t.distance / 1000
|
|
130
119
|
if (automaticReports.deviceWithFuelInfo(d)) {
|
|
131
|
-
|
|
132
|
-
|
|
120
|
+
t.fuelConsumption = Math.round((t.spentFuel * d.attributes.fuel_tank_capacity) / 100)
|
|
121
|
+
t.avgFuelConsumption = t.totalKms > 0 ? Math.round(t.fuelConsumption * 100 / t.totalKms) : 0
|
|
133
122
|
} else {
|
|
134
|
-
|
|
135
|
-
|
|
123
|
+
t.fuelConsumption = '-'
|
|
124
|
+
t.avgFuelConsumption = '-'
|
|
136
125
|
}
|
|
137
126
|
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
127
|
+
const distance = userData.geofences
|
|
128
|
+
.filter(g => g && g.area.startsWith('CIRCLE'))
|
|
129
|
+
.map(g => {
|
|
130
|
+
const str = g.area.substring('CIRCLE ('.length, g.area.indexOf(','))
|
|
131
|
+
const coord = str.trim().split(' ')
|
|
132
|
+
return {
|
|
133
|
+
p: g,
|
|
134
|
+
distance: Math.round(coordsDistance(parseFloat(coord[1]), parseFloat(coord[0]), t.endLon, t.endLat))
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
const nearestPOIs = distance.filter(a => a.distance < 100).sort((a, b) => (a.distance > b.distance) ? 1 : -1)
|
|
138
|
+
if (nearestPOIs.length > 0) {
|
|
139
|
+
t.endPOIName = nearestPOIs[0].p.name
|
|
145
140
|
}
|
|
146
141
|
})
|
|
147
142
|
|
|
148
143
|
if (trips.length > 0) {
|
|
144
|
+
trips.forEach(function(trip, index) {
|
|
145
|
+
const stop = stops.length+1 > index ? stops[index+1] : null
|
|
146
|
+
|
|
147
|
+
if (stop) {
|
|
148
|
+
trip.stopDuration = (new Date(stop.endTime) - new Date(stop.startTime))
|
|
149
|
+
trip.stopEngineHours = stop.engineHours
|
|
150
|
+
} else {
|
|
151
|
+
trip.stopDuration = 0
|
|
152
|
+
trip.stopEngineHours = 0
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
|
|
149
156
|
const deviceData = {
|
|
150
157
|
device: d,
|
|
151
158
|
from: from,
|
|
@@ -173,12 +180,11 @@ function processDrivers(from, to, drivers, data) {
|
|
|
173
180
|
console.log(data)
|
|
174
181
|
const driversResult = []
|
|
175
182
|
drivers.forEach(d => {
|
|
176
|
-
const trips = data.filter(t => t.driverUniqueId === d.uniqueId
|
|
177
|
-
&& (userData.allWeek || !userData.weekDays || isInsideTimetable(t, userData)))
|
|
178
|
-
|
|
179
|
-
trips.sort((a,b)=>new Date(a.startTime).getTime()-new Date(b.startTime).getTime())
|
|
183
|
+
const trips = data.filter(t => t.driverUniqueId === d.uniqueId)
|
|
180
184
|
|
|
181
|
-
|
|
185
|
+
trips.forEach(t => {
|
|
186
|
+
t.totalKms = t.distance / 1000
|
|
187
|
+
})
|
|
182
188
|
|
|
183
189
|
if (trips.length > 0) {
|
|
184
190
|
const driverData = {
|
|
@@ -187,22 +193,22 @@ function processDrivers(from, to, drivers, data) {
|
|
|
187
193
|
to: to,
|
|
188
194
|
totalDuration: trips.reduce((a, b) => a + b.duration, 0),
|
|
189
195
|
totalDistance: trips.reduce((a, b) => a + b.distance, 0),
|
|
190
|
-
maxSpeed: trips.reduce((a, b) => {
|
|
196
|
+
maxSpeed: trips.reduce((a, b) => {
|
|
197
|
+
return a > b.maxSpeed ? a : b.maxSpeed
|
|
198
|
+
}, 0),
|
|
191
199
|
trips: trips,
|
|
192
200
|
}
|
|
193
201
|
driversResult.push(driverData)
|
|
194
202
|
}
|
|
195
203
|
})
|
|
196
|
-
console.log(driversResult)
|
|
197
204
|
|
|
198
205
|
return driversResult
|
|
199
206
|
}
|
|
200
207
|
|
|
201
|
-
|
|
208
|
+
function exportTripReportToPDF(userData, reportData) {
|
|
202
209
|
console.log('Export to PDF')
|
|
203
210
|
|
|
204
211
|
const lang = userData.user.attributes.lang
|
|
205
|
-
const timezone = userData.user.attributes.timezone
|
|
206
212
|
const translations = messages[lang] ? messages[lang] : messages['en-GB']
|
|
207
213
|
const tripsData = userData.byDriver ? reportData.drivers : reportData.devices
|
|
208
214
|
|
|
@@ -229,38 +235,29 @@ async function exportTripReportToPDF(userData, reportData) {
|
|
|
229
235
|
}
|
|
230
236
|
|
|
231
237
|
if (tripsData) {
|
|
238
|
+
let first = true
|
|
232
239
|
const doc = new jsPDF.jsPDF('l');
|
|
233
|
-
|
|
240
|
+
doc.setFontSize(14)
|
|
241
|
+
doc.text(translations.report.titleTripReport, 15, 15 )
|
|
234
242
|
|
|
235
|
-
|
|
236
|
-
|
|
243
|
+
for(const d of tripsData){
|
|
244
|
+
let data = []
|
|
237
245
|
const name = userData.byDriver ? d.driver.name : deviceName(d.device)
|
|
238
246
|
const group = userData.byDriver ? userData.groups.find(g => g.drivers.includes(d.id)) : userData.groups.find(g => d.device.groupId === g.id)
|
|
239
247
|
|
|
240
|
-
let space =
|
|
241
|
-
if(
|
|
248
|
+
let space = 0
|
|
249
|
+
if(!first) {
|
|
242
250
|
doc.addPage()
|
|
251
|
+
} else {
|
|
252
|
+
first = false
|
|
253
|
+
space = 10
|
|
243
254
|
}
|
|
244
|
-
|
|
245
|
-
doc.setFontSize(13)
|
|
255
|
+
doc.setFontSize(12)
|
|
246
256
|
doc.text(name, 20, space+20 )
|
|
247
|
-
doc.setFontSize(
|
|
257
|
+
doc.setFontSize(10)
|
|
248
258
|
doc.text(group ? translations.report.group + ': ' + group.name : '', 200, space+20 )
|
|
249
|
-
doc.text(
|
|
250
|
-
|
|
251
|
-
doc.text((userData.weekDays.monday ? ' ' + translations.report.monday + ',' : '')
|
|
252
|
-
+ (userData.weekDays.tuesday ? ' ' + translations.report.tuesday + ',' : '')
|
|
253
|
-
+ (userData.weekDays.wednesday ? ' ' + translations.report.wednesday + ',' : '')
|
|
254
|
-
+ (userData.weekDays.thursday ? ' ' + translations.report.thursday + ',' : '')
|
|
255
|
-
+ (userData.weekDays.friday ? ' ' + translations.report.friday + ',' : '')
|
|
256
|
-
+ (userData.weekDays.saturday ? ' ' + translations.report.saturday + ',' : '')
|
|
257
|
-
+ (userData.weekDays.sunday ? ' ' + translations.report.sunday + ',' : '')
|
|
258
|
-
+ ' das '
|
|
259
|
-
+ userData.dayHours.startTime + ' - ' + userData.dayHours.endTime, 20, space + 30)
|
|
260
|
-
doc.text(translations.report.headerStartAddress + ': ' + d.trips[0].startAddress, 20, space+40 )
|
|
261
|
-
} else {
|
|
262
|
-
doc.text(translations.report.headerStartAddress + ': ' + d.trips[0].startAddress, 20, space+35 )
|
|
263
|
-
}
|
|
259
|
+
doc.text(new Date(d.from).toLocaleString() + ' - ' + new Date(d.to).toLocaleString(), 20, space+25 )
|
|
260
|
+
doc.text(translations.report.headerStartAddress + ': ' + d.trips[0].startAddress, 20, space+30 )
|
|
264
261
|
|
|
265
262
|
d.trips.map(a => {
|
|
266
263
|
const temp = [
|
|
@@ -291,6 +288,7 @@ async function exportTripReportToPDF(userData, reportData) {
|
|
|
291
288
|
'Total:' + d.trips.length,
|
|
292
289
|
'','','',
|
|
293
290
|
convertMS(d.trips.reduce((a, b) => a + b.duration, 0)),
|
|
291
|
+
|
|
294
292
|
]
|
|
295
293
|
|
|
296
294
|
if(userData.byDriver) {
|
|
@@ -305,9 +303,25 @@ async function exportTripReportToPDF(userData, reportData) {
|
|
|
305
303
|
getMaxSpeed(d.trips))
|
|
306
304
|
}
|
|
307
305
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
306
|
+
doc.autoTable({
|
|
307
|
+
head: [headers],
|
|
308
|
+
body: data,
|
|
309
|
+
foot: [footValues],
|
|
310
|
+
showFoot: 'lastPage',
|
|
311
|
+
headStyles: {
|
|
312
|
+
fillColor: reportStyle.pdfHeaderColor,
|
|
313
|
+
textColor: reportStyle.pdfHeaderTextColor
|
|
314
|
+
},
|
|
315
|
+
bodyStyles: {
|
|
316
|
+
fillColor: reportStyle.pdfBodyColor,
|
|
317
|
+
textColor: reportStyle.pdfBodyTextColor
|
|
318
|
+
},
|
|
319
|
+
footStyles: {
|
|
320
|
+
fillColor: reportStyle.pdfFooterColor,
|
|
321
|
+
textColor: reportStyle.pdfFooterTextColor
|
|
322
|
+
},
|
|
323
|
+
startY: space+40 })
|
|
324
|
+
}
|
|
311
325
|
return doc
|
|
312
326
|
}
|
|
313
327
|
}
|
|
@@ -384,17 +398,23 @@ function deviceName(device){
|
|
|
384
398
|
}
|
|
385
399
|
|
|
386
400
|
function getTripDate(user, trip){
|
|
387
|
-
return
|
|
401
|
+
return new Date(trip.startTime).toLocaleDateString(user.attributes.lang, {
|
|
402
|
+
timeZone: user.attributes.timezone,
|
|
403
|
+
hour12: false
|
|
404
|
+
})
|
|
388
405
|
}
|
|
389
|
-
|
|
390
406
|
function getTripStart(user, trip){
|
|
391
|
-
return
|
|
407
|
+
return new Date(trip.startTime).toLocaleTimeString(user.attributes.lang, {
|
|
408
|
+
timeZone: user.attributes.timezone,
|
|
409
|
+
hour12: false
|
|
410
|
+
})
|
|
392
411
|
}
|
|
393
|
-
|
|
394
412
|
function getTripEnd(user, trip){
|
|
395
|
-
return
|
|
413
|
+
return new Date(trip.endTime).toLocaleTimeString(user.attributes.lang, {
|
|
414
|
+
timeZone: user.attributes.timezone,
|
|
415
|
+
hour12: false
|
|
416
|
+
})
|
|
396
417
|
}
|
|
397
|
-
|
|
398
418
|
function getDriverName(drivers, driverUniqueId) {
|
|
399
419
|
if(driverUniqueId) {
|
|
400
420
|
const driver = drivers.find(d => d.uniqueId === driverUniqueId)
|
|
@@ -403,22 +423,18 @@ function getDriverName(drivers, driverUniqueId) {
|
|
|
403
423
|
|
|
404
424
|
return ''
|
|
405
425
|
}
|
|
406
|
-
|
|
407
426
|
function getSumTotalKms(user, data) {
|
|
408
427
|
const values = data.map(item => {
|
|
409
428
|
return item.totalKms ? parseFloat(item.totalKms) : 0
|
|
410
429
|
})
|
|
411
430
|
return Intl.NumberFormat(user.attributes.lang, {maximumFractionDigits: 2}).format(values.reduce((a, b) => a + b, 0))
|
|
412
431
|
}
|
|
413
|
-
|
|
414
432
|
function getSumAvgSpeed(data) {
|
|
415
433
|
const values = data.map(item => {
|
|
416
|
-
return Math.round(item.averageSpeed * 1.85200)
|
|
434
|
+
return Math.round(item.averageSpeed * 1.85200)
|
|
417
435
|
})
|
|
418
|
-
|
|
419
|
-
return totalKms > 0 ? Math.round((values.reduce((a, b) => a + b, 0)) / totalKms) : 0
|
|
436
|
+
return Math.round((values.reduce((a, b) => a + b, 0)) / data.length)
|
|
420
437
|
}
|
|
421
|
-
|
|
422
438
|
function getMaxSpeed(data) {
|
|
423
439
|
const values = data.map(item => {
|
|
424
440
|
return item.maxSpeed
|
|
@@ -429,15 +445,6 @@ function getMaxSpeed(data) {
|
|
|
429
445
|
return Math.round(max * 1.85200)
|
|
430
446
|
}
|
|
431
447
|
|
|
432
|
-
function getStop(tripEndDate, stops){
|
|
433
|
-
const stopList = stops.filter(s => new Date(s.startTime).getTime() >= tripEndDate.getTime())
|
|
434
|
-
if(stopList.length){
|
|
435
|
-
return stopList[0]
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
return null
|
|
439
|
-
}
|
|
440
|
-
|
|
441
448
|
exports.createTripReport = createTripReport;
|
|
442
449
|
exports.exportTripReportToPDF = exportTripReportToPDF;
|
|
443
450
|
exports.exportTripReportToExcel = exportTripReportToExcel;
|
package/src/util/driver.js
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
|
-
const
|
|
1
|
+
const automaticReports = require("../automaticReports")
|
|
2
2
|
|
|
3
3
|
//get devices used by each driver between two dates
|
|
4
|
-
async function devicesByDriver(
|
|
5
|
-
|
|
4
|
+
async function devicesByDriver(traccar, from, to, drivers, devices){
|
|
5
|
+
let eventsData = []
|
|
6
|
+
let tripsData = []
|
|
7
|
+
const arrayOfArrays = automaticReports.sliceArray(devices)
|
|
8
|
+
for (const a of arrayOfArrays) {
|
|
9
|
+
const response = await traccar.reports.reportsEventsGet(from, to, a.map(d => d.id), null, ['driverChanged'])
|
|
10
|
+
eventsData = eventsData.concat(response.data)
|
|
11
|
+
}
|
|
12
|
+
|
|
6
13
|
const deviceIds = []
|
|
7
14
|
for(const d of drivers) {
|
|
8
15
|
const events = eventsData.filter(e => {
|
|
9
16
|
return e.attributes.driverUniqueId === d.uniqueId
|
|
10
17
|
})
|
|
11
18
|
|
|
12
|
-
deviceIds.push(
|
|
19
|
+
deviceIds.push(events.map(e => e.deviceId))
|
|
13
20
|
}
|
|
14
|
-
|
|
21
|
+
|
|
22
|
+
return [...new Set(deviceIds.flat())]
|
|
15
23
|
}
|
|
16
24
|
|
|
17
25
|
exports.devicesByDriver = devicesByDriver
|
package/src/util/utils.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
const turf = require('turf')
|
|
3
3
|
|
|
4
4
|
function convertMS(duration, withSeconds) {
|
|
@@ -29,72 +29,6 @@ function coordsDistance(lon1, lat1, lon2, lat2) {
|
|
|
29
29
|
return (turf.distance(from, to, 'meters'))
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
function getDates(startDate, endDate) {
|
|
33
|
-
const dates = []
|
|
34
|
-
let currentDate = new Date(startDate.toISOString().split('T')[0] + ' 12:00 PM')
|
|
35
|
-
const addDays = function (days) {
|
|
36
|
-
const date = new Date(this.valueOf())
|
|
37
|
-
date.setDate(date.getDate() + days)
|
|
38
|
-
return date
|
|
39
|
-
}
|
|
40
|
-
while (currentDate <= endDate) {
|
|
41
|
-
dates.push(currentDate)
|
|
42
|
-
currentDate = addDays.call(currentDate, 1)
|
|
43
|
-
}
|
|
44
|
-
return dates
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async function getImgFromUrl(hostname) {
|
|
48
|
-
try {
|
|
49
|
-
const img = new Image()
|
|
50
|
-
img.src = '/img/logos/' + hostname + '.png'
|
|
51
|
-
return img
|
|
52
|
-
} catch (e) {
|
|
53
|
-
const response = await axios.get('https://' + hostname + '/img/logos/' + hostname + '.png', { responseType: 'arraybuffer' })
|
|
54
|
-
return Buffer.from(response.data, 'binary').toString('base64')
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function isClientSide() { return (typeof window !== "undefined") }
|
|
59
|
-
|
|
60
|
-
function convertToLocaleString(value, lang, timezone){
|
|
61
|
-
if(isClientSide()){
|
|
62
|
-
return new Date(value).toLocaleString()
|
|
63
|
-
} else {
|
|
64
|
-
return new Date(value).toLocaleString(lang, {
|
|
65
|
-
timeZone: timezone,
|
|
66
|
-
hour12: false
|
|
67
|
-
})
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function convertToLocaleDateString(value, lang, timezone){
|
|
72
|
-
if(isClientSide){
|
|
73
|
-
return new Date(value).toLocaleDateString()
|
|
74
|
-
} else {
|
|
75
|
-
return new Date(value).toLocaleDateString(lang, {
|
|
76
|
-
timeZone: timezone,
|
|
77
|
-
hour12: false
|
|
78
|
-
})
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function convertToLocaleTimeString(value, lang, timezone){
|
|
83
|
-
if(isClientSide){
|
|
84
|
-
return new Date(value).toLocaleTimeString()
|
|
85
|
-
} else {
|
|
86
|
-
return new Date(value).toLocaleTimeString(lang, {
|
|
87
|
-
timeZone: timezone,
|
|
88
|
-
hour12: false
|
|
89
|
-
})
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
exports.getImgFromUrl = getImgFromUrl
|
|
94
32
|
exports.convertMS = convertMS
|
|
95
33
|
exports.coordsDistance = coordsDistance
|
|
96
|
-
exports.getDates = getDates
|
|
97
|
-
exports.convertToLocaleString = convertToLocaleString
|
|
98
|
-
exports.convertToLocaleDateString = convertToLocaleDateString
|
|
99
|
-
exports.convertToLocaleTimeString = convertToLocaleTimeString
|
|
100
34
|
|
package/src/zone-report.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
const moment = require('moment')
|
|
2
2
|
const messages = require('../lang')
|
|
3
3
|
const automaticReports = require("./automaticReports");
|
|
4
|
-
const {convertMS
|
|
4
|
+
const {convertMS} = require("./util/utils")
|
|
5
5
|
const jsPDF = require('jspdf')
|
|
6
6
|
require('jspdf-autotable')
|
|
7
|
-
const
|
|
8
|
-
const {getStyle} = require("./reportStyle")
|
|
9
|
-
const {getUserPartner} = require("fleetmap-partners");
|
|
7
|
+
const reportStyle = require("./reportStyle")
|
|
10
8
|
|
|
11
9
|
const fileName = 'ZoneReport'
|
|
12
10
|
|
|
@@ -146,11 +144,10 @@ async function processDevices(from, to, devices, drivers, geofences, data, tracc
|
|
|
146
144
|
return devicesResult
|
|
147
145
|
}
|
|
148
146
|
|
|
149
|
-
|
|
147
|
+
function exportZoneReportToPDF(userData, reportData) {
|
|
150
148
|
console.log('Export to PDF')
|
|
151
149
|
|
|
152
150
|
const lang = userData.user.attributes.lang
|
|
153
|
-
const timezone = userData.user.attributes.timezone
|
|
154
151
|
const translations = messages[lang] ? messages[lang] : messages['en-GB']
|
|
155
152
|
|
|
156
153
|
const headers = [
|
|
@@ -163,7 +160,9 @@ async function exportZoneReportToPDF(userData, reportData) {
|
|
|
163
160
|
if (reportData.devices) {
|
|
164
161
|
let first = true
|
|
165
162
|
const doc = new jsPDF.jsPDF('l')
|
|
166
|
-
|
|
163
|
+
doc.setFontSize(14)
|
|
164
|
+
doc.text(translations.report.titleActivityReport, 15, 15 )
|
|
165
|
+
|
|
167
166
|
|
|
168
167
|
reportData.devices.forEach(d => {
|
|
169
168
|
let data = []
|
|
@@ -177,11 +176,11 @@ async function exportZoneReportToPDF(userData, reportData) {
|
|
|
177
176
|
first = false
|
|
178
177
|
space = 10
|
|
179
178
|
}
|
|
180
|
-
doc.setFontSize(
|
|
179
|
+
doc.setFontSize(12)
|
|
181
180
|
doc.text(name, 20, space+20 )
|
|
182
|
-
doc.setFontSize(
|
|
181
|
+
doc.setFontSize(10)
|
|
183
182
|
doc.text(group ? translations.report.group + ': ' + group.name : '', 200, space+20 )
|
|
184
|
-
doc.text(
|
|
183
|
+
doc.text(new Date(d.from).toLocaleString() + ' - ' + new Date(d.to).toLocaleString(), 20, space+25 )
|
|
185
184
|
d.geofences.map(a => {
|
|
186
185
|
const temp = [
|
|
187
186
|
geofenceEnter(userData.user, a),
|
|
@@ -197,26 +196,22 @@ async function exportZoneReportToPDF(userData, reportData) {
|
|
|
197
196
|
'Total:' + d.geofences.length
|
|
198
197
|
]
|
|
199
198
|
|
|
200
|
-
const style = getStyle(getUserPartner(userData.user))
|
|
201
199
|
doc.autoTable({
|
|
202
200
|
head: [headers],
|
|
203
201
|
body: data,
|
|
204
202
|
foot: [footValues],
|
|
205
203
|
showFoot: 'lastPage',
|
|
206
204
|
headStyles: {
|
|
207
|
-
fillColor:
|
|
208
|
-
textColor:
|
|
209
|
-
fontSize: 10
|
|
205
|
+
fillColor: reportStyle.pdfHeaderColor,
|
|
206
|
+
textColor: reportStyle.pdfHeaderTextColor
|
|
210
207
|
},
|
|
211
208
|
bodyStyles: {
|
|
212
|
-
fillColor:
|
|
213
|
-
textColor:
|
|
214
|
-
fontSize: 8
|
|
209
|
+
fillColor: reportStyle.pdfBodyColor,
|
|
210
|
+
textColor: reportStyle.pdfBodyTextColor
|
|
215
211
|
},
|
|
216
212
|
footStyles: {
|
|
217
|
-
fillColor:
|
|
218
|
-
textColor:
|
|
219
|
-
fontSize: 9
|
|
213
|
+
fillColor: reportStyle.pdfFooterColor,
|
|
214
|
+
textColor: reportStyle.pdfFooterTextColor
|
|
220
215
|
},
|
|
221
216
|
startY: space+35 });
|
|
222
217
|
})
|
|
@@ -272,10 +267,16 @@ function deviceName(device){
|
|
|
272
267
|
}
|
|
273
268
|
|
|
274
269
|
function geofenceEnter(user, row){
|
|
275
|
-
return row.inTime ?
|
|
270
|
+
return row.inTime ? new Date(row.inTime.fixTime).toLocaleString(user.attributes.lang, {
|
|
271
|
+
timeZone: user.attributes.timezone,
|
|
272
|
+
hour12: false
|
|
273
|
+
}) : ''
|
|
276
274
|
}
|
|
277
275
|
function geofenceExit(user, row){
|
|
278
|
-
return row.outTime ?
|
|
276
|
+
return row.outTime ? new Date(row.outTime.fixTime).toLocaleString(user.attributes.lang, {
|
|
277
|
+
timeZone: user.attributes.timezone,
|
|
278
|
+
hour12: false
|
|
279
|
+
}) : ''
|
|
279
280
|
}
|
|
280
281
|
|
|
281
282
|
exports.createZoneReport = createZoneReport
|