fleetmap-reports 1.0.757 → 1.0.759

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.757",
3
+ "version": "1.0.759",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -34,8 +34,7 @@
34
34
  "eslint-plugin-import": "^2.26.0",
35
35
  "eslint-plugin-node": "^11.1.0",
36
36
  "eslint-plugin-promise": "^6.0.0",
37
- "jest": "^27.5.0",
38
- "mocha": "^10.2.0",
37
+ "jest": "^29.6.1",
39
38
  "webpack": "^5.51.0",
40
39
  "webpack-cli": "^4.5.0"
41
40
  },
@@ -264,7 +264,6 @@ function processDevices (from, to, devices, data, userData) {
264
264
  }
265
265
 
266
266
  function processDrivers (from, to, drivers, data, userData) {
267
- console.log(data)
268
267
  const driversResult = []
269
268
  drivers.forEach(d => {
270
269
  const { route, trips } = getDriverData(d, data)
@@ -351,7 +350,6 @@ function exportActivityReportToPDFDriver (doc, translations, reportData, userDat
351
350
 
352
351
  doc.setFontSize(10)
353
352
  doc.text(convertToLocaleString(reportData.from, lang, timezone) + ' - ' + convertToLocaleString(reportData.to, lang, timezone), 20, 30)
354
- doc.text()
355
353
 
356
354
  const data = []
357
355
  reportData.drivers.forEach(d => {
@@ -0,0 +1,48 @@
1
+ // eslint-disable-next-line no-undef
2
+ const { getReports } = require('./index')
3
+ const assert = require('assert')
4
+ // eslint-disable-next-line no-undef
5
+ describe('activity report', function () {
6
+ // eslint-disable-next-line no-undef
7
+ it('Activity by device', async () => {
8
+ const report = await getReports()
9
+ const userData = await report.getUserData()
10
+
11
+ const data = await report.activityReport(new Date(2022, 0, 1, 0, 0, 0, 0),
12
+ new Date(2022, 0, 31, 23, 59, 59, 0),
13
+ userData)
14
+ assert.equal(data.length, 1)
15
+ const device = data[0].devices.find(d => d.device.id === 22326)
16
+ assert.equal(device.summary[0].startOdometer, 0)
17
+ assert.equal(device.summary[0].distance, 0)
18
+ assert.equal(device.summary[0].startTime, 0)
19
+ assert.equal(device.summary[0].endTime, 0)
20
+ }, 80000)
21
+
22
+ // eslint-disable-next-line no-undef
23
+ it('Activity by driver', async () => {
24
+ const report = await getReports('felipe@codepa.com.br', process.env.password)
25
+ const userData = await report.getUserData()
26
+ userData.byDriver = true
27
+ const data = await report.activityReport(new Date(2023, 0, 1, 0, 0, 0, 0),
28
+ new Date(2023, 0, 1, 23, 59, 59, 0),
29
+ userData)
30
+ assert.equal(data.length, 1)
31
+ await report.activityReportToPDF(userData, data[0])
32
+ }, 800000)
33
+ // eslint-disable-next-line no-undef
34
+ it('Activity byDevice groupByDay', async () => {
35
+ const report = await getReports()
36
+ const userData = await report.getUserData()
37
+ userData.groupByDay = true
38
+ const data = await report.activityReport(new Date(2022, 0, 1, 0, 0, 0, 0),
39
+ new Date(2022, 0, 20, 23, 59, 59, 0),
40
+ userData)
41
+ assert.equal(data.length, 1)
42
+ const device = data[0].devices.find(d => d.device.id === 22326)
43
+ assert.equal(device.summary[5].startOdometer, 0)
44
+ assert.equal(device.summary[5].distance, 0)
45
+ assert.equal(device.summary[5].startTime, 0)
46
+ assert.equal(device.summary[5].endTime, 0)
47
+ }, 90000)
48
+ })
@@ -16,6 +16,7 @@ axiosCookieJarSupport(axios)
16
16
 
17
17
  const getReports = async (email, password) => {
18
18
  try {
19
+ console.log('email / pass', process.env.email, process.env.password)
19
20
  await new SessionApi(traccarConfig, null, axios).sessionPost(email || process.env.email, password || process.env.password)
20
21
  return new Index(traccarConfig, axios, cookieJar)
21
22
  } catch (e) {
@@ -192,36 +192,6 @@ describe('Test_Reports', function () {
192
192
  assert.equal(totalIdleTime, 16000) // Total Duration
193
193
  }, 20000)
194
194
  // eslint-disable-next-line no-undef
195
- it('Activity by device', async () => {
196
- const report = await getReports()
197
- const userData = await report.getUserData()
198
-
199
- const data = await report.activityReport(new Date(2022, 0, 1, 0, 0, 0, 0),
200
- new Date(2022, 0, 31, 23, 59, 59, 0),
201
- userData)
202
- assert.equal(data.length, 1)
203
- const device = data[0].devices.find(d => d.device.id === 22326)
204
- assert.equal(device.summary[0].startOdometer, 122502742.59)
205
- assert.equal(device.summary[0].distance, 1425532.6071218813)
206
- assert.equal(device.summary[0].startTime, '2022-01-01T13:35:47.000+0000')
207
- assert.equal(device.summary[0].endTime, '2022-01-31T17:36:27.000+0000')
208
- }, 80000)
209
- // eslint-disable-next-line no-undef
210
- it('Activity byDevice groupByDay', async () => {
211
- const report = await getReports()
212
- const userData = await report.getUserData()
213
- userData.groupByDay = true
214
- const data = await report.activityReport(new Date(2022, 0, 1, 0, 0, 0, 0),
215
- new Date(2022, 0, 20, 23, 59, 59, 0),
216
- userData)
217
- assert.equal(data.length, 1)
218
- const device = data[0].devices.find(d => d.device.id === 22326)
219
- assert.equal(device.summary[5].startOdometer, 122923290.95)
220
- assert.equal(device.summary[5].distance, 77033.18999999762)
221
- assert.equal(device.summary[5].startTime, '2022-01-06T18:35:36.000+0000')
222
- assert.equal(device.summary[5].endTime, '2022-01-06T19:54:27.000+0000')
223
- }, 90000)
224
- // eslint-disable-next-line no-undef
225
195
  it('test allinone', async () => {
226
196
  console.log('Start')
227
197
  const reports = await getReports()
@@ -7,10 +7,10 @@ describe('performance', function () {
7
7
  it('performance report', async () => {
8
8
  const report = await getReports()
9
9
  const userData = await report.getUserData()
10
- userData.devices = userData.devices.filter(d => d.attributes.xpert)
10
+ userData.devices = userData.devices.filter(d => d.id === 128270)
11
11
  const data = await createPerformanceReport(
12
- new Date(Date.UTC(2023, 5, 10, 0, 0, 0, 0)),
13
- new Date(Date.UTC(2023, 5, 20, 23, 59, 59, 0)),
12
+ new Date(Date.UTC(2023, 5, 29, 0, 0, 0, 0)),
13
+ new Date(Date.UTC(2023, 5, 30, 23, 59, 59, 0)),
14
14
  userData,
15
15
  report.traccar)
16
16
  console.log(data)
@@ -77,7 +77,7 @@ describe('zones', function () {
77
77
  userData.devices = userData.devices.filter(d => d.name === 'G-1101-E Clio')
78
78
  userData.geofences = userData.geofences.filter(g => g.name === 'baliza raio verde ' || g.name === 'baliza raio amarelo ')
79
79
  const result = await report.zoneReport(
80
- new Date(Date.UTC(2023, 0, 1, 0, 0, 0, 0)),
80
+ new Date(Date.UTC(2023, 0, 29, 0, 0, 0, 0)),
81
81
  new Date(Date.UTC(2023, 0, 31, 23, 59, 59, 0)),
82
82
  userData)
83
83
  const first = result[0].devices[0].geofences[0]
@@ -86,21 +86,12 @@ async function createZoneReport (from, to, userData, traccar) {
86
86
  return reportData
87
87
  }
88
88
 
89
- function getNextIn (outDate, alerts, geofenceId, deviceRoute) {
90
- const next = alerts
91
- .filter(a => a.type === 'geofenceEnter' && (a.geofenceId === geofenceId || !geofenceId))
92
- .find(a => new Date(a.position.fixTime).getTime() > outDate)
93
- return (next && next.position && new Date(next.position.fixTime).getTime()) ||
94
- new Date(deviceRoute.slice(-1)[0].fixTime).getTime()
95
- }
96
-
97
89
  async function processDevices (from, to, devices, userData, data) {
98
90
  const devicesResult = []
99
91
 
100
92
  for (const d of devices) {
101
93
  const alerts = data.alerts.filter(t => t.deviceId === d.id)
102
94
  const deviceRoute = data.route.filter(p => p.deviceId === d.id)
103
-
104
95
  const zoneInOutData = analyseAlerts(alerts, deviceRoute, userData, from, to).filter(d => !userData.onlyWithStop || d.stopped)
105
96
 
106
97
  if (userData.groupByDay || userData.zonesByColumn) {
@@ -122,47 +113,10 @@ async function processDevices (from, to, devices, userData, data) {
122
113
  const firstIn = zoneInOutDayData.find(z => z.inTime && new Date(z.inTime.fixTime) > fromByDay)
123
114
  const lastOut = zoneInOutDayData.slice().reverse().find(z => z.outTime && new Date(z.outTime.fixTime) < toByDay)
124
115
 
125
- let timeIn = zoneInOutDayData.length ? zoneInOutDayData.reduce((a, b) => a + (b.totalInTime || 0), 0) : 0
126
-
127
- let distanceIn = zoneInOutDayData.length && dayRoute.length ? zoneInOutDayData.reduce((a, b) => a + (b.distanceIn || 0), 0) : 0
128
- let distanceOut = 0
129
- if (zoneInOutDayData.length) {
130
- distanceOut = zoneInOutDayData.reduce((a, b) => a + (b.distanceOut || 0), 0) -
131
- (zoneInOutDayData[zoneInOutDayData.length - 1].distanceOut || 0)
132
- } else {
133
- distanceOut = calculateDistance(deviceRoute.filter(p => new Date(p.fixTime) >= fromByDay && new Date(p.fixTime) < toByDay))
134
- }
135
-
136
- if (zoneInOutDayData.length) {
137
- // Check if the first entry starts only on the day before
138
- if (!zoneInOutDayData[0].inTime || new Date(zoneInOutDayData[0].inTime.fixTime) < fromByDay) {
139
- const inTime = zoneInOutDayData[0].inTime ? new Date(zoneInOutDayData[0].inTime.fixTime) : from
140
- timeIn = timeIn - (fromByDay.getTime() - inTime.getTime())
141
- const routeDayBefore = deviceRoute.filter(p => (!zoneInOutDayData[0].inTime || new Date(p.fixTime) >= new Date(zoneInOutDayData[0].inTime.fixTime)) &&
142
- new Date(p.fixTime) < fromByDay)
143
- distanceIn = distanceIn - calculateDistance(routeDayBefore)
144
- } else {
145
- // Add distanceOut before the first entry
146
- const routeOut = deviceRoute.filter(p =>
147
- new Date(p.fixTime).getTime() < new Date(zoneInOutDayData[0].inTime.fixTime).getTime() &&
148
- new Date(p.fixTime).getTime() >= fromByDay.getTime()
149
- )
150
- distanceOut = distanceOut + calculateDistance(routeOut)
151
- }
116
+ const timeIn = calculateTimeIn(zoneInOutDayData, fromByDay, from, toByDay, to)
117
+ const distanceIn = calculateDistanceIn(zoneInOutDayData, deviceRoute, dayRoute, fromByDay, toByDay, to)
118
+ const distanceOut = calculateDistanceOut(zoneInOutDayData, dayRoute, fromByDay, toByDay, 'distanceOut')
152
119
 
153
- // Check if the last entry ends only on the next day
154
- if (!zoneInOutDayData[zoneInOutDayData.length - 1].outTime || new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) > toByDay) {
155
- const outTime = zoneInOutDayData[zoneInOutDayData.length - 1].outTime ? new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) : to
156
- timeIn = timeIn - (outTime.getTime() - (toByDay.getTime() + 1000))
157
- const routeDayAfter = deviceRoute.filter(p => new Date(p.fixTime) <= outTime && new Date(p.fixTime) > toByDay)
158
- distanceIn = distanceIn - calculateDistance(routeDayAfter)
159
- } else {
160
- const routeOut = deviceRoute.filter(p =>
161
- new Date(p.fixTime) >= new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime).getTime() &&
162
- new Date(p.fixTime) < toByDay.getTime())
163
- distanceOut = distanceOut + calculateDistance(routeOut)
164
- }
165
- }
166
120
  dataByDay.push({
167
121
  date,
168
122
  firstIn: firstIn ? firstIn.inTime.fixTime : undefined,
@@ -175,6 +129,7 @@ async function processDevices (from, to, devices, userData, data) {
175
129
  }
176
130
 
177
131
  geofencesData.push({
132
+ geofenceId: geofence.id,
178
133
  geofenceName: geofence.name,
179
134
  days: dataByDay
180
135
  })
@@ -186,11 +141,14 @@ async function processDevices (from, to, devices, userData, data) {
186
141
  const fromByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0)
187
142
  const toByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59)
188
143
 
189
- const dayRoute = deviceRoute.filter(p => new Date(p.fixTime) >= fromByDay && new Date(p.fixTime) < toByDay)
190
- const totalDistance = calculateDistance(dayRoute)
144
+ const zoneInOutDayData = zoneInOutData.filter(z => (!z.inTime || (new Date(z.inTime.fixTime) < toByDay)) &&
145
+ (!z.outTime || (new Date(z.outTime.fixTime) > fromByDay)))
146
+
147
+ const distanceOut = calculateDistanceOut(zoneInOutDayData, deviceRoute, fromByDay, toByDay, 'distanceOutAny')
191
148
 
192
149
  const geofences = geofencesData.map(g => {
193
150
  return {
151
+ geofenceId: g.geofenceId,
194
152
  geofenceName: g.geofenceName,
195
153
  distanceIn: g.days.find(day => day.date === date).distanceIn
196
154
  }
@@ -199,7 +157,7 @@ async function processDevices (from, to, devices, userData, data) {
199
157
  groupByDay.push({
200
158
  date,
201
159
  geofences,
202
- distanceOut: totalDistance - geofences.reduce((a, b) => a + (b.distanceIn || 0), 0)
160
+ distanceOut
203
161
  })
204
162
  }
205
163
 
@@ -234,6 +192,90 @@ async function processDevices (from, to, devices, userData, data) {
234
192
  return devicesResult
235
193
  }
236
194
 
195
+ function calculateTimeIn (zoneInOutDayData, fromByDay, from, toByDay, to) {
196
+ let timeIn = zoneInOutDayData.length ? zoneInOutDayData.reduce((a, b) => a + (b.totalInTime || 0), 0) : 0
197
+
198
+ if (zoneInOutDayData.length) {
199
+ // Check if the first entry starts only on the day before
200
+ if (!zoneInOutDayData[0].inTime || new Date(zoneInOutDayData[0].inTime.fixTime) < fromByDay) {
201
+ const inTime = zoneInOutDayData[0].inTime ? new Date(zoneInOutDayData[0].inTime.fixTime) : from
202
+ timeIn = timeIn - (fromByDay.getTime() - inTime.getTime())
203
+ }
204
+
205
+ // Check if the last entry ends only on the next day
206
+ if (!zoneInOutDayData[zoneInOutDayData.length - 1].outTime || new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) > toByDay) {
207
+ const outTime = zoneInOutDayData[zoneInOutDayData.length - 1].outTime ? new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) : to
208
+ timeIn = timeIn - (outTime.getTime() - (toByDay.getTime() + 1000))
209
+ }
210
+ }
211
+ return timeIn
212
+ }
213
+
214
+ function getNextIn (outDate, alerts, geofenceId, deviceRoute) {
215
+ const next = alerts
216
+ .filter(a => a.type === 'geofenceEnter' && (a.geofenceId === geofenceId || !geofenceId))
217
+ .find(a => new Date(a.position.fixTime).getTime() > outDate)
218
+ return (next && next.position && new Date(next.position.fixTime).getTime()) ||
219
+ new Date(deviceRoute.slice(-1)[0].fixTime).getTime()
220
+ }
221
+
222
+ function getAnyNextIn (outDate, alerts, deviceRoute) {
223
+ const next = alerts
224
+ .filter(a => a.type === 'geofenceEnter')
225
+ .find(a => new Date(a.position.fixTime).getTime() > outDate)
226
+ return (next && next.position && new Date(next.position.fixTime).getTime()) ||
227
+ new Date(deviceRoute.slice(-1)[0].fixTime).getTime()
228
+ }
229
+
230
+ function calculateDistanceIn (zoneInOutDayData, deviceRoute, dayRoute, fromByDay, toByDay, to) {
231
+ let distanceIn = zoneInOutDayData.length && dayRoute.length ? zoneInOutDayData.reduce((a, b) => a + (b.distanceIn || 0), 0) : 0
232
+
233
+ if (zoneInOutDayData.length) {
234
+ // Check if the first entry starts only on the day before
235
+ if (!zoneInOutDayData[0].inTime || new Date(zoneInOutDayData[0].inTime.fixTime) < fromByDay) {
236
+ const routeDayBefore = deviceRoute.filter(p => (!zoneInOutDayData[0].inTime || new Date(p.fixTime) >= new Date(zoneInOutDayData[0].inTime.fixTime)) &&
237
+ new Date(p.fixTime) < fromByDay)
238
+ distanceIn = distanceIn - calculateDistance(routeDayBefore)
239
+ }
240
+
241
+ // Check if the last entry ends only on the next day
242
+ if (!zoneInOutDayData[zoneInOutDayData.length - 1].outTime || new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) > toByDay) {
243
+ const outTime = zoneInOutDayData[zoneInOutDayData.length - 1].outTime ? new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) : to
244
+ const routeDayAfter = deviceRoute.filter(p => new Date(p.fixTime) <= outTime && new Date(p.fixTime) > toByDay)
245
+ distanceIn = distanceIn - calculateDistance(routeDayAfter)
246
+ }
247
+ }
248
+
249
+ return distanceIn
250
+ }
251
+
252
+ function calculateDistanceOut (zoneInOutDayData, dayRoute, fromByDay, toByDay, field) {
253
+ if (zoneInOutDayData.length) {
254
+ let distanceOut = zoneInOutDayData.reduce((a, b) => a + (b[field] || 0), 0) -
255
+ (zoneInOutDayData[zoneInOutDayData.length - 1][field] || 0)
256
+
257
+ if (zoneInOutDayData[0].inTime && new Date(zoneInOutDayData[0].inTime.fixTime) > fromByDay) {
258
+ // Add distanceOut before the first entry
259
+ const routeOut = dayRoute.filter(p =>
260
+ new Date(p.fixTime).getTime() < new Date(zoneInOutDayData[0].inTime.fixTime).getTime() &&
261
+ new Date(p.fixTime).getTime() >= fromByDay.getTime()
262
+ )
263
+ distanceOut = distanceOut + calculateDistance(routeOut)
264
+ }
265
+
266
+ if (zoneInOutDayData[zoneInOutDayData.length - 1].outTime && new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) < toByDay) {
267
+ const routeOut = dayRoute.filter(p =>
268
+ new Date(p.fixTime) >= new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime).getTime() &&
269
+ new Date(p.fixTime) < toByDay.getTime())
270
+ distanceOut = distanceOut + calculateDistance(routeOut)
271
+ }
272
+
273
+ return distanceOut
274
+ }
275
+
276
+ return calculateDistance(dayRoute.filter(p => new Date(p.fixTime) >= fromByDay && new Date(p.fixTime) < toByDay))
277
+ }
278
+
237
279
  function analyseAlerts (alerts, deviceRoute, userData, from, to) {
238
280
  const zoneInOutData = []
239
281
  const zoneInData = {}
@@ -259,6 +301,14 @@ function analyseAlerts (alerts, deviceRoute, userData, from, to) {
259
301
  )
260
302
  const totalOutTime = nextIn - outDate
261
303
  const distanceOut = calculateDistance(routeAfterOut)
304
+
305
+ const anyNextIn = getAnyNextIn(outDate, alerts, deviceRoute)
306
+ const routeAfterOutAndBeforeAnyNextIn = deviceRoute.filter(p =>
307
+ new Date(p.fixTime).getTime() >= outDate &&
308
+ new Date(p.fixTime).getTime() < anyNextIn
309
+ )
310
+ const distanceOutAny = zoneInData.length < 2 ? calculateDistance(routeAfterOutAndBeforeAnyNextIn) : 0
311
+
262
312
  if (zoneInData[a.geofenceId]) {
263
313
  const totalInTime = new Date(a.position.fixTime).getTime() - new Date(zoneInData[a.geofenceId].position.fixTime).getTime()
264
314
  const inDate = new Date(zoneInData[a.geofenceId].position.fixTime).getTime()
@@ -273,6 +323,7 @@ function analyseAlerts (alerts, deviceRoute, userData, from, to) {
273
323
  totalOutTime,
274
324
  distanceIn: calculateDistance(routeIn),
275
325
  distanceOut,
326
+ distanceOutAny,
276
327
  geofenceName: geofence.name,
277
328
  geofenceId: geofence.id,
278
329
  stopped: routeIn.filter(p => !p.attributes.ignition).length > 0,
@@ -293,7 +344,8 @@ function analyseAlerts (alerts, deviceRoute, userData, from, to) {
293
344
  totalOutTime,
294
345
  distanceIn: calculateDistance(routeIn),
295
346
  driverName: '',
296
- distanceOut
347
+ distanceOut,
348
+ distanceOutAny
297
349
  })
298
350
  }
299
351
  }
@@ -386,26 +438,35 @@ async function exportZoneReportToPDF (userData, reportData) {
386
438
  const translations = getTranslations(userData)
387
439
  const lang = userData.user.attributes.lang || (navigator && navigator.language)
388
440
 
389
- const headers = userData.groupByDay
390
- ? [
391
- translations.report.date,
392
- translations.report.firstIn,
393
- translations.report.lastOut,
394
- translations.report.distanceIn || 'Kms Adentro',
395
- translations.report.timeIn,
396
- translations.report.distanceOut || 'Kms Afuera',
397
- translations.report.timeOut
398
- ]
399
- : [
400
- translations.report.enter,
401
- translations.report.exit,
402
- translations.report.stopped,
403
- translations.report.duration,
404
- translations.report.distanceIn || 'Kms Adentro',
405
- translations.report.distanceOut || 'Kms Afuera',
406
- translations.report.geofence,
407
- translations.report.driver
408
- ]
441
+ const headers = []
442
+
443
+ if (userData.groupByDay) {
444
+ headers.push(...[
445
+ translations.report.date,
446
+ translations.report.firstIn,
447
+ translations.report.lastOut,
448
+ translations.report.distanceIn || 'Kms Adentro',
449
+ translations.report.timeIn,
450
+ translations.report.distanceOut || 'Kms Afuera',
451
+ translations.report.timeOut
452
+ ])
453
+ } else if (userData.zonesByColumn) {
454
+ headers.push(translations.report.date)
455
+ reportData.devices[0].days[0].geofences.forEach(g => headers.push(g.geofenceName))
456
+ headers.push(translations.report.distanceOut || 'Kms Afuera')
457
+ } else {
458
+ headers.push(...[
459
+ translations.report.enter,
460
+ translations.report.exit,
461
+ translations.report.stopped,
462
+ translations.report.duration,
463
+ translations.report.distanceIn || 'Kms Adentro',
464
+ translations.report.distanceOut || 'Kms Afuera',
465
+ translations.report.geofence,
466
+ translations.report.driver
467
+ ])
468
+ }
469
+
409
470
  if (reportData.devices) {
410
471
  // eslint-disable-next-line new-cap
411
472
  const doc = new jsPDF.jsPDF('l')
@@ -447,6 +508,31 @@ async function exportZoneReportToPDF (userData, reportData) {
447
508
  6: { halign: 'right' }
448
509
  })
449
510
  })
511
+ } else if (userData.zonesByColumn) {
512
+ const data = []
513
+ space = reportHeader(index === 0, doc, translations, d, lang, timezone, userData)
514
+ d.days.forEach(day => {
515
+ const temp = [convertToLocaleDateString(day.date, lang, timezone)]
516
+ day.geofences.forEach(a => {
517
+ temp.push(a.distanceIn ? a.distanceIn.toLocaleString(lang, { maximumFractionDigits: 2 }) : 0)
518
+ })
519
+ temp.push(day.distanceOut ? day.distanceOut.toLocaleString(lang, { maximumFractionDigits: 2 }) : 0)
520
+ data.push(temp)
521
+ })
522
+ const footer = ['Total:' + d.days.length]
523
+ reportData.devices[0].days[0].geofences.forEach(gColumn => {
524
+ footer.push(d.days.reduce((a, b) => a + (b.geofences.find(g => g.geofenceId === gColumn.geofenceId).distanceIn), 0).toLocaleString(lang, { maximumFractionDigits: 2 }))
525
+ })
526
+ footer.push(d.days.reduce((a, b) => a + (b.distanceOut ? b.distanceOut : 0), 0).toLocaleString(lang, { maximumFractionDigits: 2 }))
527
+
528
+ let columnIndex = 1
529
+ const columnStyles = { }
530
+ reportData.devices[0].days[0].geofences.forEach(a => {
531
+ columnStyles[columnIndex] = { halign: 'right' }
532
+ columnIndex++
533
+ })
534
+ columnStyles[columnIndex] = { halign: 'right' }
535
+ addTable(doc, headers, data, footer, style, space + 40, columnStyles)
450
536
  } else {
451
537
  const data = []
452
538
  space = reportHeader(index === 0, doc, translations, d, lang, timezone, userData)
@@ -484,29 +570,42 @@ function exportZoneReportToExcel (userData, reportData) {
484
570
  sheetName: translations.report.titleActivityReport, // The name of the sheet
485
571
  fileName // The name of the spreadsheet
486
572
  }
487
- const headers = userData.groupByDay
488
- ? [
489
- { label: translations.report.geofence, value: 'zone' },
490
- { label: translations.report.vehicle, value: 'name' },
491
- { label: translations.report.date, value: 'date' },
492
- { label: translations.report.firstIn, value: 'firstIn' },
493
- { label: translations.report.lastOut, value: 'lastOut' },
494
- { label: translations.report.distanceIn || 'Kms Adentro', value: 'distanceIn' },
495
- { label: translations.report.timeIn, value: 'totalInTime' },
496
- { label: translations.report.distanceOut || 'Kms Afuera', value: 'distanceOut' },
497
- { label: translations.report.timeOut, value: 'totalOutTime' }
498
- ]
499
- : [
500
- { label: translations.report.vehicle, value: 'name' },
501
- { label: translations.report.enter, value: 'enter' },
502
- { label: translations.report.exit, value: 'exit' },
503
- { label: translations.report.stopped, value: 'stopped' },
504
- { label: translations.report.duration, value: 'totalInTime' },
505
- { label: translations.report.distanceIn || 'Kms Adentro', value: 'distanceIn' },
506
- { label: translations.report.distanceOut || 'Kms Afuera', value: 'distanceOut' },
507
- { label: translations.report.geofence, value: 'zone' },
508
- { label: translations.report.driver, value: 'driver' }
509
- ]
573
+ const headers = []
574
+ if (userData.groupByDay) {
575
+ headers.push([
576
+ { label: translations.report.geofence, value: 'zone' },
577
+ { label: translations.report.vehicle, value: 'name' },
578
+ { label: translations.report.date, value: 'date' },
579
+ { label: translations.report.firstIn, value: 'firstIn' },
580
+ { label: translations.report.lastOut, value: 'lastOut' },
581
+ { label: translations.report.distanceIn || 'Kms Adentro', value: 'distanceIn' },
582
+ { label: translations.report.timeIn, value: 'totalInTime' },
583
+ { label: translations.report.distanceOut || 'Kms Afuera', value: 'distanceOut' },
584
+ { label: translations.report.timeOut, value: 'totalOutTime' }
585
+ ])
586
+ } else if (userData.zonesByColumn) {
587
+ headers.push(...[
588
+ { label: translations.report.vehicle, value: 'name' },
589
+ { label: translations.report.date, value: 'date' }
590
+ ])
591
+ reportData.devices[0].days[0].geofences.forEach(g =>
592
+ headers.push({ label: g.geofenceName, value: g.geofenceId })
593
+ )
594
+ headers.push({ label: translations.report.distanceOut || 'Kms Afuera', value: 'distanceOut' })
595
+ } else {
596
+ headers.push(...[
597
+ { label: translations.report.vehicle, value: 'name' },
598
+ { label: translations.report.enter, value: 'enter' },
599
+ { label: translations.report.exit, value: 'exit' },
600
+ { label: translations.report.stopped, value: 'stopped' },
601
+ { label: translations.report.duration, value: 'totalInTime' },
602
+ { label: translations.report.distanceIn || 'Kms Adentro', value: 'distanceIn' },
603
+ { label: translations.report.distanceOut || 'Kms Afuera', value: 'distanceOut' },
604
+ { label: translations.report.geofence, value: 'zone' },
605
+ { label: translations.report.driver, value: 'driver' }
606
+ ])
607
+ }
608
+
510
609
  let data = []
511
610
  if (reportData.devices) {
512
611
  reportData.devices.forEach(d => {
@@ -518,6 +617,20 @@ function exportZoneReportToExcel (userData, reportData) {
518
617
  }))
519
618
  data = data.concat([{}])
520
619
  })
620
+ } else if (userData.zonesByColumn) {
621
+ const lang = userData.user.attributes.lang
622
+ d.days.forEach(day => {
623
+ const row = {
624
+ name: d.device.name,
625
+ date: convertToLocaleDateString(day.date, lang, userData.user.attributes.timezone),
626
+ distanceOut: day.distanceOut ? parseFloat(day.distanceOut.toFixed(2)) : 0
627
+ }
628
+ day.geofences.forEach(g => {
629
+ row[g.geofenceId] = g.distanceIn ? parseFloat(g.distanceIn.toFixed(2)) : 0
630
+ })
631
+ data.push(row)
632
+ })
633
+ data = data.concat([{}])
521
634
  } else {
522
635
  data = data.concat(d.geofences.map(a => {
523
636
  return getColumns(d, a, userData, translations, true)