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