fleetmap-reports 2.0.358 → 2.0.359
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/partnerReports/driverranking-report.js +39 -7
- package/.claude/worktrees/eager-stonebraker-c08ac7/.eslintrc.js +0 -15
- package/.claude/worktrees/eager-stonebraker-c08ac7/lang/enGB.js +0 -309
- package/.claude/worktrees/eager-stonebraker-c08ac7/lang/esCL.js +0 -297
- package/.claude/worktrees/eager-stonebraker-c08ac7/lang/frFR.json +0 -324
- package/.claude/worktrees/eager-stonebraker-c08ac7/lang/index.js +0 -35
- package/.claude/worktrees/eager-stonebraker-c08ac7/lang/ptBR.js +0 -301
- package/.claude/worktrees/eager-stonebraker-c08ac7/lang/ptPT.js +0 -310
- package/.claude/worktrees/eager-stonebraker-c08ac7/package-lock.json +0 -11944
- package/.claude/worktrees/eager-stonebraker-c08ac7/package.json +0 -45
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/activity-report.js +0 -822
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/automaticReports.js +0 -34
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/carbone/index.js +0 -13
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/custom/vistawasteActivity-report.js +0 -544
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/events-report.js +0 -360
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/fuel-consumption-report.js +0 -296
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/fuel-drop-report.js +0 -128
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/here.js +0 -172
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/idle-report.js +0 -403
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/index.js +0 -244
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/kms-report.js +0 -549
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/location-report.js +0 -496
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/machines-report.js +0 -278
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/afriquia.js +0 -129
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/dailyuse-report.js +0 -80
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/delayedstart-report.js +0 -223
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/driverranking-report.js +0 -328
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/gpsjump-report.js +0 -61
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/performance-report.js +0 -359
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/refueling-report.js +0 -345
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/reportStyle.js +0 -34
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/sensor-report.js +0 -447
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/speeding-report.js +0 -663
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/stop-report.js +0 -242
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/ActivityReportTemplate.mjml +0 -51
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/EmptyReportTemplate.mjml +0 -25
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/EventsReportTemplate.mjml +0 -75
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/FuelDropReportTemplate.mjml +0 -60
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/IdleReportTemplate.mjml +0 -54
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/KmsReportGroupByDayTemplate.mjml +0 -43
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/KmsReportTemplate.mjml +0 -44
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/LocationReportTemplate.mjml +0 -37
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/RefuelingReportTemplate.mjml +0 -60
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/SensorReportTemplate.mjml +0 -23
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/SpeedingReportTemplate.mjml +0 -80
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/TripReportTemplate.mjml +0 -97
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/ZoneReportTemplate.mjml +0 -52
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/report.mjml +0 -96
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/activity.test.js +0 -99
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/carbone.test.js +0 -20
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/events.test.js +0 -30
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/fuel.test.js +0 -35
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/idle.test.js +0 -16
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/index.js +0 -24
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/index.test.js +0 -203
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/kms.test.js +0 -74
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/performance.test.js +0 -36
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/positions.test.js +0 -67
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/speeding.test.js +0 -120
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/translations.test.js +0 -21
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/trips.test.js +0 -140
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/zones.test.js +0 -162
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/trip-report.js +0 -641
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/device.js +0 -13
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/driver.js +0 -90
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/fuel.js +0 -102
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/geofence.js +0 -52
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/odoo.js +0 -18
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/parallel.js +0 -64
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/pdfDocument.js +0 -140
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/route.js +0 -78
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/timetable.js +0 -30
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/traccar.js +0 -213
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/traccar.worker.js +0 -49
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/trips.js +0 -270
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/utils.js +0 -358
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/worker.js +0 -14
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/xpert.js +0 -58
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/word/index.js +0 -95
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/zone-report.js +0 -904
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
function getIdleEvents (route, driver, speedThreshold = 3) {
|
|
2
|
-
const idleEvents = []
|
|
3
|
-
|
|
4
|
-
const routeByDevice = route.reduce(function (a, x) {
|
|
5
|
-
(a[x.deviceId] = a[x.deviceId] || []).push(x)
|
|
6
|
-
return a
|
|
7
|
-
}, {})
|
|
8
|
-
|
|
9
|
-
Object.keys(routeByDevice).forEach(function (key) {
|
|
10
|
-
let inIdle = false
|
|
11
|
-
let last = null
|
|
12
|
-
routeByDevice[key].forEach(p => {
|
|
13
|
-
if (p.attributes.ignition && p.speed < speedThreshold && (!driver || p.attributes.driverUniqueId === driver.uniqueId)) {
|
|
14
|
-
if (!inIdle) {
|
|
15
|
-
const idleEvent = {
|
|
16
|
-
position: p,
|
|
17
|
-
idleTime: 0
|
|
18
|
-
}
|
|
19
|
-
idleEvents.push(idleEvent)
|
|
20
|
-
inIdle = true
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (!idleEvents[idleEvents.length - 1].position.attributes.driverUniqueId) {
|
|
24
|
-
idleEvents[idleEvents.length - 1].position.attributes.driverUniqueId = p.attributes.driverUniqueId
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
last = p
|
|
28
|
-
} else if (inIdle) {
|
|
29
|
-
const currentIdleEvent = idleEvents[idleEvents.length - 1]
|
|
30
|
-
currentIdleEvent.idleTime = new Date(last.fixTime) - new Date(currentIdleEvent.position.fixTime)
|
|
31
|
-
currentIdleEvent.lastPosition = last
|
|
32
|
-
inIdle = false
|
|
33
|
-
}
|
|
34
|
-
})
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
return idleEvents
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function filterPositions (positions) {
|
|
41
|
-
return positions.filter(filterPosition)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function cleanPosition (p) {
|
|
45
|
-
return {
|
|
46
|
-
id: p.id,
|
|
47
|
-
fixTime: p.fixTime,
|
|
48
|
-
address: p.address,
|
|
49
|
-
latitude: p.latitude,
|
|
50
|
-
longitude: p.longitude,
|
|
51
|
-
deviceId: p.deviceId,
|
|
52
|
-
speed: p.speed,
|
|
53
|
-
valid: p.valid,
|
|
54
|
-
attributes: {
|
|
55
|
-
ignition: p.attributes.ignition,
|
|
56
|
-
driverUniqueId: p.attributes.driverUniqueId
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
exports.cleanPositions = (positions) => {
|
|
62
|
-
return positions.map(cleanPosition)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function filterPosition (p) {
|
|
66
|
-
if (p.valid === false) {
|
|
67
|
-
return p.attributes.ignition || p.attributes.motion
|
|
68
|
-
}
|
|
69
|
-
if (p.protocol === 'osmand') {
|
|
70
|
-
return !(p.attributes.event >= 200 || p.attributes.event === 30)
|
|
71
|
-
}
|
|
72
|
-
return true
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
exports.getIdleEvents = getIdleEvents
|
|
76
|
-
exports.filterPositions = filterPositions
|
|
77
|
-
exports.filterPosition = filterPosition
|
|
78
|
-
exports.cleanPosition = cleanPosition
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
const { weekDaySelected, convertFromUTC, isClientSide, convertFromLocal } = require('./utils')
|
|
2
|
-
|
|
3
|
-
function isInside (_tripStart, _tripEnd, userData) {
|
|
4
|
-
const tripStart = new Date(_tripStart)
|
|
5
|
-
const tripEnd = new Date(_tripEnd)
|
|
6
|
-
|
|
7
|
-
if (weekDaySelected(tripStart, userData.weekDays)) {
|
|
8
|
-
const timeWindowStartLocal = new Date(convertFromUTC(_tripStart, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.startTime)
|
|
9
|
-
const timeWindowEndLocal = new Date(convertFromUTC(_tripEnd, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.endTime)
|
|
10
|
-
|
|
11
|
-
const timeWindowStartUTC = isClientSide() ? timeWindowStartLocal : convertFromLocal(timeWindowStartLocal, userData.user.attributes.timezone)
|
|
12
|
-
const timeWindowEndUTC = isClientSide() ? timeWindowEndLocal : convertFromLocal(timeWindowEndLocal, userData.user.attributes.timezone)
|
|
13
|
-
|
|
14
|
-
if (timeWindowStartUTC.getTime() > timeWindowEndUTC.getTime()) {
|
|
15
|
-
const startDatePreviousDay = new Date(timeWindowStartUTC)
|
|
16
|
-
startDatePreviousDay.setDate(timeWindowStartUTC.getDate() - 1)
|
|
17
|
-
const endDateNextDay = new Date(timeWindowEndUTC)
|
|
18
|
-
endDateNextDay.setDate(timeWindowEndUTC.getDate() + 1)
|
|
19
|
-
|
|
20
|
-
return (tripStart.getTime() > startDatePreviousDay.getTime() && tripEnd.getTime() < timeWindowEndUTC.getTime()) ||
|
|
21
|
-
(tripStart.getTime() > timeWindowStartUTC.getTime() && tripEnd.getTime() < endDateNextDay.getTime())
|
|
22
|
-
}
|
|
23
|
-
// Trips inside time period
|
|
24
|
-
return tripStart.getTime() > timeWindowStartUTC.getTime() && tripEnd.getTime() < timeWindowEndUTC.getTime()
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return false
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
exports.isInside = isInside
|
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
const automaticReports = require('../automaticReports')
|
|
2
|
-
const { convertFromUTC, isClientSide, convertFromLocal } = require('./utils')
|
|
3
|
-
const path = require('path')
|
|
4
|
-
const { cleanPositions, filterPosition } = require('./route')
|
|
5
|
-
const Piscina = require('piscina')
|
|
6
|
-
const piscina = new Piscina()
|
|
7
|
-
|
|
8
|
-
async function getRoute (traccar, from, to, devices) {
|
|
9
|
-
const devicesToSlice = devices.slice()
|
|
10
|
-
|
|
11
|
-
const arrayOfArrays = automaticReports.sliceArray(devicesToSlice, 50)
|
|
12
|
-
let requests = []
|
|
13
|
-
for (const a of arrayOfArrays) {
|
|
14
|
-
const promise = traccar.reports.reportsRouteGet(from, to, a.map(d => d.id))
|
|
15
|
-
requests = requests.concat(promise)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const result = await Promise.all(requests)
|
|
19
|
-
return result.map(r => r.data).flat()
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
async function getTrips (traccar, from, to, devices) {
|
|
23
|
-
const devicesToSlice = devices.slice()
|
|
24
|
-
const arrayOfArrays = automaticReports.sliceArray(devicesToSlice, 50)
|
|
25
|
-
let requests = []
|
|
26
|
-
for (const a of arrayOfArrays) {
|
|
27
|
-
const promise = traccar.reports.reportsTripsGet(from, to, a.map(d => d.id))
|
|
28
|
-
requests = requests.concat(promise)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const result = await Promise.all(requests)
|
|
32
|
-
return result.map(r => r.data).flat()
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async function getStops (traccar, from, to, devices) {
|
|
36
|
-
const devicesToSlice = devices.slice()
|
|
37
|
-
const arrayOfArrays = automaticReports.sliceArray(devicesToSlice, 50)
|
|
38
|
-
let requests = []
|
|
39
|
-
for (const a of arrayOfArrays) {
|
|
40
|
-
const promise = traccar.reports.reportsStopsGet(from, to, a.map(d => d.id))
|
|
41
|
-
requests = requests.concat(promise)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const result = await Promise.all(requests)
|
|
45
|
-
return result.map(r => r.data).flat()
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async function getEvents (traccar, from, to, devices, events) {
|
|
49
|
-
const devicesToSlice = devices.slice()
|
|
50
|
-
const arrayOfArrays = automaticReports.sliceArray(devicesToSlice, 50)
|
|
51
|
-
let requests = []
|
|
52
|
-
for (const a of arrayOfArrays) {
|
|
53
|
-
const promise = traccar.reports.reportsEventsGet(from, to, a.map(d => d.id), null, events)
|
|
54
|
-
requests = requests.concat(promise)
|
|
55
|
-
}
|
|
56
|
-
const result = await Promise.all(requests)
|
|
57
|
-
return result.map(r => r.data).flat()
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async function getSummary (traccar, from, to, devices) {
|
|
61
|
-
const devicesToSlice = devices.slice()
|
|
62
|
-
const arrayOfArrays = automaticReports.sliceArray(devicesToSlice, 50)
|
|
63
|
-
let requests = []
|
|
64
|
-
for (const a of arrayOfArrays) {
|
|
65
|
-
const promise = getAllInOne(traccar, from, to, a, false, false, false, true, 0, a.length, a.length, a.length, undefined, true)
|
|
66
|
-
requests = requests.concat(promise)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const result = await Promise.all(requests)
|
|
70
|
-
return result.map(r => r.summary).flat()
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async function getItems (traccar, u, _chunk, counter, devicesPerRequest, ignorePercentage,
|
|
74
|
-
totalDevices, currentDeviceCount, routeOnly, filter) {
|
|
75
|
-
try {
|
|
76
|
-
const x = routeOnly && !isClientSide()
|
|
77
|
-
? await streamJson(traccar, u.replace('allinone', 'route').replace('type=route', ''), filter)
|
|
78
|
-
: await traccar.axios.get(u, {
|
|
79
|
-
withCredentials: true,
|
|
80
|
-
timeout: 900000
|
|
81
|
-
}).then(r => {
|
|
82
|
-
if (filter && r.data.route) {
|
|
83
|
-
r.data.route = cleanPositions(r.data.route.filter(filterPosition))
|
|
84
|
-
}
|
|
85
|
-
return r.data
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
console.log('LOADING_MESSAGE:' + _chunk[0].name)
|
|
89
|
-
if (counter) {
|
|
90
|
-
counter.count += devicesPerRequest
|
|
91
|
-
ignorePercentage || console.log(`PROGRESS_PERC:${Math.round(counter.count / totalDevices * 100)}`)
|
|
92
|
-
} else {
|
|
93
|
-
currentDeviceCount += devicesPerRequest
|
|
94
|
-
ignorePercentage || console.log(`PROGRESS_PERC:${Math.round(currentDeviceCount / totalDevices * 100)}`)
|
|
95
|
-
}
|
|
96
|
-
console.log('done devices', _chunk.map(d => d.id), 'position count', x.route && x.route.length)
|
|
97
|
-
return x
|
|
98
|
-
} catch (e) {
|
|
99
|
-
console.error(e)
|
|
100
|
-
return {}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function getCookie (traccar) {
|
|
105
|
-
return (traccar.axios.defaults.headers && traccar.axios.defaults.headers.cookie) ||
|
|
106
|
-
(traccar.axios.defaults.headers && traccar.axios.defaults.headers.common && traccar.axios.defaults.headers.common.cookie) ||
|
|
107
|
-
(require('axios').defaults.headers && require('axios').defaults.headers.common && require('axios').defaults.headers.common.cookie)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function streamJson (traccar, u, filter) {
|
|
111
|
-
const cookie = getCookie(traccar)
|
|
112
|
-
return piscina.run({
|
|
113
|
-
url: traccar.axios.defaults.baseURL + u,
|
|
114
|
-
cookie,
|
|
115
|
-
filter
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
filename: path.resolve(__dirname, './traccar.worker.js')
|
|
119
|
-
})
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
async function getAllInOne (
|
|
123
|
-
traccar,
|
|
124
|
-
from,
|
|
125
|
-
to,
|
|
126
|
-
devices,
|
|
127
|
-
getRoutes,
|
|
128
|
-
getTrips,
|
|
129
|
-
getStops,
|
|
130
|
-
getSummary,
|
|
131
|
-
currentDeviceCount = 0,
|
|
132
|
-
totalDevices = devices.length,
|
|
133
|
-
sliceSize = 5,
|
|
134
|
-
devicesPerRequest = 1,
|
|
135
|
-
counter = undefined,
|
|
136
|
-
ignorePercentage = false,
|
|
137
|
-
filter) {
|
|
138
|
-
let url = `/reports/allinone?from=${from.toISOString()}&to=${to.toISOString()}`
|
|
139
|
-
if (getRoutes) url += '&type=route'
|
|
140
|
-
if (getTrips) url += '&type=trips'
|
|
141
|
-
if (getStops) url += '&type=stops'
|
|
142
|
-
if (getSummary) url += '&type=summary'
|
|
143
|
-
|
|
144
|
-
const sliced = automaticReports.sliceArray(devices, sliceSize)
|
|
145
|
-
const result = []
|
|
146
|
-
for (const chunk of sliced) {
|
|
147
|
-
const requests = []
|
|
148
|
-
for (const _chunk of automaticReports.sliceArray(chunk, devicesPerRequest)) {
|
|
149
|
-
const u = url + '&' + _chunk.map(d => `deviceId=${d.id}`).join('&')
|
|
150
|
-
console.log(u)
|
|
151
|
-
requests.push(
|
|
152
|
-
getItems(traccar, u, _chunk, counter, devicesPerRequest, ignorePercentage, totalDevices, currentDeviceCount,
|
|
153
|
-
!getTrips && !getStops && !getSummary, filter)
|
|
154
|
-
)
|
|
155
|
-
}
|
|
156
|
-
const now = new Date()
|
|
157
|
-
console.log('parallel', requests.length)
|
|
158
|
-
try {
|
|
159
|
-
result.push(...(await Promise.all(requests)))
|
|
160
|
-
} catch (e) {
|
|
161
|
-
console.error('parallel', e.message, e.config)
|
|
162
|
-
}
|
|
163
|
-
console.log('took', new Date() - now, 'ms')
|
|
164
|
-
}
|
|
165
|
-
return {
|
|
166
|
-
route: result.filter(t => t.route).map(r => r.route).flat(),
|
|
167
|
-
trips: result.filter(t => t.trips).map(r => r.trips).flat(),
|
|
168
|
-
stops: result.filter(t => t.stops).map(r => r.stops).flat(),
|
|
169
|
-
summary: result.filter(t => t.summary).map(r => r.summary).flat()
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
async function getSummaryByDay (dates, userData, traccarInstance, allDevices, ignorePercentage = false, from, to) {
|
|
174
|
-
const days = []
|
|
175
|
-
let counter = 0
|
|
176
|
-
for (const [index, date] of dates.entries()) {
|
|
177
|
-
let startDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.startTime)
|
|
178
|
-
if (index === 0) {
|
|
179
|
-
const _startDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + (isClientSide() ? from.toTimeString().slice(0, 8) : convertFromUTC(from, userData.user.attributes.timezone).toTimeString().slice(0, 8)))
|
|
180
|
-
startDateLocal = startDateLocal.getTime() > _startDateLocal.getTime() ? startDateLocal : _startDateLocal
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
let endDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.endTime)
|
|
184
|
-
if (index === dates.length - 1) {
|
|
185
|
-
const _endDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + (isClientSide() ? to.toTimeString().slice(0, 8) : convertFromUTC(to, userData.user.attributes.timezone).toTimeString().slice(0, 8)))
|
|
186
|
-
endDateLocal = endDateLocal.getTime() < _endDateLocal.getTime() ? endDateLocal : _endDateLocal
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
const startDate = isClientSide() ? startDateLocal : convertFromLocal(startDateLocal, userData.user.attributes.timezone)
|
|
190
|
-
const endDate = isClientSide() ? endDateLocal : convertFromLocal(endDateLocal, userData.user.attributes.timezone)
|
|
191
|
-
|
|
192
|
-
const summary = await getSummary(traccarInstance, startDate, endDate, allDevices)
|
|
193
|
-
|
|
194
|
-
counter = counter + 1
|
|
195
|
-
if (!ignorePercentage) {
|
|
196
|
-
console.log(`PROGRESS_PERC:${counter / dates.length * 100}`)
|
|
197
|
-
}
|
|
198
|
-
days.push({
|
|
199
|
-
date,
|
|
200
|
-
summary
|
|
201
|
-
})
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
return days
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
exports.getRoute = getRoute
|
|
208
|
-
exports.getTrips = getTrips
|
|
209
|
-
exports.getStops = getStops
|
|
210
|
-
exports.getEvents = getEvents
|
|
211
|
-
exports.getSummary = getSummary
|
|
212
|
-
exports.getSummaryByDay = getSummaryByDay
|
|
213
|
-
exports.getAllInOne = getAllInOne
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
const { chain } = require('stream-chain')
|
|
2
|
-
const { parser } = require('stream-json')
|
|
3
|
-
const { streamArray } = require('stream-json/streamers/StreamArray')
|
|
4
|
-
const { Readable } = require('stream')
|
|
5
|
-
const { cleanPosition, filterPosition } = require('./route')
|
|
6
|
-
|
|
7
|
-
function fetchRetry (url, options, retry = 3) {
|
|
8
|
-
return fetch(url, options).catch(async e => {
|
|
9
|
-
if (retry) {
|
|
10
|
-
console.warn(url, e.message, 'retrying', retry)
|
|
11
|
-
return fetchRetry(url, options, retry - 1)
|
|
12
|
-
}
|
|
13
|
-
throw e
|
|
14
|
-
})
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
module.exports = async ({ url, cookie, filter }) => {
|
|
18
|
-
const now = new Date()
|
|
19
|
-
const response = await fetchRetry(url, { headers: { cookie } })
|
|
20
|
-
.catch(e => {
|
|
21
|
-
console.error(e)
|
|
22
|
-
throw new Error(`${e.message} traccar-worker ${cookie} ${url}`)
|
|
23
|
-
})
|
|
24
|
-
if (!response.ok) {
|
|
25
|
-
throw new Error(`${cookie} ${url} Fetch failed: ${response.status} ${response.statusText}`)
|
|
26
|
-
}
|
|
27
|
-
console.log(url, 'took', new Date() - now, 'ms', 'streaming...')
|
|
28
|
-
const nodeStream = Readable.fromWeb(response.body)
|
|
29
|
-
|
|
30
|
-
const result = { route: [] }
|
|
31
|
-
return new Promise((resolve, reject) => {
|
|
32
|
-
const pipeline = chain([
|
|
33
|
-
nodeStream,
|
|
34
|
-
parser(),
|
|
35
|
-
streamArray() // Stream each item in the array
|
|
36
|
-
])
|
|
37
|
-
pipeline.on('data', ({ value }) => {
|
|
38
|
-
if (filter) {
|
|
39
|
-
if (filterPosition(value)) {
|
|
40
|
-
result.route.push(cleanPosition(value))
|
|
41
|
-
}
|
|
42
|
-
} else {
|
|
43
|
-
result.route.push(value)
|
|
44
|
-
}
|
|
45
|
-
})
|
|
46
|
-
pipeline.on('end', () => resolve(result))
|
|
47
|
-
pipeline.on('error', reject)
|
|
48
|
-
})
|
|
49
|
-
}
|
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
const { coordsDistance, convertFromUTC, weekDaySelected, convertFromLocal, isClientSide, calculateDistance } = require('./utils')
|
|
2
|
-
const { isInside } = require('./timetable')
|
|
3
|
-
const traccarHelper = require('./traccar')
|
|
4
|
-
|
|
5
|
-
async function calculatePartialTrip (device, startDate, endDate, route, t, traccarInstance) {
|
|
6
|
-
let isPartialInside = false
|
|
7
|
-
const tripStart = new Date(t.startTime)
|
|
8
|
-
const tripEnd = new Date(t.endTime)
|
|
9
|
-
|
|
10
|
-
if (startDate.getTime() > endDate.getTime()) {
|
|
11
|
-
if (tripStart.getTime() < endDate.getTime() &&
|
|
12
|
-
tripEnd.getTime() > endDate.getTime()) {
|
|
13
|
-
// Trip starts inside time period and ends outside time period
|
|
14
|
-
if (!route && device) {
|
|
15
|
-
const allInOneData = await traccarHelper.getAllInOne(traccarInstance, startDate, endDate, [device], true, false, false, false, undefined, undefined, 5, 1, undefined, true)
|
|
16
|
-
route = allInOneData.route
|
|
17
|
-
}
|
|
18
|
-
const routeInside = route.filter(p => new Date(p.fixTime).getTime() < new Date(endDate.toUTCString()).getTime() && new Date(p.fixTime).getTime() > new Date(t.startTime).getTime() && t.deviceId === p.deviceId)
|
|
19
|
-
updateTrip(device, t, routeInside)
|
|
20
|
-
t.endTime = endDate.toISOString().replace('Z', '+0000')
|
|
21
|
-
t.endTimeIsOut = true
|
|
22
|
-
isPartialInside = true
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (tripStart.getTime() < startDate.getTime() &&
|
|
26
|
-
new Date(t.endTime).getTime() > startDate.getTime()) {
|
|
27
|
-
// Trip starts outside time period and ends inside time period
|
|
28
|
-
if (!route && device) {
|
|
29
|
-
const allInOneData = await traccarHelper.getAllInOne(traccarInstance, startDate, endDate, [device], true, false, false, false, undefined, undefined, 5, 1, undefined, true)
|
|
30
|
-
route = allInOneData.route
|
|
31
|
-
}
|
|
32
|
-
const routeInside = route.filter(p => new Date(p.fixTime).getTime() > startDate.getTime() && new Date(p.fixTime).getTime() < new Date(t.endTime).getTime() && t.deviceId === p.deviceId)
|
|
33
|
-
updateTrip(device, t, routeInside)
|
|
34
|
-
t.startTime = startDate.toISOString().replace('Z', '+0000')
|
|
35
|
-
t.startTimeIsOut = true
|
|
36
|
-
isPartialInside = true
|
|
37
|
-
}
|
|
38
|
-
} else {
|
|
39
|
-
if (tripStart.getTime() < startDate.getTime() &&
|
|
40
|
-
tripEnd.getTime() > startDate.getTime()) {
|
|
41
|
-
// Trip starts outside time period and ends inside time period
|
|
42
|
-
if (!route && device) {
|
|
43
|
-
const allInOneData = await traccarHelper.getAllInOne(traccarInstance, startDate, endDate, [device], true, false, false, false, undefined, undefined, 5, 1, undefined, true)
|
|
44
|
-
route = allInOneData.route
|
|
45
|
-
}
|
|
46
|
-
const routeInside = route.filter(p => new Date(p.fixTime).getTime() > new Date(startDate.toUTCString()).getTime() && new Date(p.fixTime).getTime() < new Date(t.endTime).getTime() && t.deviceId === p.deviceId)
|
|
47
|
-
updateTrip(device, t, routeInside)
|
|
48
|
-
t.startTime = startDate.toISOString().replace('Z', '+0000')
|
|
49
|
-
t.startTimeIsOut = true
|
|
50
|
-
isPartialInside = true
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (tripStart.getTime() < endDate.getTime() &&
|
|
54
|
-
tripEnd.getTime() > endDate.getTime()) {
|
|
55
|
-
// Trip starts inside time period and ends outside time period
|
|
56
|
-
if (!route && device) {
|
|
57
|
-
const allInOneData = await traccarHelper.getAllInOne(traccarInstance, startDate, endDate, [device], true, false, false, false, undefined, undefined, 5, 1, undefined, true)
|
|
58
|
-
route = allInOneData.route
|
|
59
|
-
}
|
|
60
|
-
const routeInside = route.filter(p => new Date(p.fixTime).getTime() < endDate.getTime() && new Date(p.fixTime).getTime() > new Date(t.startTime).getTime() && t.deviceId === p.deviceId)
|
|
61
|
-
updateTrip(device, t, routeInside)
|
|
62
|
-
t.endTime = endDate.toISOString().replace('Z', '+0000')
|
|
63
|
-
t.endTimeIsOut = true
|
|
64
|
-
isPartialInside = true
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return isPartialInside
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function isPartialInsideTimetable (device, t, userData, route) {
|
|
71
|
-
if (weekDaySelected(new Date(t.startTime), userData.weekDays)) {
|
|
72
|
-
const startDateLocal = new Date(convertFromUTC(t.startTime, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.startTime)
|
|
73
|
-
const endDateLocal = new Date(convertFromUTC(t.startTime, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.endTime)
|
|
74
|
-
|
|
75
|
-
const startDate = isClientSide() ? startDateLocal : convertFromLocal(startDateLocal, userData.user.attributes.timezone)
|
|
76
|
-
const endDate = isClientSide() ? endDateLocal : convertFromLocal(endDateLocal, userData.user.attributes.timezone)
|
|
77
|
-
|
|
78
|
-
return calculatePartialTrip(device, startDate, endDate, route, t)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return false
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
async function getDataByDay (device, date, data, userData, traccarInstance) {
|
|
85
|
-
const startDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' 00:00:00')
|
|
86
|
-
const endDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' 23:59:59')
|
|
87
|
-
const startDate = isClientSide() ? startDateLocal : convertFromLocal(startDateLocal, userData.user.attributes.timezone)
|
|
88
|
-
const endDate = isClientSide() ? endDateLocal : convertFromLocal(endDateLocal, userData.user.attributes.timezone)
|
|
89
|
-
|
|
90
|
-
const tripsByDay = []
|
|
91
|
-
if (data.trips) {
|
|
92
|
-
const filteredTrips = data.trips.filter(t => new Date(t.endTime) > startDate && new Date(t.startTime) < endDate)
|
|
93
|
-
tripsByDay.push(...filteredTrips.map(t => { return { ...t } }))
|
|
94
|
-
|
|
95
|
-
for (const t of tripsByDay) {
|
|
96
|
-
await calculatePartialTrip(device, startDate, endDate, data.route, t, traccarInstance)
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const stopsByDay = []
|
|
101
|
-
if (data.stops) {
|
|
102
|
-
const filteredStops = data.stops.filter(t => new Date(t.endTime) > startDate && new Date(t.startTime) < endDate)
|
|
103
|
-
stopsByDay.push(...filteredStops.map(t => { return { ...t } }))
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const routeByDay = data.route ? data.route.filter(p => (new Date(p.fixTime) > startDate && new Date(p.fixTime) < endDate)) : []
|
|
107
|
-
|
|
108
|
-
const refuelingPositionsByDay = data.refuelingPositions ? data.refuelingPositions.filter(p => (new Date(p.date) > startDate && new Date(p.date) < endDate)) : []
|
|
109
|
-
|
|
110
|
-
const zoneInOutDayData = data.zoneInOutData
|
|
111
|
-
? data.zoneInOutData.filter(z => (!z.inTime || (new Date(z.inTime.fixTime) < endDate)) &&
|
|
112
|
-
(!z.outTime || (new Date(z.outTime.fixTime) > startDate)))
|
|
113
|
-
: []
|
|
114
|
-
|
|
115
|
-
return { tripsByDay, stopsByDay, routeByDay, refuelingPositionsByDay, zoneInOutDayData }
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function isValidAvgSpeed (kms, startTime, endTime) {
|
|
119
|
-
const totalTime = new Date(endTime).getTime() - new Date(startTime).getTime()
|
|
120
|
-
const avgSpeed = (kms / 1000) / (totalTime / (1000 * 60 * 60))
|
|
121
|
-
return avgSpeed < 200
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function getKms (trips) {
|
|
125
|
-
const odometerKms = trips.length > 0 ? trips[trips.length - 1].endOdometer - trips[0].startOdometer : 0
|
|
126
|
-
return odometerKms > 0 && isValidAvgSpeed(odometerKms, trips[0].startTime, trips[trips.length - 1].endTime) ? odometerKms : trips.filter(t => t.distance > 0).reduce((a, b) => a + b.distance, 0)
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function isInsideTimetable (t, userData) {
|
|
130
|
-
return isInside(t.startTime, t.endTime, userData)
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function updateTrip (device, t, route) {
|
|
134
|
-
route = route.filter(p => p && p.attributes.ignition)
|
|
135
|
-
if (!route.length) { return }
|
|
136
|
-
const distance = calculateDistance(route, device ? device.attributes['report.ignoreOdometer'] : true) * 1000
|
|
137
|
-
t.distance = distance
|
|
138
|
-
t.duration = new Date(route[route.length - 1].fixTime).getTime() - new Date(route[0].fixTime).getTime()
|
|
139
|
-
t.maxSpeed = route.reduce((a, b) => Math.max(a, b.speed), 0)
|
|
140
|
-
t.averageSpeed = distance > 0 ? ((route.reduce((a, b) => a + b.speed, 0)) / route.length) : 0
|
|
141
|
-
t.startOdometer = device && !device.attributes['report.ignoreOdometer'] && route[0].attributes.odometer ? route[0].attributes.odometer : route[0].attributes.totalDistance
|
|
142
|
-
t.endOdometer = device && !device.attributes['report.ignoreOdometer'] && route[route.length - 1].attributes.odometer ? route[route.length - 1].attributes.odometer : route[route.length - 1].attributes.totalDistance
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function getUncompletedTrip (device, deviceRoute, deviceTrips) {
|
|
146
|
-
if (deviceRoute.length && deviceTrips.length && deviceRoute[deviceRoute.length - 1].attributes.ignition) {
|
|
147
|
-
const uncompletedTripRoute = deviceRoute.filter(p => p.attributes.ignition && new Date(p.fixTime).getTime() > new Date(deviceTrips[deviceTrips.length - 1].endTime).getTime())
|
|
148
|
-
if (uncompletedTripRoute.length) {
|
|
149
|
-
return calculateTrip(device, uncompletedTripRoute)
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function calculateTrip (device, route) {
|
|
155
|
-
console.log('route', route.length)
|
|
156
|
-
const startPos = route[0]
|
|
157
|
-
const endPos = route[route.length - 1]
|
|
158
|
-
|
|
159
|
-
return {
|
|
160
|
-
deviceId: device.id,
|
|
161
|
-
deviceName: device.name,
|
|
162
|
-
model: device.model,
|
|
163
|
-
distance: calculateDistance(route, device.attributes['report.ignoreOdometer']) * 1000,
|
|
164
|
-
averageSpeed: Math.round((route.map(p => p.speed).reduce((a, b) => a + b, 0)) / route.length),
|
|
165
|
-
maxSpeed: route.map(p => p.speed).reduce(function (a, b) { return Math.max(a, b) }),
|
|
166
|
-
spentFuel: 0,
|
|
167
|
-
startOdometer: startPos.attributes.odometer || startPos.attributes.totalDistance,
|
|
168
|
-
endOdometer: endPos.attributes.odometer || endPos.attributes.totalDistance,
|
|
169
|
-
startPositionId: startPos.id,
|
|
170
|
-
endPositionId: endPos.id,
|
|
171
|
-
startLat: startPos.latitude,
|
|
172
|
-
startLon: startPos.longitude,
|
|
173
|
-
startTime: startPos.fixTime,
|
|
174
|
-
startAddress: startPos.address,
|
|
175
|
-
endLat: endPos.latitude,
|
|
176
|
-
endLon: endPos.longitude,
|
|
177
|
-
endTime: endPos.fixTime,
|
|
178
|
-
endAddress: endPos.address,
|
|
179
|
-
endTimeIsOut: true,
|
|
180
|
-
duration: new Date(endPos.fixTime).getTime() - new Date(startPos.fixTime).getTime(),
|
|
181
|
-
driverUniqueId: null,
|
|
182
|
-
driverName: null
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
function getTripIdleTime (trip, idleEvents) {
|
|
187
|
-
const tripStartDate = new Date(trip.startTime)
|
|
188
|
-
const tripEndDate = new Date(trip.endTime)
|
|
189
|
-
const idleEventsInsideTrip = idleEvents.filter(i => tripStartDate < new Date(i.position.fixTime) && tripEndDate > new Date(i.position.fixTime))
|
|
190
|
-
return idleEventsInsideTrip.reduce((a, b) => a + b.idleTime, 0)
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
function calculateStopDuration (stop) {
|
|
194
|
-
const totalStopTime = new Date(stop.endTime) - new Date(stop.startTime)
|
|
195
|
-
if (totalStopTime < stop.idleTime) return 0
|
|
196
|
-
return totalStopTime - (stop.idleTime > 0 ? stop.idleTime : 0)
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const maxDistanceDiff = 10000
|
|
200
|
-
|
|
201
|
-
function shouldRecalculate (trip, route) {
|
|
202
|
-
if (route && route.length) {
|
|
203
|
-
if (!trip.distance) {
|
|
204
|
-
return true
|
|
205
|
-
}
|
|
206
|
-
if (route[0].protocol === 'osmand' && route[0].attributes.odometer) {
|
|
207
|
-
const positions = route.filter(p => p.deviceId === trip.deviceId &&
|
|
208
|
-
new Date(p.fixTime).getTime() >= new Date(trip.startTime).getTime() &&
|
|
209
|
-
new Date(p.fixTime).getTime() <= new Date(trip.endTime).getTime())
|
|
210
|
-
if (positions.length) {
|
|
211
|
-
const totalDistance = positions[positions.length - 1].attributes.totalDistance - positions[0].attributes.totalDistance
|
|
212
|
-
return trip.distance < (totalDistance - maxDistanceDiff)
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
return false
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function getTripTotalKms (trip, stop, route) {
|
|
220
|
-
// we need to add stop kms to ensure that the total kms for the day, calculated with the odometer difference, will be equal to the sum of kms of all trips
|
|
221
|
-
const stopKms = stop &&
|
|
222
|
-
!route.find(p => p.attributes.putAccumulators
|
|
223
|
-
|| p.protocol === 'startek') //fix ticket 2263
|
|
224
|
-
&& (stop.endOdometer - stop.startOdometer)
|
|
225
|
-
let distance = trip.distance + (stop && stopKms > 0 ? stopKms : 0)
|
|
226
|
-
if (shouldRecalculate(trip, route)) {
|
|
227
|
-
distance = 0
|
|
228
|
-
const positions = route.filter(p => p.deviceId === trip.deviceId &&
|
|
229
|
-
new Date(p.fixTime).getTime() >= new Date(trip.startTime).getTime() &&
|
|
230
|
-
new Date(p.fixTime).getTime() <= new Date(trip.endTime).getTime())
|
|
231
|
-
|
|
232
|
-
let current = null
|
|
233
|
-
for (const p of positions) {
|
|
234
|
-
if (current) {
|
|
235
|
-
distance += coordsDistance(parseFloat(current.longitude), parseFloat(current.latitude),
|
|
236
|
-
parseFloat(p.longitude), parseFloat(p.latitude))
|
|
237
|
-
}
|
|
238
|
-
current = p
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
return distance / 1000
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
function calculateMultiDayTrips (trips, route, tripsByDay, fromByDay, toByDay, devices) {
|
|
245
|
-
const startsOutside = trips.filter(t => (new Date(t.startTime) < fromByDay && new Date(t.endTime) > fromByDay))
|
|
246
|
-
if (startsOutside.length > 0) {
|
|
247
|
-
tripsByDay.push(calculateTrip(devices.find(d => d.id === startsOutside[0].deviceId),
|
|
248
|
-
route.filter(p => new Date(p.fixTime) >= fromByDay &&
|
|
249
|
-
new Date(p.fixTime) <= new Date(startsOutside[0].endTime))))
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
const endsOutside = trips.filter(t => (new Date(t.startTime) < toByDay && new Date(t.endTime) > toByDay))
|
|
253
|
-
if (endsOutside.length > 0) {
|
|
254
|
-
tripsByDay.push(calculateTrip(devices.find(d => d.id === endsOutside[0].deviceId),
|
|
255
|
-
route.filter(p => new Date(p.fixTime) >= new Date(endsOutside[0].startTime) &&
|
|
256
|
-
new Date(p.fixTime) <= toByDay)))
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
exports.isInsideTimetable = isInsideTimetable
|
|
261
|
-
exports.isPartialInsideTimetable = isPartialInsideTimetable
|
|
262
|
-
exports.getDataByDay = getDataByDay
|
|
263
|
-
exports.getKms = getKms
|
|
264
|
-
exports.calculatePartialTrip = calculatePartialTrip
|
|
265
|
-
exports.calculateTrip = calculateTrip
|
|
266
|
-
exports.getTripIdleTime = getTripIdleTime
|
|
267
|
-
exports.calculateStopDuration = calculateStopDuration
|
|
268
|
-
exports.getUncompletedTrip = getUncompletedTrip
|
|
269
|
-
exports.getTripTotalKms = getTripTotalKms
|
|
270
|
-
exports.calculateMultiDayTrips = calculateMultiDayTrips
|