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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetmap-reports",
3
- "version": "1.0.405",
3
+ "version": "1.0.408",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
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(new Date(2021, 11, 6, 0, 0, 0, 0),
151
- new Date(2021, 11, 9, 23, 59, 59, 0),
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
- const report = await getReports()
344
- const userData = await report.getUserData()
345
- const data = await report.zoneReport(new Date(2022, 3, 25, 0, 0, 0, 0),
346
- new Date(2022, 3, 28, 23, 59, 59, 0),
347
- userData)
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
- assert.equal(data.length, 1)
350
- const device = data[0].devices.find(d => d.device.id===22326)
351
- assert.equal(device.geofences.length, 19)
352
- assert.equal(device.geofences[0].inTime.fixTime, '2022-04-25T23:47:58.000+0000')
353
- assert.equal(device.geofences[0].outTime.fixTime, '2022-04-26T07:47:35.000+0000')
354
- assert.equal(device.geofences[0].totalTime, '28777')
355
- assert.equal(device.geofences[0].geofenceName, 'Casa João')
356
- }, 30000)
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
  })
@@ -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 (traccar, from, to, devices, getRoutes, getTrips, getStops, getSummary, currentDeviceCount = 0, totalDevices = devices.length) {
69
- let url = `/reports/allinone?&from=${from.toISOString()}&to=${to.toISOString()}`
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, 5)
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 = chunk.map(d =>
80
- traccar.axios.get(url + '&' + `deviceId=${d.id}`, {
81
- jar: traccar.cookieJar,
82
- withCredentials: true
83
- }).then(r => r.data).then(x => {
84
- console.log('LOADING_MESSAGE:' + d.name)
85
- deviceCount = deviceCount + 1
86
- console.log(`PROGRESS_PERC:${deviceCount / totalDevices * 100}`)
87
- return x
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 {
@@ -1,352 +1,355 @@
1
1
  const moment = require('moment')
2
- const automaticReports = require("./automaticReports")
3
- const {convertMS, convertToLocaleString, getTranslations, convertToFeature, convertPositionToFeature} = require("./util/utils")
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("./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")
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
- 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
-
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
- console.log('Geofence Enter/Exit Alerts:'+data.length)
34
+ const response = await traccar.reports.reportsEventsGet(from, to, null, [g.id], types)
35
+ const data = response.data
38
36
 
39
- devices.sort((a, b) => (a.name > b.name) ? 1 : -1)
37
+ console.log('Geofence Enter/Exit Alerts:' + data.length)
40
38
 
41
- if (data.length > 0) {
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
- reportData.push(groupData)
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
- const devices = devicesToProcess(userData)
49
+ const devices = devicesToProcess(userData)
51
50
 
52
- const allData = {
53
- devices: [],
54
- xpert: devices.filter(d => d.attributes.xpert).length > 0
55
- }
51
+ const allData = {
52
+ devices: [],
53
+ xpert: devices.filter(d => d.attributes.xpert).length > 0
54
+ }
56
55
 
57
- const sliced = automaticReports.sliceArray(devices, 5)
56
+ const sliced = automaticReports.sliceArray(devices, 50)
58
57
 
59
- let deviceCount = 0
60
- for(const slice of sliced) {
61
- const allInOne = await traccarHelper.getAllInOne(traccar, from, to, slice, true, false, false, false, deviceCount, devices.length)
62
- const routeData = allInOne.route
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
- const data = getInAndOutEvents(slice, routeData, userData)
65
+ const data = getInAndOutEvents(slice, routeData, userData)
65
66
 
66
- console.log('Geofence Enter/Exit Alerts:' + data.length)
67
+ console.log('Geofence Enter/Exit Alerts:' + data.length)
67
68
 
68
- if (data.length) {
69
- allData.devices.push(...await processDevices(from, to, devices, userData.drivers, userData.geofences, data, traccar))
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
- reportData.push(allData)
75
+ reportData.push(allData)
75
76
 
76
- return reportData
77
+ return reportData
77
78
  }
78
79
 
79
- async function processDevices(from, to, devices, drivers, geofences, data) {
80
- const devicesResult = []
81
-
82
- for (const d of devices) {
83
- const alerts = data.filter(t => t.deviceId===d.id)
84
- if(alerts.length > 0) {
85
- //const response = await traccar.reports.reportsRouteGet(from, to, [d.id])
86
-
87
- const zoneInOutData = []
88
- const zoneInData = {}
89
- //const positions = response.data
90
-
91
- alerts.forEach(a => {
92
- //a.position = positions.find(p => p.id === a.positionId)
93
- if (a.position) {
94
- if (a.type === 'geofenceEnter') {
95
- const driver = drivers.find(d => a.position.attributes && d.uniqueId === a.position.attributes.driverUniqueId)
96
- a.position.driverName = driver ? driver.name : ''
97
- zoneInData[a.geofenceId] = a
98
- } else if (a.type === 'geofenceExit') {
99
- const geofence = geofences.find(g => g.id === a.geofenceId)
100
- if (zoneInData[a.geofenceId]) {
101
- const totalInTime = moment(a.position.fixTime).diff(moment(zoneInData[a.geofenceId].position.fixTime), 'seconds')
102
- if (geofence) {
103
- zoneInOutData.push({
104
- inTime: zoneInData[a.geofenceId].position,
105
- outTime: a.position,
106
- totalTime: totalInTime,
107
- geofenceName: geofence.name,
108
- driverName: zoneInData[a.geofenceId].position.driverName
109
- })
110
- }
111
- zoneInData[a.geofenceId] = null
112
- } else {
113
- if (geofence) {
114
- zoneInOutData.push({
115
- outTime: a.position,
116
- geofenceName: geofence.name,
117
- driverName: ''
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
- return devicesResult
150
+ return devicesResult
150
151
  }
151
152
 
152
- function getInAndOutEvents(devices, route, userData) {
153
- const events = []
154
- devices.forEach(d => {
155
- const deviceRoute = route.filter(p => p.deviceId === d.id)
156
-
157
- const routePoints = deviceRoute.map(p => convertPositionToFeature(p))
158
- const geofencesFeatures = userData.geofences.map(g => convertToFeature(g))
159
-
160
- const entryMap = []
161
- routePoints.forEach(p => {
162
- geofencesFeatures.forEach(g => {
163
- if(g.geometry.type === 'Polygon') {
164
- if (booleanPointInPolygon.default(p, g)) {
165
- if (!entryMap.includes(g)) {
166
- events.push(createEvent('geofenceEnter',d.id,p,g))
167
- entryMap.push(g)
168
- }
169
- } else {
170
- if (entryMap.includes(g)) {
171
- events.push(createEvent('geofenceExit',d.id,p,g))
172
- const index = entryMap.indexOf(g)
173
- entryMap.splice(index, 1)
174
- }
175
- }
176
- }
177
- if(g.geometry.type === 'Point') {
178
- if (distance.default(p, g, {units: 'meters'}) < g.properties.distance) {
179
- if (!entryMap.includes(g)) {
180
- events.push(createEvent('geofenceEnter',d.id,p,g))
181
- entryMap.push(g)
182
- }
183
- } else {
184
- if (entryMap.includes(g)) {
185
- events.push(createEvent('geofenceExit',d.id,p,g))
186
- const index = entryMap.indexOf(g)
187
- entryMap.splice(index, 1)
188
- }
189
- }
190
- }
191
- if(g.geometry.type === 'LineString') {
192
- if (pointToLineDistance.default(p, g,{units: 'meters'}) < (g.properties.geofence.attributes.polylineDistance || 25)) {
193
- if (!entryMap.includes(g)) {
194
- events.push(createEvent('geofenceEnter',d.id,p,g))
195
- entryMap.push(g)
196
- }
197
- } else {
198
- if (entryMap.includes(g)) {
199
- events.push(createEvent('geofenceExit',d.id,p,g))
200
- const index = entryMap.indexOf(g)
201
- entryMap.splice(index, 1)
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
- return events
210
+ return events
210
211
  }
211
212
 
212
- function createEvent(type, deviceId, p, g) {
213
- return {
214
- type: type,
215
- position: p.properties.position,
216
- geofenceId: g.properties.geofence.id,
217
- deviceId: deviceId
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
- console.log('Export to PDF')
223
-
224
- const timezone = userData.user.attributes.timezone
225
- const translations = getTranslations(userData)
226
- const lang = userData.user.attributes.lang || (navigator && navigator.language)
227
-
228
- const headers = [
229
- translations.report.enter,
230
- translations.report.exit,
231
- translations.report.duration,
232
- translations.report.geofence,
233
- translations.report.driver
234
- ]
235
- if (reportData.devices) {
236
- let first = true
237
- const doc = new jsPDF.jsPDF('l')
238
- await headerFromUser(doc, translations.report.titleZoneReport, userData.user)
239
-
240
- reportData.devices.forEach(d => {
241
- let data = []
242
- const name = deviceName(d.device)
243
- const group = userData.groups.find(g => d.device.groupId === g.id)
244
-
245
- let space = 0
246
- if(!first) {
247
- doc.addPage()
248
- } else {
249
- first = false
250
- space = 10
251
- }
252
- doc.setFontSize(13)
253
- doc.text(name, 20, space+20 )
254
- doc.setFontSize(11)
255
- doc.text(group ? translations.report.group + ': ' + group.name : '', 200, space+20 )
256
- doc.text(convertToLocaleString(d.from, lang, timezone) + ' - ' + convertToLocaleString(d.to, lang, timezone), 20, space+25 )
257
- d.geofences.map(a => {
258
- const temp = [
259
- geofenceEnter(userData.user, a),
260
- geofenceExit(userData.user, a),
261
- a.totalTime ? convertMS(a.totalTime * 1000, true) : '',
262
- a.geofenceName,
263
- a.driverName
264
- ]
265
- data.push(temp)
266
- })
267
-
268
- const footValues = [
269
- 'Total:' + d.geofences.length
270
- ]
271
-
272
- const style = getStyle(getUserPartner(userData.user))
273
- doc.autoTable({
274
- head: [headers],
275
- body: data,
276
- foot: [footValues],
277
- showFoot: 'lastPage',
278
- headStyles: {
279
- fillColor: style.pdfHeaderColor,
280
- textColor: style.pdfHeaderTextColor,
281
- fontSize: 10
282
- },
283
- bodyStyles: {
284
- fillColor: style.pdfBodyColor,
285
- textColor: style.pdfBodyTextColor,
286
- fontSize: 8
287
- },
288
- footStyles: {
289
- fillColor: style.pdfFooterColor,
290
- textColor: style.pdfFooterTextColor,
291
- fontSize: 9
292
- },
293
- startY: space+35 });
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
- return doc
297
- }
299
+ return doc
300
+ }
298
301
  }
299
302
 
300
- function exportZoneReportToExcel(userData, reportData) {
301
- console.log('Export to Excel')
302
-
303
- const translations = getTranslations(userData)
304
-
305
- const settings = {
306
- sheetName: translations.report.titleActivityReport, // The name of the sheet
307
- fileName: fileName, // The name of the spreadsheet
308
- }
309
- const headers = [
310
- {label: translations.report.vehicle, value:'name'},
311
- {label: translations.report.enter, value:'enter'},
312
- {label: translations.report.exit, value:'exit'},
313
- {label: translations.report.duration, value:'duration'},
314
- {label: translations.report.geofence, value:'zone'},
315
- {label: translations.report.driver, value:'driver'},
316
- ]
317
- let data = []
318
- if (reportData.devices) {
319
- reportData.devices.forEach(d => {
320
- data = data.concat([{}])
321
- data = data.concat(d.geofences.map(a => {
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
- headers,
335
- data,
336
- settings
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
- return device.name + (device.attributes.license_plate ? ', ' +device.attributes.license_plate : '') + (device.model ? ', ' + device.model : '')
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
- return row.inTime ? convertToLocaleString(row.inTime.fixTime, user.attributes.lang, user.attributes.timezone) : ''
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
- return row.outTime ? convertToLocaleString(row.outTime.fixTime, user.attributes.lang, user.attributes.timezone) : ''
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