fleetmap-reports 1.0.401 → 1.0.402
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/package.json +1 -1
- package/src/activity-report.js +697 -687
- package/src/trip-report.js +384 -385
- package/src/util/traccar.js +79 -80
package/src/trip-report.js
CHANGED
|
@@ -1,457 +1,456 @@
|
|
|
1
|
-
const automaticReports = require(
|
|
1
|
+
const automaticReports = require('./automaticReports')
|
|
2
2
|
const jsPDF = require('jspdf')
|
|
3
|
-
const {convertMS, convertToLocaleString, convertToLocaleDateString, convertToLocaleTimeString, getTranslations} = require(
|
|
3
|
+
const { convertMS, convertToLocaleString, convertToLocaleDateString, convertToLocaleTimeString, getTranslations } = require('./util/utils')
|
|
4
4
|
require('jspdf-autotable')
|
|
5
|
-
const {getUserPartner} = require(
|
|
6
|
-
const {headerFromUser, addTable} = require(
|
|
7
|
-
const {getStyle} = require(
|
|
8
|
-
const traccarHelper = require(
|
|
9
|
-
const trips = require(
|
|
10
|
-
const {isInsideTimetable, addNearestPOIs, isPartialInsideTimetable, calculateTrip} = require(
|
|
11
|
-
const {devicesToProcess} = require(
|
|
5
|
+
const { getUserPartner } = require('fleetmap-partners')
|
|
6
|
+
const { headerFromUser, addTable } = require('./util/pdfDocument')
|
|
7
|
+
const { getStyle } = require('./reportStyle')
|
|
8
|
+
const traccarHelper = require('./util/traccar')
|
|
9
|
+
const trips = require('./util/trips')
|
|
10
|
+
const { isInsideTimetable, addNearestPOIs, isPartialInsideTimetable, calculateTrip } = require('./util/trips')
|
|
11
|
+
const { devicesToProcess } = require('./util/device')
|
|
12
12
|
|
|
13
13
|
const fileName = 'TripReport'
|
|
14
14
|
|
|
15
|
-
async function createTripReport(from, to, userData, traccar) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return reportData
|
|
15
|
+
async function createTripReport (from, to, userData, traccar) {
|
|
16
|
+
console.log('Create TripReport')
|
|
17
|
+
const reportData = []
|
|
18
|
+
|
|
19
|
+
if (userData.byDriver) {
|
|
20
|
+
console.log('ByDriver')
|
|
21
|
+
const report = await createTripReportByDriver(from, to, userData, traccar)
|
|
22
|
+
reportData.push(report)
|
|
23
|
+
} else if (userData.byGroup) {
|
|
24
|
+
console.log('ByGroup')
|
|
25
|
+
const allData = await createTripReportByGroup(from, to, userData, traccar)
|
|
26
|
+
reportData.push(...allData)
|
|
27
|
+
} else {
|
|
28
|
+
console.log('ByDevice')
|
|
29
|
+
const report = await createTripReportByDevice(from, to, userData, traccar)
|
|
30
|
+
reportData.push(report)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return reportData
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
async function createTripReportByDevice(from, to, userData, traccar) {
|
|
38
|
-
|
|
36
|
+
async function createTripReportByDevice (from, to, userData, traccar) {
|
|
37
|
+
const devices = devicesToProcess(userData)
|
|
39
38
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
const allData = {
|
|
40
|
+
devices: [],
|
|
41
|
+
xpert: devices.filter(d => d.attributes.xpert).length > 0
|
|
42
|
+
}
|
|
44
43
|
|
|
45
|
-
|
|
44
|
+
const sliced = automaticReports.sliceArray(devices, 5)
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
let deviceCount = 0
|
|
47
|
+
for (const slice of sliced) {
|
|
48
|
+
const allInOne = await traccarHelper.getAllInOne(traccar, from, to, slice, true, true, true, false, deviceCount, devices.length)
|
|
49
|
+
const tripsData = allInOne.trips
|
|
50
|
+
const stopsData = allInOne.stops
|
|
51
|
+
const routeData = allInOne.route
|
|
53
52
|
|
|
54
|
-
|
|
53
|
+
console.log('Trips:' + tripsData.length)
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
deviceCount = deviceCount + slice.length
|
|
55
|
+
if (tripsData.length > 0) {
|
|
56
|
+
trips.checkTripsKms(traccar, from, to, slice, { trips: tripsData, route: routeData })
|
|
57
|
+
allData.devices.push(...processDevices(from, to, slice, {
|
|
58
|
+
trips: tripsData,
|
|
59
|
+
stops: stopsData,
|
|
60
|
+
route: routeData
|
|
61
|
+
}, userData))
|
|
65
62
|
}
|
|
63
|
+
deviceCount = deviceCount + slice.length
|
|
64
|
+
}
|
|
66
65
|
|
|
67
|
-
|
|
66
|
+
return allData
|
|
68
67
|
}
|
|
69
68
|
|
|
70
|
-
async function createTripReportByGroup(from, to, userData, traccar) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
69
|
+
async function createTripReportByGroup (from, to, userData, traccar) {
|
|
70
|
+
const reportData = []
|
|
71
|
+
for (const g of userData.groups) {
|
|
72
|
+
const devices = userData.devices.filter(d => d.groupId === g.id)
|
|
73
|
+
console.log(g.name + ' devices:' + devices.length)
|
|
74
|
+
if (devices.length > 0) {
|
|
75
|
+
const groupData = {
|
|
76
|
+
devices: [],
|
|
77
|
+
group: g,
|
|
78
|
+
xpert: devices.filter(d => d.attributes.xpert).length > 0
|
|
79
|
+
}
|
|
81
80
|
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
const response = await traccar.reports.reportsTripsGet(from, to, null, [g.id])
|
|
82
|
+
const tripsData = response.data
|
|
84
83
|
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
const stopsResponse = await traccar.reports.reportsStopsGet(from, to, null, [g.id])
|
|
85
|
+
const stopsData = stopsResponse.data
|
|
87
86
|
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
const routeResponse = await traccar.reports.reportsRouteGet(from, to, null, [g.id])
|
|
88
|
+
const routeData = routeResponse.data
|
|
90
89
|
|
|
91
|
-
|
|
90
|
+
devices.sort((a, b) => (a.name > b.name) ? 1 : -1)
|
|
92
91
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
if (tripsData.length > 0) {
|
|
93
|
+
console.log('Trips:' + tripsData.length)
|
|
94
|
+
groupData.devices = processDevices(from, to, devices, { trips: tripsData, stops: stopsData, route: routeData }, userData)
|
|
96
95
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
96
|
+
reportData.push(groupData)
|
|
97
|
+
}
|
|
100
98
|
}
|
|
99
|
+
}
|
|
101
100
|
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
const allData = await createTripReportByDevice(from, to, userData, traccar)
|
|
102
|
+
reportData.push(allData)
|
|
104
103
|
|
|
105
|
-
|
|
104
|
+
return reportData
|
|
106
105
|
}
|
|
107
106
|
|
|
108
|
-
async function createTripReportByDriver(from, to, userData, traccar){
|
|
109
|
-
|
|
110
|
-
|
|
107
|
+
async function createTripReportByDriver (from, to, userData, traccar) {
|
|
108
|
+
const devices = await traccar.devices.devicesGet().then(d => d.data)
|
|
109
|
+
console.log(devices.length)
|
|
111
110
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
111
|
+
if (!devices.length) {
|
|
112
|
+
// Empty report
|
|
113
|
+
return { drivers: [] }
|
|
114
|
+
}
|
|
116
115
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
116
|
+
const allInOne = await traccarHelper.getAllInOne(traccar, from, to, devices, true, true, false, false)
|
|
117
|
+
const tripsData = allInOne.trips
|
|
118
|
+
const routeData = allInOne.route
|
|
120
119
|
|
|
121
|
-
|
|
120
|
+
return { drivers: processDrivers(from, to, userData, { trips: tripsData, route: routeData }) }
|
|
122
121
|
}
|
|
123
122
|
|
|
123
|
+
function processDevices (from, to, devices, data, userData) {
|
|
124
|
+
const devicesResult = []
|
|
124
125
|
|
|
126
|
+
devices.forEach(d => {
|
|
127
|
+
const deviceRoute = data.route.filter(t => t.deviceId === d.id)
|
|
128
|
+
const deviceTrips = data.trips.filter(t => t.deviceId === d.id)
|
|
125
129
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
if(deviceRoute.length && deviceTrips.length && deviceRoute[deviceRoute.length-1].attributes.ignition) {
|
|
134
|
-
const uncompletedTripRoute = deviceRoute.filter(p => p.attributes.ignition && new Date(p.fixTime).getTime() > new Date(deviceTrips[deviceTrips.length-1].endTime).getTime())
|
|
135
|
-
if(uncompletedTripRoute.length) {
|
|
136
|
-
deviceTrips.push(calculateTrip(d, uncompletedTripRoute))
|
|
137
|
-
}
|
|
138
|
-
}
|
|
130
|
+
if (deviceRoute.length && deviceTrips.length && deviceRoute[deviceRoute.length - 1].attributes.ignition) {
|
|
131
|
+
const uncompletedTripRoute = deviceRoute.filter(p => p.attributes.ignition && new Date(p.fixTime).getTime() > new Date(deviceTrips[deviceTrips.length - 1].endTime).getTime())
|
|
132
|
+
if (uncompletedTripRoute.length) {
|
|
133
|
+
deviceTrips.push(calculateTrip(d, uncompletedTripRoute))
|
|
134
|
+
}
|
|
135
|
+
}
|
|
139
136
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
if (trips.length > 0) {
|
|
165
|
-
const deviceData = {
|
|
166
|
-
device: d,
|
|
167
|
-
from: from,
|
|
168
|
-
to: to,
|
|
169
|
-
totalDuration: trips.reduce((a, b) => a + b.duration, 0),
|
|
170
|
-
totalDistance: trips.reduce((a, b) => a + b.distance, 0),
|
|
171
|
-
maxSpeed: trips.reduce((a, b) => {
|
|
172
|
-
return a > b.maxSpeed ? a : b.maxSpeed
|
|
173
|
-
}, 0),
|
|
174
|
-
trips: trips,
|
|
175
|
-
}
|
|
176
|
-
if (d.attributes.xpert) {
|
|
177
|
-
deviceData.totalFuelConsumption = trips.reduce((a, b) => a + b.fuelConsumption, 0)
|
|
178
|
-
deviceData.avgFuelConsumption = deviceData.totalDistance > 0 ? Math.round((deviceData.totalFuelConsumption * 100) / (deviceData.totalDistance / 1000)) : 0
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
devicesResult.push(deviceData)
|
|
182
|
-
}
|
|
137
|
+
const trips = deviceTrips.filter(t => userData.allWeek || !userData.weekDays || isInsideTimetable(t, userData) || isPartialInsideTimetable(t, userData, deviceRoute))
|
|
138
|
+
const stops = data.stops.filter(s => s.deviceId === d.id)
|
|
139
|
+
|
|
140
|
+
addNearestPOIs(trips, userData)
|
|
141
|
+
|
|
142
|
+
trips.forEach(trip => {
|
|
143
|
+
if (automaticReports.deviceWithFuelInfo(d)) {
|
|
144
|
+
trip.fuelConsumption = Math.round((trip.spentFuel * d.attributes.fuel_tank_capacity) / 100)
|
|
145
|
+
trip.avgFuelConsumption = trip.totalKms > 0 ? Math.round(trip.fuelConsumption * 100 / trip.totalKms) : 0
|
|
146
|
+
} else {
|
|
147
|
+
trip.fuelConsumption = '-'
|
|
148
|
+
trip.avgFuelConsumption = '-'
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const stop = getStop(new Date(trip.startTime), stops)
|
|
152
|
+
if (stop && !trip.endTimeIsOut) {
|
|
153
|
+
trip.stopDuration = (new Date(stop.endTime) - new Date(stop.startTime))
|
|
154
|
+
trip.stopEngineHours = stop.engineHours
|
|
155
|
+
} else {
|
|
156
|
+
trip.stopDuration = 0
|
|
157
|
+
trip.stopEngineHours = 0
|
|
158
|
+
}
|
|
183
159
|
})
|
|
184
160
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
totalDuration: trips.reduce((a, b) => a + b.duration, 0),
|
|
206
|
-
totalDistance: trips.reduce((a, b) => a + b.distance, 0),
|
|
207
|
-
maxSpeed: trips.reduce((a, b) => { return a > b.maxSpeed ? a : b.maxSpeed }, 0),
|
|
208
|
-
trips: trips,
|
|
209
|
-
}
|
|
210
|
-
driversResult.push(driverData)
|
|
211
|
-
}
|
|
212
|
-
})
|
|
213
|
-
console.log(driversResult)
|
|
161
|
+
if (trips.length > 0) {
|
|
162
|
+
const deviceData = {
|
|
163
|
+
device: d,
|
|
164
|
+
from,
|
|
165
|
+
to,
|
|
166
|
+
totalDuration: trips.reduce((a, b) => a + b.duration, 0),
|
|
167
|
+
totalDistance: trips.reduce((a, b) => a + b.distance, 0),
|
|
168
|
+
maxSpeed: trips.reduce((a, b) => {
|
|
169
|
+
return a > b.maxSpeed ? a : b.maxSpeed
|
|
170
|
+
}, 0),
|
|
171
|
+
trips
|
|
172
|
+
}
|
|
173
|
+
if (d.attributes.xpert) {
|
|
174
|
+
deviceData.totalFuelConsumption = trips.reduce((a, b) => a + b.fuelConsumption, 0)
|
|
175
|
+
deviceData.avgFuelConsumption = deviceData.totalDistance > 0 ? Math.round((deviceData.totalFuelConsumption * 100) / (deviceData.totalDistance / 1000)) : 0
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
devicesResult.push(deviceData)
|
|
179
|
+
}
|
|
180
|
+
})
|
|
214
181
|
|
|
215
|
-
|
|
182
|
+
return devicesResult
|
|
216
183
|
}
|
|
217
184
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
const
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
translations.report.stopTime,
|
|
242
|
-
translations.report.distance,
|
|
243
|
-
translations.report.avgSpeed,
|
|
244
|
-
translations.report.maxSpeed,
|
|
245
|
-
translations.report.driver)
|
|
185
|
+
function processDrivers (from, to, userData, data) {
|
|
186
|
+
console.log(data)
|
|
187
|
+
const driversResult = []
|
|
188
|
+
userData.drivers.forEach(d => {
|
|
189
|
+
const route = data.route.filter(p => p.attributes.driverUniqueId === d.uniqueId)
|
|
190
|
+
const trips = data.trips.filter(t => t.driverUniqueId === d.uniqueId &&
|
|
191
|
+
(userData.allWeek || !userData.weekDays || isInsideTimetable(t, userData) || isPartialInsideTimetable(t, userData, route)))
|
|
192
|
+
|
|
193
|
+
trips.sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime())
|
|
194
|
+
|
|
195
|
+
addNearestPOIs(trips, userData)
|
|
196
|
+
|
|
197
|
+
if (trips.length > 0) {
|
|
198
|
+
const driverData = {
|
|
199
|
+
driver: d,
|
|
200
|
+
from,
|
|
201
|
+
to,
|
|
202
|
+
totalDuration: trips.reduce((a, b) => a + b.duration, 0),
|
|
203
|
+
totalDistance: trips.reduce((a, b) => a + b.distance, 0),
|
|
204
|
+
maxSpeed: trips.reduce((a, b) => { return a > b.maxSpeed ? a : b.maxSpeed }, 0),
|
|
205
|
+
trips
|
|
206
|
+
}
|
|
207
|
+
driversResult.push(driverData)
|
|
246
208
|
}
|
|
209
|
+
})
|
|
210
|
+
console.log(driversResult)
|
|
247
211
|
|
|
248
|
-
|
|
249
|
-
const doc = new jsPDF.jsPDF('l');
|
|
250
|
-
await headerFromUser(doc, translations.report.titleTripReport, userData.user)
|
|
251
|
-
|
|
252
|
-
tripsData.forEach(function (d, index) {
|
|
253
|
-
const data = []
|
|
254
|
-
const name = userData.byDriver ? d.driver.name : deviceName(d.device)
|
|
255
|
-
const group = userData.byDriver ? userData.groups.find(g => g.drivers.includes(d.id)) : userData.groups.find(g => d.device.groupId === g.id)
|
|
256
|
-
|
|
257
|
-
let space = index === 0 ? 8 : 0
|
|
258
|
-
if(index){
|
|
259
|
-
doc.addPage()
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
doc.setFontSize(13)
|
|
263
|
-
doc.text(name, 20, space+20 )
|
|
264
|
-
doc.setFontSize(11)
|
|
265
|
-
doc.text(group ? translations.report.group + ': ' + group.name : '', 200, space+20 )
|
|
266
|
-
doc.text(convertToLocaleString(d.from, lang, timezone) + ' - ' + convertToLocaleString(d.to, lang, timezone), 20, space+25 )
|
|
267
|
-
if(!userData.allWeek && userData.weekDays) {
|
|
268
|
-
doc.text((userData.weekDays.monday ? ' ' + translations.report.monday + ',' : '')
|
|
269
|
-
+ (userData.weekDays.tuesday ? ' ' + translations.report.tuesday + ',' : '')
|
|
270
|
-
+ (userData.weekDays.wednesday ? ' ' + translations.report.wednesday + ',' : '')
|
|
271
|
-
+ (userData.weekDays.thursday ? ' ' + translations.report.thursday + ',' : '')
|
|
272
|
-
+ (userData.weekDays.friday ? ' ' + translations.report.friday + ',' : '')
|
|
273
|
-
+ (userData.weekDays.saturday ? ' ' + translations.report.saturday + ',' : '')
|
|
274
|
-
+ (userData.weekDays.sunday ? ' ' + translations.report.sunday + ',' : '')
|
|
275
|
-
+ ' das '
|
|
276
|
-
+ userData.dayHours.startTime + ' - ' + userData.dayHours.endTime, 20, space + 30)
|
|
277
|
-
doc.text(translations.report.headerStartAddress + ': ' + d.trips[0].startAddress, 20, space+40 )
|
|
278
|
-
} else {
|
|
279
|
-
doc.text(translations.report.headerStartAddress + ': ' + d.trips[0].startAddress, 20, space+35 )
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
d.trips.map(a => {
|
|
283
|
-
const temp = [
|
|
284
|
-
getTripDate(userData.user, a),
|
|
285
|
-
getTripStart(userData.user, a),
|
|
286
|
-
getTripEnd(userData.user, a),
|
|
287
|
-
a.endPOIName || a.endAddress,
|
|
288
|
-
convertMS(a.duration)
|
|
289
|
-
]
|
|
290
|
-
|
|
291
|
-
if(userData.byDriver) {
|
|
292
|
-
temp.push(Intl.NumberFormat(userData.user.attributes.lang, {maximumFractionDigits: 2}).format(a.totalKms),
|
|
293
|
-
Math.round(a.averageSpeed * 1.85200),
|
|
294
|
-
Math.round(a.maxSpeed * 1.85200),
|
|
295
|
-
a.deviceName)
|
|
296
|
-
} else {
|
|
297
|
-
temp.push(convertMS(a.stopEngineHours),
|
|
298
|
-
convertMS(a.stopDuration),
|
|
299
|
-
Intl.NumberFormat(userData.user.attributes.lang, {maximumFractionDigits: 2}).format(a.totalKms),
|
|
300
|
-
Math.round(a.averageSpeed * 1.85200),
|
|
301
|
-
Math.round(a.maxSpeed * 1.85200),
|
|
302
|
-
getDriverName(userData.drivers, a.driverUniqueId))
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
data.push(temp)
|
|
306
|
-
})
|
|
307
|
-
const footValues = [
|
|
308
|
-
'Total:' + d.trips.length,
|
|
309
|
-
'','','',
|
|
310
|
-
convertMS(d.trips.reduce((a, b) => a + b.duration, 0)),
|
|
311
|
-
]
|
|
312
|
-
|
|
313
|
-
if(userData.byDriver) {
|
|
314
|
-
footValues.push(getSumTotalKms(userData.user, d.trips),
|
|
315
|
-
getSumAvgSpeed(d.trips),
|
|
316
|
-
getMaxSpeed(d.trips))
|
|
317
|
-
} else {
|
|
318
|
-
footValues.push(convertMS(d.trips.reduce((a, b) => a + b.stopEngineHours, 0)),
|
|
319
|
-
convertMS(d.trips.reduce((a, b) => a + b.stopDuration, 0)),
|
|
320
|
-
getSumTotalKms(userData.user, d.trips),
|
|
321
|
-
getSumAvgSpeed(d.trips),
|
|
322
|
-
getMaxSpeed(d.trips))
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
const style = getStyle(getUserPartner(userData.user))
|
|
326
|
-
addTable(doc, headers, data, footValues, style, space + (userData.allWeek ? 40 : 45))
|
|
327
|
-
})
|
|
328
|
-
return doc
|
|
329
|
-
}
|
|
212
|
+
return driversResult
|
|
330
213
|
}
|
|
331
214
|
|
|
332
|
-
function
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
215
|
+
async function exportTripReportToPDF (userData, reportData) {
|
|
216
|
+
console.log('exportTripReportToPDF')
|
|
217
|
+
|
|
218
|
+
const timezone = userData.user.attributes.timezone
|
|
219
|
+
const translations = getTranslations(userData)
|
|
220
|
+
const lang = userData.user.attributes.lang || (navigator && navigator.language)
|
|
221
|
+
const tripsData = userData.byDriver ? reportData.drivers : reportData.devices
|
|
222
|
+
|
|
223
|
+
const headers = [
|
|
224
|
+
translations.report.date,
|
|
225
|
+
translations.report.start,
|
|
226
|
+
translations.report.end,
|
|
227
|
+
translations.report.endAddress,
|
|
228
|
+
translations.report.tripTime
|
|
229
|
+
]
|
|
230
|
+
|
|
231
|
+
if (userData.byDriver) {
|
|
232
|
+
headers.push(translations.report.distance,
|
|
233
|
+
translations.report.avgSpeed,
|
|
234
|
+
translations.report.maxSpeed,
|
|
235
|
+
translations.report.name)
|
|
236
|
+
} else {
|
|
237
|
+
headers.push(translations.report.idleTime,
|
|
238
|
+
translations.report.stopTime,
|
|
239
|
+
translations.report.distance,
|
|
240
|
+
translations.report.avgSpeed,
|
|
241
|
+
translations.report.maxSpeed,
|
|
242
|
+
translations.report.driver)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (tripsData) {
|
|
246
|
+
const doc = new jsPDF.jsPDF('l')
|
|
247
|
+
await headerFromUser(doc, translations.report.titleTripReport, userData.user)
|
|
248
|
+
|
|
249
|
+
tripsData.forEach(function (d, index) {
|
|
250
|
+
const data = []
|
|
251
|
+
const name = userData.byDriver ? d.driver.name : deviceName(d.device)
|
|
252
|
+
const group = userData.byDriver ? userData.groups.find(g => g.drivers.includes(d.id)) : userData.groups.find(g => d.device.groupId === g.id)
|
|
253
|
+
|
|
254
|
+
const space = index === 0 ? 8 : 0
|
|
255
|
+
if (index) {
|
|
256
|
+
doc.addPage()
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
doc.setFontSize(13)
|
|
260
|
+
doc.text(name, 20, space + 20)
|
|
261
|
+
doc.setFontSize(11)
|
|
262
|
+
doc.text(group ? translations.report.group + ': ' + group.name : '', 200, space + 20)
|
|
263
|
+
doc.text(convertToLocaleString(d.from, lang, timezone) + ' - ' + convertToLocaleString(d.to, lang, timezone), 20, space + 25)
|
|
264
|
+
if (!userData.allWeek && userData.weekDays) {
|
|
265
|
+
doc.text((userData.weekDays.monday ? ' ' + translations.report.monday + ',' : '') +
|
|
266
|
+
(userData.weekDays.tuesday ? ' ' + translations.report.tuesday + ',' : '') +
|
|
267
|
+
(userData.weekDays.wednesday ? ' ' + translations.report.wednesday + ',' : '') +
|
|
268
|
+
(userData.weekDays.thursday ? ' ' + translations.report.thursday + ',' : '') +
|
|
269
|
+
(userData.weekDays.friday ? ' ' + translations.report.friday + ',' : '') +
|
|
270
|
+
(userData.weekDays.saturday ? ' ' + translations.report.saturday + ',' : '') +
|
|
271
|
+
(userData.weekDays.sunday ? ' ' + translations.report.sunday + ',' : '') +
|
|
272
|
+
' das ' +
|
|
273
|
+
userData.dayHours.startTime + ' - ' + userData.dayHours.endTime, 20, space + 30)
|
|
274
|
+
doc.text(translations.report.headerStartAddress + ': ' + d.trips[0].startAddress, 20, space + 40)
|
|
275
|
+
} else {
|
|
276
|
+
doc.text(translations.report.headerStartAddress + ': ' + d.trips[0].startAddress, 20, space + 35)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
d.trips.map(a => {
|
|
280
|
+
const temp = [
|
|
281
|
+
getTripDate(userData.user, a),
|
|
282
|
+
getTripStart(userData.user, a),
|
|
283
|
+
getTripEnd(userData.user, a),
|
|
284
|
+
a.endPOIName || a.endAddress,
|
|
285
|
+
convertMS(a.duration)
|
|
286
|
+
]
|
|
287
|
+
|
|
288
|
+
if (userData.byDriver) {
|
|
289
|
+
temp.push(Intl.NumberFormat(userData.user.attributes.lang, { maximumFractionDigits: 2 }).format(a.totalKms),
|
|
290
|
+
Math.round(a.averageSpeed * 1.85200),
|
|
291
|
+
Math.round(a.maxSpeed * 1.85200),
|
|
292
|
+
a.deviceName)
|
|
293
|
+
} else {
|
|
294
|
+
temp.push(convertMS(a.stopEngineHours),
|
|
295
|
+
convertMS(a.stopDuration),
|
|
296
|
+
Intl.NumberFormat(userData.user.attributes.lang, { maximumFractionDigits: 2 }).format(a.totalKms),
|
|
297
|
+
Math.round(a.averageSpeed * 1.85200),
|
|
298
|
+
Math.round(a.maxSpeed * 1.85200),
|
|
299
|
+
getDriverName(userData.drivers, a.driverUniqueId))
|
|
300
|
+
}
|
|
336
301
|
|
|
337
|
-
|
|
302
|
+
data.push(temp)
|
|
303
|
+
})
|
|
304
|
+
const footValues = [
|
|
305
|
+
'Total:' + d.trips.length,
|
|
306
|
+
'', '', '',
|
|
307
|
+
convertMS(d.trips.reduce((a, b) => a + b.duration, 0))
|
|
308
|
+
]
|
|
309
|
+
|
|
310
|
+
if (userData.byDriver) {
|
|
311
|
+
footValues.push(getSumTotalKms(userData.user, d.trips),
|
|
312
|
+
getSumAvgSpeed(d.trips),
|
|
313
|
+
getMaxSpeed(d.trips))
|
|
314
|
+
} else {
|
|
315
|
+
footValues.push(convertMS(d.trips.reduce((a, b) => a + b.stopEngineHours, 0)),
|
|
316
|
+
convertMS(d.trips.reduce((a, b) => a + b.stopDuration, 0)),
|
|
317
|
+
getSumTotalKms(userData.user, d.trips),
|
|
318
|
+
getSumAvgSpeed(d.trips),
|
|
319
|
+
getMaxSpeed(d.trips))
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const style = getStyle(getUserPartner(userData.user))
|
|
323
|
+
addTable(doc, headers, data, footValues, style, space + (userData.allWeek ? 40 : 45))
|
|
324
|
+
})
|
|
325
|
+
return doc
|
|
326
|
+
}
|
|
327
|
+
}
|
|
338
328
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
{label: translations.report.
|
|
353
|
-
{label: translations.report.
|
|
354
|
-
|
|
355
|
-
{label: translations.report.
|
|
356
|
-
{label: translations.report.
|
|
357
|
-
{label: translations.report.
|
|
358
|
-
{label: translations.report.
|
|
359
|
-
{label: translations.report.
|
|
360
|
-
{label: translations.report.
|
|
361
|
-
{label: translations.report.
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
{label: translations.report.
|
|
365
|
-
{label: translations.report.
|
|
366
|
-
{label: translations.report.
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
distance: Number(a.totalKms.toFixed(2)),
|
|
383
|
-
averageSpeed: Math.round(a.averageSpeed * 1.85200),
|
|
384
|
-
maxSpeed: Math.round(a.maxSpeed * 1.85200),
|
|
385
|
-
driver: getDriverName(userData.drivers, a.driverUniqueId)
|
|
386
|
-
}
|
|
387
|
-
}))
|
|
388
|
-
})
|
|
389
|
-
console.log(data)
|
|
329
|
+
function exportTripReportToExcel (userData, reportData) {
|
|
330
|
+
console.log('Export to Excel')
|
|
331
|
+
|
|
332
|
+
const translations = getTranslations(userData)
|
|
333
|
+
|
|
334
|
+
const tripsData = userData.byDriver ? reportData.drivers : reportData.devices
|
|
335
|
+
|
|
336
|
+
const settings = {
|
|
337
|
+
sheetName: translations.report.titleTripReport, // The name of the sheet
|
|
338
|
+
fileName // The name of the spreadsheet
|
|
339
|
+
}
|
|
340
|
+
const headers = userData.byDriver
|
|
341
|
+
? [
|
|
342
|
+
{ label: translations.report.driver, value: 'driver' },
|
|
343
|
+
{ label: translations.report.date, value: 'date' },
|
|
344
|
+
{ label: translations.report.start, value: 'start' },
|
|
345
|
+
{ label: translations.report.end, value: 'end' },
|
|
346
|
+
{ label: translations.report.endAddress, value: 'endAddress' },
|
|
347
|
+
{ label: translations.report.tripTime, value: 'tripTime' },
|
|
348
|
+
{ label: translations.report.distance, value: 'distance' },
|
|
349
|
+
{ label: translations.report.avgSpeed, value: 'averageSpeed' },
|
|
350
|
+
{ label: translations.report.maxSpeed, value: 'maxSpeed' },
|
|
351
|
+
{ label: translations.report.vehicle, value: 'name' }
|
|
352
|
+
]
|
|
353
|
+
: [
|
|
354
|
+
{ label: translations.report.vehicle, value: 'name' },
|
|
355
|
+
{ label: translations.report.date, value: 'date' },
|
|
356
|
+
{ label: translations.report.start, value: 'start' },
|
|
357
|
+
{ label: translations.report.end, value: 'end' },
|
|
358
|
+
{ label: translations.report.endAddress, value: 'endAddress' },
|
|
359
|
+
{ label: translations.report.tripTime, value: 'tripTime' },
|
|
360
|
+
{ label: translations.report.idleTime, value: 'idleTime' },
|
|
361
|
+
{ label: translations.report.stopTime, value: 'stopTime' },
|
|
362
|
+
{ label: translations.report.distance, value: 'distance' },
|
|
363
|
+
{ label: translations.report.avgSpeed, value: 'averageSpeed' },
|
|
364
|
+
{ label: translations.report.maxSpeed, value: 'maxSpeed' },
|
|
365
|
+
{ label: translations.report.driver, value: 'driver' }
|
|
366
|
+
]
|
|
367
|
+
let data = []
|
|
368
|
+
if (tripsData) {
|
|
369
|
+
tripsData.forEach(d => {
|
|
370
|
+
data = data.concat([{}])
|
|
371
|
+
data = data.concat(d.trips.map(a => {
|
|
390
372
|
return {
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
373
|
+
name: a.deviceName,
|
|
374
|
+
date: getTripDate(userData.user, a),
|
|
375
|
+
start: getTripStart(userData.user, a),
|
|
376
|
+
end: getTripEnd(userData.user, a),
|
|
377
|
+
endAddress: a.endPOIName || a.endAddress,
|
|
378
|
+
tripTime: convertMS(a.duration),
|
|
379
|
+
idleTime: convertMS(a.stopEngineHours),
|
|
380
|
+
stopTime: convertMS(a.stopDuration),
|
|
381
|
+
distance: Number(a.totalKms.toFixed(2)),
|
|
382
|
+
averageSpeed: Math.round(a.averageSpeed * 1.85200),
|
|
383
|
+
maxSpeed: Math.round(a.maxSpeed * 1.85200),
|
|
384
|
+
driver: getDriverName(userData.drivers, a.driverUniqueId)
|
|
394
385
|
}
|
|
386
|
+
}))
|
|
387
|
+
})
|
|
388
|
+
console.log(data)
|
|
389
|
+
return {
|
|
390
|
+
headers,
|
|
391
|
+
data,
|
|
392
|
+
settings
|
|
395
393
|
}
|
|
394
|
+
}
|
|
396
395
|
}
|
|
397
396
|
|
|
398
|
-
function deviceName(device){
|
|
399
|
-
|
|
397
|
+
function deviceName (device) {
|
|
398
|
+
return device.name + (device.attributes.license_plate ? ', ' + device.attributes.license_plate : '') + (device.model ? ', ' + device.model : '')
|
|
400
399
|
}
|
|
401
400
|
|
|
402
|
-
function getTripDate(user, trip){
|
|
403
|
-
|
|
401
|
+
function getTripDate (user, trip) {
|
|
402
|
+
return convertToLocaleDateString(trip.startTime, user.attributes.lang, user.attributes.timezone)
|
|
404
403
|
}
|
|
405
404
|
|
|
406
|
-
function getTripStart(user, trip){
|
|
407
|
-
|
|
405
|
+
function getTripStart (user, trip) {
|
|
406
|
+
return convertToLocaleTimeString(trip.startTime, user.attributes.lang, user.attributes.timezone)
|
|
408
407
|
}
|
|
409
408
|
|
|
410
|
-
function getTripEnd(user, trip){
|
|
411
|
-
|
|
409
|
+
function getTripEnd (user, trip) {
|
|
410
|
+
return convertToLocaleTimeString(trip.endTime, user.attributes.lang, user.attributes.timezone)
|
|
412
411
|
}
|
|
413
412
|
|
|
414
|
-
function getDriverName(drivers, driverUniqueId) {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
413
|
+
function getDriverName (drivers, driverUniqueId) {
|
|
414
|
+
if (driverUniqueId) {
|
|
415
|
+
const driver = drivers.find(d => d.uniqueId === driverUniqueId)
|
|
416
|
+
return driver ? driver.name : driverUniqueId
|
|
417
|
+
}
|
|
419
418
|
|
|
420
|
-
|
|
419
|
+
return ''
|
|
421
420
|
}
|
|
422
421
|
|
|
423
|
-
function getSumTotalKms(user, data) {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
422
|
+
function getSumTotalKms (user, data) {
|
|
423
|
+
const values = data.map(item => {
|
|
424
|
+
return item.totalKms ? parseFloat(item.totalKms) : 0
|
|
425
|
+
})
|
|
426
|
+
return Intl.NumberFormat(user.attributes.lang, { maximumFractionDigits: 2 }).format(values.reduce((a, b) => a + b, 0))
|
|
428
427
|
}
|
|
429
428
|
|
|
430
|
-
function getSumAvgSpeed(data) {
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
429
|
+
function getSumAvgSpeed (data) {
|
|
430
|
+
const values = data.map(item => {
|
|
431
|
+
return Math.round(item.averageSpeed * 1.85200) * item.totalKms
|
|
432
|
+
})
|
|
433
|
+
const totalKms = data.reduce((a, b) => a + b.totalKms, 0)
|
|
434
|
+
return totalKms > 0 ? Math.round((values.reduce((a, b) => a + b, 0)) / totalKms) : 0
|
|
436
435
|
}
|
|
437
436
|
|
|
438
|
-
function getMaxSpeed(data) {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
437
|
+
function getMaxSpeed (data) {
|
|
438
|
+
const values = data.map(item => {
|
|
439
|
+
return item.maxSpeed
|
|
440
|
+
})
|
|
441
|
+
const max = values.reduce(function (a, b) {
|
|
442
|
+
return Math.max(a, b)
|
|
443
|
+
})
|
|
444
|
+
return Math.round(max * 1.85200)
|
|
446
445
|
}
|
|
447
446
|
|
|
448
|
-
function getStop(tripEndDate, stops){
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
447
|
+
function getStop (tripEndDate, stops) {
|
|
448
|
+
const stopList = stops.filter(s => new Date(s.startTime).getTime() >= tripEndDate.getTime())
|
|
449
|
+
if (stopList.length) {
|
|
450
|
+
return stopList[0]
|
|
451
|
+
}
|
|
453
452
|
|
|
454
|
-
|
|
453
|
+
return null
|
|
455
454
|
}
|
|
456
455
|
|
|
457
456
|
exports.createTripReport = createTripReport
|