fleetmap-reports 1.0.264 → 1.0.265

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.
@@ -1,13 +1,17 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <project version="4">
3
3
  <component name="ChangeListManager">
4
- <list default="true" id="eb665c86-c893-4333-bd2a-721dc27980b9" name="Changes" comment="activity report by driver grouped by day">
4
+ <list default="true" id="eb665c86-c893-4333-bd2a-721dc27980b9" name="Changes" comment="fix kms-report by driver and fix activity report with time period">
5
5
  <change beforePath="$PROJECT_DIR$/package-lock.json" beforeDir="false" afterPath="$PROJECT_DIR$/package-lock.json" afterDir="false" />
6
6
  <change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
7
7
  <change beforePath="$PROJECT_DIR$/src/activity-report.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/activity-report.js" afterDir="false" />
8
8
  <change beforePath="$PROJECT_DIR$/src/index.test.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/index.test.js" afterDir="false" />
9
9
  <change beforePath="$PROJECT_DIR$/src/kms-report.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/kms-report.js" afterDir="false" />
10
+ <change beforePath="$PROJECT_DIR$/src/speeding-report.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/speeding-report.js" afterDir="false" />
10
11
  <change beforePath="$PROJECT_DIR$/src/trip-report.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/trip-report.js" afterDir="false" />
12
+ <change beforePath="$PROJECT_DIR$/src/util/driver.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/util/driver.js" afterDir="false" />
13
+ <change beforePath="$PROJECT_DIR$/src/util/traccar.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/util/traccar.js" afterDir="false" />
14
+ <change beforePath="$PROJECT_DIR$/src/util/trips.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/util/trips.js" afterDir="false" />
11
15
  </list>
12
16
  <option name="SHOW_DIALOG" value="false" />
13
17
  <option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -222,7 +226,9 @@
222
226
  <workItem from="1640866782794" duration="123000" />
223
227
  <workItem from="1640866964393" duration="1022000" />
224
228
  <workItem from="1640870147277" duration="8236000" />
225
- <workItem from="1641321068227" duration="13602000" />
229
+ <workItem from="1641321068227" duration="14805000" />
230
+ <workItem from="1641387675790" duration="32947000" />
231
+ <workItem from="1641509412324" duration="41000" />
226
232
  </task>
227
233
  <task id="LOCAL-00001" summary="Fix getStyle">
228
234
  <created>1636983717385</created>
@@ -371,7 +377,14 @@
371
377
  <option name="project" value="LOCAL" />
372
378
  <updated>1640878664617</updated>
373
379
  </task>
374
- <option name="localTasksCounter" value="22" />
380
+ <task id="LOCAL-00022" summary="fix kms-report by driver and fix activity report with time period">
381
+ <created>1641348028566</created>
382
+ <option name="number" value="00022" />
383
+ <option name="presentableId" value="LOCAL-00022" />
384
+ <option name="project" value="LOCAL" />
385
+ <updated>1641348028566</updated>
386
+ </task>
387
+ <option name="localTasksCounter" value="23" />
375
388
  <servers />
376
389
  </component>
377
390
  <component name="TypeScriptGeneratedFilesManager">
@@ -410,6 +423,7 @@
410
423
  <MESSAGE value="calculate avg speed" />
411
424
  <MESSAGE value="fix activity report by driver" />
412
425
  <MESSAGE value="activity report by driver grouped by day" />
413
- <option name="LAST_COMMIT_MESSAGE" value="activity report by driver grouped by day" />
426
+ <MESSAGE value="fix kms-report by driver and fix activity report with time period" />
427
+ <option name="LAST_COMMIT_MESSAGE" value="fix kms-report by driver and fix activity report with time period" />
414
428
  </component>
415
429
  </project>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetmap-reports",
