fleetmap-reports 1.0.758 → 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.758",
3
+ "version": "1.0.759",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -2,14 +2,15 @@ const { getReports } = require('./index')
2
2
  const { createPerformanceReport } = require('../partnerReports/performance-report')
3
3
  // eslint-disable-next-line no-undef
4
4
  describe('performance', function () {
5
+ this.timeout(500000)
5
6
  // eslint-disable-next-line no-undef
6
7
  it('performance report', async () => {
7
8
  const report = await getReports()
8
9
  const userData = await report.getUserData()
9
- userData.devices = userData.devices.filter(d => d.attributes.xpert)
10
+ userData.devices = userData.devices.filter(d => d.id === 128270)
10
11
  const data = await createPerformanceReport(
11
- new Date(Date.UTC(2023, 5, 10, 0, 0, 0, 0)),
12
- 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)),
13
14
  userData,
14
15
  report.traccar)
15
16
  console.log(data)
@@ -2,6 +2,7 @@ const { getReports } = require('./index')
2
2
  const assert = require('assert')
3
3
  // eslint-disable-next-line no-undef
4
4
  describe('zones', function () {
5
+ this.timeout(500000)
5
6
  // eslint-disable-next-line no-undef
6
7
  it('works with ellca', async () => {
7
8
  const report = await getReports()
@@ -47,4 +48,41 @@ describe('zones', function () {
47
48
  assert.equal(first.inTime.fixTime, '2023-01-03T21:23:24.000+0000')
48
49
  assert.equal(first.outTime.fixTime, '2023-01-07T12:22:53.000+0000')
49
50
  }, 4000000)
51
+
52
+ // eslint-disable-next-line no-undef
53
+ it('works with casais 2', async () => {
54
+ const report = await getReports('mario.andre.moreira@casais.gi', 'Casais.23')
55
+ const userData = await report.getUserData()
56
+ userData.groupByDay = true
57
+ userData.devices = userData.devices.filter(d => d.name === 'G-2542-F Fiat Tipo')
58
+ userData.geofences = userData.geofences.filter(g => g.name === 'baliza raio verde ')
59
+ assert.equal(userData.geofences.length > 0, true)
60
+ assert.equal(userData.devices.length > 0, true)
61
+ const result = await report.zoneReport(
62
+ new Date(2023, 1, 27, 0, 0, 0, 0),
63
+ new Date(2023, 1, 27, 23, 59, 59, 0),
64
+ userData)
65
+ assert.equal(result[0].devices[0].geofences.length, 1)
66
+ assert.equal(result[0].devices[0].geofences[0].days.length, 1)
67
+ const first = result[0].devices[0].geofences[0].days[0]
68
+ assert.equal(first.firstIn, '2023-02-27T21:53:16.000+0000')
69
+ assert.equal(first.distanceIn, 93.03917199839687)
70
+ assert.equal(first.distanceOut, 819.6685737216337)
71
+ }, 4000000)
72
+
73
+ it('works with casais 3', async () => {
74
+ const report = await getReports(process.env.USER_CASAIS, process.env.PASS_CASAIS)
75
+ const userData = await report.getUserData()
76
+ userData.zonesByColumn = true
77
+ userData.devices = userData.devices.filter(d => d.name === 'G-1101-E Clio')
78
+ userData.geofences = userData.geofences.filter(g => g.name === 'baliza raio verde ' || g.name === 'baliza raio amarelo ')
79
+ const result = await report.zoneReport(
80
+ new Date(Date.UTC(2023, 0, 29, 0, 0, 0, 0)),
81
+ new Date(Date.UTC(2023, 0, 31, 23, 59, 59, 0)),
82
+ userData)
83
+ const first = result[0].devices[0].geofences[0]
84
+ console.log(first)
85
+ assert.equal(first.name, 'baliza raio verde ')
86
+ assert.equal(first.distanceIn, '1069.343491503579')
87
+ }, 4000000)
50
88
  })
@@ -70,8 +70,13 @@ async function createZoneReport (from, to, userData, traccar) {
70
70
  deviceCount, devices.length, sliceSize, deviceChunk, undefined)
71
71
 
72
72
  const route = filterPositions(data.route)
73
- const alerts = await parallel('zone-report', 'getInAndOutEvents', slice, cleanPositions(route), userData)
74
- allData.devices.push(...await processDevices(from, to, devices, userData, { alerts, route }))
73
+ const alerts = []
74
+ if (isClientSide()) {
75
+ alerts.push(...(await getInAndOutEvents(slice, cleanPositions(route), userData)))
76
+ } else {
77
+ alerts.push(...(await parallel('zone-report', 'getInAndOutEvents', slice, cleanPositions(route), userData)))
78
+ }
79
+ allData.devices.push(...await processDevices(from, to, devices, userData, { alerts, route, summary: data.summary }))
75
80
 
76
81
  deviceCount = deviceCount + slice.length
77
82
  }
@@ -81,24 +86,15 @@ async function createZoneReport (from, to, userData, traccar) {
81
86
  return reportData
82
87
  }
83
88
 
84
- function getNextIn (outDate, alerts, geofenceId, deviceRoute) {
85
- const next = alerts
86
- .filter(a => a.type === 'geofenceEnter' && (a.geofenceId === geofenceId || !geofenceId))
87
- .find(a => new Date(a.position.fixTime).getTime() > outDate)
88
- return (next && next.position && new Date(next.position.fixTime).getTime()) ||
89
- new Date(deviceRoute.slice(-1)[0].fixTime).getTime()
90
- }
91
-
92
89
  async function processDevices (from, to, devices, userData, data) {
93
90
  const devicesResult = []
94
91
 
95
92
  for (const d of devices) {
96
93
  const alerts = data.alerts.filter(t => t.deviceId === d.id)
97
94
  const deviceRoute = data.route.filter(p => p.deviceId === d.id)
98
-
99
95
  const zoneInOutData = analyseAlerts(alerts, deviceRoute, userData, from, to).filter(d => !userData.onlyWithStop || d.stopped)
100
96
 
101
- if (userData.groupByDay) {
97
+ if (userData.groupByDay || userData.zonesByColumn) {
102
98
  const dates = getDates(from, to, userData.user.attributes.timezone)
103
99
 
104
100
  const geofencesData = []
@@ -117,47 +113,10 @@ async function processDevices (from, to, devices, userData, data) {
117
113
  const firstIn = zoneInOutDayData.find(z => z.inTime && new Date(z.inTime.fixTime) > fromByDay)
118
114
  const lastOut = zoneInOutDayData.slice().reverse().find(z => z.outTime && new Date(z.outTime.fixTime) < toByDay)
119
115
 
120
- let timeIn = zoneInOutDayData.length ? zoneInOutDayData.reduce((a, b) => a + (b.totalInTime || 0), 0) : 0
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')
121
119
 
122
- let distanceIn = zoneInOutDayData.length && dayRoute.length ? zoneInOutDayData.reduce((a, b) => a + (b.distanceIn || 0), 0) : 0
123
- let distanceOut = 0
124
- if (zoneInOutDayData.length) {
125
- distanceOut = zoneInOutDayData.reduce((a, b) => a + (b.distanceOut || 0), 0) -
126
- (zoneInOutDayData[zoneInOutDayData.length - 1].distanceOut || 0)
127
- } else {
128
- distanceOut = calculateDistance(deviceRoute.filter(p => new Date(p.fixTime) >= fromByDay && new Date(p.fixTime) < toByDay))
129
- }
130
-
131
- if (zoneInOutDayData.length) {
132
- // Check if the first entry starts only on the day before
133
- if (!zoneInOutDayData[0].inTime || new Date(zoneInOutDayData[0].inTime.fixTime) < fromByDay) {
134
- const inTime = zoneInOutDayData[0].inTime ? new Date(zoneInOutDayData[0].inTime.fixTime) : from
135
- timeIn = timeIn - (fromByDay.getTime() - inTime.getTime())
136
- const routeDayBefore = deviceRoute.filter(p => (!zoneInOutDayData[0].inTime || new Date(p.fixTime) >= new Date(zoneInOutDayData[0].inTime.fixTime)) &&
137
- new Date(p.fixTime) < fromByDay)
138
- distanceIn = distanceIn - calculateDistance(routeDayBefore)
139
- } else {
140
- // Add distanceOut before the first entry
141
- const routeOut = deviceRoute.filter(p =>
142
- new Date(p.fixTime).getTime() < new Date(zoneInOutDayData[0].inTime.fixTime).getTime() &&
143
- new Date(p.fixTime).getTime() >= fromByDay.getTime()
144
- )
145
- distanceOut = distanceOut + calculateDistance(routeOut)
146
- }
147
-
148
- // Check if the last entry ends only on the next day
149
- if (!zoneInOutDayData[zoneInOutDayData.length - 1].outTime || new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) > toByDay) {
150
- const outTime = zoneInOutDayData[zoneInOutDayData.length - 1].outTime ? new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) : to
151
- timeIn = timeIn - (outTime.getTime() - (toByDay.getTime() + 1000))
152
- const routeDayAfter = deviceRoute.filter(p => new Date(p.fixTime) <= outTime && new Date(p.fixTime) > toByDay)
153
- distanceIn = distanceIn - calculateDistance(routeDayAfter)
154
- } else {
155
- const routeOut = deviceRoute.filter(p =>
156
- new Date(p.fixTime) >= new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime).getTime() &&
157
- new Date(p.fixTime) < toByDay.getTime())
158
- distanceOut = distanceOut + calculateDistance(routeOut)
159
- }
160
- }
161
120
  dataByDay.push({
162
121
  date,
163
122
  firstIn: firstIn ? firstIn.inTime.fixTime : undefined,
@@ -170,18 +129,54 @@ async function processDevices (from, to, devices, userData, data) {
170
129
  }
171
130
 
172
131
  geofencesData.push({
132
+ geofenceId: geofence.id,
173
133
  geofenceName: geofence.name,
174
134
  days: dataByDay
175
135
  })
176
136
  }
177
137
 
178
- devicesResult.push({
179
- device: d,
180
- from,
181
- to,
182
- groupByDay: true,
183
- geofences: geofencesData
184
- })
138
+ if (userData.zonesByColumn) {
139
+ const groupByDay = []
140
+ for (const date of dates) {
141
+ const fromByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0)
142
+ const toByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59)
143
+
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')
148
+
149
+ const geofences = geofencesData.map(g => {
150
+ return {
151
+ geofenceId: g.geofenceId,
152
+ geofenceName: g.geofenceName,
153
+ distanceIn: g.days.find(day => day.date === date).distanceIn
154
+ }
155
+ })
156
+
157
+ groupByDay.push({
158
+ date,
159
+ geofences,
160
+ distanceOut
161
+ })
162
+ }
163
+
164
+ devicesResult.push({
165
+ device: d,
166
+ from,
167
+ to,
168
+ zonesByColumn: true,
169
+ days: groupByDay
170
+ })
171
+ } else {
172
+ devicesResult.push({
173
+ device: d,
174
+ from,
175
+ to,
176
+ groupByDay: true,
177
+ geofences: geofencesData
178
+ })
179
+ }
185
180
  } else {
186
181
  if (zoneInOutData.length > 0) {
187
182
  devicesResult.push({
@@ -197,6 +192,90 @@ async function processDevices (from, to, devices, userData, data) {
197
192
  return devicesResult
198
193
  }
199
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
+
200
279
  function analyseAlerts (alerts, deviceRoute, userData, from, to) {
201
280
  const zoneInOutData = []
202
281
  const zoneInData = {}
@@ -222,6 +301,14 @@ function analyseAlerts (alerts, deviceRoute, userData, from, to) {
222
301
  )
223
302
  const totalOutTime = nextIn - outDate
224
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
+
225
312
  if (zoneInData[a.geofenceId]) {
226
313
  const totalInTime = new Date(a.position.fixTime).getTime() - new Date(zoneInData[a.geofenceId].position.fixTime).getTime()
227
314
  const inDate = new Date(zoneInData[a.geofenceId].position.fixTime).getTime()
@@ -236,6 +323,7 @@ function analyseAlerts (alerts, deviceRoute, userData, from, to) {
236
323
  totalOutTime,
237
324
  distanceIn: calculateDistance(routeIn),
238
325
  distanceOut,
326
+ distanceOutAny,
239
327
  geofenceName: geofence.name,
240
328
  geofenceId: geofence.id,
241
329
  stopped: routeIn.filter(p => !p.attributes.ignition).length > 0,
@@ -256,7 +344,8 @@ function analyseAlerts (alerts, deviceRoute, userData, from, to) {
256
344
  totalOutTime,
257
345
  distanceIn: calculateDistance(routeIn),
258
346
  driverName: '',
259
- distanceOut
347
+ distanceOut,
348
+ distanceOutAny
260
349
  })
261
350
  }
262
351
  }
@@ -349,26 +438,35 @@ async function exportZoneReportToPDF (userData, reportData) {
349
438
  const translations = getTranslations(userData)
350
439
  const lang = userData.user.attributes.lang || (navigator && navigator.language)
351
440
 
352
- const headers = userData.groupByDay
353
- ? [
354
- translations.report.date,
355
- translations.report.firstIn,
356
- translations.report.lastOut,
357
- translations.report.distanceIn || 'Kms Adentro',
358
- translations.report.timeIn,
359
- translations.report.distanceOut || 'Kms Afuera',
360
- translations.report.timeOut
361
- ]
362
- : [
363
- translations.report.enter,
364
- translations.report.exit,
365
- translations.report.stopped,
366
- translations.report.duration,
367
- translations.report.distanceIn || 'Kms Adentro',
368
- translations.report.distanceOut || 'Kms Afuera',
369
- translations.report.geofence,
370
- translations.report.driver
371
- ]
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
+
372
470
  if (reportData.devices) {
373
471
  // eslint-disable-next-line new-cap
374
472
  const doc = new jsPDF.jsPDF('l')
@@ -410,6 +508,31 @@ async function exportZoneReportToPDF (userData, reportData) {
410
508
  6: { halign: 'right' }
411
509
  })
412
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)
413
536
  } else {
414
537
  const data = []
415
538
  space = reportHeader(index === 0, doc, translations, d, lang, timezone, userData)
@@ -447,29 +570,42 @@ function exportZoneReportToExcel (userData, reportData) {
447
570
  sheetName: translations.report.titleActivityReport, // The name of the sheet
448
571
  fileName // The name of the spreadsheet
449
572
  }
450
- const headers = userData.groupByDay
451
- ? [
452
- { label: translations.report.geofence, value: 'zone' },
453
- { label: translations.report.vehicle, value: 'name' },
454
- { label: translations.report.date, value: 'date' },
455
- { label: translations.report.firstIn, value: 'firstIn' },
456
- { label: translations.report.lastOut, value: 'lastOut' },
457
- { label: translations.report.distanceIn || 'Kms Adentro', value: 'distanceIn' },
458
- { label: translations.report.timeIn, value: 'totalInTime' },
459
- { label: translations.report.distanceOut || 'Kms Afuera', value: 'distanceOut' },
460
- { label: translations.report.timeOut, value: 'totalOutTime' }
461
- ]
462
- : [
463
- { label: translations.report.vehicle, value: 'name' },
464
- { label: translations.report.enter, value: 'enter' },
465
- { label: translations.report.exit, value: 'exit' },
466
- { label: translations.report.stopped, value: 'stopped' },
467
- { label: translations.report.duration, value: 'totalInTime' },
468
- { label: translations.report.distanceIn || 'Kms Adentro', value: 'distanceIn' },
469
- { label: translations.report.distanceOut || 'Kms Afuera', value: 'distanceOut' },
470
- { label: translations.report.geofence, value: 'zone' },
471
- { label: translations.report.driver, value: 'driver' }
472
- ]
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
+
473
609
  let data = []
474
610
  if (reportData.devices) {
475
611
  reportData.devices.forEach(d => {
@@ -481,6 +617,20 @@ function exportZoneReportToExcel (userData, reportData) {
481
617
  }))
482
618
  data = data.concat([{}])
483
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([{}])
484
634
  } else {
485
635
  data = data.concat(d.geofences.map(a => {
486
636
  return getColumns(d, a, userData, translations, true)