fleetmap-reports 1.0.758 → 1.0.760

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.760",
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
121
-
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
- }
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')
147
119
 
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,58 @@ 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
+ if (distanceOut && geofences.filter(g => g.distanceIn)) {
158
+ groupByDay.push({
159
+ date,
160
+ geofences,
161
+ distanceOut
162
+ })
163
+ }
164
+ }
165
+
166
+ if (groupByDay.length) {
167
+ devicesResult.push({
168
+ device: d,
169
+ from,
170
+ to,
171
+ zonesByColumn: true,
172
+ days: groupByDay
173
+ })
174
+ }
175
+ } else {
176
+ devicesResult.push({
177
+ device: d,
178
+ from,
179
+ to,
180
+ groupByDay: true,
181
+ geofences: geofencesData
182
+ })
183
+ }
185
184
  } else {
186
185
  if (zoneInOutData.length > 0) {
187
186
  devicesResult.push({
@@ -197,6 +196,90 @@ async function processDevices (from, to, devices, userData, data) {
197
196
  return devicesResult
198
197
  }
199
198
 
199
+ function calculateTimeIn (zoneInOutDayData, fromByDay, from, toByDay, to) {
200
+ let timeIn = zoneInOutDayData.length ? zoneInOutDayData.reduce((a, b) => a + (b.totalInTime || 0), 0) : 0
201
+
202
+ if (zoneInOutDayData.length) {
203
+ // Check if the first entry starts only on the day before
204
+ if (!zoneInOutDayData[0].inTime || new Date(zoneInOutDayData[0].inTime.fixTime) < fromByDay) {
205
+ const inTime = zoneInOutDayData[0].inTime ? new Date(zoneInOutDayData[0].inTime.fixTime) : from
206
+ timeIn = timeIn - (fromByDay.getTime() - inTime.getTime())
207
+ }
208
+
209
+ // Check if the last entry ends only on the next day
210
+ if (!zoneInOutDayData[zoneInOutDayData.length - 1].outTime || new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) > toByDay) {
211
+ const outTime = zoneInOutDayData[zoneInOutDayData.length - 1].outTime ? new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) : to
212
+ timeIn = timeIn - (outTime.getTime() - (toByDay.getTime() + 1000))
213
+ }
214
+ }
215
+ return timeIn
216
+ }
217
+
218
+ function getNextIn (outDate, alerts, geofenceId, deviceRoute) {
219
+ const next = alerts
220
+ .filter(a => a.type === 'geofenceEnter' && (a.geofenceId === geofenceId || !geofenceId))
221
+ .find(a => new Date(a.position.fixTime).getTime() > outDate)
222
+ return (next && next.position && new Date(next.position.fixTime).getTime()) ||
223
+ new Date(deviceRoute.slice(-1)[0].fixTime).getTime()
224
+ }
225
+
226
+ function getAnyNextIn (outDate, alerts, deviceRoute) {
227
+ const next = alerts
228
+ .filter(a => a.type === 'geofenceEnter')
229
+ .find(a => new Date(a.position.fixTime).getTime() > outDate)
230
+ return (next && next.position && new Date(next.position.fixTime).getTime()) ||
231
+ new Date(deviceRoute.slice(-1)[0].fixTime).getTime()
232
+ }
233
+
234
+ function calculateDistanceIn (zoneInOutDayData, deviceRoute, dayRoute, fromByDay, toByDay, to) {
235
+ let distanceIn = zoneInOutDayData.length && dayRoute.length ? zoneInOutDayData.reduce((a, b) => a + (b.distanceIn || 0), 0) : 0
236
+
237
+ if (zoneInOutDayData.length) {
238
+ // Check if the first entry starts only on the day before
239
+ if (!zoneInOutDayData[0].inTime || new Date(zoneInOutDayData[0].inTime.fixTime) < fromByDay) {
240
+ const routeDayBefore = deviceRoute.filter(p => (!zoneInOutDayData[0].inTime || new Date(p.fixTime) >= new Date(zoneInOutDayData[0].inTime.fixTime)) &&
241
+ new Date(p.fixTime) < fromByDay)
242
+ distanceIn = distanceIn - calculateDistance(routeDayBefore)
243
+ }
244
+
245
+ // Check if the last entry ends only on the next day
246
+ if (!zoneInOutDayData[zoneInOutDayData.length - 1].outTime || new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) > toByDay) {
247
+ const outTime = zoneInOutDayData[zoneInOutDayData.length - 1].outTime ? new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) : to
248
+ const routeDayAfter = deviceRoute.filter(p => new Date(p.fixTime) <= outTime && new Date(p.fixTime) > toByDay)
249
+ distanceIn = distanceIn - calculateDistance(routeDayAfter)
250
+ }
251
+ }
252
+
253
+ return distanceIn
254
+ }
255
+
256
+ function calculateDistanceOut (zoneInOutDayData, dayRoute, fromByDay, toByDay, field) {
257
+ if (zoneInOutDayData.length) {
258
+ let distanceOut = zoneInOutDayData.reduce((a, b) => a + (b[field] || 0), 0) -
259
+ (zoneInOutDayData[zoneInOutDayData.length - 1][field] || 0)
260
+
261
+ if (zoneInOutDayData[0].inTime && new Date(zoneInOutDayData[0].inTime.fixTime) > fromByDay) {
262
+ // Add distanceOut before the first entry
263
+ const routeOut = dayRoute.filter(p =>
264
+ new Date(p.fixTime).getTime() < new Date(zoneInOutDayData[0].inTime.fixTime).getTime() &&
265
+ new Date(p.fixTime).getTime() >= fromByDay.getTime()
266
+ )
267
+ distanceOut = distanceOut + calculateDistance(routeOut)
268
+ }
269
+
270
+ if (zoneInOutDayData[zoneInOutDayData.length - 1].outTime && new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) < toByDay) {
271
+ const routeOut = dayRoute.filter(p =>
272
+ new Date(p.fixTime) >= new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime).getTime() &&
273
+ new Date(p.fixTime) < toByDay.getTime())
274
+ distanceOut = distanceOut + calculateDistance(routeOut)
275
+ }
276
+
277
+ return distanceOut
278
+ }
279
+
280
+ return calculateDistance(dayRoute.filter(p => new Date(p.fixTime) >= fromByDay && new Date(p.fixTime) < toByDay))
281
+ }
282
+
200
283
  function analyseAlerts (alerts, deviceRoute, userData, from, to) {
201
284
  const zoneInOutData = []
202
285
  const zoneInData = {}
@@ -222,6 +305,14 @@ function analyseAlerts (alerts, deviceRoute, userData, from, to) {
222
305
  )
223
306
  const totalOutTime = nextIn - outDate
224
307
  const distanceOut = calculateDistance(routeAfterOut)
308
+
309
+ const anyNextIn = getAnyNextIn(outDate, alerts, deviceRoute)
310
+ const routeAfterOutAndBeforeAnyNextIn = deviceRoute.filter(p =>
311
+ new Date(p.fixTime).getTime() >= outDate &&
312
+ new Date(p.fixTime).getTime() < anyNextIn
313
+ )
314
+ const distanceOutAny = zoneInData.length < 2 ? calculateDistance(routeAfterOutAndBeforeAnyNextIn) : 0
315
+
225
316
  if (zoneInData[a.geofenceId]) {
226
317
  const totalInTime = new Date(a.position.fixTime).getTime() - new Date(zoneInData[a.geofenceId].position.fixTime).getTime()
227
318
  const inDate = new Date(zoneInData[a.geofenceId].position.fixTime).getTime()
@@ -236,6 +327,7 @@ function analyseAlerts (alerts, deviceRoute, userData, from, to) {
236
327
  totalOutTime,
237
328
  distanceIn: calculateDistance(routeIn),
238
329
  distanceOut,
330
+ distanceOutAny,
239
331
  geofenceName: geofence.name,
240
332
  geofenceId: geofence.id,
241
333
  stopped: routeIn.filter(p => !p.attributes.ignition).length > 0,
@@ -256,7 +348,8 @@ function analyseAlerts (alerts, deviceRoute, userData, from, to) {
256
348
  totalOutTime,
257
349
  distanceIn: calculateDistance(routeIn),
258
350
  driverName: '',
259
- distanceOut
351
+ distanceOut,
352
+ distanceOutAny
260
353
  })
261
354
  }
262
355
  }
