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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetmap-reports",
3
- "version": "1.0.406",
3
+ "version": "1.0.409",
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,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 (traccar, from, to, devices, getRoutes, getTrips, getStops, getSummary, currentDeviceCount = 0, totalDevices = devices.length, sliceSize= 5) {
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'
@@ -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 = chunk.map(d =>
79
- traccar.axios.get(url + '&' + `deviceId=${d.id}`, {
80
- jar: traccar.cookieJar,
81
- withCredentials: true
82
- }).then(r => r.data).then(x => {
83
- console.log('LOADING_MESSAGE:' + d.name)
84
- console.log(`PROGRESS_PERC:${currentDeviceCount++ / totalDevices * 100}`)
85
- return x
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 {
@@ -1,352 +1,358 @@
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
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
- 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, 20)
62
- const routeData = allInOne.route
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
- const data = getInAndOutEvents(slice, routeData, userData)
66
+ const data = getInAndOutEvents(slice, routeData, userData)
65
67
 
66
- console.log('Geofence Enter/Exit Alerts:' + data.length)
68
+ console.log('Geofence Enter/Exit Alerts:' + data.length)
67
69
 
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
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
- reportData.push(allData)
78
+ reportData.push(allData)
75
79
 
76
- return reportData
80
+ return reportData
77
81
  }
78
82
 
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,
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
- return devicesResult
153
+ return devicesResult
150
154
  }
151
155
 
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
- })
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
- return events
213
+ return events
210
214
  }
211
215
 
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
- }
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
- 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
- })
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
- return doc
297
- }
302
+ return doc
303
+ }
298
304
  }
299
305
 
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)
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
- headers,
335
- data,
336
- settings
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
- return device.name + (device.attributes.license_plate ? ', ' +device.attributes.license_plate : '') + (device.model ? ', ' + device.model : '')
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
- return row.inTime ? convertToLocaleString(row.inTime.fixTime, user.attributes.lang, user.attributes.timezone) : ''
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
- return row.outTime ? convertToLocaleString(row.outTime.fixTime, user.attributes.lang, user.attributes.timezone) : ''
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