3
- "version": "1.0.264",
3
+ "version": "1.0.265",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -94,7 +94,7 @@ async function createActivityReportByDevice(from, to){
94
94
  if(userData.groupByDay) {
95
95
  const dates = getDates(from, to)
96
96
  for(const date of dates){
97
- if(userData.allWeek){
97
+ if(userData.allWeek || !userData.weekDays){
98
98
  const fromByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0)
99
99
  const toByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59)
100
100
 
@@ -160,11 +160,11 @@ async function createActivityReportByDevice(from, to){
160
160
  }
161
161
 
162
162
  async function createActivityReportByDriver(from, to){
163
- const deviceIds = await drivers.devicesByDriver(traccarInstance, from, to, userData.drivers, userData.devices)
164
- console.log(deviceIds)
163
+ const devices = await drivers.devicesByDriver(traccarInstance, from, to, userData.drivers, userData.devices)
164
+
165
165
  let tripsData = []
166
- if(deviceIds.length > 0) {
167
- tripsData = await traccar.getTrips(traccarInstance, from, to, deviceIds)
166
+ if(devices.length > 0) {
167
+ tripsData = await traccar.getTrips(traccarInstance, from, to, devices)
168
168
  }
169
169
 
170
170
  const allData = {
@@ -187,9 +187,6 @@ function processDevices(devices, data, kmsReport) {
187
187
  if (summary) {
188
188
  summary.forEach(s => {
189
189
  const deviceKms = kmsReport[0].devices.filter(r => r.device.id === d.id)
190
-
191
- console.log(deviceKms)
192
-
193
190
  s.convertedSpentFuel = automaticReports.calculateSpentFuel(s.spentFuel, d)
194
191
  s.distance = deviceKms.length ? (userData.groupByDay ? deviceKms[0].days.find(d => d.date.getTime() === s.date.getTime()).kms : deviceKms[0].summary.distance) : 0
195
192
  })
package/src/kms-report.js CHANGED
@@ -27,7 +27,7 @@ async function createKmsReportByDevice(from, to) {
27
27
 
28
28
  devicesToProcess.sort((a, b) => (a.name > b.name) ? 1 : -1)
29
29
  const route = userData.allWeek ? [] : await traccar.getRoute(traccarInstance, from, to, devicesToProcess)
30
- const tripsData = await traccar.getTrips(traccarInstance, from, to, devicesToProcess.map(d => d.id))
30
+ const tripsData = await traccar.getTrips(traccarInstance, from, to, devicesToProcess)
31
31
 
32
32
  console.log('trips:' + tripsData.length)
33
33
 
@@ -40,22 +40,16 @@ async function createKmsReportByDevice(from, to) {
40
40
  }
41
41
 
42
42
  async function createKmsReportByDriver(from, to) {
43
- const deviceIds = await drivers.devicesByDriver(traccarInstance, from, to, userData.drivers, userData.devices)
44
- console.log(deviceIds.length)
43
+ const devices = await drivers.devicesByDriver(traccarInstance, from, to, userData.drivers, userData.devices)
44
+ console.log(devices.length)
45
45
 
46
- let tripsData = []
47
- if(deviceIds.length > 0) {
48
- const response = await traccarInstance.reports.reportsTripsGet(from, to, deviceIds)
49
- tripsData = response.data
46
+ if(!devices.length) {
47
+ //empty report
48
+ return { drivers: [] }
50
49
  }
51
50
 
52
- const allData = {
53
- drivers: []
54
- }
55
-
56
- allData.drivers = processDrivers(from, to, userData.drivers, tripsData)
57
-
58
- return allData
51
+ const tripsData = await traccar.getTrips(traccarInstance, from, to, devices)
52
+ return { drivers: processDrivers(from, to, userData.drivers, tripsData) }
59
53
  }
60
54
 
61
55
  async function createKmsReportByGroup(from, to) {
@@ -75,7 +69,7 @@ function processDrivers(from, to, drivers, data) {
75
69
  driverData.days = []
76
70
  const dates = getDates(from, to)
77
71
  for(const date of dates){
78
- if(userData.allWeek){
72
+ if(userData.allWeek || !userData.weekDays){
79
73
  const fromByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0)
80
74
  const toByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59)
81
75
 
@@ -16,109 +16,135 @@ let traccarInstance
16
16
  let userData
17
17
 
18
18
  const fileName = 'SpeedingReport'
19
+ const eventTypes = ['deviceOverspeed']
19
20
 
20
21
  async function createSpeedingReport(from, to, reportUserData, traccar) {
22
+ console.log('Create SpeedingReport')
21
23
  traccarInstance = traccar
22
24
  userData = reportUserData
23
- console.log('createSpeedingReport', from, to, userData, traccar)
24
25
  const reportData = []
25
26
 
26
- if(userData.byDriver){
27
+ if (userData.byDriver) {
28
+ console.log("ByDriver")
27
29
  const allData = await createSpeedingReportByDriver(from, to)
28
30
  reportData.push(allData)
29
31
  }
30
- else if(userData.byGroup){
32
+ else if (userData.byGroup) {
31
33
  console.log("ByGroup")
32
- for (const g of userData.groups) {
33
- const devices = userData.devices.filter(d => d.groupId === g.id)
34
- console.log(g.name + ' devices:' + devices.length)
35
- if(devices.length > 0) {
36
- const groupData = {
37
- devices: [],
38
- group: g,
39
- xpert: devices.filter(d => d.attributes.xpert).length > 0
40
- }
34
+ const allData = await createSpeedingReportByGroup(from, to)
35
+ reportData.push(...allData)
36
+ } else {
37
+ console.log("ByDevice")
38
+ const allData = await createSpeedingReportByDevice(from, to, userData.devices)
39
+ reportData.push(allData)
40
+ }
41
41
 
42
- const eventTypes = ['deviceOverspeed']
43
- const events = await traccar.getEvents(traccarInstance, from, to, devices, eventTypes)
44
- const routes = userData.useVehicleSpeedLimit ? [] : await traccar.getRoute(traccarInstance, from, to, devices)
42
+ return reportData
43
+ }
45
44
 
46
- devices.sort((a, b) => (a.name > b.name) ? 1 : -1)
45
+ async function createSpeedingReportByGroup(from, to){
46
+ const reportData = []
47
+ for (const g of userData.groups) {
48
+ const devices = userData.devices.filter(d => d.groupId === g.id)
49
+ console.log(g.name + ' devices:' + devices.length)
50
+ if(devices.length > 0) {
51
+ const groupData = {
52
+ devices: [],
53
+ group: g,
54
+ xpert: devices.filter(d => d.attributes.xpert).length > 0
55
+ }
47
56
 
48
- if (events.length > 0) {
49
- groupData.devices = await processDevices(from, to, devices, events, routes)
50
- reportData.push(groupData)
51
- }
57
+ const events = await traccar.getEvents(traccarInstance, from, to, devices, eventTypes)
58
+ const routes = await traccar.getRoute(traccarInstance, from, to, devices)
59
+
60
+ devices.sort((a, b) => (a.name > b.name) ? 1 : -1)
61
+
62
+ if (events.length > 0) {
63
+ groupData.devices = await processDevices(from, to, devices, events, routes)
64
+ reportData.push(groupData)
52
65
  }
53
66
  }
54
-
55
- const withoutGroupData = await createSpeedingReportByDevice(from, to)
56
- reportData.push(withoutGroupData)
57
- } else {
58
- const allData = await createSpeedingReportByDevice(from, to)
59
- reportData.push(allData)
60
67
  }
61
68
 
69
+ const groupIds = userData.groups.map(g => g.id)
70
+ const withoutGroupDevices = userData.devices.filter(d => !groupIds.includes(d.groupId))
71
+
72
+ const withoutGroupData = await createSpeedingReportByDevice(from, to, withoutGroupDevices)
73
+ reportData.push(withoutGroupData)
74
+
62
75
  return reportData
63
76
  }
64
77
 
65
- async function createSpeedingReportByDevice(from, to) {
66
- const groupIds = userData.groups.map(g => g.id)
67
- const withoutGroupDevices = userData.byGroup ? userData.devices.filter(d => !groupIds.includes(d.groupId)) : userData.devices
68
-
69
- withoutGroupDevices.sort((a, b) => (a.name > b.name) ? 1 : -1)
78
+ async function createSpeedingReportByDevice(from, to, devices) {
79
+ devices.sort((a, b) => (a.name > b.name) ? 1 : -1)
70
80
 
71
- const eventTypes = ['deviceOverspeed']
72
- const events = await traccar.getEvents(traccarInstance, from, to, withoutGroupDevices, eventTypes)
73
- const routes = userData.useVehicleSpeedLimit ? [] : await traccar.getRoute(traccarInstance, from, to, withoutGroupDevices)
81
+ const routes = await traccar.getRoute(traccarInstance, from, to, devices)
82
+ const events = []
83
+ if(!userData.useVehicleSpeedLimit && userData.customSpeed){
84
+ events.push(...await getCustomSpeedLimitEvents(devices, routes))
85
+ } else {
86
+ events.push(...await traccar.getEvents(traccarInstance, from, to, devices, eventTypes))
87
+ }
74
88
 
75
- const allData = { devices: [] }
89
+ if(userData.roadSpeedLimits){
90
+ events.push(...await getHereEvents(devices, routes))
91
+ }
76
92
 
77
- if(events.length > 0 || userData.roadSpeedLimits) {
78
- allData.devices = await processDevices(from, to, withoutGroupDevices, events, routes)
79
- allData.xpert = withoutGroupDevices.filter(d => d && d.attributes && d.attributes.xpert).length > 0
93
+ if(!events.length) {
94
+ //empty report
95
+ return { devices: [] }
80
96
  }
81
97
 
82
- return allData
98
+ return {
99
+ devices: await processDevices(from, to, devices, events, routes),
100
+ xpert: devices.filter(d => d && d.attributes && d.attributes.xpert).length > 0
101
+ }
83
102
  }
84
103
 
85
104
  async function createSpeedingReportByDriver(from, to) {
86
- const deviceIds = await drivers.devicesByDriver(traccarInstance, from, to, userData.drivers, userData.devices)
87
- console.log('Devices with driver',deviceIds.length)
105
+ const devices = await drivers.devicesByDriver(traccarInstance, from, to, userData.drivers, userData.devices)
106
+ console.log('Devices with driver',devices.length)
107
+
108
+ if(!devices.length) {
109
+ //empty report
110
+ return { drivers: [] }
111
+ }
88
112
 
89
- let eventsData = []
90
- if(deviceIds.length > 0) {
91
- const devices = userData.devices.filter(d => deviceIds.includes(d.id))
92
- eventsData = await traccar.getEvents(traccarInstance, from, to, devices,['deviceOverspeed'])
113
+ const routes = await traccar.getRoute(traccarInstance, from, to, devices)
114
+ const events = []
115
+ if(!userData.useVehicleSpeedLimit && userData.customSpeed){
116
+ events.push(...await getCustomSpeedLimitEvents(devices, routes))
117
+ } else {
118
+ events.push(...await traccar.getEvents(traccarInstance, from, to, devices, eventTypes))
93
119
  }
94
120
 
95
- const allData = {
96
- drivers: []
121
+ if(userData.roadSpeedLimits){
122
+ events.push(...await getHereEvents(devices, routes))
97
123
  }
98
- console.log(eventsData.length)
99
124
 
100
- await getEventsPosition(from , to, userData.devices, eventsData)
101
- allData.drivers = await processDrivers(from, to, eventsData)
102
- console.log(allData.drivers.length)
103
- return allData
125
+ if(!events.length) {
126
+ //empty report
127
+ return { drivers: [] }
128
+ }
129
+
130
+ return {drivers: await processDrivers(from, to, events, routes)}
104
131
  }
105
132
 
106
- async function processDrivers(from, to, data) {
107
- console.log(data)
133
+ async function processDrivers(from, to, events, routes) {
108
134
  const driversResult = []
109
- const alertsWithPosition = data.filter(a => a.position)
110
-
111
- userData.drivers.forEach(d => {
112
- const alerts = alertsWithPosition.filter(e => e.position.attributes.driverUniqueId === d.uniqueId)
113
135
 
114
- if (alerts.length > 0) {
136
+ await findEventsPosition(from, to, userData.devices, events, routes)
115
137
 
138
+ userData.drivers.forEach(d => {
139
+ const driverEvents = events.filter(e => e.position && e.position.attributes.driverUniqueId === d.uniqueId)
140
+ if (driverEvents.length > 0) {
141
+ driverEvents.sort((a, b) => a.positionId - b.positionId)
116
142
  driversResult.push({
117
143
  driver: d,
118
144
  from: from,
119
145
  to: to,
120
- alerts: alerts,
121
- maxSpeed: alerts.reduce((a, b) => {
146
+ alerts: driverEvents,
147
+ maxSpeed: driverEvents.reduce((a, b) => {
122
148
  return a > b.attributes.maxSpeed ? a : b.attributes.maxSpeed
123
149
  }, 0),
124
150
  })
@@ -130,117 +156,38 @@ async function processDrivers(from, to, data) {
130
156
 
131
157
  async function processDevices(from, to, devices, events, routes) {
132
158
  const devicesResult = []
159
+ await findEventsPosition(from, to, devices, events, routes)
133
160
 
134
- if(userData.useVehicleSpeedLimit) {
135
- await getEventsPosition(from, to, devices, events)
136
-
137
- console.log(events)
138
-
139
- for (const d of devices) {
140
- const deviceEvents = events.filter(t => t.deviceId === d.id)
141
-
142
- if (deviceEvents.length > 0) {
143
- const alertsWithPosition = deviceEvents.filter(a => a.position).sort((a, b) => a.positionId - b.positionId)
144
- devicesResult.push({
145
- device: d,
146
- from: from,
147
- to: to,
148
- alerts: alertsWithPosition,
149
- maxSpeed: alertsWithPosition.reduce((a, b) => {
150
- return a > (b && b.attributes && b.attributes.maxSpeed) ? a : (b && b.attributes && b.attributes.maxSpeed)
151
- }, 0),
152
- })
153
- }
154
- }
155
- } else {
156
- for (const d of devices) {
157
- const positions = routes.filter(t => t.deviceId === d.id)
158
- const maxSpeed = userData.customSpeed / 1.85200
159
-
160
- const alerts = []
161
- for(let pIndex = 0; pIndex < positions.length ; pIndex++){
162
- const position = positions[pIndex]
163
- if(position.speed > maxSpeed){
164
- const alert = {
165
- position: position,
166
- attributes: {
167
- speedLimit: maxSpeed,
168
- speed: position.speed
169
- }
170
- }
171
-
172
- pIndex = calculateEventData(positions, pIndex, alert)
173
-
174
- alerts.push(alert)
175
- }
176
- }
177
- if(alerts.length > 0){
178
- devicesResult.push({
179
- device: d,
180
- from: from,
181
- to: to,
182
- alerts: alerts,
183
- maxSpeed: alerts.reduce((a, b) => {
184
- return a > (b && b.attributes && b.attributes.maxSpeed) ? a : (b && b.attributes && b.attributes.maxSpeed)
185
- }, 0),
186
- })
187
- }
161
+ for (const d of devices) {
162
+ const deviceEvents = events.filter(e => e.deviceId === d.id && e.position)
163
+ if (deviceEvents.length > 0) {
164
+ deviceEvents.sort((a, b) => a.positionId - b.positionId)
165
+ devicesResult.push({
166
+ device: d,
167
+ from: from,
168
+ to: to,
169
+ alerts: deviceEvents,
170
+ maxSpeed: deviceEvents.reduce((a, b) => {
171
+ return a > (b && b.attributes && b.attributes.maxSpeed) ? a : (b && b.attributes && b.attributes.maxSpeed)
172
+ }, 0),
173
+ })
188
174
  }
189
175
  }
190
176
 
191
177
  return devicesResult
192
178
  }
193
179
 
194
- async function getEventsPosition(from, to, devices, events){
195
-
196
- const deviceIds = [...new Set(events.map(e => e.deviceId))]
197
- const routeData = await traccar.getRoute(traccarInstance, from, to, deviceIds.map(id => { return { id: id } } ))
198
-
199
- console.log(events)
200
-
180
+ async function findEventsPosition(from, to, devices, events, routes){
201
181
  for (const d of devices) {
202
- let alerts = events.filter(t => t.deviceId === d.id)
203
-
204
- if (alerts.length > 0 || userData.roadSpeedLimits) {
205
- const positions = routeData.filter(p => p.deviceId === d.id)
206
-
207
- if (userData.roadSpeedLimits && positions.length) {
208
- try {
209
- const results = await here.routeMatch(positions)
210
- const hereAlerts = results.map(r => {
211
- const position = positions.find(p => new Date(p.fixTime).getTime() === r.timestamp)
212
- return {
213
- ...r,
214
- roadSpeedLimit: r.speedLimit,
215
- deviceId: d.id,
216
- position,
217
- positionId: position && position.id,
218
- attributes: {speedLimit: r.speedLimit, speed: r.currentSpeedKmh / 1.85200}
219
- }
220
- })
221
- console.log('hereAlerts', hereAlerts)
222
- const reduced = hereAlerts.reduce((acc, cur, idx, src) => {
223
- if (idx === 1) {
224
- return [cur]
225
- }
226
- if (cur.timestamp - src[idx - 1].timestamp > 300000 || cur.roadSpeedLimit !== src[idx - 1].roadSpeedLimit) {
227
- return acc.concat(cur)
228
- }
229
- return acc
230
- })
231
- events.push(...reduced)
232
- alerts = events.filter(t => t.deviceId === d.id)
233
- } catch (e) {
234
- console.error(e)
235
- }
236
- }
182
+ let deviceEvents = events.filter(e => e.deviceId === d.id && e.positionId)
183
+ if (deviceEvents.length > 0) {
184
+ deviceEvents.sort((a,b) => a.positionId-b.positionId )
185
+ const positions = routes.filter(p => p.deviceId === d.id)
237
186
 
238
- for (const a of alerts) {
187
+ for (const a of deviceEvents) {
239
188
  let pIndex = positions.findIndex(p => p.id === a.positionId)
240
189
  if (pIndex > 0) {
241
- a.position = positions[pIndex]
242
190
  let geofence = null
243
-
244
191
  if (a.geofenceId) {
245
192
  geofence = userData.geofences.find(g => g.id === a.geofenceId)
246
193
  if (geofence) {
@@ -248,44 +195,87 @@ async function getEventsPosition(from, to, devices, events){
248
195
  }
249
196
  }
250
197
 
251
- let endEventPosition = a.position
252
- let maxSpeed = a.position.speed
253
- let dist = 0
254
- while (pIndex + 1 < positions.length) {
255
- pIndex++
256
-
257
- dist += distance(point([endEventPosition.longitude, endEventPosition.latitude]),
258
- point([positions[pIndex].longitude, positions[pIndex].latitude]))
259
- endEventPosition = positions[pIndex]
260
- if (endEventPosition.speed <= a.attributes.speedLimit || (geofence && isOutsideGeofence(geofence, endEventPosition))) {
261
- a.eventTime = new Date(endEventPosition.fixTime) - new Date(a.position.fixTime)
262
- a.attributes.maxSpeed = maxSpeed
263
- a.distance = dist
264
- break
265
- } else {
266
- if (maxSpeed < endEventPosition.speed) {
267
- maxSpeed = endEventPosition.speed
268
- }
269
- }
270
- }
198
+ if(!a.position) {
199
+ a.position = positions[pIndex]
200
+ pIndex = calculateEventData(positions, pIndex, a, d, geofence)
271
201
 
272
- if (a.position.attributes.driverUniqueId) {
273
- const driver = userData.drivers.find(d => d.uniqueId === a.position.attributes.driverUniqueId)
274
- a.driver = driver && driver.name
202
+ positions.slice(pIndex)
275
203
  }
204
+ }
205
+ }
206
+ }
207
+ }
208
+ }
276
209
 
277
- a.deviceName = d.name
210
+ async function getCustomSpeedLimitEvents(devices, routes){
211
+ console.log('calculate custom speed limit events')
212
+ const events = []
213
+ const maxSpeed = userData.customSpeed / 1.85200
278
214
 
279
- positions.slice(pIndex)
215
+ for (const d of devices) {
216
+ const positions = routes.filter(p => p.deviceId === d.id)
217
+ let eventIsActive = false
218
+
219
+ for (const position of positions) {
220
+ if(position.speed > maxSpeed && !eventIsActive){
221
+ const event = {
222
+ positionId: position && position.id,
223
+ deviceId: d.id,
224
+ attributes: {
225
+ speedLimit: maxSpeed,
226
+ speed: position.speed
227
+ }
280
228
  }
229
+ events.push(event)
230
+ eventIsActive = true
231
+ } else if (position.speed <= maxSpeed) {
232
+ eventIsActive = false
281
233
  }
282
234
  }
283
235
  }
236
+
237
+ return events
284
238
  }
285
239
 
286
- function calculateEventData(positions, pIndex, a, geofence){
287
- let endEventPosition = a.position
288
- let maxSpeed = a.position.speed
240
+ async function getHereEvents(devices, routes){
241
+ console.log('calculate custom speed limit events')
242
+ const events = []
243
+ for (const d of devices) {
244
+ const positions = routes.filter(p => p.deviceId === d.id)
245
+ try {
246
+ const results = await here.routeMatch(positions)
247
+ const hereAlerts = results.map(r => {
248
+ const position = positions.find(p => new Date(p.fixTime).getTime() === r.timestamp)
249
+ return {
250
+ ...r,
251
+ roadSpeedLimit: r.speedLimit,
252
+ deviceId: d.id,
253
+ position,
254
+ positionId: position && position.id,
255
+ attributes: {speedLimit: r.speedLimit, speed: r.currentSpeedKmh / 1.85200}
256
+ }
257
+ })
258
+ console.log('hereAlerts', hereAlerts)
259
+ const reduced = hereAlerts.reduce((acc, cur, idx, src) => {
260
+ if (idx === 1) {
261
+ return [cur]
262
+ }
263
+ if (cur.timestamp - src[idx - 1].timestamp > 300000 || cur.roadSpeedLimit !== src[idx - 1].roadSpeedLimit) {
264
+ return acc.concat(cur)
265
+ }
266
+ return acc
267
+ })
268
+ events.push(...reduced)
269
+ } catch (e) {
270
+ //console.error(e)
271
+ }
272
+ }
273
+ return events
274
+ }
275
+
276
+ function calculateEventData(positions, pIndex, alert, device, geofence){
277
+ let endEventPosition = alert.position
278
+ let maxSpeed = alert.position.speed
289
279
  let dist = 0
290
280
  while (pIndex + 1 < positions.length) {
291
281
  pIndex++
@@ -293,10 +283,10 @@ function calculateEventData(positions, pIndex, a, geofence){
293
283
  dist += distance(point([endEventPosition.longitude, endEventPosition.latitude]),
294
284
  point([positions[pIndex].longitude, positions[pIndex].latitude]))
295
285
  endEventPosition = positions[pIndex]
296
- if (endEventPosition.speed <= a.attributes.speedLimit || (geofence && isOutsideGeofence(geofence, endEventPosition))) {
297
- a.eventTime = new Date(endEventPosition.fixTime) - new Date(a.position.fixTime)
298
- a.attributes.maxSpeed = maxSpeed
299
- a.distance = dist
286
+ if (endEventPosition.speed <= alert.attributes.speedLimit || (geofence && isOutsideGeofence(geofence, endEventPosition))) {
287
+ alert.eventTime = new Date(endEventPosition.fixTime) - new Date(alert.position.fixTime)
288
+ alert.attributes.maxSpeed = maxSpeed
289
+ alert.distance = dist
300
290
  break
301
291
  } else {
302
292
  if (maxSpeed < endEventPosition.speed) {
@@ -305,6 +295,14 @@ function calculateEventData(positions, pIndex, a, geofence){
305
295
  }
306
296
  }
307
297
 
298
+
299
+ if (alert.position.attributes.driverUniqueId) {
300
+ const driver = userData.drivers.find(d => d.uniqueId === alert.position.attributes.driverUniqueId)
301
+ alert.driver = driver && driver.name
302
+ }
303
+
304
+ alert.deviceName = device.name
305
+
308
306
  return pIndex
309
307
  }
310
308
 
@@ -3,13 +3,13 @@ const messages = require('../lang')
3
3
  const jsPDF = require('jspdf')
4
4
  const {convertMS, convertToLocaleString, convertToLocaleDateString, convertToLocaleTimeString} = require("./util/utils")
5
5
  require('jspdf-autotable')
6
- const {coordsDistance} = require("./util/utils")
7
6
  const drivers = require("./util/driver")
8
7
  const {getUserPartner} = require("fleetmap-partners")
9
8
  const {headerFromUser, addTable} = require("./util/pdfDocument")
10
9
  const {getStyle} = require("./reportStyle")
11
10
  const traccar = require("./util/traccar")
12
11
  const trips = require("./util/trips");
12
+ const {isInsideTimetable, addNearestPOIs} = require("./util/trips");
13
13
 
14
14
 
15
15
  let traccarInstance
@@ -23,26 +23,26 @@ async function createTripReport(from, to, reportUserData, traccar) {
23
23
  traccarInstance = traccar
24
24
  const reportData = []
25
25
 
26
- if(userData.byDriver){
27
- const allData = await createTripReportByDriver(from, to)
28
- reportData.push(allData)
26
+ if (userData.byDriver) {
27
+ console.log("ByDriver")
28
+ const report = await createTripReportByDriver(from, to)
29
+ reportData.push(report)
29
30
  }
30
- else if(userData.byGroup){
31
+ else if (userData.byGroup) {
31
32
  console.log("ByGroup")
32
33
  const allData = await createTripReportByGroup(from, to)
33
34
  reportData.push(...allData)
35
+ } else {
36
+ console.log("ByDevice")
37
+ const report = await createTripReportByDevice(from, to)
38
+ reportData.push(report)
34
39
  }
35
40
 
36
- const groupIds = userData.groups.map(g => g.id)
37
- const withoutGroupDevices = userData.byGroup ? userData.devices.filter(d => !groupIds.includes(d.groupId)) : userData.devices
38
-
39
- const allData = await createTripReportByDevice(from, to, withoutGroupDevices)
40
- reportData.push(allData)
41
-
42
41
  return reportData
43
42
  }
44
43
 
45
- async function createTripReportByDevice(from, to, devices) {
44
+ async function createTripReportByDevice(from, to) {
45
+ const devices = userData.devices
46
46
  const allData = {
47
47
  devices: [],
48
48
  xpert: devices.filter(d => d.attributes.xpert).length > 0
@@ -51,7 +51,7 @@ async function createTripReportByDevice(from, to, devices) {
51
51
  devices.sort((a, b) => (a.name > b.name) ? 1 : -1)
52
52
 
53
53
  const devicesToSlice = devices.slice()
54
- const data = await traccar.getTrips(traccarInstance, from, to, devicesToSlice.map(d => d.id))
54
+ const data = await traccar.getTrips(traccarInstance, from, to, devicesToSlice)
55
55
  const stopsData = await traccar.getStops(traccarInstance, from, to, devicesToSlice)
56
56
 
57
57
  console.log('Trips:' + data.length)
@@ -77,90 +77,75 @@ async function createTripReportByGroup(from, to) {
77
77
  }
78
78
 
79
79
  const response = await traccarInstance.reports.reportsTripsGet(from, to, null, [g.id])
80
- const data = response.data
80
+ const tripsData = response.data
81
81
 
82
82
  const stopsResponse = await traccarInstance.reports.reportsStopsGet(from, to, null, [g.id])
83
83
  const stopsData = stopsResponse.data
84
84
 
85
85
  devices.sort((a, b) => (a.name > b.name) ? 1 : -1)
86
86
 
87
- if (data.length > 0) {
88
-
89
- console.log('Trips:' + data.length)
90
- groupData.devices = processDevices(from, to, devices, data, stopsData, userData)
87
+ if (tripsData.length > 0) {
88
+ console.log('Trips:' + tripsData.length)
89
+ groupData.devices = processDevices(from, to, devices, tripsData, stopsData, userData)
91
90
 
92
91
  reportData.push(groupData)
93
92
  }
94
93
  }
95
94
  }
95
+
96
+ const groupIds = userData.groups.map(g => g.id)
97
+ const withoutGroupDevices = userData.devices.filter(d => !groupIds.includes(d.groupId))
98
+
99
+ const allData = await createTripReportByDevice(from, to, withoutGroupDevices)
100
+ reportData.push(allData)
101
+
96
102
  return reportData
97
103
  }
98
104
 
99
105
  async function createTripReportByDriver(from, to){
100
- const deviceIds = await drivers.devicesByDriver(traccarInstance, from, to, userData.drivers, userData.devices)
101
- console.log(deviceIds.length)
106
+ const devices = await drivers.devicesByDriver(traccarInstance, from, to, userData.drivers, userData.devices)
107
+ console.log(devices.length)
102
108
 
103
- let tripsData = []
104
- if(deviceIds.length > 0) {
105
- const response = await traccarInstance.reports.reportsTripsGet(from, to, deviceIds)
106
- tripsData = response.data
109
+ if(!devices.length){
110
+ //Empty report
111
+ return { drivers:[] }
107
112
  }
108
113
 
109
- const allData = {
110
- drivers: []
111
- }
112
-
113
- allData.drivers = processDrivers(from, to, userData.drivers, tripsData)
114
+ const tripsData = await traccar.getTrips(traccarInstance, from, to, devices)
114
115
 
115
- return allData
116
+ return { drivers: processDrivers(from, to, userData.drivers, tripsData)}
116
117
  }
117
118
 
118
119
  function processDevices(from, to, devices, data, stopsData) {
119
120
  const devicesResult = []
120
121
 
121
122
  devices.forEach(d => {
122
- const trips = data.filter(t => t.deviceId === d.id && (userData.allWeek || isInsideTimetable(t, userData)))
123
+ const trips = data.filter(t => t.deviceId === d.id
124
+ && (userData.allWeek || !userData.weekDays || isInsideTimetable(t, userData)))
123
125
  const stops = stopsData.filter(s => s.deviceId === d.id)
124
126
 
125
- trips.forEach(t => {
126
- t.totalKms = t.distance / 1000
127
+ addNearestPOIs(trips, userData)
128
+
129
+ trips.forEach(trip => {
127
130
  if (automaticReports.deviceWithFuelInfo(d)) {
128
- t.fuelConsumption = Math.round((t.spentFuel * d.attributes.fuel_tank_capacity) / 100)
129
- t.avgFuelConsumption = t.totalKms > 0 ? Math.round(t.fuelConsumption * 100 / t.totalKms) : 0
131
+ trip.fuelConsumption = Math.round((t.spentFuel * d.attributes.fuel_tank_capacity) / 100)
132
+ trip.avgFuelConsumption = t.totalKms > 0 ? Math.round(t.fuelConsumption * 100 / t.totalKms) : 0
130
133
  } else {
131
- t.fuelConsumption = '-'
132
- t.avgFuelConsumption = '-'
134
+ trip.fuelConsumption = '-'
135
+ trip.avgFuelConsumption = '-'
133
136
  }
134
137
 
135
- const distance = userData.geofences
136
- .filter(g => g && g.area.startsWith('CIRCLE'))
137
- .map(g => {
138
- const str = g.area.substring('CIRCLE ('.length, g.area.indexOf(','))
139
- const coord = str.trim().split(' ')
140
- return {
141
- p: g,
142
- distance: Math.round(coordsDistance(parseFloat(coord[1]), parseFloat(coord[0]), t.endLon, t.endLat))
143
- }
144
- })
145
- const nearestPOIs = distance.filter(a => a.distance < 100).sort((a, b) => (a.distance > b.distance) ? 1 : -1)
146
- if (nearestPOIs.length > 0) {
147
- t.endPOIName = nearestPOIs[0].p.name
138
+ const stop = getStop(new Date(trip.startTime), stops)
139
+ if (stop) {
140
+ trip.stopDuration = (new Date(stop.endTime) - new Date(stop.startTime))
141
+ trip.stopEngineHours = stop.engineHours
142
+ } else {
143
+ trip.stopDuration = 0
144
+ trip.stopEngineHours = 0
148
145
  }
149
146
  })
150
147
 
151
148
  if (trips.length > 0) {
152
- trips.forEach(trip => {
153
- const stop = getStop(new Date(trip.startTime), stops)
154
-
155
- if (stop) {
156
- trip.stopDuration = (new Date(stop.endTime) - new Date(stop.startTime))
157
- trip.stopEngineHours = stop.engineHours
158
- } else {
159
- trip.stopDuration = 0
160
- trip.stopEngineHours = 0
161
- }
162
- })
163
-
164
149
  const deviceData = {
165
150
  device: d,
166
151
  from: from,
@@ -188,11 +173,12 @@ function processDrivers(from, to, drivers, data) {
188
173
  console.log(data)
189
174
  const driversResult = []
190
175
  drivers.forEach(d => {
191
- const trips = data.filter(t => t.driverUniqueId === d.uniqueId)
176
+ const trips = data.filter(t => t.driverUniqueId === d.uniqueId
177
+ && (userData.allWeek || !userData.weekDays || isInsideTimetable(t, userData)))
192
178
 
193
- trips.forEach(t => {
194
- t.totalKms = t.distance / 1000
195
- })
179
+ trips.sort((a,b)=>new Date(a.startTime).getTime()-new Date(b.startTime).getTime())
180
+
181
+ addNearestPOIs(trips, userData)
196
182
 
197
183
  if (trips.length > 0) {
198
184
  const driverData = {
@@ -201,14 +187,13 @@ function processDrivers(from, to, drivers, data) {
201
187
  to: to,
202
188
  totalDuration: trips.reduce((a, b) => a + b.duration, 0),
203
189
  totalDistance: trips.reduce((a, b) => a + b.distance, 0),
204
- maxSpeed: trips.reduce((a, b) => {
205
- return a > b.maxSpeed ? a : b.maxSpeed
206
- }, 0),
190
+ maxSpeed: trips.reduce((a, b) => { return a > b.maxSpeed ? a : b.maxSpeed }, 0),
207
191
  trips: trips,
208
192
  }
209
193
  driversResult.push(driverData)
210
194
  }
211
195
  })
196
+ console.log(driversResult)
212
197
 
213
198
  return driversResult
214
199
  }
@@ -453,35 +438,6 @@ function getStop(tripEndDate, stops){
453
438
  return null
454
439
  }
455
440
 
456
- function isInsideTimetable(t, userData){
457
- const tripStart = new Date(t.startTime)
458
- const tripEnd = new Date(t.endTime)
459
-
460
- if((tripStart.getDay() === 0 && userData.weekDays.sunday) ||
461
- (tripStart.getDay() === 1 && userData.weekDays.monday) ||
462
- (tripStart.getDay() === 2 && userData.weekDays.tuesday) ||
463
- (tripStart.getDay() === 3 && userData.weekDays.wednesday) ||
464
- (tripStart.getDay() === 4 && userData.weekDays.thursday) ||
465
- (tripStart.getDay() === 5 && userData.weekDays.friday) ||
466
- (tripStart.getDay() === 6 && userData.weekDays.saturday)) {
467
-
468
- const startDate = new Date(new Date(tripStart).toISOString().split('T')[0] + ' '+userData.dayHours.startTime)
469
- const endDate = new Date(new Date(tripStart).toISOString().split('T')[0] + ' '+userData.dayHours.endTime)
470
-
471
- console.log(tripStart, startDate, endDate)
472
-
473
- //Trips inside time period
474
- if(startDate.getTime() < endDate.getTime()) {
475
- return tripStart.getTime() > startDate.getTime() && tripEnd.getTime() < endDate.getTime()
476
- } else {
477
- return (tripStart.getTime() < endDate.getTime() && tripEnd.getTime() < endDate.getTime()) ||
478
- (tripStart.getTime() > startDate.getTime())
479
- }
480
- }
481
-
482
- return false
483
- }
484
-
485
441
  exports.createTripReport = createTripReport;
486
442
  exports.exportTripReportToPDF = exportTripReportToPDF;
487
443
  exports.exportTripReportToExcel = exportTripReportToExcel;
@@ -9,10 +9,9 @@ async function devicesByDriver(traccarInstance, from, to, drivers, devices){
9
9
  return e.attributes.driverUniqueId === d.uniqueId
10
10
  })
11
11
 
12
- deviceIds.push(events.map(e => e.deviceId))
12
+ deviceIds.push(...events.map(e => e.deviceId))
13
13
  }
14
-
15
- return [...new Set(deviceIds.flat())]
14
+ return devices.filter(d => deviceIds.includes(d.id))
16
15
  }
17
16
 
18
17
  exports.devicesByDriver = devicesByDriver
@@ -14,12 +14,12 @@ async function getRoute(traccar, from, to, devices){
14
14
  return result.map(r => r.data).flat()
15
15
  }
16
16
 
17
- async function getTrips(traccar, from, to, deviceIds){
18
- const devicesToSlice = deviceIds.slice()
17
+ async function getTrips(traccar, from, to, devices){
18
+ const devicesToSlice = devices.slice()
19
19
  const arrayOfArrays = automaticReports.sliceArray(devicesToSlice)
20
20
  let requests = []
21
21
  for (const a of arrayOfArrays) {
22
- const promise = traccar.reports.reportsTripsGet(from, to, a)
22
+ const promise = traccar.reports.reportsTripsGet(from, to, a.map(d => d.id))
23
23
  requests = requests.concat(promise)
24
24
  }
25
25
 
package/src/util/trips.js CHANGED
@@ -1,8 +1,30 @@
1
1
  const traccar = require("./traccar");
2
+ const {coordsDistance} = require("./utils");
2
3
 
3
4
  const minDistance = 0
4
5
  const minAvgSpeed = 0
5
6
 
7
+ function addNearestPOIs(trips, userData){
8
+ trips.forEach(t => {
9
+ t.totalKms = t.distance / 1000
10
+
11
+ const distance = userData.geofences
12
+ .filter(g => g && g.area.startsWith('CIRCLE'))
13
+ .map(g => {
14
+ const str = g.area.substring('CIRCLE ('.length, g.area.indexOf(','))
15
+ const coord = str.trim().split(' ')
16
+ return {
17
+ p: g,
18
+ distance: Math.round(coordsDistance(parseFloat(coord[1]), parseFloat(coord[0]), t.endLon, t.endLat))
19
+ }
20
+ })
21
+ const nearestPOIs = distance.filter(a => a.distance < 100).sort((a, b) => (a.distance > b.distance) ? 1 : -1)
22
+ if (nearestPOIs.length > 0) {
23
+ t.endPOIName = nearestPOIs[0].p.name
24
+ }
25
+ })
26
+ }
27
+
6
28
  async function checkTripsKms(traccarInstance, from, to, routeData, tripsData, devices) {
7
29
  console.log('checkTripsKms')
8
30
  const trips = tripsData.filter(t => t.distance === minDistance && t.averageSpeed > minAvgSpeed)
@@ -20,4 +42,35 @@ async function checkTripsKms(traccarInstance, from, to, routeData, tripsData, de
20
42
  }
21
43
  }
22
44
 
45
+ function isInsideTimetable(t, userData){
46
+ const tripStart = new Date(t.startTime)
47
+ const tripEnd = new Date(t.endTime)
48
+
49
+ if((tripStart.getDay() === 0 && userData.weekDays.sunday) ||
50
+ (tripStart.getDay() === 1 && userData.weekDays.monday) ||
51
+ (tripStart.getDay() === 2 && userData.weekDays.tuesday) ||
52
+ (tripStart.getDay() === 3 && userData.weekDays.wednesday) ||
53
+ (tripStart.getDay() === 4 && userData.weekDays.thursday) ||
54
+ (tripStart.getDay() === 5 && userData.weekDays.friday) ||
55
+ (tripStart.getDay() === 6 && userData.weekDays.saturday)) {
56
+
57
+ const startDate = new Date(new Date(tripStart).toISOString().split('T')[0] + ' '+userData.dayHours.startTime)
58
+ const endDate = new Date(new Date(tripStart).toISOString().split('T')[0] + ' '+userData.dayHours.endTime)
59
+
60
+ console.log(tripStart, startDate, endDate)
61
+
62
+ //Trips inside time period
63
+ if(startDate.getTime() < endDate.getTime()) {
64
+ return tripStart.getTime() > startDate.getTime() && tripEnd.getTime() < endDate.getTime()
65
+ } else {
66
+ return (tripStart.getTime() < endDate.getTime() && tripEnd.getTime() < endDate.getTime()) ||
67
+ (tripStart.getTime() > startDate.getTime())
68
+ }
69
+ }
70
+
71
+ return false
72
+ }
73
+
23
74
  exports.checkTripsKms = checkTripsKms
75
+ exports.isInsideTimetable = isInsideTimetable
76
+ exports.addNearestPOIs = addNearestPOIs