fleetmap-reports 1.0.660 → 1.0.662

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/lang/enGB.js CHANGED
@@ -270,7 +270,11 @@ module.exports = {
270
270
  minimumMinutes: 'Minimum time',
271
271
  maximumSpeed: 'Maximum speed',
272
272
  minutes: 'Minutes',
273
- zone: 'Zone'
273
+ zone: 'Zone',
274
+ firstIn: 'First In',
275
+ lastOut: 'Last Out',
276
+ timeIn: 'Time In',
277
+ timeOut: 'Time Out'
274
278
  },
275
279
  layout: {
276
280
  deviceOnline: 'Device Online',
package/lang/esCL.js CHANGED
@@ -259,7 +259,11 @@ module.exports = {
259
259
  minimumMinutes: 'Tiempo mínimo',
260
260
  maximumSpeed: 'Velocidad máxima',
261
261
  minutes: 'Minutos',
262
- zone: 'Zona'
262
+ zone: 'Zona',
263
+ firstIn: 'Primeira Entrada',
264
+ lastOut: 'Última Saída',
265
+ timeIn: 'Tempo Adentro',
266
+ timeOut: 'Tempo Afuera'
263
267
  },
264
268
  layout: {
265
269
  deviceOnline: 'Dispositivo en línea',
package/lang/ptBR.js CHANGED
@@ -264,7 +264,11 @@ module.exports = {
264
264
  minimumMinutes: 'Tempo mínimo',
265
265
  maximumSpeed: 'Velocidade máxima',
266
266
  minutes: 'Minutos',
267
- zone: 'Zona'
267
+ zone: 'Zona',
268
+ firstIn: 'Primeira Entrada',
269
+ lastOut: 'Última Saída',
270
+ timeIn: 'Tempo Dentro',
271
+ timeOut: 'Tempo Fora'
268
272
  },
269
273
  layout: {
270
274
  deviceOnline: 'Dispositivo Online',
package/lang/ptPT.js CHANGED
@@ -273,7 +273,11 @@ module.exports = {
273
273
  minimumMinutes: 'Tempo mínimo',
274
274
  maximumSpeed: 'Velocidade máxima',
275
275
  minutes: 'Minutos',
276
- zone: 'Zone'
276
+ zone: 'Zone',
277
+ firstIn: 'Primeira Entrada',
278
+ lastOut: 'Última Saída',
279
+ timeIn: 'Tempo Dentro',
280
+ timeOut: 'Tempo Fora'
277
281
  },
278
282
  layout: {
279
283
  test: 'Test Notification',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetmap-reports",
3
- "version": "1.0.660",
3
+ "version": "1.0.662",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -130,7 +130,8 @@ function processDevices (from, to, devices, data) {
130
130
  door2: p.attributes.door2,
131
131
  sensor: p.attributes.sensor,
132
132
  rain: p.attributes.rain,
133
- ignition: p.attributes.ignition
133
+ ignition: p.attributes.ignition,
134
+ alarm: p.attributes.alarm
134
135
  }
135
136
  }
136
137
  })
@@ -3,7 +3,7 @@ const automaticReports = require('./automaticReports')
3
3
  const {
4
4
  convertMS, convertToLocaleString, getTranslations, convertToFeature, convertPositionToFeature,
5
5
  calculateDistance,
6
- sortPositions
6
+ sortPositions, getDates, convertToLocaleDateString, convertToLocaleTimeString
7
7
  } = require('./util/utils')
8
8
  const jsPDF = require('jspdf')
9
9
  require('jspdf-autotable')
@@ -84,7 +84,7 @@ async function createZoneReport (from, to, userData, traccar) {
84
84
 
85
85
  function getNextIn (outDate, alerts, geofenceId, deviceRoute) {
86
86
  const next = alerts
87
- .filter(a => a.type === 'geofenceEnter' && a.geofenceId === geofenceId)
87
+ .filter(a => a.type === 'geofenceEnter' && (a.geofenceId === geofenceId || !geofenceId))
88
88
  .find(a => new Date(a.position.fixTime).getTime() > outDate)
89
89
  return (next && next.position && new Date(next.position.fixTime).getTime()) ||
90
90
  new Date(deviceRoute.slice(-1)[0].fixTime).getTime()
@@ -98,75 +98,80 @@ async function processDevices (from, to, devices, userData, data) {
98
98
  const deviceRoute = data.route.filter(p => p.deviceId === d.id)
99
99
 
100
100
  if (alerts.length > 0) {
101
- const zoneInOutData = []
102
- const zoneInData = {}
103
-
104
- alerts.forEach(a => {
105
- if (!a.position) { return }
106
- if (a.type === 'geofenceEnter') {
107
- const driver = userData.drivers.find(d => a.position.attributes && d.uniqueId === a.position.attributes.driverUniqueId)
108
- a.position.driverName = driver ? driver.name : ''
109
- zoneInData[a.geofenceId] = a
110
- } else if (a.type === 'geofenceExit') {
111
- const geofence = userData.geofences.find(g => g.id === a.geofenceId)
112
- if (!geofence) { return }
113
- const outDate = new Date(a.position.fixTime).getTime()
114
- const routeAfterOut = deviceRoute.filter(p =>
115
- new Date(p.fixTime).getTime() >= outDate &&
116
- new Date(p.fixTime).getTime() < getNextIn(outDate, alerts, a.geofenceId, deviceRoute)
117
- )
118
- const distanceOut = calculateDistance(routeAfterOut)
119
- if (zoneInData[a.geofenceId]) {
120
- const totalInTime = moment(a.position.fixTime).diff(moment(zoneInData[a.geofenceId].position.fixTime), 'seconds')
121
- const inDate = new Date(zoneInData[a.geofenceId].position.fixTime).getTime()
122
- const routeIn = deviceRoute.filter(p =>
123
- new Date(p.fixTime).getTime() >= inDate &&
124
- new Date(p.fixTime).getTime() < outDate
125
- )
126
- zoneInOutData.push({
127
- inTime: zoneInData[a.geofenceId].position,
128
- outTime: a.position,
129
- totalTime: totalInTime,
130
- distanceIn: calculateDistance(routeIn),
131
- distanceOut,
132
- geofenceName: geofence.name,
133
- stopped: routeIn.filter(p => !p.attributes.ignition).length > 0,
134
- driverName: zoneInData[a.geofenceId].position.driverName
135
- })
136
- zoneInData[a.geofenceId] = null
137
- } else {
138
- zoneInOutData.push({
139
- outTime: a.position,
140
- geofenceName: geofence.name,
141
- driverName: '',
142
- distanceOut
143
- })
144
- }
145
- }
146
- })
101
+ const zoneInOutData = userData.groupByDay
102
+ ? analyseAlertsGroupGeofences(alerts, deviceRoute)
103
+ : analyseAlerts(alerts, deviceRoute, userData)
147
104
 
148
- for (const i in zoneInData) {
149
- if (zoneInData[i]) {
150
- const geofence = userData.geofences.find(g => g.id === zoneInData[i].geofenceId)
151
- if (geofence) {
152
- zoneInOutData.push({
153
- inTime: zoneInData[i].position,
154
- geofenceName: geofence.name,
155
- driverName: zoneInData[i].position.driverName
156
- })
105
+ const result = userData.onlyWithStop ? zoneInOutData.filter(d => d.stopped) : zoneInOutData
106
+ const resultSorted = result.sort((a, b) => a.inTime && b.inTime ? new Date(a.inTime.fixTime).getTime() - new Date(b.inTime.fixTime).getTime() : -1)
107
+
108
+ if (userData.groupByDay) {
109
+ const dates = getDates(from, to)
110
+
111
+ const dataByDay = []
112
+ for (const date of dates) {
113
+ const fromByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0)
114
+ const toByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59)
115
+
116
+ const zoneInOutDayData = resultSorted.filter(z => new Date(z.inTime.fixTime) < toByDay &&
117
+ new Date(z.outTime.fixTime) > fromByDay)
118
+ const firstIn = zoneInOutDayData.find(z => new Date(z.inTime.fixTime) > fromByDay)
119
+ const lastOut = zoneInOutDayData.findLast(z => new Date(z.outTime.fixTime) < toByDay)
120
+
121
+ let timeIn = zoneInOutDayData.length ? zoneInOutData.reduce((a, b) => a + (b.totalTime || 0), 0) * 1000 : 0
122
+ let distanceIn = zoneInOutDayData.length ? zoneInOutData.reduce((a, b) => a + (b.distanceIn || 0), 0) : 0
123
+ let distanceOut = zoneInOutDayData.length
124
+ ? zoneInOutData.reduce((a, b) => a + (b.distanceOut || 0), 0)
125
+ : calculateDistance(deviceRoute.filter(p => new Date(p.fixTime) >= fromByDay && new Date(p.fixTime) < toByDay))
126
+
127
+ if (zoneInOutDayData.length) {
128
+ // Check if the first entry starts only on the day before
129
+ if (new Date(zoneInOutDayData[0].inTime.fixTime) < fromByDay) {
130
+ timeIn = timeIn - (fromByDay.getTime() - new Date(zoneInOutDayData[0].inTime.fixTime).getTime())
131
+ const routeDayBefore = deviceRoute.filter(p => new Date(p.fixTime) > new Date(zoneInOutDayData[0].inTime.fixTime) &&
132
+ new Date(p.fixTime) < fromByDay)
133
+ distanceIn = distanceIn - calculateDistance(routeDayBefore)
134
+ }
135
+
136
+ // Check if the last entry ends only on the next day
137
+ if (new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) > toByDay) {
138
+ timeIn = timeIn - (new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime).getTime() - (toByDay.getTime() + 1000))
139
+ const routeDayAfter = deviceRoute.filter(p => new Date(p.fixTime) < new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) &&
140
+ new Date(p.fixTime) > toByDay)
141
+ distanceIn = distanceIn - calculateDistance(routeDayAfter)
142
+ distanceOut = distanceOut - zoneInOutDayData[zoneInOutDayData.length - 1].distanceOut
143
+ const routeOut = deviceRoute.filter(p => new Date(p.fixTime) > new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) &&
144
+ new Date(p.fixTime) < toByDay)
145
+ distanceOut = distanceOut + calculateDistance(routeOut)
146
+ }
157
147
  }
158
- }
159
- }
160
148
 
161
- const result = userData.onlyWithStop ? zoneInOutData.filter(d => d.stopped) : zoneInOutData
149
+ dataByDay.push({
150
+ date,
151
+ firstIn: firstIn ? firstIn.inTime.fixTime : undefined,
152
+ lastOut: lastOut ? lastOut.outTime.fixTime : undefined,
153
+ distanceIn,
154
+ distanceOut,
155
+ timeIn: (timeIn / 1000),
156
+ timeOut: (24 * 60 * 60) - (timeIn / 1000)
157
+ })
158
+ }
162
159
 
163
- if (result.length > 0) {
164
160
  devicesResult.push({
165
161
  device: d,
166
162
  from,
167
163
  to,
168
- geofences: result
164
+ days: dataByDay
169
165
  })
166
+ } else {
167
+ if (result.length > 0) {
168
+ devicesResult.push({
169
+ device: d,
170
+ from,
171
+ to,
172
+ geofences: resultSorted
173
+ })
174
+ }
170
175
  }
171
176
  }
