fleetmap-reports 1.0.405 → 1.0.408
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/index.test.js +17 -16
- package/src/util/traccar.js +29 -14
- package/src/zone-report.js +304 -301
package/package.json
CHANGED
package/src/index.test.js
CHANGED
|
@@ -147,12 +147,13 @@ describe('Test_Reports', function () {
|
|
|
147
147
|
const report = await getReports()
|
|
148
148
|
const userData = await report.getUserData()
|
|
149
149
|
userData.byDriver = true
|
|
150
|
-
const data = await report.locationReport(
|
|
151
|
-
new Date(2021, 11,
|
|
150
|
+
const data = await report.locationReport(
|
|
151
|
+
new Date(Date.UTC(2021, 11, 6, 0, 0, 0, 0)),
|
|
152
|
+
new Date(Date.UTC(2021, 11, 9, 23, 59, 59, 0)),
|
|
152
153
|
userData)
|
|
153
|
-
|
|
154
154
|
assert.equal(data.length, 1)
|
|
155
155
|
const driver = data[0].drivers.find(d => d.driver.id === 14020)
|
|
156
|
+
console.log(driver.positions)
|
|
156
157
|
assert.equal(driver.positions.length, 85) // Total Positions
|
|
157
158
|
}, 20000)
|
|
158
159
|
// eslint-disable-next-line no-undef
|
|
@@ -340,18 +341,18 @@ describe('Test_Reports', function () {
|
|
|
340
341
|
}, 30000)
|
|
341
342
|
// eslint-disable-next-line no-undef
|
|
342
343
|
it('Zone Report', async () => {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
344
|
+
const report = await getReports()
|
|
345
|
+
const userData = await report.getUserData()
|
|
346
|
+
const data = await report.zoneReport(new Date(2022, 3, 25, 0, 0, 0, 0),
|
|
347
|
+
new Date(2022, 3, 28, 23, 59, 59, 0),
|
|
348
|
+
userData)
|
|
348
349
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
350
|
+
assert.equal(data.length, 1)
|
|
351
|
+
const device = data[0].devices.find(d => d.device.id === 22326)
|
|
352
|
+
assert.equal(device.geofences.length, 19)
|
|
353
|
+
assert.equal(device.geofences[0].inTime.fixTime, '2022-04-25T23:47:58.000+0000')
|
|
354
|
+
assert.equal(device.geofences[0].outTime.fixTime, '2022-04-26T07:47:35.000+0000')
|
|
355
|
+
assert.equal(device.geofences[0].totalTime, '28777')
|
|
356
|
+
assert.equal(device.geofences[0].geofenceName, 'Casa João')
|
|
357
|
+
}, 30000)
|
|
357
358
|
})
|
package/src/util/traccar.js
CHANGED
|
@@ -65,27 +65,42 @@ async function getSummary (traccar, from, to, devices) {
|
|
|
65
65
|
return result.map(r => r.data).flat()
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
async function getAllInOne (
|
|
69
|
-
|
|
68
|
+
async function getAllInOne (
|
|
69
|
+
traccar,
|
|
70
|
+
from,
|
|
71
|
+
to,
|
|
72
|
+
devices,
|
|
73
|
+
getRoutes,
|
|
74
|
+
getTrips,
|
|
75
|
+
getStops,
|
|
76
|
+
getSummary,
|
|
77
|
+
currentDeviceCount = 0,
|
|
78
|
+
totalDevices = devices.length,
|
|
79
|
+
sliceSize = 5,
|
|
80
|
+
devicesPerRequest = 1) {
|
|
81
|
+
let url = `/reports/allinone?from=${from.toISOString()}&to=${to.toISOString()}`
|
|
70
82
|
if (getRoutes) url += '&type=route'
|
|
71
83
|
if (getTrips) url += '&type=trips'
|
|
72
84
|
if (getStops) url += '&type=stops'
|
|
73
85
|
if (getSummary) url += '&type=summary'
|
|
74
86
|
|
|
75
|
-
const sliced = automaticReports.sliceArray(devices,
|
|
87
|
+
const sliced = automaticReports.sliceArray(devices, sliceSize)
|
|
76
88
|
const result = []
|
|
77
|
-
let deviceCount = currentDeviceCount
|
|
78
89
|
for (const chunk of sliced) {
|
|
79
|
-
const requests =
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
90
|
+
const requests = []
|
|
91
|
+
for (const _chunk of automaticReports.sliceArray(chunk, devicesPerRequest)) {
|
|
92
|
+
const u = url + '&' + _chunk.map(d => `deviceId=${d.id}`).join('&')
|
|
93
|
+
requests.push(
|
|
94
|
+
traccar.axios.get(u, {
|
|
95
|
+
jar: traccar.cookieJar,
|
|
96
|
+
withCredentials: true
|
|
97
|
+
}).then(r => r.data).then(x => {
|
|
98
|
+
console.log('LOADING_MESSAGE:' + _chunk[0].name)
|
|
99
|
+
currentDeviceCount += devicesPerRequest
|
|
100
|
+
console.log(`PROGRESS_PERC:${currentDeviceCount / totalDevices * 100}`)
|
|
101
|
+
return x
|
|
102
|
+
}))
|
|
103
|
+
}
|
|
89
104
|
result.push(...(await Promise.all(requests)))
|
|
90
105
|
}
|
|
91
106
|
return {
|
package/src/zone-report.js
CHANGED
|
@@ -1,352 +1,355 @@
|
|
|
1
1
|
const moment = require('moment')
|
|
2
|
-
const automaticReports = require(
|
|
3
|
-
const {convertMS, convertToLocaleString, getTranslations, convertToFeature, convertPositionToFeature} = require(
|
|
2
|
+
const automaticReports = require('./automaticReports')
|
|
3
|
+
const { convertMS, convertToLocaleString, getTranslations, convertToFeature, convertPositionToFeature } = require('./util/utils')
|
|
4
4
|
const jsPDF = require('jspdf')
|
|
5
5
|
require('jspdf-autotable')
|
|
6
|
-
const {headerFromUser} = require(
|
|
7
|
-
const {getStyle} = require(
|
|
8
|
-
const {getUserPartner} = require(
|
|
9
|
-
const {devicesToProcess} = require(
|
|
10
|
-
const traccarHelper = require(
|
|
11
|
-
const pointToLineDistance = require(
|
|
12
|
-
const booleanPointInPolygon = require(
|
|
13
|
-
const distance = require(
|
|
6
|
+
const { headerFromUser } = require('./util/pdfDocument')
|
|
7
|
+
const { getStyle } = require('./reportStyle')
|
|
8
|
+
const { getUserPartner } = require('fleetmap-partners')
|
|
9
|
+
const { devicesToProcess } = require('./util/device')
|
|
10
|
+
const traccarHelper = require('./util/traccar')
|
|
11
|
+
const pointToLineDistance = require('@turf/point-to-line-distance')
|
|
12
|
+
const booleanPointInPolygon = require('@turf/boolean-point-in-polygon')
|
|
13
|
+
const distance = require('@turf/distance')
|
|
14
14
|
|
|
15
15
|
const fileName = 'ZoneReport'
|
|
16
16
|
|
|
17
|
-
async function createZoneReport(from, to, userData, traccar) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const response = await traccar.reports.reportsEventsGet(from, to, null, [g.id], types)
|
|
35
|
-
const data = response.data
|
|
17
|
+
async function createZoneReport (from, to, userData, traccar) {
|
|
18
|
+
console.log('Create ZoneReport')
|
|
19
|
+
const reportData = []
|
|
20
|
+
const types = ['geofenceEnter', 'geofenceExit']
|
|
21
|
+
|
|
22
|
+
if (userData.byGroup) {
|
|
23
|
+
console.log('ByGroup')
|
|
24
|
+
for (const g of userData.groups) {
|
|
25
|
+
const devices = userData.devices.filter(d => d.groupId === g.id)
|
|
26
|
+
console.log(g.name + ' devices:' + devices.length)
|
|
27
|
+
if (devices.length > 0) {
|
|
28
|
+
const groupData = {
|
|
29
|
+
devices: [],
|
|
30
|
+
group: g,
|
|
31
|
+
xpert: devices.filter(d => d.attributes.xpert).length > 0
|
|
32
|
+
}
|
|
36
33
|
|
|
37
|
-
|
|
34
|
+
const response = await traccar.reports.reportsEventsGet(from, to, null, [g.id], types)
|
|
35
|
+
const data = response.data
|
|
38
36
|
|
|
39
|
-
|
|
37
|
+
console.log('Geofence Enter/Exit Alerts:' + data.length)
|
|
40
38
|
|
|
41
|
-
|
|
42
|
-
groupData.devices = await processDevices(from, to, devices, userData.drivers, userData.geofences, data)
|
|
39
|
+
devices.sort((a, b) => (a.name > b.name) ? 1 : -1)
|
|
43
40
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
if (data.length > 0) {
|
|
42
|
+
groupData.devices = await processDevices(from, to, devices, userData.drivers, userData.geofences, data)
|
|
43
|
+
reportData.push(groupData)
|
|
47
44
|
}
|
|
45
|
+
}
|
|
48
46
|
}
|
|
47
|
+
}
|
|
49
48
|
|
|
50
|
-
|
|
49
|
+
const devices = devicesToProcess(userData)
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
const allData = {
|
|
52
|
+
devices: [],
|
|
53
|
+
xpert: devices.filter(d => d.attributes.xpert).length > 0
|
|
54
|
+
}
|
|
56
55
|
|
|
57
|
-
|
|
56
|
+
const sliced = automaticReports.sliceArray(devices, 50)
|
|
58
57
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
let deviceCount = 0
|
|
59
|
+
for (const slice of sliced) {
|
|
60
|
+
const allInOne = await traccarHelper.getAllInOne(
|
|
61
|
+
traccar, from, to, slice, true, false, false, false,
|
|
62
|
+
deviceCount, devices.length, 30, 10)
|
|
63
|
+
const routeData = allInOne.route
|
|
63
64
|
|
|
64
|
-
|
|
65
|
+
const data = getInAndOutEvents(slice, routeData, userData)
|
|
65
66
|
|
|
66
|
-
|
|
67
|
+
console.log('Geofence Enter/Exit Alerts:' + data.length)
|
|
67
68
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
deviceCount = deviceCount + slice.length
|
|
69
|
+
if (data.length) {
|
|
70
|
+
allData.devices.push(...await processDevices(from, to, devices, userData.drivers, userData.geofences, data, traccar))
|
|
72
71
|
}
|
|
72
|
+
deviceCount = deviceCount + slice.length
|
|
73
|
+
}
|
|
73
74
|
|
|
74
|
-
|
|
75
|
+
reportData.push(allData)
|
|
75
76
|
|
|
76
|
-
|
|
77
|
+
return reportData
|
|
77
78
|
}
|
|
78
79
|
|
|
79
|
-
async function processDevices(from, to, devices, drivers, geofences, data) {
|
|
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
|
-
for (const i in zoneInData) {
|
|
126
|
-
if(zoneInData[i]) {
|
|
127
|
-
const geofence = geofences.find(g => g.id === zoneInData[i].geofenceId)
|
|
128
|
-
if(geofence) {
|
|
129
|
-
zoneInOutData.push({
|
|
130
|
-
inTime: zoneInData[i].position,
|
|
131
|
-
geofenceName: geofence.name,
|
|
132
|
-
driverName: zoneInData[i].position.driverName
|
|
133
|
-
})
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
if(zoneInOutData.length > 0) {
|
|
139
|
-
devicesResult.push({
|
|
140
|
-
device: d,
|
|
141
|
-
from: from,
|
|
142
|
-
to: to,
|
|
143
|
-
geofences: zoneInOutData,
|
|
80
|
+
async function processDevices (from, to, devices, drivers, geofences, data) {
|
|
81
|
+
const devicesResult = []
|
|
82
|
+
|
|
83
|
+
for (const d of devices) {
|
|
84
|
+
const alerts = data.filter(t => t.deviceId === d.id)
|
|
85
|
+
if (alerts.length > 0) {
|
|
86
|
+
// const response = await traccar.reports.reportsRouteGet(from, to, [d.id])
|
|
87
|
+
|
|
88
|
+
const zoneInOutData = []
|
|
89
|
+
const zoneInData = {}
|
|
90
|
+
// const positions = response.data
|
|
91
|
+
|
|
92
|
+
alerts.forEach(a => {
|
|
93
|
+
// a.position = positions.find(p => p.id === a.positionId)
|
|
94
|
+
if (a.position) {
|
|
95
|
+
if (a.type === 'geofenceEnter') {
|
|
96
|
+
const driver = drivers.find(d => a.position.attributes && d.uniqueId === a.position.attributes.driverUniqueId)
|
|
97
|
+
a.position.driverName = driver ? driver.name : ''
|
|
98
|
+
zoneInData[a.geofenceId] = a
|
|
99
|
+
} else if (a.type === 'geofenceExit') {
|
|
100
|
+
const geofence = geofences.find(g => g.id === a.geofenceId)
|
|
101
|
+
if (zoneInData[a.geofenceId]) {
|
|
102
|
+
const totalInTime = moment(a.position.fixTime).diff(moment(zoneInData[a.geofenceId].position.fixTime), 'seconds')
|
|
103
|
+
if (geofence) {
|
|
104
|
+
zoneInOutData.push({
|
|
105
|
+
inTime: zoneInData[a.geofenceId].position,
|
|
106
|
+
outTime: a.position,
|
|
107
|
+
totalTime: totalInTime,
|
|
108
|
+
geofenceName: geofence.name,
|
|
109
|
+
driverName: zoneInData[a.geofenceId].position.driverName
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
zoneInData[a.geofenceId] = null
|
|
113
|
+
} else {
|
|
114
|
+
if (geofence) {
|
|
115
|
+
zoneInOutData.push({
|
|
116
|
+
outTime: a.position,
|
|
117
|
+
geofenceName: geofence.name,
|
|
118
|
+
driverName: ''
|
|
144
119
|
})
|
|
120
|
+
}
|
|
145
121
|
}
|
|
122
|
+
}
|
|
146
123
|
}
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
for (const i in zoneInData) {
|
|
127
|
+
if (zoneInData[i]) {
|
|
128
|
+
const geofence = geofences.find(g => g.id === zoneInData[i].geofenceId)
|
|
129
|
+
if (geofence) {
|
|
130
|
+
zoneInOutData.push({
|
|
131
|
+
inTime: zoneInData[i].position,
|
|
132
|
+
geofenceName: geofence.name,
|
|
133
|
+
driverName: zoneInData[i].position.driverName
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (zoneInOutData.length > 0) {
|
|
140
|
+
devicesResult.push({
|
|
141
|
+
device: d,
|
|
142
|
+
from,
|
|
143
|
+
to,
|
|
144
|
+
geofences: zoneInOutData
|
|
145
|
+
})
|
|
146
|
+
}
|
|
147
147
|
}
|
|
148
|
+
}
|
|
148
149
|
|
|
149
|
-
|
|
150
|
+
return devicesResult
|
|
150
151
|
}
|
|
151
152
|
|
|
152
|
-
function getInAndOutEvents(devices, route, userData) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
})
|
|
153
|
+
function getInAndOutEvents (devices, route, userData) {
|
|
154
|
+
const events = []
|
|
155
|
+
devices.forEach(d => {
|
|
156
|
+
const deviceRoute = route.filter(p => p.deviceId === d.id)
|
|
157
|
+
|
|
158
|
+
const routePoints = deviceRoute.map(p => convertPositionToFeature(p))
|
|
159
|
+
const geofencesFeatures = userData.geofences.map(g => convertToFeature(g))
|
|
160
|
+
|
|
161
|
+
const entryMap = []
|
|
162
|
+
routePoints.forEach(p => {
|
|
163
|
+
geofencesFeatures.forEach(g => {
|
|
164
|
+
if (g.geometry.type === 'Polygon') {
|
|
165
|
+
if (booleanPointInPolygon.default(p, g)) {
|
|
166
|
+
if (!entryMap.includes(g)) {
|
|
167
|
+
events.push(createEvent('geofenceEnter', d.id, p, g))
|
|
168
|
+
entryMap.push(g)
|
|
169
|
+
}
|
|
170
|
+
} else {
|
|
171
|
+
if (entryMap.includes(g)) {
|
|
172
|
+
events.push(createEvent('geofenceExit', d.id, p, g))
|
|
173
|
+
const index = entryMap.indexOf(g)
|
|
174
|
+
entryMap.splice(index, 1)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (g.geometry.type === 'Point') {
|
|
179
|
+
if (distance.default(p, g, { units: 'meters' }) < g.properties.distance) {
|
|
180
|
+
if (!entryMap.includes(g)) {
|
|
181
|
+
events.push(createEvent('geofenceEnter', d.id, p, g))
|
|
182
|
+
entryMap.push(g)
|
|
183
|
+
}
|
|
184
|
+
} else {
|
|
185
|
+
if (entryMap.includes(g)) {
|
|
186
|
+
events.push(createEvent('geofenceExit', d.id, p, g))
|
|
187
|
+
const index = entryMap.indexOf(g)
|
|
188
|
+
entryMap.splice(index, 1)
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (g.geometry.type === 'LineString') {
|
|
193
|
+
if (pointToLineDistance.default(p, g, { units: 'meters' }) < (g.properties.geofence.attributes.polylineDistance || 25)) {
|
|
194
|
+
if (!entryMap.includes(g)) {
|
|
195
|
+
events.push(createEvent('geofenceEnter', d.id, p, g))
|
|
196
|
+
entryMap.push(g)
|
|
197
|
+
}
|
|
198
|
+
} else {
|
|
199
|
+
if (entryMap.includes(g)) {
|
|
200
|
+
events.push(createEvent('geofenceExit', d.id, p, g))
|
|
201
|
+
const index = entryMap.indexOf(g)
|
|
202
|
+
entryMap.splice(index, 1)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
})
|
|
207
207
|
})
|
|
208
|
+
})
|
|
208
209
|
|
|
209
|
-
|
|
210
|
+
return events
|
|
210
211
|
}
|
|
211
212
|
|
|
212
|
-
function createEvent(type, deviceId, p, g) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
213
|
+
function createEvent (type, deviceId, p, g) {
|
|
214
|
+
return {
|
|
215
|
+
type,
|
|
216
|
+
position: p.properties.position,
|
|
217
|
+
geofenceId: g.properties.geofence.id,
|
|
218
|
+
deviceId
|
|
219
|
+
}
|
|
219
220
|
}
|
|
220
221
|
|
|
221
|
-
async function exportZoneReportToPDF(userData, reportData) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
222
|
+
async function exportZoneReportToPDF (userData, reportData) {
|
|
223
|
+
console.log('Export to PDF')
|
|
224
|
+
|
|
225
|
+
const timezone = userData.user.attributes.timezone
|
|
226
|
+
const translations = getTranslations(userData)
|
|
227
|
+
const lang = userData.user.attributes.lang || (navigator && navigator.language)
|
|
228
|
+
|
|
229
|
+
const headers = [
|
|
230
|
+
translations.report.enter,
|
|
231
|
+
translations.report.exit,
|
|
232
|
+
translations.report.duration,
|
|
233
|
+
translations.report.geofence,
|
|
234
|
+
translations.report.driver
|
|
235
|
+
]
|
|
236
|
+
if (reportData.devices) {
|
|
237
|
+
let first = true
|
|
238
|
+
// eslint-disable-next-line new-cap
|
|
239
|
+
const doc = new jsPDF.jsPDF('l')
|
|
240
|
+
await headerFromUser(doc, translations.report.titleZoneReport, userData.user)
|
|
241
|
+
|
|
242
|
+
reportData.devices.forEach(d => {
|
|
243
|
+
const data = []
|
|
244
|
+
const name = deviceName(d.device)
|
|
245
|
+
const group = userData.groups.find(g => d.device.groupId === g.id)
|
|
246
|
+
|
|
247
|
+
let space = 0
|
|
248
|
+
if (!first) {
|
|
249
|
+
doc.addPage()
|
|
250
|
+
} else {
|
|
251
|
+
first = false
|
|
252
|
+
space = 10
|
|
253
|
+
}
|
|
254
|
+
doc.setFontSize(13)
|
|
255
|
+
doc.text(name, 20, space + 20)
|
|
256
|
+
doc.setFontSize(11)
|
|
257
|
+
doc.text(group ? translations.report.group + ': ' + group.name : '', 200, space + 20)
|
|
258
|
+
doc.text(convertToLocaleString(d.from, lang, timezone) + ' - ' + convertToLocaleString(d.to, lang, timezone), 20, space + 25)
|
|
259
|
+
d.geofences.forEach(a => {
|
|
260
|
+
const temp = [
|
|
261
|
+
geofenceEnter(userData.user, a),
|
|
262
|
+
geofenceExit(userData.user, a),
|
|
263
|
+
a.totalTime ? convertMS(a.totalTime * 1000, true) : '',
|
|
264
|
+
a.geofenceName,
|
|
265
|
+
a.driverName
|
|
266
|
+
]
|
|
267
|
+
data.push(temp)
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
const footValues = [
|
|
271
|
+
'Total:' + d.geofences.length
|
|
272
|
+
]
|
|
273
|
+
|
|
274
|
+
const style = getStyle(getUserPartner(userData.user))
|
|
275
|
+
doc.autoTable({
|
|
276
|
+
head: [headers],
|
|
277
|
+
body: data,
|
|
278
|
+
foot: [footValues],
|
|
279
|
+
showFoot: 'lastPage',
|
|
280
|
+
headStyles: {
|
|
281
|
+
fillColor: style.pdfHeaderColor,
|
|
282
|
+
textColor: style.pdfHeaderTextColor,
|
|
283
|
+
fontSize: 10
|
|
284
|
+
},
|
|
285
|
+
bodyStyles: {
|
|
286
|
+
fillColor: style.pdfBodyColor,
|
|
287
|
+
textColor: style.pdfBodyTextColor,
|
|
288
|
+
fontSize: 8
|
|
289
|
+
},
|
|
290
|
+
footStyles: {
|
|
291
|
+
fillColor: style.pdfFooterColor,
|
|
292
|
+
textColor: style.pdfFooterTextColor,
|
|
293
|
+
fontSize: 9
|
|
294
|
+
},
|
|
295
|
+
startY: space + 35
|
|
296
|
+
})
|
|
297
|
+
})
|
|
295
298
|
|
|
296
|
-
|
|
297
|
-
|
|
299
|
+
return doc
|
|
300
|
+
}
|
|
298
301
|
}
|
|
299
302
|
|
|
300
|
-
function exportZoneReportToExcel(userData, reportData) {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
return {
|
|
323
|
-
name: d.device.name,
|
|
324
|
-
enter: geofenceEnter(userData.user, a),
|
|
325
|
-
exit: geofenceExit(userData.user, a),
|
|
326
|
-
duration: a.totalTime ? convertMS(a.totalTime * 1000, true) : '',
|
|
327
|
-
zone: a.geofenceName,
|
|
328
|
-
driver: a.driverName
|
|
329
|
-
}
|
|
330
|
-
}))
|
|
331
|
-
})
|
|
332
|
-
console.log(data)
|
|
303
|
+
function exportZoneReportToExcel (userData, reportData) {
|
|
304
|
+
console.log('Export to Excel')
|
|
305
|
+
|
|
306
|
+
const translations = getTranslations(userData)
|
|
307
|
+
|
|
308
|
+
const settings = {
|
|
309
|
+
sheetName: translations.report.titleActivityReport, // The name of the sheet
|
|
310
|
+
fileName // The name of the spreadsheet
|
|
311
|
+
}
|
|
312
|
+
const headers = [
|
|
313
|
+
{ label: translations.report.vehicle, value: 'name' },
|
|
314
|
+
{ label: translations.report.enter, value: 'enter' },
|
|
315
|
+
{ label: translations.report.exit, value: 'exit' },
|
|
316
|
+
{ label: translations.report.duration, value: 'duration' },
|
|
317
|
+
{ label: translations.report.geofence, value: 'zone' },
|
|
318
|
+
{ label: translations.report.driver, value: 'driver' }
|
|
319
|
+
]
|
|
320
|
+
let data = []
|
|
321
|
+
if (reportData.devices) {
|
|
322
|
+
reportData.devices.forEach(d => {
|
|
323
|
+
data = data.concat([{}])
|
|
324
|
+
data = data.concat(d.geofences.map(a => {
|
|
333
325
|
return {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
326
|
+
name: d.device.name,
|
|
327
|
+
enter: geofenceEnter(userData.user, a),
|
|
328
|
+
exit: geofenceExit(userData.user, a),
|
|
329
|
+
duration: a.totalTime ? convertMS(a.totalTime * 1000, true) : '',
|
|
330
|
+
zone: a.geofenceName,
|
|
331
|
+
driver: a.driverName
|
|
337
332
|
}
|
|
333
|
+
}))
|
|
334
|
+
})
|
|
335
|
+
console.log(data)
|
|
336
|
+
return {
|
|
337
|
+
headers,
|
|
338
|
+
data,
|
|
339
|
+
settings
|
|
338
340
|
}
|
|
341
|
+
}
|
|
339
342
|
}
|
|
340
343
|
|
|
341
|
-
function deviceName(device){
|
|
342
|
-
|
|
344
|
+
function deviceName (device) {
|
|
345
|
+
return device.name + (device.attributes.license_plate ? ', ' + device.attributes.license_plate : '') + (device.model ? ', ' + device.model : '')
|
|
343
346
|
}
|
|
344
347
|
|
|
345
|
-
function geofenceEnter(user, row){
|
|
346
|
-
|
|
348
|
+
function geofenceEnter (user, row) {
|
|
349
|
+
return row.inTime ? convertToLocaleString(row.inTime.fixTime, user.attributes.lang, user.attributes.timezone) : ''
|
|
347
350
|
}
|
|
348
|
-
function geofenceExit(user, row){
|
|
349
|
-
|
|
351
|
+
function geofenceExit (user, row) {
|
|
352
|
+
return row.outTime ? convertToLocaleString(row.outTime.fixTime, user.attributes.lang, user.attributes.timezone) : ''
|
|
350
353
|
}
|
|
351
354
|
|
|
352
355
|
exports.createZoneReport = createZoneReport
|