fleetmap-reports 1.0.513 → 1.0.515
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 +8 -7
- package/src/refueling-report.js +12 -6
- 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()
|
|
@@ -396,15 +397,15 @@ describe('Test_Reports', function () {
|
|
|
396
397
|
const report = await getReports()
|
|
397
398
|
const userData = await report.getUserData()
|
|
398
399
|
userData.withOdooServices = true
|
|
399
|
-
userData.devices = userData.devices.filter(d => d.id ===
|
|
400
|
+
userData.devices = userData.devices.filter(d => d.id === 22326)
|
|
400
401
|
const data = await report.fuelConsumptionReport(
|
|
401
|
-
new Date(Date.UTC(2022,
|
|
402
|
-
new Date(Date.UTC(2022,
|
|
402
|
+
new Date(Date.UTC(2022, 9, 1, 0, 0, 0, 0)),
|
|
403
|
+
new Date(Date.UTC(2022, 9, 31, 23, 59, 59, 0)),
|
|
403
404
|
userData)
|
|
404
405
|
|
|
405
406
|
assert.equal(data.length, 1)
|
|
406
|
-
const device = data[0].devices.find(d => d.device.id ===
|
|
407
|
-
assert.equal(device.days.length,
|
|
407
|
+
const device = data[0].devices.find(d => d.device.id === 22326)
|
|
408
|
+
assert.equal(device.days.length, 23)
|
|
408
409
|
}, 30000)
|
|
409
410
|
// eslint-disable-next-line no-undef
|
|
410
411
|
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,9 +45,10 @@ 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
54
|
refuelingPositions.forEach(p => {
|
|
@@ -121,7 +127,7 @@ async function calculateRefuelingPositions (userData, d, data) {
|
|
|
121
127
|
|
|
122
128
|
const routeBeforeService = data.route.filter(r => new Date(r.fixTime).getTime() < serviceDate.getTime())
|
|
123
129
|
|
|
124
|
-
const quantity = s.
|
|
130
|
+
const quantity = s.liter
|
|
125
131
|
|
|
126
132
|
if (routeBeforeService.length) {
|
|
127
133
|
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
|