fleetmap-reports 1.0.597 → 1.0.599

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/lang/enGB.js CHANGED
@@ -189,6 +189,7 @@ module.exports = {
189
189
  titleKmsReport: 'Kms Report',
190
190
  titleIdleReport: 'Idle Report',
191
191
  titleMachinesReport: 'Machines Report',
192
+ titleStopReport: 'Stop Report',
192
193
  from: 'From',
193
194
  to: 'to',
194
195
  headerStartAddress: 'Start address',
package/lang/esCL.js CHANGED
@@ -179,6 +179,7 @@ module.exports = {
179
179
  titleKmsReport: 'Informe de Kms',
180
180
  titleIdleReport: 'Informe de Ralenti',
181
181
  titleMachinesReport: 'Informe de Maquinas',
182
+ titleStopReport: 'Informe de Paragens',
182
183
  from: 'De',
183
184
  to: 'a',
184
185
  headerStartAddress: 'Lugar de início',
package/lang/frFR.js CHANGED
@@ -173,6 +173,7 @@ module.exports = {
173
173
  titleKmsReport: 'Rapport de km',
174
174
  titleIdleReport: 'Rapport ralenti',
175
175
  titleMachinesReport: 'Rapport sur les machines',
176
+ titleStopReport: 'Rapport de Arrêté',
176
177
  headerStartAddress: 'Adresse de départ',
177
178
  headerDistance: 'Distance',
178
179
  headerDrivingTime: 'Driving Time',
package/lang/ptBR.js CHANGED
@@ -181,6 +181,7 @@ module.exports = {
181
181
  titleKmsReport: 'Relatórios de Kms',
182
182
  titleIdleReport: 'Relatórios de Ralenti',
183
183
  titleMachinesReport: 'Relatório de Máquinas',
184
+ titleStopReport: 'Relatório de Paragens',
184
185
  from: 'De',
185
186
  to: 'a',
186
187
  headerStartAddress: 'Local de início',
package/lang/ptPT.js CHANGED
@@ -187,6 +187,7 @@ module.exports = {
187
187
  titleKmsReport: 'Relatórios de Kms',
188
188
  titleIdleReport: 'Relatórios de Ralenti',
189
189
  titleMachinesReport: 'Relatório de Máquinas',
190
+ titleStopReport: 'Relatório de Paragens',
190
191
  from: 'De',
191
192
  to: 'a',
192
193
  headerStartAddress: 'Local de início',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetmap-reports",
3
- "version": "1.0.597",
3
+ "version": "1.0.599",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
package/src/index.js CHANGED
@@ -172,5 +172,15 @@ function Reports (config, axios, cookieJar) {
172
172
  this.machinesReportToExcel = (userData, reportData) => {
173
173
  return require('./machines-report').exportMachinesReportToExcel(userData, reportData)
174
174
  }
175
+
176
+ this.stopReport = (from, to, userData) => {
177
+ return require('./stop-report').createStopReport(from, to, userData, this.traccar)
178
+ }
179
+ this.stopReportToPDF = (userData, reportData) => {
180
+ return require('./stop-report').exportStopReportToPDF(userData, reportData)
181
+ }
182
+ this.stopReportToExcel = (userData, reportData) => {
183
+ return require('./stop-report').exportStopReportToExcel(userData, reportData)
184
+ }
175
185
  }
176
186
  module.exports = Reports
@@ -0,0 +1,220 @@
1
+ const { devicesToProcess, deviceName } = require('./util/device')
2
+ const automaticReports = require('./automaticReports')
3
+ const traccarHelper = require('./util/traccar')
4
+ const { getNearestPOIs, insideGeofence } = require('./util/geofence')
5
+ const { getTranslations, convertToLocaleString, convertMS, convertToLocaleDateString, convertToLocaleTimeString } = require('./util/utils')
6
+ const jsPDF = require('jspdf')
7
+ const { headerFromUser, addTable } = require('./util/pdfDocument')
8
+ const { getStyle } = require('./reportStyle')
9
+ const { getUserPartner } = require('fleetmap-partners')
10
+
11
+ const fileName = 'StopReport'
12
+
13
+ async function createStopReport (from, to, userData, traccar) {
14
+ console.log('Create StopReport')
15
+ const reportData = []
16
+
17
+ const report = await createStopReportByDevice(from, to, userData, traccar)
18
+ reportData.push(report)
19
+
20
+ return reportData
21
+ }
22
+
23
+ async function createStopReportByDevice (from, to, userData, traccar) {
24
+ const devices = devicesToProcess(userData)
25
+
26
+ const allData = {
27
+ devices: []
28
+ }
29
+
30
+ const sliced = automaticReports.sliceArray(devices, 5)
31
+
32
+ let deviceCount = 0
33
+ for (const slice of sliced) {
34
+ const allInOne = await traccarHelper.getAllInOne(traccar, from, to, slice, false, false, true, false, deviceCount, devices.length)
35
+ const stopsData = allInOne.stops
36
+
37
+ console.log('Stops:' + stopsData.length)
38
+
39
+ if (stopsData.length > 0) {
40
+ allData.devices.push(...processDevices(from, to, slice, {
41
+ stops: stopsData
42
+ }, userData))
43
+ }
44
+ deviceCount = deviceCount + slice.length
45
+ }
46
+
47
+ return allData
48
+ }
49
+
50
+ function processDevices (from, to, devices, data, userData) {
51
+ const devicesResult = []
52
+
53
+ devices.forEach(d => {
54
+ const deviceStops = data.stops.filter(t => t.deviceId === d.id)
55
+
56
+ deviceStops.forEach(stop => {
57
+ const nearestPOIs = getNearestPOIs(stop.longitude, stop.latitude, userData.geofences)
58
+ if (nearestPOIs.length > 0) {
59
+ stop.endPOIName = nearestPOIs[0].p.name
60
+ } else {
61
+ const geofence = userData.geofences.filter(g => g && g.area.startsWith('POLYGON')).some(g =>
62
+ insideGeofence({ latitude: stop.latitude, longitude: stop.longitude }, g)
63
+ )
64
+ if (geofence) {
65
+ stop.endPOIName = geofence.name
66
+ }
67
+ }
68
+
69
+ stop.stopDuration = ((new Date(stop.endTime) - new Date(stop.startTime)) - stop.engineHours)
70
+ })
71
+
72
+ if (deviceStops.length > 0) {
73
+ const deviceData = {
74
+ device: d,
75
+ from,
76
+ to,
77
+ stops: deviceStops
78
+ }
79
+
80
+ devicesResult.push(deviceData)
81
+ }
82
+ })
83
+
84
+ return devicesResult
85
+ }
86
+
87
+ async function exportStopReportToPDF (userData, reportData) {
88
+ console.log('Export stop report to PDF')
89
+
90
+ const timezone = userData.user.attributes.timezone
91
+ const translations = getTranslations(userData)
92
+ const lang = userData.user.attributes.lang || (navigator && navigator.language)
93
+ const stopsData = userData.byDriver ? reportData.drivers : reportData.devices
94
+
95
+ const headers = [
96
+ translations.report.date,
97
+ translations.report.start,
98
+ translations.report.end,
99
+ translations.report.address,
100
+ translations.report.idleTime,
101
+ translations.report.stopTime
102
+ ]
103
+
104
+ if (stopsData) {
105
+ // eslint-disable-next-line new-cap
106
+ const doc = new jsPDF.jsPDF('l')
107
+ await headerFromUser(doc, translations.report.titleTripReport, userData.user)
108
+
109
+ stopsData.forEach(function (d, index) {
110
+ const data = []
111
+ const name = deviceName(d.device)
112
+ const group = userData.groups.find(g => d.device.groupId === g.id)
113
+
114
+ const space = index === 0 ? 8 : 0
115
+ if (index) {
116
+ doc.addPage()
117
+ }
118
+
119
+ doc.setFontSize(13)
120
+ doc.text(name, 20, space + 20)
121
+ doc.setFontSize(11)
122
+ doc.text(group ? translations.report.group + ': ' + group.name : '', 200, space + 20)
123
+ doc.text(convertToLocaleString(d.from, lang, timezone) + ' - ' + convertToLocaleString(d.to, lang, timezone), 20, space + 25)
124
+
125
+ d.stops.forEach(a => {
126
+ data.push([
127
+ getStopDate(userData.user, a),
128
+ getStopStart(userData.user, a),
129
+ getStopEnd(userData.user, a),
130
+ a.endPOIName || a.address,
131
+ convertMS(a.engineHours),
132
+ convertMS(a.stopDuration)
133
+ ])
134
+ })
135
+
136
+ const footValues = [
137
+ 'Total:' + d.stops.length,
138
+ '', '', '',
139
+ convertMS(d.stops.reduce((a, b) => a + b.engineHours, 0)),
140
+ convertMS(d.stops.reduce((a, b) => a + b.stopDuration, 0))]
141
+
142
+ const style = getStyle(getUserPartner(userData.user))
143
+ addTable(doc,
144
+ headers, data, footValues, style,
145
+ space + 40,
146
+ {
147
+ 4: { halign: 'right' },
148
+ 5: { halign: 'right' }
149
+ })
150
+ })
151
+ return doc
152
+ }
153
+ }
154
+
155
+ function exportStopReportToExcel (userData, reportData) {
156
+ console.log('Export stop report to Excel')
157
+
158
+ const translations = getTranslations(userData)
159
+
160
+ const settings = {
161
+ sheetName: translations.report.titleStopReport, // The name of the sheet
162
+ fileName // The name of the spreadsheet
163
+ }
164
+
165
+ const headers = [
166
+ { label: translations.report.date, value: 'date' },
167
+ { label: translations.report.start, value: 'start' },
168
+ { label: translations.report.end, value: 'end' },
169
+ { label: translations.report.address, value: 'address' },
170
+ { label: translations.report.idleTime, value: 'idleTime' },
171
+ { label: translations.report.stopTime, value: 'stopTime' }
172
+ ]
173
+
174
+ let data = []
175
+ if (reportData.devices) {
176
+ reportData.devices.forEach(d => {
177
+ data = data.concat([{}])
178
+ data = data.concat(d.stops.map(a => {
179
+ return {
180
+ name: a.deviceName,
181
+ date: getStopDate(userData.user, a),
182
+ start: getStopStart(userData.user, a),
183
+ end: getStopEnd(userData.user, a),
184
+ address: a.endPOIName || a.address,
185
+ idleTime: convertMS(a.engineHours),
186
+ stopTime: convertMS(a.stopDuration)
187
+ }
188
+ }))
189
+ // Totals
190
+ data = data.concat([{
191
+ name: d.stops.length,
192
+ idleTime: convertMS(d.stops.reduce((a, b) => a + b.engineHours, 0)),
193
+ stopTime: convertMS(d.stops.reduce((a, b) => a + b.stopDuration, 0))
194
+ }])
195
+ data = data.concat([{}])
196
+ })
197
+ console.log(data)
198
+ return {
199
+ headers,
200
+ data,
201
+ settings
202
+ }
203
+ }
204
+ }
205
+
206
+ function getStopDate (user, stop) {
207
+ return convertToLocaleDateString(stop.startTime, user.attributes.lang, user.attributes.timezone)
208
+ }
209
+
210
+ function getStopStart (user, stop) {
211
+ return convertToLocaleTimeString(stop.startTime, user.attributes.lang, user.attributes.timezone)
212
+ }
213
+
214
+ function getStopEnd (user, stop) {
215
+ return convertToLocaleTimeString(stop.endTime, user.attributes.lang, user.attributes.timezone)
216
+ }
217
+
218
+ exports.createStopReport = createStopReport
219
+ exports.exportStopReportToPDF = exportStopReportToPDF
220
+ exports.exportStopReportToExcel = exportStopReportToExcel
@@ -5,6 +5,7 @@ const utils = require('../util/utils')
5
5
 
6
6
  // eslint-disable-next-line no-undef
7
7
  describe('Test_Reports', function () {
8
+ this.timeout(5000000)
8
9
  it('converts to pdf', async () => {
9
10
  const report = await getReports()
10
11
  const userData = await report.getUserData()
@@ -7,10 +7,11 @@ const { headerFromUser, addTable } = require('./util/pdfDocument')
7
7
  const { getStyle } = require('./reportStyle')
8
8
  const traccarHelper = require('./util/traccar')
9
9
  const trips = require('./util/trips')
10
- const { isInsideTimetable, addNearestPOIs, isPartialInsideTimetable, calculateTrip, getTripIdleTime } = require('./util/trips')
11
- const { devicesToProcess } = require('./util/device')
10
+ const { isInsideTimetable, isPartialInsideTimetable, calculateTrip, getTripIdleTime } = require('./util/trips')
11
+ const { devicesToProcess, deviceName } = require('./util/device')
12
12
  const { getIdleEvents } = require('./util/route')
13
13
  const { reportByDriver } = require('./util/driver')
14
+ const { getNearestPOIs } = require('./util/geofence')
14
15
 
15
16
  const fileName = 'TripReport'
16
17
 
@@ -160,9 +161,14 @@ function processDevices (from, to, devices, data, userData, traccar) {
160
161
  const trips = deviceTrips.filter(t => userData.allWeek || !userData.weekDays || isInsideTimetable(t, userData) || isPartialInsideTimetable(t, userData, deviceRoute))
161
162
  const stops = data.stops.filter(s => s.deviceId === d.id)
162
163
 
163
- addNearestPOIs(trips, userData)
164
-
165
164
  trips.forEach(trip => {
165
+ trip.totalKms = trip.distance / 1000
166
+
167
+ const nearestPOIs = getNearestPOIs(trip.endLon, trip.endLat, userData.geofences)
168
+ if (nearestPOIs.length > 0) {
169
+ trip.endPOIName = nearestPOIs[0].p.name
170
+ }
171
+
166
172
  if ((deviceRoute[0].protocol === 'teltonika' && deviceRoute[0].attributes.fuel) ||
167
173
  automaticReports.deviceWithFuelInfo(d)) {
168
174
  trip.fuelConsumption = trip.spentFuel
@@ -172,8 +178,8 @@ function processDevices (from, to, devices, data, userData, traccar) {
172
178
  const stop = getStop(new Date(trip.startTime), stops)
173
179
 
174
180
  if (stop && !trip.endTimeIsOut) {
175
- trip.stopDuration = (new Date(stop.endTime) - new Date(stop.startTime))
176
- trip.stopEngineHours = trip.idleTime + stop.idleTime
181
+ trip.stopDuration = ((new Date(stop.endTime) - new Date(stop.startTime)) - stop.engineHours)
182
+ trip.stopEngineHours = trip.idleTime + stop.engineHours
177
183
  } else {
178
184
  trip.stopDuration = 0
179
185
  trip.stopEngineHours = 0
@@ -220,12 +226,17 @@ function processDrivers (from, to, userData, data) {
220
226
  const idleEvents = getIdleEvents(data.route, d)
221
227
 
222
228
  trips.forEach(function (trip, i) {
229
+ trip.totalKms = trip.distance / 1000
230
+
231
+ const nearestPOIs = getNearestPOIs(trip.endLon, trip.endLat, userData.geofences)
232
+ if (nearestPOIs.length > 0) {
233
+ trip.endPOIName = nearestPOIs[0].p.name
234
+ }
235
+
223
236
  trip.stopEngineHours = getTripIdleTime(trip, idleEvents)
224
237
  trip.stopDuration = i !== trips.length - 1 ? (new Date(trips[i + 1].startTime) - new Date(trip.endTime)) : 0
225
238
  })
226
239
 
227
- addNearestPOIs(trips, userData)
228
-
229
240
  if (trips.length > 0) {
230
241
  const driverData = {
231
242
  driver: d,
@@ -461,10 +472,6 @@ function exportTripReportToExcel (userData, reportData) {
461
472
  }
462
473
  }
463
474
 
464
- function deviceName (device) {
465
- return device.name + (device.attributes.license_plate ? ', ' + device.attributes.license_plate : '') + (device.model ? ', ' + device.model : '')
466
- }
467
-
468
475
  function getTripDate (user, trip) {
469
476
  return convertToLocaleDateString(trip.startTime, user.attributes.lang, user.attributes.timezone)
470
477
  }
@@ -7,4 +7,8 @@ function devicesToProcess (userData) {
7
7
  return devices
8
8
  }
9
9
 
10
+ exports.deviceName = function deviceName (device) {
11
+ return device.name + (device.attributes.license_plate ? ', ' + device.attributes.license_plate : '') + (device.model ? ', ' + device.model : '')
12
+ }
13
+
10
14
  exports.devicesToProcess = devicesToProcess
@@ -1,5 +1,6 @@
1
1
  const turf = require('@turf/helpers')
2
2
  const inside = require('@turf/boolean-point-in-polygon')
3
+ const { coordsDistance } = require('./utils')
3
4
 
4
5
  exports.insideGeofence = function insideGeofence (position, geofence) {
5
6
  const coords = geofence.area.slice(9, geofence.area.length - 2).split(',')
@@ -11,3 +12,17 @@ exports.insideGeofence = function insideGeofence (position, geofence) {
11
12
 
12
13
  return inside.default(pt, poly)
13
14
  }
15
+
16
+ exports.getNearestPOIs = function getNearestPOIs (long, lat, geofences) {
17
+ const distance = geofences
18
+ .filter(g => g && g.area.startsWith('CIRCLE'))
19
+ .map(g => {
20
+ const str = g.area.substring('CIRCLE ('.length, g.area.indexOf(','))
21
+ const coord = str.trim().split(' ')
22
+ return {
23
+ p: g,
24
+ distance: Math.round(coordsDistance(parseFloat(coord[1]), parseFloat(coord[0]), long, lat))
25
+ }
26
+ })
27
+ return distance.filter(a => a.distance < 100).sort((a, b) => (a.distance > b.distance) ? 1 : -1)
28
+ }
@@ -48,6 +48,12 @@ function addTable (doc, headers, data, footValues, style, startY, columnStyles =
48
48
 
49
49
  },
50
50
  didDrawCell: (data) => {
51
+ data.table.head.forEach((footRow) => {
52
+ const keys = Object.keys(columnStyles)
53
+ keys.forEach(a => {
54
+ footRow.cells[a].styles.halign = 'right'
55
+ })
56
+ })
51
57
  data.table.foot.forEach((footRow) => {
52
58
  const keys = Object.keys(columnStyles)
53
59
  keys.forEach(a => {
package/src/util/trips.js CHANGED
@@ -4,27 +4,6 @@ const { isInside } = require('./timetable')
4
4
  const minDistance = 0
5
5
  const minAvgSpeed = 0
6
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
-
28
7
  function checkTripsKms (traccarInstance, from, to, devices, data) {
29
8
  console.log('checkTripsKms')
30
9
  const trips = data.trips.filter(t => t.distance === minDistance && t.averageSpeed > minAvgSpeed)
@@ -165,6 +144,5 @@ function getTripIdleTime (trip, idleEvents) {
165
144
  exports.checkTripsKms = checkTripsKms
166
145
  exports.isInsideTimetable = isInsideTimetable
167
146
  exports.isPartialInsideTimetable = isPartialInsideTimetable
168
- exports.addNearestPOIs = addNearestPOIs
169
147
  exports.calculateTrip = calculateTrip
170
148
  exports.getTripIdleTime = getTripIdleTime