fleetmap-reports 1.0.513 → 1.0.516
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/automaticReports.js +45 -46
- package/src/fuelconsumption-report.js +10 -7
- package/src/index.test.js +13 -27
- package/src/refueling-report.js +22 -14
- package/src/speeding-report.js +1 -1
- package/src/util/odoo.js +7 -8
package/package.json
CHANGED
package/src/automaticReports.js
CHANGED
|
@@ -1,67 +1,66 @@
|
|
|
1
1
|
const moment = require('moment')
|
|
2
2
|
|
|
3
|
-
function sliceArray(longArray,
|
|
4
|
-
|
|
3
|
+
function sliceArray (longArray, size = 1) {
|
|
4
|
+
const arrayToSlice = longArray.slice()
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
const arrayOfArrays = []
|
|
7
|
+
for (let i = 0; i < arrayToSlice.length; i += size) {
|
|
8
|
+
arrayOfArrays.push(arrayToSlice.slice(i, i + size))
|
|
9
|
+
}
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
return arrayOfArrays
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
function deviceWithFuelInfo(device) {
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
function deviceWithFuelInfo (device) {
|
|
15
|
+
return device.attributes.odooId || device.attributes.xpert ||
|
|
16
|
+
(device.attributes.fuel_low_threshold >= 0 && device.attributes.fuel_high_threshold >= 0 && device.attributes.fuel_tank_capacity)
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
function fuelSignalInverter(device) {
|
|
20
|
-
|
|
19
|
+
function fuelSignalInverter (device) {
|
|
20
|
+
return device.attributes.fuel_low_threshold <= device.attributes.fuel_high_threshold ? 1 : -1
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
function calculateFuelDiff(a, b, device) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
function calculateFuelDiff (a, b, device) {
|
|
24
|
+
const diff = (b - a) * fuelSignalInverter(device)
|
|
25
|
+
if (device.attributes.xpert) {
|
|
26
|
+
return diff
|
|
27
|
+
} else {
|
|
28
|
+
return (diff * 100) / Math.abs(device.attributes.fuel_low_threshold - device.attributes.fuel_high_threshold)
|
|
29
|
+
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
function calculateXpertSpentFuel(date, positions) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
32
|
+
function calculateXpertSpentFuel (date, positions) {
|
|
33
|
+
const begin = moment(date, 'YYYY-MM-DD').startOf('day')
|
|
34
|
+
const end = moment(date, 'YYYY-MM-DD').endOf('day')
|
|
35
|
+
const datePositions = positions.filter(p => moment(p.fixTime).isAfter(begin) && moment(p.fixTime).isBefore(end))
|
|
36
|
+
const xpertMessages = datePositions.map(p => p.attributes.xpert).flat().filter(p => p)
|
|
37
|
+
const xpertEndTripMessage = xpertMessages.filter(x => x.type === '3')
|
|
38
|
+
if (xpertEndTripMessage.length > 1) {
|
|
39
|
+
const diff = xpertEndTripMessage[xpertEndTripMessage.length - 1].total_fuel - xpertEndTripMessage[0].total_fuel
|
|
40
|
+
console.log('Diff:', diff)
|
|
41
|
+
return Math.round(diff)
|
|
42
|
+
}
|
|
43
|
+
return 0
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
function calculateXpertDistance(date, positions) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
function calculateXpertDistance (date, positions) {
|
|
47
|
+
const begin = moment(date, 'YYYY-MM-DD').startOf('day')
|
|
48
|
+
const end = moment(date, 'YYYY-MM-DD').endOf('day')
|
|
49
|
+
const datePositions = positions.filter(p => moment(p.fixTime).isAfter(begin) && moment(p.fixTime).isBefore(end))
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
return datePositions.reduce((a, b) => a + b.attributes.distance, 0)
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
function calculateSpentFuel(value, device) {
|
|
55
|
-
|
|
56
|
-
return value
|
|
54
|
+
function calculateSpentFuel (value, device) {
|
|
55
|
+
if (!value) { return value }
|
|
57
56
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
57
|
+
if (device.attributes.xpert) {
|
|
58
|
+
return Math.round((value * device.attributes.fuel_tank_capacity) / 100)
|
|
59
|
+
} else {
|
|
60
|
+
const valueSignalCheck = value * fuelSignalInverter(device)
|
|
61
|
+
const valuePercentage = (valueSignalCheck * 100) / Math.abs(device.attributes.fuel_low_threshold - device.attributes.fuel_high_threshold)
|
|
62
|
+
return Math.round((valuePercentage * device.attributes.fuel_tank_capacity) / 100)
|
|
63
|
+
}
|
|
65
64
|
}
|
|
66
65
|
|
|
67
66
|
exports.sliceArray = sliceArray
|
|
@@ -36,7 +36,7 @@ async function createFuelConsumptionReport (from, to, userData, traccar) {
|
|
|
36
36
|
for (const d of devices) {
|
|
37
37
|
const trips = tripsData.filter(t => t.deviceId === d.id)
|
|
38
38
|
const route = routeData.filter(r => r.deviceId === d.id)
|
|
39
|
-
const deviceFuelServices = fuelServicesData.filter(f => d.attributes.odooId === f.vehicle_id[0])
|
|
39
|
+
const deviceFuelServices = fuelServicesData.filter(f => Number.parseInt(d.attributes.odooId) === f.vehicle_id[0])
|
|
40
40
|
|
|
41
41
|
if (trips.length > 0) {
|
|
42
42
|
const refuelingPositions = await refuelingReport.calculateRefuelingPositions(userData, d, { route, trips, fuelServices: deviceFuelServices })
|
|
@@ -45,17 +45,16 @@ async function createFuelConsumptionReport (from, to, userData, traccar) {
|
|
|
45
45
|
new Map()
|
|
46
46
|
)
|
|
47
47
|
|
|
48
|
-
trips.forEach(t => {
|
|
49
|
-
t.startDate = t.startTime.substring(0, 10)
|
|
50
|
-
})
|
|
48
|
+
trips.forEach(t => { t.startDate = t.startTime.substring(0, 10) })
|
|
51
49
|
const groupedTripsByDay = trips.reduce(
|
|
52
50
|
(entryMap, e) => entryMap.set(e.startDate, [...entryMap.get(e.startDate) || [], e]),
|
|
53
51
|
new Map()
|
|
54
52
|
)
|
|
55
53
|
|
|
54
|
+
const odooAvgConsumption = userData.withOdooServices ? getOdooAvgConsumption(refuelingPositions, trips) : 0
|
|
55
|
+
|
|
56
56
|
const days = []
|
|
57
57
|
const keys = Array.from(groupedTripsByDay.keys())
|
|
58
|
-
const odooAvgConsumption = userData.withOdooServices ? calculateAvgConsumption(refuelingPositions, trips) : 0
|
|
59
58
|
|
|
60
59
|
keys.forEach(day => {
|
|
61
60
|
const dayTrips = groupedTripsByDay.get(day)
|
|
@@ -67,7 +66,7 @@ async function createFuelConsumptionReport (from, to, userData, traccar) {
|
|
|
67
66
|
date: day,
|
|
68
67
|
distance,
|
|
69
68
|
spentFuel,
|
|
70
|
-
avgConsumption: userData.withOdooServices ? odooAvgConsumption :
|
|
69
|
+
avgConsumption: userData.withOdooServices ? odooAvgConsumption : getCanAvgConsumption(userData, odooAvgConsumption, distance, spentFuel),
|
|
71
70
|
endOdometer: dayTrips.slice(-1)[0].endOdometer,
|
|
72
71
|
duration: dayTrips.reduce((a, b) => a + b.duration, 0),
|
|
73
72
|
refueling: (dayRefueling && dayRefueling.length > 0) ? dayRefueling.reduce((a, b) => a + b.diff, 0) : 0
|
|
@@ -91,12 +90,16 @@ async function createFuelConsumptionReport (from, to, userData, traccar) {
|
|
|
91
90
|
return reportData
|
|
92
91
|
}
|
|
93
92
|
|
|
94
|
-
function
|
|
93
|
+
function getOdooAvgConsumption (refuelingPositions, trips) {
|
|
95
94
|
const odooTotalfuel = refuelingPositions.reduce((a, b) => a + b.diff, 0)
|
|
96
95
|
const totalKms = trips.reduce((a, b) => a + b.distance, 0)
|
|
97
96
|
return Math.round(odooTotalfuel * 100 / (totalKms / 1000))
|
|
98
97
|
}
|
|
99
98
|
|
|
99
|
+
function getCanAvgConsumption (userData, distance, spentFuel) {
|
|
100
|
+
return distance > 0 && spentFuel > 0 ? Math.round(spentFuel * 100 / (distance / 1000)) : 0
|
|
101
|
+
}
|
|
102
|
+
|
|
100
103
|
function calculateConsumption (userData, d, day, avgConsumption, data) {
|
|
101
104
|
if (d.attributes.xpert) {
|
|
102
105
|
return automaticReports.calculateXpertSpentFuel(day, data.route)
|
package/src/index.test.js
CHANGED
|
@@ -15,6 +15,7 @@ async function getSpeedingReport (report, userData) {
|
|
|
15
15
|
|
|
16
16
|
// eslint-disable-next-line no-undef
|
|
17
17
|
describe('Test_Reports', function () {
|
|
18
|
+
this.timeout(5000000)
|
|
18
19
|
// eslint-disable-next-line no-undef
|
|
19
20
|
it('works with road speed limits', async () => {
|
|
20
21
|
const report = await getReports()
|
|
@@ -25,7 +26,7 @@ describe('Test_Reports', function () {
|
|
|
25
26
|
assert.equal(totalDistance, 36.63687856826021) // Total Kms
|
|
26
27
|
assert.equal(totalEventTime, 1524000) // Total Duration
|
|
27
28
|
}, 200000)
|
|
28
|
-
|
|
29
|
+
// eslint-disable-next-line no-undef
|
|
29
30
|
it('works by device speed limit', async () => {
|
|
30
31
|
const report = await getReports()
|
|
31
32
|
const userData = await report.getUserData()
|
|
@@ -69,7 +70,7 @@ describe('Test_Reports', function () {
|
|
|
69
70
|
assert.equal(device.trips[0].idleTime, 602000)
|
|
70
71
|
assert.equal(device.trips[1].endPOIName, undefined)
|
|
71
72
|
assert.equal(device.totalDistance, 339170.3099999875) // Total Kms
|
|
72
|
-
},
|
|
73
|
+
}, 30000)
|
|
73
74
|
// eslint-disable-next-line no-undef
|
|
74
75
|
it('Trip by driver', async () => {
|
|
75
76
|
const report = await getReports()
|
|
@@ -350,33 +351,18 @@ describe('Test_Reports', function () {
|
|
|
350
351
|
it('Refueling Report', async () => {
|
|
351
352
|
const report = await getReports()
|
|
352
353
|
const userData = await report.getUserData()
|
|
353
|
-
|
|
354
|
+
userData.withOdooServices = true
|
|
354
355
|
const data = await report.refuelingReport(
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
356
|
+
new Date(Date.UTC(2022, 9, 1, 0, 0, 0, 0)),
|
|
357
|
+
new Date(Date.UTC(2022, 9, 31, 23, 59, 59, 0)),
|
|
358
|
+
userData)
|
|
358
359
|
|
|
359
360
|
assert.equal(data.length, 1)
|
|
360
361
|
console.log(data[0])
|
|
361
|
-
const device = data[0].devices.find(d => d.device.id ===
|
|
362
|
+
const device = data[0].devices.find(d => d.device.id === 22326)
|
|
362
363
|
assert.equal(device.refuelings.length, 2)
|
|
363
364
|
}, 30000)
|
|
364
365
|
// eslint-disable-next-line no-undef
|
|
365
|
-
it('Refueling2 Report', async () => {
|
|
366
|
-
const report = await getReports()
|
|
367
|
-
const userData = await report.getUserData()
|
|
368
|
-
|
|
369
|
-
const data = await report.refuelingReport(new Date(2022, 1, 21, 0, 0, 0, 0),
|
|
370
|
-
new Date(2022, 1, 25, 23, 59, 59, 0),
|
|
371
|
-
userData)
|
|
372
|
-
|
|
373
|
-
assert.equal(data.length, 1)
|
|
374
|
-
console.log(data[0])
|
|
375
|
-
const device = data[0].devices.find(d => d.device.id === 16245)
|
|
376
|
-
console.log(device.refuelings)
|
|
377
|
-
assert.equal(device.refuelings.length, 4)
|
|
378
|
-
}, 30000)
|
|
379
|
-
// eslint-disable-next-line no-undef
|
|
380
366
|
it('FuelConsumption Report', async () => {
|
|
381
367
|
const report = await getReports()
|
|
382
368
|
const userData = await report.getUserData()
|
|
@@ -396,15 +382,15 @@ describe('Test_Reports', function () {
|
|
|
396
382
|
const report = await getReports()
|
|
397
383
|
const userData = await report.getUserData()
|
|
398
384
|
userData.withOdooServices = true
|
|
399
|
-
userData.devices = userData.devices.filter(d => d.id ===
|
|
385
|
+
userData.devices = userData.devices.filter(d => d.id === 22326)
|
|
400
386
|
const data = await report.fuelConsumptionReport(
|
|
401
|
-
new Date(Date.UTC(2022,
|
|
402
|
-
new Date(Date.UTC(2022,
|
|
387
|
+
new Date(Date.UTC(2022, 9, 1, 0, 0, 0, 0)),
|
|
388
|
+
new Date(Date.UTC(2022, 9, 31, 23, 59, 59, 0)),
|
|
403
389
|
userData)
|
|
404
390
|
|
|
405
391
|
assert.equal(data.length, 1)
|
|
406
|
-
const device = data[0].devices.find(d => d.device.id ===
|
|
407
|
-
assert.equal(device.days.length,
|
|
392
|
+
const device = data[0].devices.find(d => d.device.id === 22326)
|
|
393
|
+
assert.equal(device.days.length, 23)
|
|
408
394
|
}, 30000)
|
|
409
395
|
// eslint-disable-next-line no-undef
|
|
410
396
|
it('Zone Report', async () => {
|
package/src/refueling-report.js
CHANGED
|
@@ -3,6 +3,8 @@ const automaticReports = require('./automaticReports')
|
|
|
3
3
|
const { devicesToProcess } = require('./util/device')
|
|
4
4
|
const distance = require('@turf/distance')
|
|
5
5
|
const { getTranslations } = require('./util/utils')
|
|
6
|
+
const odoo = require('./util/odoo')
|
|
7
|
+
const traccarHelper = require('./util/traccar')
|
|
6
8
|
|
|
7
9
|
const positionsToCheck = 15
|
|
8
10
|
|
|
@@ -22,13 +24,16 @@ async function createRefuelingReport (from, to, userData, traccar) {
|
|
|
22
24
|
console.log('Devices:' + devices.length)
|
|
23
25
|
|
|
24
26
|
const arrayOfArrays = automaticReports.sliceArray(devices)
|
|
25
|
-
|
|
27
|
+
const data = []
|
|
26
28
|
for (const a of arrayOfArrays) {
|
|
27
|
-
const
|
|
28
|
-
data
|
|
29
|
+
const allInOne = await traccarHelper.getAllInOne(traccar, from, to, a, true, false, false, false)
|
|
30
|
+
data.push(...allInOne.route)
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
const fuelServicesData = []
|
|
34
|
+
if (userData.withOdooServices) {
|
|
35
|
+
fuelServicesData.push(...(await odoo.getOdooFuelServices(traccar, from, to)))
|
|
36
|
+
}
|
|
32
37
|
|
|
33
38
|
if (data.length === 0) {
|
|
34
39
|
return reportData
|
|
@@ -40,19 +45,22 @@ async function createRefuelingReport (from, to, userData, traccar) {
|
|
|
40
45
|
|
|
41
46
|
for (const d of devices) {
|
|
42
47
|
const positions = data.filter(t => t.deviceId === d.id)
|
|
48
|
+
const deviceFuelServices = fuelServicesData.filter(f => Number.parseInt(d.attributes.odooId) === f.vehicle_id[0])
|
|
43
49
|
|
|
44
50
|
if (positions.length > 0) {
|
|
45
|
-
const refuelingPositions = await this.calculateRefuelingPositions(userData, d, { route: positions })
|
|
51
|
+
const refuelingPositions = await this.calculateRefuelingPositions(userData, d, { route: positions, fuelServices: deviceFuelServices })
|
|
46
52
|
|
|
47
53
|
if (userData.drivers.length > 0) {
|
|
48
|
-
refuelingPositions.forEach(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
refuelingPositions.forEach(r => {
|
|
55
|
+
if (r.position) {
|
|
56
|
+
const geofence = findNearestPOI(r.position, userData.geofences)
|
|
57
|
+
if (geofence) {
|
|
58
|
+
r.position.geofenceName = geofence.name
|
|
59
|
+
}
|
|
60
|
+
const driver = userData.drivers.find(d => d.uniqueId === r.position.attributes.driverUniqueId)
|
|
61
|
+
if (driver) {
|
|
62
|
+
r.position.driverName = driver.name
|
|
63
|
+
}
|
|
56
64
|
}
|
|
57
65
|
})
|
|
58
66
|
}
|
|
@@ -121,7 +129,7 @@ async function calculateRefuelingPositions (userData, d, data) {
|
|
|
121
129
|
|
|
122
130
|
const routeBeforeService = data.route.filter(r => new Date(r.fixTime).getTime() < serviceDate.getTime())
|
|
123
131
|
|
|
124
|
-
const quantity = s.
|
|
132
|
+
const quantity = s.liter
|
|
125
133
|
|
|
126
134
|
if (routeBeforeService.length) {
|
|
127
135
|
refuelingPositions.push({ date: s.date, diff: Number.parseFloat(quantity), cost: s.amount })
|
package/src/speeding-report.js
CHANGED
|
@@ -343,7 +343,7 @@ async function getHereEvents (devices, routes, threshold) {
|
|
|
343
343
|
events.push(...reduced)
|
|
344
344
|
resolve()
|
|
345
345
|
}).catch(e => {
|
|
346
|
-
console.warn('
|
|
346
|
+
console.warn('route match, moving on', e.message)
|
|
347
347
|
resolve()
|
|
348
348
|
})
|
|
349
349
|
}))
|
package/src/util/odoo.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
|
|
2
|
-
async function getOdooFuelServices(traccar, from, to) {
|
|
3
|
-
|
|
2
|
+
async function getOdooFuelServices (traccar, from, to) {
|
|
3
|
+
const url = `/odoo/reports/refuelingServices?startDate=${from.toDateString()}&endDate=${to.toDateString()}`
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
const { data } = await traccar.axios.get(url, {
|
|
6
|
+
jar: traccar.cookieJar,
|
|
7
|
+
withCredentials: true
|
|
8
|
+
})
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return data
|
|
10
|
+
return data
|
|
12
11
|
}
|
|
13
12
|
|
|
14
13
|
exports.getOdooFuelServices = getOdooFuelServices
|