fleetmap-reports 1.0.679 → 1.0.681

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetmap-reports",
3
- "version": "1.0.679",
3
+ "version": "1.0.681",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -1,6 +1,7 @@
1
1
  const traccar = require('../util/traccar')
2
2
  const { getIdleEvents } = require('../util/route')
3
- const { insideGeofence, getNearestPOIs } = require('../util/geofence')
3
+ const { getNearestPOIs, checkGeofenceIn } = require('../util/geofence')
4
+ const { convertToFeature, convertPositionToFeature } = require('../util/utils')
4
5
 
5
6
  function calculateLastStopTime (stopTime, to, time) {
6
7
  return stopTime + (to.getTime() - new Date(time).getTime())
@@ -16,10 +17,12 @@ async function createActivityReport (from, to, userData, traccarInstance) {
16
17
 
17
18
  const notAuthGeofenceIds = (await traccarInstance.geofences.geofencesGet(undefined, undefined, undefined, Number(process.env.AFRIQUIA_NOT_AUTH_GROUP_ID), undefined, undefined).then(r => r.data)).map(g => g.id)
18
19
  unauthorizedGeofences.push(...(userData.geofences.filter(g => notAuthGeofenceIds.includes(g.id))))
20
+ const unauthorizedGeofencesFeatures = unauthorizedGeofences.map(g => convertToFeature(g))
19
21
  console.log('unauthorizedGeofences', unauthorizedGeofences)
20
22
 
21
23
  const authGeofenceIds = (await traccarInstance.geofences.geofencesGet(undefined, undefined, undefined, Number(process.env.AFRIQUIA_AUTH_GROUP_ID), undefined, undefined).then(r => r.data)).map(g => g.id)
22
24
  authorizedGeofences.push(...(userData.geofences.filter(g => authGeofenceIds.includes(g.id))))
25
+ const authorizedGeofencesFeatures = authorizedGeofences.map(g => convertToFeature(g))
23
26
  console.log('authorizedGeofences', authorizedGeofences)
24
27
 
25
28
  const allInOne = await traccar.getAllInOne(traccarInstance, from, to, userData.devices, true, true, true, false)
@@ -37,12 +40,19 @@ async function createActivityReport (from, to, userData, traccarInstance) {
37
40
  let authorizedStopsTime = 0
38
41
 
39
42
  stops.forEach(s => {
40
- const unauthorized = unauthorizedGeofences.find(g => insideGeofence({ latitude: s.latitude, longitude: s.longitude }, g))
43
+ const point = convertPositionToFeature({ latitude: s.latitude, longitude: s.longitude })
44
+ const unauthorized = unauthorizedGeofencesFeatures.find(g => {
45
+ const geofenceFeature = unauthorizedGeofencesFeatures.find(gF => gF.properties.geofence.id === g.id)
46
+ return checkGeofenceIn(point, geofenceFeature)
47
+ })
41
48
 
42
49
  if (unauthorized) {
43
50
  unauthorizedStops = unauthorizedStops + 1
44
51
  } else {
45
- const authorized = authorizedGeofences.find(g => insideGeofence({ latitude: s.latitude, longitude: s.longitude }, g))
52
+ const authorized = authorizedGeofences.find(g => {
53
+ const geofenceFeature = authorizedGeofencesFeatures.find(gF => gF.properties.geofence.id === g.id)
54
+ return checkGeofenceIn(point, geofenceFeature)
55
+ })
46
56
 
47
57
  if (authorized) {
48
58
  authorizedStops = authorizedStops + 1
@@ -1,6 +1,9 @@
1
1
  const turf = require('@turf/helpers')
2
2
  const inside = require('@turf/boolean-point-in-polygon')
3
3
  const { coordsDistance } = require('./utils')
4
+ const booleanPointInPolygon = require('@turf/boolean-point-in-polygon')
5
+ const distance = require('@turf/distance')
6
+ const pointToLineDistance = require('@turf/point-to-line-distance')
4
7
 
5
8
  exports.insideGeofence = function insideGeofence (position, geofence) {
6
9
  const coords = geofence.area.slice(9, geofence.area.length - 2).split(',')
@@ -32,3 +35,14 @@ exports.loadGroupsData = async function loadGroupsData (userData, traccarInstanc
32
35
  g.geofenceIds = (await traccarInstance.geofences.geofencesGet(undefined, undefined, undefined, g.id, undefined, undefined).then(r => r.data)).map(g => g.id)
33
36
  }
34
37
  }
38
+
39
+ exports.checkGeofenceIn = function checkGeofenceIn (p, g) {
40
+ switch (g.geometry.type) {
41
+ case 'Polygon':
42
+ return booleanPointInPolygon.default(p, g)
43
+ case 'Point':
44
+ return distance.default(p, g, { units: 'meters' }) >= g.properties.distance
45
+ case 'LineString':
46
+ return pointToLineDistance.default(p, g, { units: 'meters' }) > (g.properties.geofence.attributes.polylineDistance || 25)
47
+ }
48
+ }
@@ -11,12 +11,10 @@ const { headerFromUser, addTable } = require('./util/pdfDocument')
11
11
  const { getStyle } = require('./reportStyle')
12
12
  const { getUserPartner } = require('fleetmap-partners')
13
13
  const { devicesToProcess } = require('./util/device')
14
- const pointToLineDistance = require('@turf/point-to-line-distance')
15
- const booleanPointInPolygon = require('@turf/boolean-point-in-polygon')
16
- const distance = require('@turf/distance')
17
14
  const axios = require('axios')
18
15
  const { processServerSide } = require('./util')
19
16
  const { filterPositions } = require('./util/route')
17
+ const { checkGeofenceIn } = require('./util/geofence')
20
18
  const sliceSize = 100
21
19
  const deviceChunk = 5
22
20
  const fileName = 'ZoneReport'
@@ -97,91 +95,91 @@ async function processDevices (from, to, devices, userData, data) {
97
95
 
98
96
  const zoneInOutData = analyseAlerts(alerts, deviceRoute, userData, from, to).filter(d => !userData.onlyWithStop || d.stopped)
99
97
 
100
- if (zoneInOutData.length > 0) {
101
- if (userData.groupByDay) {
102
- const dates = getDates(from, to)
98
+ if (userData.groupByDay) {
99
+ const dates = getDates(from, to)
103
100
 
104
- const geofencesData = []
105
- for (const geofence of userData.geofences) {
106
- const filteredByGeofence = zoneInOutData.filter(d => d.geofenceId === geofence.id)
101
+ const geofencesData = []
102
+ for (const geofence of userData.geofences) {
103
+ const filteredByGeofence = zoneInOutData.filter(d => d.geofenceId === geofence.id)
107
104
 
108
- const dataByDay = []
109
- for (const date of dates) {
110
- const fromByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0)
111
- const toByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59)
105
+ const dataByDay = []
106
+ for (const date of dates) {
107
+ const fromByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0)
108
+ const toByDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59)
112
109
 
113
- const dayRoute = deviceRoute.filter(p => new Date(p.fixTime) >= fromByDay && new Date(p.fixTime) < toByDay)
114
- const zoneInOutDayData = filteredByGeofence.filter(z => (!z.inTime || (new Date(z.inTime.fixTime) < toByDay)) &&
110
+ const dayRoute = deviceRoute.filter(p => new Date(p.fixTime) >= fromByDay && new Date(p.fixTime) < toByDay)
111
+ const zoneInOutDayData = filteredByGeofence.filter(z => (!z.inTime || (new Date(z.inTime.fixTime) < toByDay)) &&
115
112
  (!z.outTime || (new Date(z.outTime.fixTime) > fromByDay)))
116
113
 
117
- const firstIn = zoneInOutDayData.find(z => z.inTime && new Date(z.inTime.fixTime) > fromByDay)
118
- const lastOut = zoneInOutDayData.slice().reverse().find(z => z.outTime && new Date(z.outTime.fixTime) < toByDay)
114
+ const firstIn = zoneInOutDayData.find(z => z.inTime && new Date(z.inTime.fixTime) > fromByDay)
115
+ const lastOut = zoneInOutDayData.slice().reverse().find(z => z.outTime && new Date(z.outTime.fixTime) < toByDay)
119
116
 
120
- let timeIn = zoneInOutDayData.length ? zoneInOutDayData.reduce((a, b) => a + (b.totalInTime || 0), 0) : 0
117
+ let timeIn = zoneInOutDayData.length ? zoneInOutDayData.reduce((a, b) => a + (b.totalInTime || 0), 0) : 0
121
118
 
122
- let distanceIn = zoneInOutDayData.length && dayRoute.length ? zoneInOutDayData.reduce((a, b) => a + (b.distanceIn || 0), 0) : 0
123
- let distanceOut = 0
124
- if (zoneInOutDayData.length) {
125
- distanceOut = zoneInOutDayData.reduce((a, b) => a + (b.distanceOut || 0), 0) - zoneInOutDayData[zoneInOutDayData.length - 1].distanceOut
126
- } else {
127
- distanceOut = calculateDistance(deviceRoute.filter(p => new Date(p.fixTime) >= fromByDay && new Date(p.fixTime) < toByDay))
128
- }
119
+ let distanceIn = zoneInOutDayData.length && dayRoute.length ? zoneInOutDayData.reduce((a, b) => a + (b.distanceIn || 0), 0) : 0
120
+ let distanceOut = 0
121
+ if (zoneInOutDayData.length) {
122
+ distanceOut = zoneInOutDayData.reduce((a, b) => a + (b.distanceOut || 0), 0) - zoneInOutDayData[zoneInOutDayData.length - 1].distanceOut
123
+ } else {
124
+ distanceOut = calculateDistance(deviceRoute.filter(p => new Date(p.fixTime) >= fromByDay && new Date(p.fixTime) < toByDay))
125
+ }
129
126
 
130
- if (zoneInOutDayData.length) {
131
- // Check if the first entry starts only on the day before
132
- if (!zoneInOutDayData[0].inTime || new Date(zoneInOutDayData[0].inTime.fixTime) < fromByDay) {
133
- const inTime = zoneInOutDayData[0].inTime ? new Date(zoneInOutDayData[0].inTime.fixTime) : from
134
- timeIn = timeIn - (fromByDay.getTime() - inTime.getTime())
135
- const routeDayBefore = deviceRoute.filter(p => (!zoneInOutDayData[0].inTime || new Date(p.fixTime) >= new Date(zoneInOutDayData[0].inTime.fixTime)) &&
127
+ if (zoneInOutDayData.length) {
128
+ // Check if the first entry starts only on the day before
129
+ if (!zoneInOutDayData[0].inTime || new Date(zoneInOutDayData[0].inTime.fixTime) < fromByDay) {
130
+ const inTime = zoneInOutDayData[0].inTime ? new Date(zoneInOutDayData[0].inTime.fixTime) : from
131
+ timeIn = timeIn - (fromByDay.getTime() - inTime.getTime())
132
+ const routeDayBefore = deviceRoute.filter(p => (!zoneInOutDayData[0].inTime || new Date(p.fixTime) >= new Date(zoneInOutDayData[0].inTime.fixTime)) &&
136
133
  new Date(p.fixTime) < fromByDay)
137
- distanceIn = distanceIn - calculateDistance(routeDayBefore)
138
- } else {
139
- // Add distanceOut before the first entry
140
- const routeOut = deviceRoute.filter(p =>
141
- new Date(p.fixTime).getTime() < new Date(zoneInOutDayData[0].inTime.fixTime).getTime() &&
134
+ distanceIn = distanceIn - calculateDistance(routeDayBefore)
135
+ } else {
136
+ // Add distanceOut before the first entry
137
+ const routeOut = deviceRoute.filter(p =>
138
+ new Date(p.fixTime).getTime() < new Date(zoneInOutDayData[0].inTime.fixTime).getTime() &&
142
139
  new Date(p.fixTime).getTime() >= fromByDay.getTime()
143
- )
144
- distanceOut = distanceOut + calculateDistance(routeOut)
145
- }
146
-
147
- // Check if the last entry ends only on the next day
148
- if (!zoneInOutDayData[zoneInOutDayData.length - 1].outTime || new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) > toByDay) {
149
- const outTime = zoneInOutDayData[zoneInOutDayData.length - 1].outTime ? new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) : to
150
- timeIn = timeIn - (outTime.getTime() - (toByDay.getTime() + 1000))
151
- const routeDayAfter = deviceRoute.filter(p => new Date(p.fixTime) <= outTime && new Date(p.fixTime) > toByDay)
152
- distanceIn = distanceIn - calculateDistance(routeDayAfter)
153
- } else {
154
- const routeOut = deviceRoute.filter(p =>
155
- new Date(p.fixTime) >= new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime).getTime() &&
140
+ )
141
+ distanceOut = distanceOut + calculateDistance(routeOut)
142
+ }
143
+
144
+ // Check if the last entry ends only on the next day
145
+ if (!zoneInOutDayData[zoneInOutDayData.length - 1].outTime || new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) > toByDay) {
146
+ const outTime = zoneInOutDayData[zoneInOutDayData.length - 1].outTime ? new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime) : to
147
+ timeIn = timeIn - (outTime.getTime() - (toByDay.getTime() + 1000))
148
+ const routeDayAfter = deviceRoute.filter(p => new Date(p.fixTime) <= outTime && new Date(p.fixTime) > toByDay)
149
+ distanceIn = distanceIn - calculateDistance(routeDayAfter)
150
+ } else {
151
+ const routeOut = deviceRoute.filter(p =>
152
+ new Date(p.fixTime) >= new Date(zoneInOutDayData[zoneInOutDayData.length - 1].outTime.fixTime).getTime() &&
156
153
  new Date(p.fixTime) < toByDay.getTime())
157
- distanceOut = distanceOut + calculateDistance(routeOut)
158
- }
154
+ distanceOut = distanceOut + calculateDistance(routeOut)
159
155
  }
160
- dataByDay.push({
161
- date,
162
- firstIn: firstIn ? firstIn.inTime.fixTime : undefined,
163
- lastOut: lastOut ? lastOut.outTime.fixTime : undefined,
164
- distanceIn: distanceIn > 0 ? distanceIn : 0,
165
- distanceOut,
166
- totalInTime: timeIn,
167
- totalOutTime: (24 * 60 * 60 * 1000) - timeIn
168
- })
169
156
  }
170
-
171
- geofencesData.push({
172
- geofenceName: geofence.name,
173
- days: dataByDay
157
+ dataByDay.push({
158
+ date,
159
+ firstIn: firstIn ? firstIn.inTime.fixTime : undefined,
160
+ lastOut: lastOut ? lastOut.outTime.fixTime : undefined,
161
+ distanceIn: distanceIn > 0 ? distanceIn : 0,
162
+ distanceOut,
163
+ totalInTime: timeIn,
164
+ totalOutTime: (24 * 60 * 60 * 1000) - timeIn
174
165
  })
175
166
  }
176
167
 
177
- devicesResult.push({
178
- device: d,
179
- from,
180
- to,
181
- groupByDay: true,
182
- geofences: geofencesData
168
+ geofencesData.push({
169
+ geofenceName: geofence.name,
170
+ days: dataByDay
183
171
  })
184
- } else {
172
+ }
173
+
174
+ devicesResult.push({
175
+ device: d,
176
+ from,
177
+ to,
178
+ groupByDay: true,
179
+ geofences: geofencesData
180
+ })
181
+ } else {
182
+ if (zoneInOutData.length > 0) {
185
183
  devicesResult.push({
186
184
  device: d,
187
185
  from,
@@ -281,6 +279,15 @@ function analyseAlerts (alerts, deviceRoute, userData, from, to) {
281
279
  }
282
280
  }
283
281
 
282
+ if (!zoneInOutData.length && userData.groupByDay) {
283
+ const geofenceIn = alerts.find(a => a.type === 'geofenceIn')
284
+ zoneInOutData.push({
285
+ distanceIn: geofenceIn ? calculateDistance(deviceRoute) : 0,
286
+ distanceOut: !geofenceIn ? calculateDistance(deviceRoute) : 0,
287
+ totalTime: to.getTime() - from.getTime()
288
+ })
289
+ }
290
+
284
291
  return zoneInOutData
285
292
  }
286
293
 
@@ -292,17 +299,6 @@ function checkGeofenceExit (p1, p2, g) {
292
299
  return checkGeofenceEnter(p2, p1, g)
293
300
  }
294
301
 
295
- function checkGeofenceIn (p, g) {
296
- switch (g.geometry.type) {
297
- case 'Polygon':
298
- return booleanPointInPolygon.default(p, g)
299
- case 'Point':
300
- return distance.default(p, g, { units: 'meters' }) >= g.properties.distance
301
- case 'LineString':
302
- return pointToLineDistance.default(p, g, { units: 'meters' }) > (g.properties.geofence.attributes.polylineDistance || 25)
303
- }
304
- }
305
-
306
302
  function getInAndOutEvents (devices, route, userData) {
307
303
  const events = []
308
304
  devices.forEach(d => {