fleetmap-reports 1.0.677 → 1.0.679

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.677",
3
+ "version": "1.0.679",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -6,7 +6,7 @@ describe('zones', function () {
6
6
  const ellca = require('./ellca.json')
7
7
  userData.devices = userData.devices.filter(d => ellca.find(e => e === d.name))
8
8
  console.log(userData.devices.length)
9
- userData.geofences = userData.geofences.filter(g => g.name === 'Geofence Ellca')
9
+ userData.geofences = userData.geofences.filter(g => g.name === 'Geofence Ellca 2')
10
10
  console.log(userData.geofences)
11
11
  const result = await report.zoneReport(
12
12
  new Date(Date.UTC(2022, 6, 24, 0, 0, 0, 0)),
@@ -1,4 +1,3 @@
1
- const moment = require('moment')
2
1
  const automaticReports = require('./automaticReports')
3
2
  const {
4
3
  convertMS, convertToLocaleString, getTranslations, convertToFeature, convertPositionToFeature,
@@ -8,7 +7,7 @@ const {
8
7
  const jsPDF = require('jspdf')
9
8
  require('jspdf-autotable')
10
9
  const traccarHelper = require('./util/traccar')
11
- const { headerFromUser } = require('./util/pdfDocument')
10
+ const { headerFromUser, addTable } = require('./util/pdfDocument')
12
11
  const { getStyle } = require('./reportStyle')
13
12
  const { getUserPartner } = require('fleetmap-partners')
14
13
  const { devicesToProcess } = require('./util/device')
@@ -18,8 +17,8 @@ const distance = require('@turf/distance')
18
17
  const axios = require('axios')
19
18
  const { processServerSide } = require('./util')
20
19
  const { filterPositions } = require('./util/route')
21
- const sliceSize = 1
22
- const deviceChunk = 1
20
+ const sliceSize = 100
21
+ const deviceChunk = 5
23
22
  const fileName = 'ZoneReport'
24
23
 
25
24
  async function createZoneReport (from, to, userData, traccar) {
@@ -96,76 +95,82 @@ async function processDevices (from, to, devices, userData, data) {
96
95
  const alerts = data.alerts.filter(t => t.deviceId === d.id)
97
96
  const deviceRoute = data.route.filter(p => p.deviceId === d.id)
98
97
 
99
- const zoneInOutData = userData.groupByDay
100
- ? analyseAlertsGroupGeofences(alerts, deviceRoute, from, to)
101
- : analyseAlerts(alerts, deviceRoute, userData)
98
+ const zoneInOutData = analyseAlerts(alerts, deviceRoute, userData, from, to).filter(d => !userData.onlyWithStop || d.stopped)
102
99
 
103
100
  if (zoneInOutData.length > 0) {
104
- const result = userData.onlyWithStop ? zoneInOutData.filter(d => d.stopped) : zoneInOutData
105
-
106
101
  if (userData.groupByDay) {
107
102
  const dates = getDates(from, to)
108
103
 
109
- const dataByDay = []
110
- for (const date of dates) {
111
- const fromByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0)
112
- const toByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59)
104
+ const geofencesData = []
105
+ for (const geofence of userData.geofences) {
106
+ const filteredByGeofence = zoneInOutData.filter(d => d.geofenceId === geofence.id)
113
107
 
114
- const zoneInOutDayData = result.filter(z => (!z.inTime || (new Date(z.inTime.fixTime) < toByDay)) &&
115
- (!z.outTime || (new Date(z.outTime.fixTime) > fromByDay)))
108
+ const dataByDay = []
109
+ for (const date of dates) {
110
+ const fromByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0)
111
+ const toByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59)
116
112
 
117
- const firstIn = zoneInOutDayData.find(z => z.inTime && new Date(z.inTime.fixTime) > fromByDay)
118
- const lastOut = zoneInOutDayData.slice().reverse().find(z => z.outTime && new Date(z.outTime.fixTime) < toByDay)
113
+ const dayRoute = deviceRoute.filter(p => new Date(p.fixTime) >= fromByDay && new Date(p.fixTime) < toByDay)
114
+ const zoneInOutDayData = filteredByGeofence.filter(z => (!z.inTime || (new Date(z.inTime.fixTime) < toByDay)) &&
115
+ (!z.outTime || (new Date(z.outTime.fixTime) > fromByDay)))
119
116
 
120
- let timeIn = zoneInOutDayData.length ? zoneInOutDayData.reduce((a, b) => a + (b.totalTime || 0), 0) : 0
117
+ const firstIn = zoneInOutDayData.find(z => z.inTime && new Date(z.inTime.fixTime) > fromByDay)
118
+ const lastOut = zoneInOutDayData.slice().reverse().find(z => z.outTime && new Date(z.outTime.fixTime) < toByDay)
121
119
 
122
- let distanceIn = zoneInOutDayData.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) - zoneInOutDayData[zoneInOutDayData.length - 1].distanceOut
126
- } else {
127
- distanceOut = calculateDistance(deviceRoute.filter(p => new Date(p.fixTime) >= fromByDay && new Date(p.fixTime) < toByDay))
128
- }
120
+ let timeIn = zoneInOutDayData.length ? zoneInOutDayData.reduce((a, b) => a + (b.totalInTime || 0), 0) : 0
129
121
 
130
- if (zoneInOutDayData.length) {
131
- // Check if the first entry starts only on the day before
132
- if (!zoneInOutDayData[0].inTime || new Date(zoneInOutDayData[0].inTime.fixTime) < fromByDay) {
133
- const inTime = zoneInOutDayData[0].inTime ? new Date(zoneInOutDayData[0].inTime.fixTime) : from
134
- timeIn = timeIn - (fromByDay.getTime() - inTime.getTime())
135
- const routeDayBefore = deviceRoute.filter(p => (!zoneInOutDayData[0].inTime || new Date(p.fixTime) > new Date(zoneInOutDayData[0].inTime.fixTime)) &&
136
- new Date(p.fixTime) < fromByDay)
137
- distanceIn = distanceIn - calculateDistance(routeDayBefore)
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) - zoneInOutDayData[zoneInOutDayData.length - 1].distanceOut
138
126
  } else {
139
- // Add distanceOut before the first entry
140
- const routeOut = deviceRoute.filter(p =>
141
- new Date(p.fixTime).getTime() < new Date(zoneInOutDayData[0].inTime.fixTime).getTime() &&
142
- new Date(p.fixTime).getTime() >= fromByDay.getTime()
143
- )
144
- distanceOut = distanceOut + calculateDistance(routeOut)
127
+ distanceOut = calculateDistance(deviceRoute.filter(p => new Date(p.fixTime) >= fromByDay && new Date(p.fixTime) < toByDay))
145
128
  }
146
129
 
147
- // Check if the last entry ends only on the next day
148
- if (!zoneInOutDayData[zoneInOutDayData.length - 1].outTime || new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) > toByDay) {
149
- const outTime = zoneInOutDayData[zoneInOutDayData.length - 1].outTime ? new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) : to
150
- timeIn = timeIn - (outTime.getTime() - (toByDay.getTime() + 1000))
151
- const routeDayAfter = deviceRoute.filter(p => new Date(p.fixTime) < outTime && new Date(p.fixTime) > toByDay)
152
- distanceIn = distanceIn - calculateDistance(routeDayAfter)
153
- } else {
154
- const routeOut = deviceRoute.filter(p =>
155
- new Date(p.fixTime) > new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime).getTime() &&
156
- new Date(p.fixTime) < toByDay.getTime())
157
- distanceOut = distanceOut + calculateDistance(routeOut)
130
+ if (zoneInOutDayData.length) {
131
+ // Check if the first entry starts only on the day before
132
+ if (!zoneInOutDayData[0].inTime || new Date(zoneInOutDayData[0].inTime.fixTime) < fromByDay) {
133
+ const inTime = zoneInOutDayData[0].inTime ? new Date(zoneInOutDayData[0].inTime.fixTime) : from
134
+ timeIn = timeIn - (fromByDay.getTime() - inTime.getTime())
135
+ const routeDayBefore = deviceRoute.filter(p => (!zoneInOutDayData[0].inTime || new Date(p.fixTime) >= new Date(zoneInOutDayData[0].inTime.fixTime)) &&
136
+ new Date(p.fixTime) < fromByDay)
137
+ distanceIn = distanceIn - calculateDistance(routeDayBefore)
138
+ } else {
139
+ // Add distanceOut before the first entry
140
+ const routeOut = deviceRoute.filter(p =>
141
+ new Date(p.fixTime).getTime() < new Date(zoneInOutDayData[0].inTime.fixTime).getTime() &&
142
+ new Date(p.fixTime).getTime() >= fromByDay.getTime()
143
+ )
144
+ distanceOut = distanceOut + calculateDistance(routeOut)
145
+ }
146
+
147
+ // Check if the last entry ends only on the next day
148
+ if (!zoneInOutDayData[zoneInOutDayData.length - 1].outTime || new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) > toByDay) {
149
+ const outTime = zoneInOutDayData[zoneInOutDayData.length - 1].outTime ? new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) : to
150
+ timeIn = timeIn - (outTime.getTime() - (toByDay.getTime() + 1000))
151
+ const routeDayAfter = deviceRoute.filter(p => new Date(p.fixTime) <= outTime && new Date(p.fixTime) > toByDay)
152
+ distanceIn = distanceIn - calculateDistance(routeDayAfter)
153
+ } else {
154
+ const routeOut = deviceRoute.filter(p =>
155
+ new Date(p.fixTime) >= new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime).getTime() &&
156
+ new Date(p.fixTime) < toByDay.getTime())
157
+ distanceOut = distanceOut + calculateDistance(routeOut)
158
+ }
158
159
  }
160
+ dataByDay.push({
161
+ date,
162
+ firstIn: firstIn ? firstIn.inTime.fixTime : undefined,
163
+ lastOut: lastOut ? lastOut.outTime.fixTime : undefined,
164
+ distanceIn: distanceIn > 0 ? distanceIn : 0,
165
+ distanceOut,
166
+ totalInTime: timeIn,
167
+ totalOutTime: (24 * 60 * 60 * 1000) - timeIn
168
+ })
159
169
  }