@@ -349,26 +442,35 @@ async function exportZoneReportToPDF (userData, reportData) {
349
442
  const translations = getTranslations(userData)
350
443
  const lang = userData.user.attributes.lang || (navigator && navigator.language)
351
444
 
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
- ]
445
+ const headers = []
446
+
447
+ if (userData.groupByDay) {
448
+ headers.push(...[
449
+ translations.report.date,
450
+ translations.report.firstIn,
451
+ translations.report.lastOut,
452
+ translations.report.distanceIn || 'Kms Adentro',
453
+ translations.report.timeIn,
454
+ translations.report.distanceOut || 'Kms Afuera',
455
+ translations.report.timeOut
456
+ ])
457
+ } else if (userData.zonesByColumn) {
458
+ headers.push(translations.report.date)
459
+ reportData.devices[0].days[0].geofences.forEach(g => headers.push(g.geofenceName))
460
+ headers.push(translations.report.distanceOut || 'Kms Afuera')
461
+ } else {
462
+ headers.push(...[
463
+ translations.report.enter,
464
+ translations.report.exit,
465
+ translations.report.stopped,
466
+ translations.report.duration,
467
+ translations.report.distanceIn || 'Kms Adentro',
468
+ translations.report.distanceOut || 'Kms Afuera',
469
+ translations.report.geofence,
470
+ translations.report.driver
471
+ ])
472
+ }
473
+
372
474
  if (reportData.devices) {
373
475
  // eslint-disable-next-line new-cap
374
476
  const doc = new jsPDF.jsPDF('l')
@@ -410,6 +512,31 @@ async function exportZoneReportToPDF (userData, reportData) {
410
512
  6: { halign: 'right' }
411
513
  })
412
514
  })
