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 +1 -1
- package/src/tests/performance.test.js +4 -3
- package/src/tests/zones.test.js +38 -0
- package/src/zone-report.js +257 -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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
-
|
|
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
|
+
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 =
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
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 =
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
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)
|