fleetmap-reports 1.0.404 → 1.0.407

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.404",
3
+ "version": "1.0.407",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -10,9 +10,9 @@
10
10
  "author": "",
11
11
  "license": "ISC",
12
12
  "dependencies": {
13
+ "@turf/boolean-point-in-polygon": "^6.5.0",
13
14
  "@turf/distance": "^6.5.0",
14
15
  "@turf/helpers": "^6.5.0",
15
- "@turf/point-on-feature": "^6.5.0",
16
16
  "@turf/point-to-line-distance": "^6.5.0",
17
17
  "axios": "^0.21.1",
18
18
  "axios-cookiejar-support": "^1.0.1",
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
@@ -338,19 +339,20 @@ describe('Test_Reports', function () {
338
339
  const device = data[0].devices.find(d => d.device.id === 25508)
339
340
  assert.equal(device.days.length, 25)
340
341
  }, 30000)
341
- /* it('Zone Report', async () => {
342
- const report = await getReports()
343
- const userData = await report.getUserData()
344
- const data = await report.zoneReport(new Date(2022, 3, 25, 0, 0, 0, 0),
345
- new Date(2022, 3, 28, 23, 59, 59, 0),
346
- userData)
342
+ // eslint-disable-next-line no-undef
343
+ it('Zone Report', async () => {
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)
347
349
 
348
- assert.equal(data.length, 1)
349
- const device = data[0].devices.find(d => d.device.id===22326)
350
- assert.equal(device.geofences.length, 11)
351
- assert.equal(device.geofences[0].inTime.fixTime, '2022-04-25T23:48:05.000+0000')
352
- assert.equal(device.geofences[0].outTime.fixTime, '2022-04-26T07:47:35.000+0000')
353
- assert.equal(device.geofences[0].totalTime, '28770')
354
- assert.equal(device.geofences[0].geofenceName, 'Casa João')
355
- }, 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)
356
358
  })
@@ -65,27 +65,45 @@ 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
+ vehiclesByRequest = 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
+ console.log('getAllInOn', devices.map(d => d.id))
88
+
89
+ const sliced = automaticReports.sliceArray(devices, sliceSize)
76
90
  const result = []
77
- let deviceCount = currentDeviceCount
78
91
  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
- }))
92
+ const requests = []
93
+ for (const _chunk of automaticReports.sliceArray(chunk, vehiclesByRequest)) {
94
+ const u = url + '&' + _chunk.map(d => `deviceId=${d.id}`).join('&')
95
+ console.log(u)
96
+ requests.push(
97
+ traccar.axios.get(u, {
98
+ jar: traccar.cookieJar,
99
+ withCredentials: true
100
+ }).then(r => r.data).then(x => {
101
+ console.log('LOADING_MESSAGE:' + _chunk[0].name)
102
+ currentDeviceCount += vehiclesByRequest
103
+ console.log(`PROGRESS_PERC:${currentDeviceCount / totalDevices * 100}`)
104
+ return x
105
+ }))
106
+ }
89
107
  result.push(...(await Promise.all(requests)))
90
108
  }
91
109
  return {
@@ -1,352 +1,353 @@
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 pointOnFeature = require("@turf/point-on-feature")
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, 5)
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(traccar, from, to, slice, true, false, false, false, deviceCount, devices.length, 30, 10)
61
+ const routeData = allInOne.route
63
62
 
64
- const data = getInAndOutEvents(slice, routeData, userData)
63
+ const data = getInAndOutEvents(slice, routeData, userData)
65
64
 
66
- console.log('Geofence Enter/Exit Alerts:' + data.length)
65
+ console.log('Geofence Enter/Exit Alerts:' + data.length)
67
66
 
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
67
+ if (data.length) {
68
+ allData.devices.push(...await processDevices(from, to, devices, userData.drivers, userData.geofences, data, traccar))
72
69
  }
70
+ deviceCount = deviceCount + slice.length
71
+ }
73
72
 
74
- reportData.push(allData)
73
+ reportData.push(allData)
75
74
 
76
- return reportData
75
+ return reportData
77
76
  }
78
77
 
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,
78
+ async function processDevices (from, to, devices, drivers, geofences, data) {
79
+ const devicesResult = []
80
+
81
+ for (const d of devices) {
82
+ const alerts = data.filter(t => t.deviceId === d.id)
83
+ if (alerts.length > 0) {
84
+ // const response = await traccar.reports.reportsRouteGet(from, to, [d.id])
85
+
86
+ const zoneInOutData = []
87
+ const zoneInData = {}
88
+ // const positions = response.data
89
+
90
+ alerts.forEach(a => {
91
+ // a.position = positions.find(p => p.id === a.positionId)
92
+ if (a.position) {
93
+ if (a.type === 'geofenceEnter') {
94
+ const driver = drivers.find(d => a.position.attributes && d.uniqueId === a.position.attributes.driverUniqueId)
95
+ a.position.driverName = driver ? driver.name : ''
96
+ zoneInData[a.geofenceId] = a
97
+ } else if (a.type === 'geofenceExit') {
98
+ const geofence = geofences.find(g => g.id === a.geofenceId)
99
+ if (zoneInData[a.geofenceId]) {
100
+ const totalInTime = moment(a.position.fixTime).diff(moment(zoneInData[a.geofenceId].position.fixTime), 'seconds')
101
+ if (geofence) {
102
+ zoneInOutData.push({
103
+ inTime: zoneInData[a.geofenceId].position,
104
+ outTime: a.position,
105
+ totalTime: totalInTime,
106
+ geofenceName: geofence.name,
107
+ driverName: zoneInData[a.geofenceId].position.driverName
108
+ })
109
+ }
110
+ zoneInData[a.geofenceId] = null
111
+ } else {
112
+ if (geofence) {
113
+ zoneInOutData.push({
114
+ outTime: a.position,
115
+ geofenceName: geofence.name,
116
+ driverName: ''
144
117
  })
118
+ }
145
119
  }
120
+ }
146
121
  }
122
+ })
123
+
124
+ for (const i in zoneInData) {
125
+ if (zoneInData[i]) {
126
+ const geofence = geofences.find(g => g.id === zoneInData[i].geofenceId)
127
+ if (geofence) {
128
+ zoneInOutData.push({
129
+ inTime: zoneInData[i].position,
130
+ geofenceName: geofence.name,
131
+ driverName: zoneInData[i].position.driverName
132
+ })
133
+ }
134
+ }
135
+ }
136
+
137
+ if (zoneInOutData.length > 0) {
138
+ devicesResult.push({
139
+ device: d,
140
+ from,
141
+ to,
142
+ geofences: zoneInOutData
143
+ })
144
+ }
147
145
  }
146
+ }
148
147
 
149
- return devicesResult
148
+ return devicesResult
150
149
  }
151
150
 
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 (pointOnFeature(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(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
- })
151
+ function getInAndOutEvents (devices, route, userData) {
152
+ const events = []
153
+ devices.forEach(d => {
154
+ const deviceRoute = route.filter(p => p.deviceId === d.id)
155
+
156
+ const routePoints = deviceRoute.map(p => convertPositionToFeature(p))
157
+ const geofencesFeatures = userData.geofences.map(g => convertToFeature(g))
158
+
159
+ const entryMap = []
160
+ routePoints.forEach(p => {
161
+ geofencesFeatures.forEach(g => {
162
+ if (g.geometry.type === 'Polygon') {
163
+ if (booleanPointInPolygon.default(p, g)) {
164
+ if (!entryMap.includes(g)) {
165
+ events.push(createEvent('geofenceEnter', d.id, p, g))
166
+ entryMap.push(g)
167
+ }
168
+ } else {
169
+ if (entryMap.includes(g)) {
170
+ events.push(createEvent('geofenceExit', d.id, p, g))
171
+ const index = entryMap.indexOf(g)
172
+ entryMap.splice(index, 1)
173
+ }
174
+ }
175
+ }
176
+ if (g.geometry.type === 'Point') {
177
+ if (distance.default(p, g, { units: 'meters' }) < g.properties.distance) {
178
+ if (!entryMap.includes(g)) {
179
+ events.push(createEvent('geofenceEnter', d.id, p, g))
180
+ entryMap.push(g)
181
+ }
182
+ } else {
183
+ if (entryMap.includes(g)) {
184
+ events.push(createEvent('geofenceExit', d.id, p, g))
185
+ const index = entryMap.indexOf(g)
186
+ entryMap.splice(index, 1)
187
+ }
188
+ }
189
+ }
190
+ if (g.geometry.type === 'LineString') {
191
+ if (pointToLineDistance.default(p, g, { units: 'meters' }) < (g.properties.geofence.attributes.polylineDistance || 25)) {
192
+ if (!entryMap.includes(g)) {
193
+ events.push(createEvent('geofenceEnter', d.id, p, g))
194
+ entryMap.push(g)
195
+ }
196
+ } else {
197
+ if (entryMap.includes(g)) {
198
+ events.push(createEvent('geofenceExit', d.id, p, g))
199
+ const index = entryMap.indexOf(g)
200
+ entryMap.splice(index, 1)
201
+ }
202
+ }
203
+ }
204
+ })
207
205
  })
206
+ })
208
207
 
209
- return events
208
+ return events
210
209
  }
211
210
 
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
- }
211
+ function createEvent (type, deviceId, p, g) {
212
+ return {
213
+ type,
214
+ position: p.properties.position,
215
+ geofenceId: g.properties.geofence.id,
216
+ deviceId
217
+ }
219
218
  }
220
219
 
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
- })
220
+ async function exportZoneReportToPDF (userData, reportData) {
221
+ console.log('Export to PDF')
222
+
223
+ const timezone = userData.user.attributes.timezone
224
+ const translations = getTranslations(userData)
225
+ const lang = userData.user.attributes.lang || (navigator && navigator.language)
226
+
227
+ const headers = [
228
+ translations.report.enter,
229
+ translations.report.exit,
230
+ translations.report.duration,
231
+ translations.report.geofence,
232
+ translations.report.driver
233
+ ]
234
+ if (reportData.devices) {
235
+ let first = true
236
+ // eslint-disable-next-line new-cap
237
+ const doc = new jsPDF.jsPDF('l')
238
+ await headerFromUser(doc, translations.report.titleZoneReport, userData.user)
239
+
240
+ reportData.devices.forEach(d => {
241
+ const 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.forEach(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
+ })
295
+ })
295
296
 
296
- return doc
297
- }
297
+ return doc
298
+ }
298
299
  }
299
300
 
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)
301
+ function exportZoneReportToExcel (userData, reportData) {
302
+ console.log('Export to Excel')
303
+
304
+ const translations = getTranslations(userData)
305
+
306
+ const settings = {
307
+ sheetName: translations.report.titleActivityReport, // The name of the sheet
308
+ fileName // The name of the spreadsheet
309
+ }
310
+ const headers = [
311
+ { label: translations.report.vehicle, value: 'name' },
312
+ { label: translations.report.enter, value: 'enter' },
313
+ { label: translations.report.exit, value: 'exit' },
314
+ { label: translations.report.duration, value: 'duration' },
315
+ { label: translations.report.geofence, value: 'zone' },
316
+ { label: translations.report.driver, value: 'driver' }
317
+ ]
318
+ let data = []
319
+ if (reportData.devices) {
320
+ reportData.devices.forEach(d => {
321
+ data = data.concat([{}])
322
+ data = data.concat(d.geofences.map(a => {
333
323
  return {
334
- headers,
335
- data,
336
- settings
324
+ name: d.device.name,
325
+ enter: geofenceEnter(userData.user, a),
326
+ exit: geofenceExit(userData.user, a),
327
+ duration: a.totalTime ? convertMS(a.totalTime * 1000, true) : '',
328
+ zone: a.geofenceName,
329
+ driver: a.driverName
337
330
  }
331
+ }))
332
+ })
333
+ console.log(data)
334
+ return {
335
+ headers,
336
+ data,
337
+ settings
338
338
  }
339
+ }
339
340
  }
340
341
 
341
- function deviceName(device){
342
- return device.name + (device.attributes.license_plate ? ', ' +device.attributes.license_plate : '') + (device.model ? ', ' + device.model : '')
342
+ function deviceName (device) {
343
+ return device.name + (device.attributes.license_plate ? ', ' + device.attributes.license_plate : '') + (device.model ? ', ' + device.model : '')
343
344
  }
344
345
 
345
- function geofenceEnter(user, row){
346
- return row.inTime ? convertToLocaleString(row.inTime.fixTime, user.attributes.lang, user.attributes.timezone) : ''
346
+ function geofenceEnter (user, row) {
347
+ return row.inTime ? convertToLocaleString(row.inTime.fixTime, user.attributes.lang, user.attributes.timezone) : ''
347
348
  }
348
- function geofenceExit(user, row){
349
- return row.outTime ? convertToLocaleString(row.outTime.fixTime, user.attributes.lang, user.attributes.timezone) : ''
349
+ function geofenceExit (user, row) {
350
+ return row.outTime ? convertToLocaleString(row.outTime.fixTime, user.attributes.lang, user.attributes.timezone) : ''
350
351
  }
351
352
 
352
353
  exports.createZoneReport = createZoneReport