160
170
 
161
- dataByDay.push({
162
- date,
163
- firstIn: firstIn ? firstIn.inTime.fixTime : undefined,
164
- lastOut: lastOut ? lastOut.outTime.fixTime : undefined,
165
- distanceIn,
166
- distanceOut,
167
- timeIn,
168
- timeOut: (24 * 60 * 60 * 1000) - timeIn
171
+ geofencesData.push({
172
+ geofenceName: geofence.name,
173
+ days: dataByDay
169
174
  })
170
175
  }
171
176
 
@@ -173,117 +178,24 @@ async function processDevices (from, to, devices, userData, data) {
173
178
  device: d,
174
179
  from,
175
180
  to,
176
- days: dataByDay
181
+ groupByDay: true,
182
+ geofences: geofencesData
177
183
  })
178
184
  } else {
179
- if (result.length > 0) {
180
- devicesResult.push({
181
- device: d,
182
- from,
183
- to,
184
- geofences: result
185
- })
186
- }
187
- }
188
- }
189
- }
190
-
191
- return devicesResult
192
- }
193
-
194
- function analyseAlertsGroupGeofences (alerts, deviceRoute, from, to) {
195
- const zoneInOutData = []
196
- const zoneInData = { inCount: 0 }
197
-
198
- alerts.forEach(a => {
199
- if (!a.position) {
200
- return
201
- }
202
- if (a.type === 'geofenceEnter') {
203
- if (zoneInData.inTime) {
204
- zoneInData.inCount++
205
- } else {
206
- zoneInData.inTime = a
207
- zoneInData.inCount = 1
208
- }
209
- return
210
- }
211
- if (a.type === 'geofenceExit') {
212
- if (zoneInData.inCount === 0) {
213
- zoneInOutData.splice(0, zoneInOutData.length)
214
- const totalInTime = new Date(a.position.fixTime).getTime() - from.getTime()
215
- const outDate = new Date(a.position.fixTime).getTime()
216
- const routeIn = deviceRoute.filter(p =>
217
- new Date(p.fixTime).getTime() >= from &&
218
- new Date(p.fixTime).getTime() < outDate
219
- )
220
- const routeAfterOut = deviceRoute.filter(p =>
221
- new Date(p.fixTime).getTime() >= outDate &&
222
- new Date(p.fixTime).getTime() < getNextIn(outDate, alerts, undefined, deviceRoute)
223
- )
224
- const distanceOut = calculateDistance(routeAfterOut)
225
- zoneInOutData.push({
226
- outTime: a.position,
227
- totalTime: totalInTime,
228
- distanceIn: calculateDistance(routeIn),
229
- distanceOut
230
- })
231
- return
232
- }
233
-
234
- zoneInData.inCount--
235
- if (zoneInData.inCount === 0) {
236
- const totalInTime = new Date(a.position.fixTime).getTime() - new Date(zoneInData.inTime.position.fixTime).getTime()
237
- const inDate = new Date(zoneInData.inTime.position.fixTime).getTime()
238
- const outDate = new Date(a.position.fixTime).getTime()
239
- const routeAfterOut = deviceRoute.filter(p =>
240
- new Date(p.fixTime).getTime() >= outDate &&
241
- new Date(p.fixTime).getTime() < getNextIn(outDate, alerts, undefined, deviceRoute)
242
- )
243
- const distanceOut = calculateDistance(routeAfterOut)
244
- const routeIn = deviceRoute.filter(p =>
245
- new Date(p.fixTime).getTime() >= inDate &&
246
- new Date(p.fixTime).getTime() < outDate
247
- )
248
- zoneInOutData.push({
249
- inTime: zoneInData.inTime.position,
250
- outTime: a.position,
251
- totalTime: totalInTime,
252
- distanceIn: calculateDistance(routeIn),
253
- distanceOut
185
+ devicesResult.push({
186
+ device: d,
187
+ from,
188
+ to,
189
+ geofences: zoneInOutData
254
190
  })
255
- zoneInData.inTime = undefined
256
191
  }
257
192
  }
258
- })
259
-
260
- if (zoneInData.inTime) {
261
- const totalInTime = to.getTime() - new Date(zoneInData.inTime.position.fixTime).getTime()
262
- const routeIn = deviceRoute.filter(p =>
263
- new Date(p.fixTime).getTime() >= new Date(zoneInData.inTime.position.fixTime).getTime() &&
264
- new Date(p.fixTime).getTime() < to.getTime()
265
- )
266
- zoneInOutData.push({
267
- inTime: zoneInData.inTime.position,
268
- distanceIn: calculateDistance(routeIn),
269
- distanceOut: 0,
270
- totalTime: totalInTime
271
- })
272
193
  }
273
194
 
274
- if (!zoneInOutData.length) {
275
- const geofenceIn = alerts.find(a => a.type === 'geofenceIn')
276
- zoneInOutData.push({
277
- distanceIn: geofenceIn ? calculateDistance(deviceRoute) : 0,
278
- distanceOut: !geofenceIn ? calculateDistance(deviceRoute) : 0,
279
- totalTime: to.getTime() - from.getTime()
280
- })
281
- }
282
-
283
- return zoneInOutData
195
+ return devicesResult
284
196
  }
285
197
 
286
- function analyseAlerts (alerts, deviceRoute, userData) {
198
+ function analyseAlerts (alerts, deviceRoute, userData, from, to) {
287
199
  const zoneInOutData = []
288
200
  const zoneInData = {}
289
201
 
@@ -301,13 +213,15 @@ function analyseAlerts (alerts, deviceRoute, userData) {
301
213
  return
302
214
  }
303
215
  const outDate = new Date(a.position.fixTime).getTime()
216
+ const nextIn = getNextIn(outDate, alerts, a.geofenceId, deviceRoute)
304
217
  const routeAfterOut = deviceRoute.filter(p =>
305
218
  new Date(p.fixTime).getTime() >= outDate &&
306
- new Date(p.fixTime).getTime() < getNextIn(outDate, alerts, a.geofenceId, deviceRoute)
219
+ new Date(p.fixTime).getTime() < nextIn
307
220
  )
221
+ const totalOutTime = nextIn - outDate
308
222
  const distanceOut = calculateDistance(routeAfterOut)
309
223
  if (zoneInData[a.geofenceId]) {
310
- const totalInTime = moment(a.position.fixTime).diff(moment(zoneInData[a.geofenceId].position.fixTime), 'seconds')
224
+ const totalInTime = new Date(a.position.fixTime).getTime() - new Date(zoneInData[a.geofenceId].position.fixTime).getTime()
311
225
  const inDate = new Date(zoneInData[a.geofenceId].position.fixTime).getTime()
312
226
  const routeIn = deviceRoute.filter(p =>
313
227
  new Date(p.fixTime).getTime() >= inDate &&
@@ -316,18 +230,29 @@ function analyseAlerts (alerts, deviceRoute, userData) {
316
230
  zoneInOutData.push({
317
231
  inTime: zoneInData[a.geofenceId].position,
318
232
  outTime: a.position,
319
- totalTime: totalInTime,
233
+ totalInTime,
234
+ totalOutTime,
320
235
  distanceIn: calculateDistance(routeIn),
321
236
  distanceOut,
322
237
  geofenceName: geofence.name,
238
+ geofenceId: geofence.id,
323
239
  stopped: routeIn.filter(p => !p.attributes.ignition).length > 0,
324
240
  driverName: zoneInData[a.geofenceId].position.driverName
325
241
  })
326
242
  zoneInData[a.geofenceId] = null
327
243
  } else {
244
+ const totalInTime = new Date(a.position.fixTime).getTime() - from.getTime()
245
+ const routeIn = deviceRoute.filter(p =>
246
+ new Date(p.fixTime).getTime() >= from.getTime() &&
247
+ new Date(p.fixTime).getTime() < outDate
248
+ )
328
249
  zoneInOutData.push({
329
250
  outTime: a.position,
330
251
  geofenceName: geofence.name,
252
+ geofenceId: geofence.id,
253
+ totalInTime,
254
+ totalOutTime,
255
+ distanceIn: calculateDistance(routeIn),
331
256
  driverName: '',
332
257
  distanceOut
333
258
  })
@@ -339,9 +264,17 @@ function analyseAlerts (alerts, deviceRoute, userData) {
339
264
  if (zoneInData[i]) {
340
265
  const geofence = userData.geofences.find(g => g.id === zoneInData[i].geofenceId)
341
266
  if (geofence) {
267
+ const totalInTime = to.getTime() - new Date(zoneInData[i].position.fixTime).getTime()
268
+ const routeIn = deviceRoute.filter(p =>
269
+ new Date(p.fixTime).getTime() >= new Date(zoneInData[i].position.fixTime).getTime() &&
270
+ new Date(p.fixTime).getTime() < to.getTime()
271
+ )
342
272
  zoneInOutData.push({
343
273
  inTime: zoneInData[i].position,
274
+ totalInTime,
275
+ distanceIn: calculateDistance(routeIn),
344
276
  geofenceName: geofence.name,
277
+ geofenceId: geofence.id,
345
278
  driverName: zoneInData[i].position.driverName
346
279
  })
347
280
  }
@@ -437,92 +370,67 @@ async function exportZoneReportToPDF (userData, reportData) {
437
370
  translations.report.driver
438
371
  ]
439
372
  if (reportData.devices) {
440
- let first = true
441
373
  // eslint-disable-next-line new-cap
442
374
  const doc = new jsPDF.jsPDF('l')
443
375
  await headerFromUser(doc, translations.report.titleZoneReport, userData.user)
376
+ const style = getStyle(getUserPartner(userData.user))
377
+ let space = 0
444
378
 
445
- reportData.devices.forEach(d => {
446
- const data = []
447
- const name = deviceName(d.device)
448
- const group = userData.groups.find(g => d.device.groupId === g.id)
449
-
450
- let space = 0
451
- if (!first) {
452
- doc.addPage()
453
- } else {
454
- first = false
455
- space = 10
456
- }
457
- doc.setFontSize(13)
458
- doc.text(name, 20, space + 20)
459
- doc.setFontSize(11)
460
- doc.text(group ? translations.report.group + ': ' + group.name : '', 200, space + 20)
461
- doc.text(convertToLocaleString(d.from, lang, timezone) + ' - ' + convertToLocaleString(d.to, lang, timezone), 20, space + 25)
462
- userData.groupByDay
463
- ? d.days.forEach(a => {
464
- const temp = [
465
- convertToLocaleDateString(a.date, userData.user.attributes.lang, userData.user.attributes.timezone),
466
- a.firstIn ? convertToLocaleTimeString(a.firstIn, userData.user.attributes.lang, userData.user.attributes.timezone) : '-',
467
- a.lastOut ? convertToLocaleTimeString(a.lastOut, userData.user.attributes.lang, userData.user.attributes.timezone) : '-',
468
- a.distanceIn && a.distanceIn.toLocaleString(this.user.attributes.lang, { maximumFractionDigits: 2 }),
469
- convertMS(a.timeIn, false),
470
- a.distanceOut && a.distanceOut.toLocaleString(this.user.attributes.lang, { maximumFractionDigits: 2 }),
471
- convertMS(a.timeOut, false)
379
+ reportData.devices.forEach((d, index) => {
380
+ if (userData.groupByDay) {
381
+ d.geofences.forEach((g, i) => {
382
+ const data = []
383
+ space = reportHeader(index === 0 && i === 0, doc, translations, d, lang, timezone, userData, g)
384
+ g.days.forEach(a => {
385
+ const temp = [
386
+ convertToLocaleDateString(a.date, lang, timezone),
387
+ a.firstIn ? convertToLocaleTimeString(a.firstIn, lang, timezone) : '-',
388
+ a.lastOut ? convertToLocaleTimeString(a.lastOut, lang, timezone) : '-',
389
+ a.distanceIn ? a.distanceIn.toLocaleString(lang, { maximumFractionDigits: 2 }) : 0,
390
+ convertMS(a.totalInTime, false),
391
+ a.distanceOut ? a.distanceOut.toLocaleString(lang, { maximumFractionDigits: 2 }) : 0,
392
+ convertMS(a.totalOutTime, false)
393
+ ]
394
+ data.push(temp)
395
+ })
396
+ const footer = [
397
+ 'Total:' + g.days.length,
398
+ '', '',
399
+ g.days.reduce((a, b) => a + (b.distanceIn ? b.distanceIn : 0), 0).toLocaleString(lang, { maximumFractionDigits: 2 }),
400
+ '',
401
+ g.days.reduce((a, b) => a + (b.distanceOut ? b.distanceOut : 0), 0).toLocaleString(lang, { maximumFractionDigits: 2 })
472
402
  ]
473
- data.push(temp)
403
+ addTable(doc, headers, data, footer, style, space + 40, {
404
+ 3: { halign: 'right' },
405
+ 4: { halign: 'right' },
406
+ 5: { halign: 'right' },
407
+ 6: { halign: 'right' }
408
+ })
474
409
  })
475
- : d.geofences.forEach(a => {
410
+ } else {
411
+ const data = []
412
+ space = reportHeader(index === 0, doc, translations, d, lang, timezone, userData)
413
+ d.geofences.forEach(a => {
476
414
  const temp = [
477
415
  geofenceEnter(userData.user, a),
478
416
  geofenceExit(userData.user, a),
479
417
  a.stopped ? translations.report.yes : translations.report.no,
480
- a.totalTime ? convertMS(a.totalTime * 1000, true) : '',
481
- a.distanceIn && a.distanceIn.toLocaleString(userData.user.attributes.lang, { maximumFractionDigits: 2 }),
482
- a.distanceOut && a.distanceOut.toLocaleString(userData.user.attributes.lang, { maximumFractionDigits: 2 }),
418
+ convertMS(a.totalInTime, true),
419
+ a.distanceIn ? a.distanceIn.toLocaleString(lang, { maximumFractionDigits: 2 }) : 0,
420
+ a.distanceOut ? a.distanceOut.toLocaleString(lang, { maximumFractionDigits: 2 }) : 0,
483
421
  a.geofenceName,
484
422
  a.driverName
485
423
  ]
486
424
  data.push(temp)
487
425
  })
488
-
489
- const footValues = userData.groupByDay
490
- ? [
491
- 'Total:' + d.days.length,
492
- '', '',
493
- d.days.reduce((a, b) => a + b.distanceIn, 0).toLocaleString(userData.user.attributes.lang, { maximumFractionDigits: 2 }),
494
- '',
495
- d.days.reduce((a, b) => a + b.distanceOut, 0).toLocaleString(userData.user.attributes.lang, { maximumFractionDigits: 2 })
496
- ]
497
- : [
498
- 'Total:' + d.geofences.length
499
- ]
500
-
501
- const style = getStyle(getUserPartner(userData.user))
502
- doc.autoTable({
503
- head: [headers],
504
- body: data,
505
- foot: [footValues],
506
- showFoot: 'lastPage',
507
- headStyles: {
508
- fillColor: style.pdfHeaderColor,
509
- textColor: style.pdfHeaderTextColor,
510
- fontSize: 10
511
- },
512
- bodyStyles: {
513
- fillColor: style.pdfBodyColor,
514
- textColor: style.pdfBodyTextColor,
515
- fontSize: 8
516
- },
517
- footStyles: {
518
- fillColor: style.pdfFooterColor,
519
- textColor: style.pdfFooterTextColor,
520
- fontSize: 9
521
- },
522
- startY: space + 35
523
- })
426
+ const footer = ['Total:' + d.geofences.length]
427
+ addTable(doc, headers, data, footer, style, space + 35, {
428
+ 3: { halign: 'right' },
429
+ 4: { halign: 'right' },
430
+ 5: { halign: 'right' }
431
+ })
432
+ }
524
433
  })
525
-
526
434
  return doc
527
435
  }
528
436
  }
@@ -538,21 +446,22 @@ function exportZoneReportToExcel (userData, reportData) {
538
446
  }
539
447
  const headers = userData.groupByDay
540
448
  ? [
449
+ { label: translations.report.geofence, value: 'zone' },
541
450
  { label: translations.report.vehicle, value: 'name' },
542
451
  { label: translations.report.date, value: 'date' },
543
452
  { label: translations.report.firstIn, value: 'firstIn' },
544
453
  { label: translations.report.lastOut, value: 'lastOut' },
545
454
  { label: translations.report.distanceIn || 'Kms Adentro', value: 'distanceIn' },
546
- { label: translations.report.timeIn, value: 'timeIn' },
455
+ { label: translations.report.timeIn, value: 'totalInTime' },
547
456
  { label: translations.report.distanceOut || 'Kms Afuera', value: 'distanceOut' },
548
- { label: translations.report.timeOut, value: 'timeOut' }
457
+ { label: translations.report.timeOut, value: 'totalOutTime' }
549
458
  ]
550
459
  : [
551
460
  { label: translations.report.vehicle, value: 'name' },
552
461
  { label: translations.report.enter, value: 'enter' },
553
462
  { label: translations.report.exit, value: 'exit' },
554
463
  { label: translations.report.stopped, value: 'stopped' },
555
- { label: translations.report.duration, value: 'duration' },
464
+ { label: translations.report.duration, value: 'totalInTime' },
556
465
  { label: translations.report.distanceIn || 'Kms Adentro', value: 'distanceIn' },
557
466
  { label: translations.report.distanceOut || 'Kms Afuera', value: 'distanceOut' },
558
467
  { label: translations.report.geofence, value: 'zone' },
@@ -561,33 +470,20 @@ function exportZoneReportToExcel (userData, reportData) {
561
470
  let data = []
562
471
  if (reportData.devices) {
563
472
  reportData.devices.forEach(d => {
564
- data = userData.groupByDay
565
- ? data.concat(d.days.map(a => {
566
- return {
567
- name: d.device.name,
568
- date: convertToLocaleDateString(a.date, userData.user.attributes.lang, userData.user.attributes.timezone),
569
- firstIn: a.firstIn ? convertToLocaleTimeString(a.firstIn, userData.user.attributes.lang, userData.user.attributes.timezone) : '-',
570
- lastOut: a.lastOut ? convertToLocaleTimeString(a.lastOut, userData.user.attributes.lang, userData.user.attributes.timezone) : '-',
571
- distanceIn: a.distanceIn && a.distanceIn.toLocaleString(this.user.attributes.lang, { maximumFractionDigits: 2 }),
572
- distanceOut: a.distanceOut && a.distanceOut.toLocaleString(this.user.attributes.lang, { maximumFractionDigits: 2 }),
573
- timeIn: convertMS(a.timeIn),
574
- timeOut: convertMS(a.timeOut)
575
- }
576
- }))
577
- : data.concat(d.geofences.map(a => {
578
- return {
579
- ...a,
580
- name: d.device.name,
581
- enter: geofenceEnter(userData.user, a),
582
- exit: geofenceExit(userData.user, a),
583
- stopped: a.stopped ? translations.report.yes : translations.report.no,
584
- duration: a.totalTime ? convertMS(a.totalTime * 1000, true) : '',
585
- distanceIn: a.distanceIn && a.distanceIn.toLocaleString(this.user.attributes.lang, { maximumFractionDigits: 2 }),
586
- distanceOut: a.distanceOut && a.distanceOut.toLocaleString(this.user.attributes.lang, { maximumFractionDigits: 2 }),
587
- zone: a.geofenceName,
588
- driver: a.driverName
589
- }
473
+ if (userData.groupByDay) {
474
+ d.geofences.forEach(g => {
475
+ data = data.concat([{ zone: g.geofenceName }])
476
+ data = data.concat(g.days.map(a => {
477
+ return getColumns(d, a, userData, translations)
478
+ }))
479
+ data = data.concat([{}])
480
+ })
481
+ } else {
482
+ data = data.concat(d.geofences.map(a => {
483
+ return getColumns(d, a, userData, translations)
590
484
  }))
485
+ data = data.concat([{}])
486
+ }
591
487
  })
592
488
  return {
593
489
  headers,
@@ -597,6 +493,46 @@ function exportZoneReportToExcel (userData, reportData) {
597
493
  }
598
494
  }
599
495
 
496
+ function reportHeader (first, doc, translations, device, lang, timezone, userData, geofence) {
497
+ const name = deviceName(device.device)
498
+ const group = userData.groups.find(g => device.device.groupId === g.id)
499
+
500
+ const space = first ? 8 : 0
501
+ if (!first) {
502
+ doc.addPage()
503
+ }
504
+
505
+ doc.setFontSize(13)
506
+ doc.text(name, 20, space + 20)
507
+ doc.setFontSize(11)
508
+ doc.text(group ? translations.report.group + ': ' + group.name : '', 200, space + 20)
509
+ doc.text(convertToLocaleString(device.from, lang, timezone) + ' - ' + convertToLocaleString(device.to, lang, timezone), 20, space + 25)
510
+ if (userData.groupByDay) {
511
+ doc.text(translations.report.geofence + ': ' + geofence.geofenceName, 20, space + 30)
512
+ }
513
+
514
+ return space
515
+ }
516
+
517
+ function getColumns (device, data, userData, translations) {
518
+ return {
519
+ ...data,
520
+ name: device.device.name,
521
+ enter: geofenceEnter(userData.user, data),
522
+ exit: geofenceExit(userData.user, data),
523
+ stopped: data.stopped ? translations.report.yes : translations.report.no,
524
+ date: convertToLocaleDateString(data.date, userData.user.attributes.lang, userData.user.attributes.timezone),
525
+ firstIn: data.firstIn ? convertToLocaleTimeString(data.firstIn, userData.user.attributes.lang, userData.user.attributes.timezone) : '-',
526
+ lastOut: data.lastOut ? convertToLocaleTimeString(data.lastOut, userData.user.attributes.lang, userData.user.attributes.timezone) : '-',
527
+ distanceIn: data.distanceIn ? data.distanceIn.toLocaleString(userData.user.attributes.lang, { maximumFractionDigits: 2 }) : 0,
528
+ distanceOut: data.distanceOut ? data.distanceOut.toLocaleString(userData.user.attributes.lang, { maximumFractionDigits: 2 }) : 0,
529
+ totalInTime: convertMS(data.totalInTime, !userData.groupByDay),
530
+ totalOutTime: convertMS(data.totalOutTime, !userData.groupByDay),
531
+ zone: data.geofenceName,
532
+ driver: data.driverName
533
+ }
534
+ }
535
+
600
536
  function deviceName (device) {
601
537
  return device.name + (device.attributes.license_plate ? ', ' + device.attributes.license_plate : '') + (device.model ? ', ' + device.model : '')
602
538
  }