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 +1 -1
- package/src/tests/performance.test.js +4 -3
- package/src/tests/zones.test.js +38 -0
- package/src/zone-report.js +253 -103
package/package.json
CHANGED
|
@@ -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.
|
|
10
|
+
userData.devices = userData.devices.filter(d => d.id === 128270)
|
|
10
11
|
const data = await createPerformanceReport(
|
|
11
|
-
new Date(Date.UTC(2023, 5,
|
|
12
|
-
new Date(Date.UTC(2023, 5,
|
|
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)
|
package/src/tests/zones.test.js
CHANGED
|
@@ -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
|
})
|
package/src/zone-report.js
CHANGED
|
@@ -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 =
|
|
74
|
-
|
|
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
|
-
|
|
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
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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 =
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
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 =
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
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)
|