515
+ } else if (userData.zonesByColumn) {
516
+ const data = []
517
+ space = reportHeader(index === 0, doc, translations, d, lang, timezone, userData)
518
+ d.days.forEach(day => {
519
+ const temp = [convertToLocaleDateString(day.date, lang, timezone)]
520
+ day.geofences.forEach(a => {
521
+ temp.push(a.distanceIn ? a.distanceIn.toLocaleString(lang, { maximumFractionDigits: 2 }) : 0)
522
+ })
523
+ temp.push(day.distanceOut ? day.distanceOut.toLocaleString(lang, { maximumFractionDigits: 2 }) : 0)
524
+ data.push(temp)
525
+ })
526
+ const footer = ['Total:' + d.days.length]
527
+ reportData.devices[0].days[0].geofences.forEach(gColumn => {
528
+ footer.push(d.days.reduce((a, b) => a + (b.geofences.find(g => g.geofenceId === gColumn.geofenceId).distanceIn), 0).toLocaleString(lang, { maximumFractionDigits: 2 }))
529
+ })
530
+ footer.push(d.days.reduce((a, b) => a + (b.distanceOut ? b.distanceOut : 0), 0).toLocaleString(lang, { maximumFractionDigits: 2 }))
531
+
532
+ let columnIndex = 1
533
+ const columnStyles = { }
534
+ reportData.devices[0].days[0].geofences.forEach(a => {
535
+ columnStyles[columnIndex] = { halign: 'right' }
536
+ columnIndex++
537
+ })
538
+ columnStyles[columnIndex] = { halign: 'right' }
539
+ addTable(doc, headers, data, footer, style, space + 40, columnStyles)
413
540
  } else {
414
541
  const data = []
415
542
  space = reportHeader(index === 0, doc, translations, d, lang, timezone, userData)
@@ -447,29 +574,42 @@ function exportZoneReportToExcel (userData, reportData) {
447
574
  sheetName: translations.report.titleActivityReport, // The name of the sheet
448
575
  fileName // The name of the spreadsheet
449
576
  }
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
- ]
577
+ const headers = []
578
+ if (userData.groupByDay) {
579
+ headers.push([
580
+ { label: translations.report.geofence, value: 'zone' },
581
+ { label: translations.report.vehicle, value: 'name' },
582
+ { label: translations.report.date, value: 'date' },
583
+ { label: translations.report.firstIn, value: 'firstIn' },
584
+ { label: translations.report.lastOut, value: 'lastOut' },
585
+ { label: translations.report.distanceIn || 'Kms Adentro', value: 'distanceIn' },
586
+ { label: translations.report.timeIn, value: 'totalInTime' },
587
+ { label: translations.report.distanceOut || 'Kms Afuera', value: 'distanceOut' },
588
+ { label: translations.report.timeOut, value: 'totalOutTime' }
589
+ ])
590
+ } else if (userData.zonesByColumn) {
591
+ headers.push(...[
592
+ { label: translations.report.vehicle, value: 'name' },
593
+ { label: translations.report.date, value: 'date' }
594
+ ])
595
+ reportData.devices[0].days[0].geofences.forEach(g =>
596
+ headers.push({ label: g.geofenceName, value: g.geofenceId })
597
+ )
598
+ headers.push({ label: translations.report.distanceOut || 'Kms Afuera', value: 'distanceOut' })
599
+ } else {
600
+ headers.push(...[
601
+ { label: translations.report.vehicle, value: 'name' },
602
+ { label: translations.report.enter, value: 'enter' },
603
+ { label: translations.report.exit, value: 'exit' },
604
+ { label: translations.report.stopped, value: 'stopped' },
605
+ { label: translations.report.duration, value: 'totalInTime' },
606
+ { label: translations.report.distanceIn || 'Kms Adentro', value: 'distanceIn' },
607
+ { label: translations.report.distanceOut || 'Kms Afuera', value: 'distanceOut' },
608
+ { label: translations.report.geofence, value: 'zone' },
609
+ { label: translations.report.driver, value: 'driver' }
610
+ ])
611
+ }
612
+
473
613
  let data = []
474
614
  if (reportData.devices) {
475
615
  reportData.devices.forEach(d => {
@@ -481,6 +621,20 @@ function exportZoneReportToExcel (userData, reportData) {
481
621
  }))
482
622
  data = data.concat([{}])
483
623
  })
624
+ } else if (userData.zonesByColumn) {
625
+ const lang = userData.user.attributes.lang
626
+ d.days.forEach(day => {
627
+ const row = {
628
+ name: d.device.name,
629
+ date: convertToLocaleDateString(day.date, lang, userData.user.attributes.timezone),
630
+ distanceOut: day.distanceOut ? parseFloat(day.distanceOut.toFixed(2)) : 0
631
+ }
632
+ day.geofences.forEach(g => {
633
+ row[g.geofenceId] = g.distanceIn ? parseFloat(g.distanceIn.toFixed(2)) : 0
634
+ })
635
+ data.push(row)
636
+ })
637
+ data = data.concat([{}])
484
638
  } else {
485
639
  data = data.concat(d.geofences.map(a => {
486
640
  return getColumns(d, a, userData, translations, true)