172
177
  }
@@ -174,6 +179,125 @@ async function processDevices (from, to, devices, userData, data) {
174
179
  return devicesResult
175
180
  }
176
181
 
182
+ function analyseAlertsGroupGeofences (alerts, deviceRoute) {
183
+ const zoneInOutData = []
184
+ const zoneInData = {}
185
+
186
+ alerts.forEach(a => {
187
+ if (!a.position) {
188
+ return
189
+ }
190
+ if (a.type === 'geofenceEnter') {
191
+ if (zoneInData.inTime) {
192
+ zoneInData.inCount++
193
+ } else {
194
+ zoneInData.inTime = a
195
+ zoneInData.inCount = 1
196
+ }
197
+ return
198
+ }
199
+ if (a.type === 'geofenceExit') {
200
+ zoneInData.inCount--
201
+ if (zoneInData.inCount === 0) {
202
+ const totalInTime = moment(a.position.fixTime).diff(moment(zoneInData.inTime.position.fixTime), 'seconds')
203
+ const inDate = new Date(zoneInData.inTime.position.fixTime).getTime()
204
+ const outDate = new Date(a.position.fixTime).getTime()
205
+ const routeAfterOut = deviceRoute.filter(p =>
206
+ new Date(p.fixTime).getTime() >= outDate &&
207
+ new Date(p.fixTime).getTime() < getNextIn(outDate, alerts, undefined, deviceRoute)
208
+ )
209
+ const distanceOut = calculateDistance(routeAfterOut)
210
+ const routeIn = deviceRoute.filter(p =>
211
+ new Date(p.fixTime).getTime() >= inDate &&
212
+ new Date(p.fixTime).getTime() < outDate
213
+ )
214
+ zoneInOutData.push({
215
+ inTime: zoneInData.inTime.position,
216
+ outTime: a.position,
217
+ totalTime: totalInTime,
218
+ distanceIn: calculateDistance(routeIn),
219
+ distanceOut,
220
+ stopped: routeIn.filter(p => !p.attributes.ignition).length > 0
221
+ })
222
+ zoneInData.inTime = undefined
223
+ }
224
+ }
225
+ })
226
+
227
+ if (zoneInData.inTime) {
228
+ zoneInOutData.push({ ...zoneInData })
229
+ }
230
+ return zoneInOutData
231
+ }
232
+
233
+ function analyseAlerts (alerts, deviceRoute, userData) {
234
+ const zoneInOutData = []
235
+ const zoneInData = {}
236
+
237
+ alerts.forEach(a => {
238
+ if (!a.position) {
239
+ return
240
+ }
241
+ if (a.type === 'geofenceEnter') {
242
+ const driver = userData.drivers.find(d => a.position.attributes && d.uniqueId === a.position.attributes.driverUniqueId)
243
+ a.position.driverName = driver ? driver.name : ''
244
+ zoneInData[a.geofenceId] = a
245
+ } else if (a.type === 'geofenceExit') {
246
+ const geofence = userData.geofences.find(g => g.id === a.geofenceId)
247
+ if (!geofence) {
248
+ return
249
+ }
250
+ const outDate = new Date(a.position.fixTime).getTime()
251
+ const routeAfterOut = deviceRoute.filter(p =>
252
+ new Date(p.fixTime).getTime() >= outDate &&
253
+ new Date(p.fixTime).getTime() < getNextIn(outDate, alerts, a.geofenceId, deviceRoute)
254
+ )
255
+ const distanceOut = calculateDistance(routeAfterOut)
256
+ if (zoneInData[a.geofenceId]) {
257
+ const totalInTime = moment(a.position.fixTime).diff(moment(zoneInData[a.geofenceId].position.fixTime), 'seconds')
258
+ const inDate = new Date(zoneInData[a.geofenceId].position.fixTime).getTime()
259
+ const routeIn = deviceRoute.filter(p =>
260
+ new Date(p.fixTime).getTime() >= inDate &&
261
+ new Date(p.fixTime).getTime() < outDate
262
+ )
263
+ zoneInOutData.push({
264
+ inTime: zoneInData[a.geofenceId].position,
265
+ outTime: a.position,
266
+ totalTime: totalInTime,
267
+ distanceIn: calculateDistance(routeIn),
268
+ distanceOut,
269
+ geofenceName: geofence.name,
270
+ stopped: routeIn.filter(p => !p.attributes.ignition).length > 0,
271
+ driverName: zoneInData[a.geofenceId].position.driverName
272
+ })
273
+ zoneInData[a.geofenceId] = null
274
+ } else {
275
+ zoneInOutData.push({
276
+ outTime: a.position,
277
+ geofenceName: geofence.name,
278
+ driverName: '',
279
+ distanceOut
280
+ })
281
+ }
282
+ }
283
+ })
284
+
285
+ for (const i in zoneInData) {
286
+ if (zoneInData[i]) {
287
+ const geofence = userData.geofences.find(g => g.id === zoneInData[i].geofenceId)
288
+ if (geofence) {
289
+ zoneInOutData.push({
290
+ inTime: zoneInData[i].position,
291
+ geofenceName: geofence.name,
292
+ driverName: zoneInData[i].position.driverName
293
+ })
294
+ }
295
+ }
296
+ }
297
+
298
+ return zoneInOutData
299
+ }
300
+
177
301
  function checkGeofenceEnter (p1, p2, g) {
178
302
  switch (g.geometry.type) {
179
303
  case 'Polygon':
@@ -229,16 +353,26 @@ async function exportZoneReportToPDF (userData, reportData) {
229
353
  const translations = getTranslations(userData)
230
354
  const lang = userData.user.attributes.lang || (navigator && navigator.language)
231
355
 
232
- const headers = [
233
- translations.report.enter,
234
- translations.report.exit,
235
- translations.report.stopped,
236
- translations.report.duration,
237
- translations.report.distanceIn || 'Kms Adentro',
238
- translations.report.distanceOut || 'Kms Afuera',
239
- translations.report.geofence,
240
- translations.report.driver
241
- ]
356
+ const headers = userData.groupByDay
357
+ ? [
358
+ translations.report.date,
359
+ translations.report.firstIn,
360
+ translations.report.lastOut,
361
+ translations.report.distanceIn || 'Kms Adentro',
362
+ translations.report.timeIn,
363
+ translations.report.distanceOut || 'Kms Afuera',
364
+ translations.report.timeOut
365
+ ]
366
+ : [
367
+ translations.report.enter,
368
+ translations.report.exit,
369
+ translations.report.stopped,
370
+ translations.report.duration,
371
+ translations.report.distanceIn || 'Kms Adentro',
372
+ translations.report.distanceOut || 'Kms Afuera',
373
+ translations.report.geofence,
374
+ translations.report.driver
375
+ ]
242
376
  if (reportData.devices) {
243
377
  let first = true
244
378
  // eslint-disable-next-line new-cap
@@ -262,23 +396,44 @@ async function exportZoneReportToPDF (userData, reportData) {
262
396
  doc.setFontSize(11)
263
397
  doc.text(group ? translations.report.group + ': ' + group.name : '', 200, space + 20)
264
398
  doc.text(convertToLocaleString(d.from, lang, timezone) + ' - ' + convertToLocaleString(d.to, lang, timezone), 20, space + 25)
265
- d.geofences.forEach(a => {
266
- const temp = [
267
- geofenceEnter(userData.user, a),
268
- geofenceExit(userData.user, a),
269
- a.stopped ? translations.report.yes : translations.report.no,
270
- a.totalTime ? convertMS(a.totalTime * 1000, true) : '',
271
- a.distanceIn && a.distanceIn.toLocaleString(userData.user.attributes.lang, { maximumFractionDigits: 1 }),
272
- a.distanceOut && a.distanceOut.toLocaleString(userData.user.attributes.lang, { maximumFractionDigits: 1 }),
273
- a.geofenceName,
274
- a.driverName
275
- ]
276
- data.push(temp)
277
- })
399
+ userData.groupByDay
400
+ ? d.days.forEach(a => {
401
+ const temp = [
402
+ convertToLocaleDateString(a.date, userData.user.attributes.lang, userData.user.attributes.timezone),
403
+ a.firstIn ? convertToLocaleTimeString(a.firstIn, userData.user.attributes.lang, userData.user.attributes.timezone) : '-',
404
+ a.lastOut ? convertToLocaleTimeString(a.lastOut, userData.user.attributes.lang, userData.user.attributes.timezone) : '-',
405
+ a.distanceIn.toLocaleString(userData.user.attributes.lang, { maximumFractionDigits: 1 }),
406
+ a.timeIn ? convertMS(a.timeIn * 1000, false) : '',
407
+ a.distanceOut.toLocaleString(userData.user.attributes.lang, { maximumFractionDigits: 1 }),
408
+ a.timeOut ? convertMS(a.timeOut * 1000, false) : ''
409
+ ]
410
+ data.push(temp)
411
+ })
412
+ : d.geofences.forEach(a => {
413
+ const temp = [
414
+ geofenceEnter(userData.user, a),
415
+ geofenceExit(userData.user, a),
416
+ a.stopped ? translations.report.yes : translations.report.no,
417
+ a.totalTime ? convertMS(a.totalTime * 1000, true) : '',
418
+ a.distanceIn && a.distanceIn.toLocaleString(userData.user.attributes.lang, { maximumFractionDigits: 1 }),
419
+ a.distanceOut && a.distanceOut.toLocaleString(userData.user.attributes.lang, { maximumFractionDigits: 1 }),
420
+ a.geofenceName,
421
+ a.driverName
422
+ ]
423
+ data.push(temp)
424
+ })
278
425
 
279
- const footValues = [
280
- 'Total:' + d.geofences.length
281
- ]
426
+ const footValues = userData.groupByDay
427
+ ? [
428
+ 'Total:' + d.days.length,
429
+ '', '',
430
+ d.days.reduce((a, b) => a + b.distanceIn, 0).toLocaleString(userData.user.attributes.lang, { maximumFractionDigits: 1 }),
431
+ '',
432
+ d.days.reduce((a, b) => a + b.distanceOut, 0).toLocaleString(userData.user.attributes.lang, { maximumFractionDigits: 1 })
433
+ ]
434
+ : [
435
+ 'Total:' + d.geofences.length
436
+ ]
282
437
 
283
438
  const style = getStyle(getUserPartner(userData.user))
284
439
  doc.autoTable({
@@ -318,32 +473,54 @@ function exportZoneReportToExcel (userData, reportData) {
318
473
  sheetName: translations.report.titleActivityReport, // The name of the sheet
319
474
  fileName // The name of the spreadsheet
320
475
  }
321
- const headers = [
322
- { label: translations.report.vehicle, value: 'name' },
323
- { label: translations.report.enter, value: 'enter' },
324
- { label: translations.report.exit, value: 'exit' },
325
- { label: translations.report.stopped, value: 'stopped' },
326
- { label: translations.report.duration, value: 'duration' },
327
- { label: translations.report.distanceIn || 'Kms Adentro', value: 'distanceIn' },
328
- { label: translations.report.distanceOut || 'Kms Afuera', value: 'distanceOut' },
329
- { label: translations.report.geofence, value: 'zone' },
330
- { label: translations.report.driver, value: 'driver' }
331
- ]
476
+ const headers = userData.groupByDay
477
+ ? [
478
+ { label: translations.report.date, value: 'date' },
479
+ { label: translations.report.firstIn, value: 'firstIn' },
480
+ { label: translations.report.lastOut, value: 'lastOut' },
481
+ { label: translations.report.distanceIn || 'Kms Adentro', value: 'distanceIn' },
482
+ { label: translations.report.timeIn, value: 'timeIn' },
483
+ { label: translations.report.distanceOut || 'Kms Afuera', value: 'distanceOut' },
484
+ { label: translations.report.timeOut, value: 'timeOut' }
485
+ ]
486
+ : [
487
+ { label: translations.report.vehicle, value: 'name' },
488
+ { label: translations.report.enter, value: 'enter' },
489
+ { label: translations.report.exit, value: 'exit' },
490
+ { label: translations.report.stopped, value: 'stopped' },
491
+ { label: translations.report.duration, value: 'duration' },
492
+ { label: translations.report.distanceIn || 'Kms Adentro', value: 'distanceIn' },
493
+ { label: translations.report.distanceOut || 'Kms Afuera', value: 'distanceOut' },
494
+ { label: translations.report.geofence, value: 'zone' },
495
+ { label: translations.report.driver, value: 'driver' }
496
+ ]
332
497
  let data = []
333
498
  if (reportData.devices) {
334
499
  reportData.devices.forEach(d => {
335
- data = data.concat(d.geofences.map(a => {
336
- return {
337
- ...a,
338
- name: d.device.name,
339
- enter: geofenceEnter(userData.user, a),
340
- exit: geofenceExit(userData.user, a),
341
- stopped: a.stopped ? translations.report.yes : translations.report.no,
342
- duration: a.totalTime ? convertMS(a.totalTime * 1000, true) : '',
343
- zone: a.geofenceName,
344
- driver: a.driverName
345
- }
346
- }))
500
+ data = userData.groupByDay
501
+ ? data.concat(d.days.map(a => {
502
+ return {
503
+ date: convertToLocaleDateString(a.date, userData.user.attributes.lang, userData.user.attributes.timezone),
504
+ firstIn: a.firstIn ? convertToLocaleTimeString(a.firstIn, userData.user.attributes.lang, userData.user.attributes.timezone) : '-',
505
+ lastOut: a.lastOut ? convertToLocaleTimeString(a.lastOut, userData.user.attributes.lang, userData.user.attributes.timezone) : '-',
506
+ distanceIn: a.distanceIn && a.distanceIn.toLocaleString(userData.user.attributes.lang, { maximumFractionDigits: 1 }),
507
+ distanceOut: a.distanceOut && a.distanceOut.toLocaleString(userData.user.attributes.lang, { maximumFractionDigits: 1 }),
508
+ timeIn: convertMS(a.timeIn * 1000),
509
+ timeOut: convertMS(a.timeOut * 1000)
510
+ }
511
+ }))
512
+ : data.concat(d.geofences.map(a => {
513
+ return {
514
+ ...a,
515
+ name: d.device.name,
516
+ enter: geofenceEnter(userData.user, a),
517
+ exit: geofenceExit(userData.user, a),
518
+ stopped: a.stopped ? translations.report.yes : translations.report.no,
519
+ duration: a.totalTime ? convertMS(a.totalTime * 1000, true) : '',
520
+ zone: a.geofenceName,
521
+ driver: a.driverName
522
+ }
523
+ }))
347
524
  })
348
525
  return {
349
526
  headers,