fleetmap-reports 2.0.358 → 2.0.360

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.
Files changed (82) hide show
  1. package/package.json +1 -1
  2. package/src/partnerReports/driverranking-report.js +39 -7
  3. package/src/util/utils.js +3 -0
  4. package/.claude/worktrees/eager-stonebraker-c08ac7/.eslintrc.js +0 -15
  5. package/.claude/worktrees/eager-stonebraker-c08ac7/lang/enGB.js +0 -309
  6. package/.claude/worktrees/eager-stonebraker-c08ac7/lang/esCL.js +0 -297
  7. package/.claude/worktrees/eager-stonebraker-c08ac7/lang/frFR.json +0 -324
  8. package/.claude/worktrees/eager-stonebraker-c08ac7/lang/index.js +0 -35
  9. package/.claude/worktrees/eager-stonebraker-c08ac7/lang/ptBR.js +0 -301
  10. package/.claude/worktrees/eager-stonebraker-c08ac7/lang/ptPT.js +0 -310
  11. package/.claude/worktrees/eager-stonebraker-c08ac7/package-lock.json +0 -11944
  12. package/.claude/worktrees/eager-stonebraker-c08ac7/package.json +0 -45
  13. package/.claude/worktrees/eager-stonebraker-c08ac7/src/activity-report.js +0 -822
  14. package/.claude/worktrees/eager-stonebraker-c08ac7/src/automaticReports.js +0 -34
  15. package/.claude/worktrees/eager-stonebraker-c08ac7/src/carbone/index.js +0 -13
  16. package/.claude/worktrees/eager-stonebraker-c08ac7/src/custom/vistawasteActivity-report.js +0 -544
  17. package/.claude/worktrees/eager-stonebraker-c08ac7/src/events-report.js +0 -360
  18. package/.claude/worktrees/eager-stonebraker-c08ac7/src/fuel-consumption-report.js +0 -296
  19. package/.claude/worktrees/eager-stonebraker-c08ac7/src/fuel-drop-report.js +0 -128
  20. package/.claude/worktrees/eager-stonebraker-c08ac7/src/here.js +0 -172
  21. package/.claude/worktrees/eager-stonebraker-c08ac7/src/idle-report.js +0 -403
  22. package/.claude/worktrees/eager-stonebraker-c08ac7/src/index.js +0 -244
  23. package/.claude/worktrees/eager-stonebraker-c08ac7/src/kms-report.js +0 -549
  24. package/.claude/worktrees/eager-stonebraker-c08ac7/src/location-report.js +0 -496
  25. package/.claude/worktrees/eager-stonebraker-c08ac7/src/machines-report.js +0 -278
  26. package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/afriquia.js +0 -129
  27. package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/dailyuse-report.js +0 -80
  28. package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/delayedstart-report.js +0 -223
  29. package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/driverranking-report.js +0 -328
  30. package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/gpsjump-report.js +0 -61
  31. package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/performance-report.js +0 -359
  32. package/.claude/worktrees/eager-stonebraker-c08ac7/src/refueling-report.js +0 -345
  33. package/.claude/worktrees/eager-stonebraker-c08ac7/src/reportStyle.js +0 -34
  34. package/.claude/worktrees/eager-stonebraker-c08ac7/src/sensor-report.js +0 -447
  35. package/.claude/worktrees/eager-stonebraker-c08ac7/src/speeding-report.js +0 -663
  36. package/.claude/worktrees/eager-stonebraker-c08ac7/src/stop-report.js +0 -242
  37. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/ActivityReportTemplate.mjml +0 -51
  38. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/EmptyReportTemplate.mjml +0 -25
  39. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/EventsReportTemplate.mjml +0 -75
  40. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/FuelDropReportTemplate.mjml +0 -60
  41. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/IdleReportTemplate.mjml +0 -54
  42. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/KmsReportGroupByDayTemplate.mjml +0 -43
  43. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/KmsReportTemplate.mjml +0 -44
  44. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/LocationReportTemplate.mjml +0 -37
  45. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/RefuelingReportTemplate.mjml +0 -60
  46. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/SensorReportTemplate.mjml +0 -23
  47. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/SpeedingReportTemplate.mjml +0 -80
  48. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/TripReportTemplate.mjml +0 -97
  49. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/ZoneReportTemplate.mjml +0 -52
  50. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/report.mjml +0 -96
  51. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/activity.test.js +0 -99
  52. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/carbone.test.js +0 -20
  53. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/events.test.js +0 -30
  54. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/fuel.test.js +0 -35
  55. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/idle.test.js +0 -16
  56. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/index.js +0 -24
  57. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/index.test.js +0 -203
  58. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/kms.test.js +0 -74
  59. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/performance.test.js +0 -36
  60. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/positions.test.js +0 -67
  61. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/speeding.test.js +0 -120
  62. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/translations.test.js +0 -21
  63. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/trips.test.js +0 -140
  64. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/zones.test.js +0 -162
  65. package/.claude/worktrees/eager-stonebraker-c08ac7/src/trip-report.js +0 -641
  66. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/device.js +0 -13
  67. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/driver.js +0 -90
  68. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/fuel.js +0 -102
  69. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/geofence.js +0 -52
  70. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/odoo.js +0 -18
  71. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/parallel.js +0 -64
  72. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/pdfDocument.js +0 -140
  73. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/route.js +0 -78
  74. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/timetable.js +0 -30
  75. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/traccar.js +0 -213
  76. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/traccar.worker.js +0 -49
  77. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/trips.js +0 -270
  78. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/utils.js +0 -358
  79. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/worker.js +0 -14
  80. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/xpert.js +0 -58
  81. package/.claude/worktrees/eager-stonebraker-c08ac7/src/word/index.js +0 -95
  82. package/.claude/worktrees/eager-stonebraker-c08ac7/src/zone-report.js +0 -904
@@ -1,223 +0,0 @@
1
- const automaticReports = require('../automaticReports')
2
- const traccarHelper = require('../util/traccar')
3
- const {
4
- getDates, getTranslations, convertMS, isClientSide, convertToLocaleString, convertToLocaleDateString,
5
- convertToLocaleTimeString
6
- } = require('../util/utils')
7
- const { getUserPartner } = require('fleetmap-partners')
8
- const { getDataByDay } = require('../util/trips')
9
- const jsPDF = require('jspdf')
10
- const { headerFromUser, addTable } = require('../util/pdfDocument')
11
- const { getStyle } = require('../reportStyle')
12
-
13
- async function createDelayedStartReport (from, to, userData, traccar) {
14
- const reportData = {
15
- devices: [],
16
- from,
17
- to
18
- }
19
-
20
- const devices = userData.devices
21
-
22
- const sliced = automaticReports.sliceArray(devices, 5)
23
- let deviceCount = 0
24
- for (const slice of sliced) {
25
- const allInOne = await traccarHelper.getAllInOne(traccar, from, to, slice, true, true, false, false, deviceCount, devices.length)
26
-
27
- for (const d of slice) {
28
- const deviceData = await processDeviceData(from, to, allInOne, d, userData, traccar)
29
- reportData.devices.push(deviceData)
30
- }
31
-
32
- deviceCount = deviceCount + slice.length
33
- }
34
-
35
- reportData.devices = reportData.devices.flat()
36
-
37
- return reportData
38
- }
39
-
40
- function getDelayDescription (startTime, activityStart, lowDelay, mediumDelay, highDelay) {
41
- const startTimeDate = new Date(startTime)
42
- const activityStartDate = new Date(startTime)
43
- activityStartDate.setHours(activityStart.substring(0, 2), activityStart.substring(3, 5))
44
-
45
- if (startTimeDate >= activityStartDate) {
46
- const delay = startTimeDate.getTime() - activityStartDate.getTime()
47
- if (delay < (lowDelay * 60 * 1000)) {
48
- return '-'
49
- } else if (delay < (mediumDelay * 60 * 1000)) {
50
- return convertMS(delay, false) + ' - Low (+' + lowDelay + ')'
51
- } else if (delay < (highDelay * 60 * 1000)) {
52
- return convertMS(delay, false) + ' - Medium (+' + mediumDelay + ')'
53
- } else {
54
- return convertMS(delay, false) + ' - High (+' + highDelay + ')'
55
- }
56
- }
57
-
58
- return ''
59
- }
60
-
61
- async function processDeviceData (from, to, allInOne, d, userData, traccar) {
62
- const trips = allInOne.trips.filter(t => t.deviceId === d.id)
63
- const route = allInOne.route.filter(t => t.deviceId === d.id)
64
-
65
- const translations = getTranslations(userData)
66
-
67
- const weekDays = [
68
- translations.report.sunday,
69
- translations.report.monday,
70
- translations.report.tuesday,
71
- translations.report.wednesday,
72
- translations.report.thursday,
73
- translations.report.friday,
74
- translations.report.saturday
75
- ]
76
-
77
- const dates = getDates(from, to, userData.user.attributes.timezone || getUserPartner(userData.user).timezone)
78
-
79
- const days = []
80
- for (const date of dates) {
81
- const { tripsByDay, routeByDay } = await getDataByDay(d, date, { trips, route }, userData, traccar)
82
-
83
- let startTime
84
- let endTime
85
- if (userData.useIgnition) {
86
- const firstIgnitionOn = routeByDay.find(p => p.attributes.ignition)
87
- if (firstIgnitionOn) {
88
- startTime = firstIgnitionOn.fixTime
89
- }
90
- } else {
91
- if (tripsByDay.length) {
92
- startTime = tripsByDay[0].startTime
93
- }
94
- }
95
-
96
- if (tripsByDay.length) {
97
- endTime = tripsByDay[tripsByDay.length - 1].endTime
98
- }
99
-
100
- if (startTime) {
101
- const deviceDayData = {
102
- device: d.name,
103
- groupId: d.groupId,
104
- licensePlate: d.attributes.license_plate,
105
- driver: '',
106
- weekDay: weekDays[new Date(date).getDay()],
107
- startTime,
108
- delayDescription: getDelayDescription(startTime, userData.activityStart, userData.lowDelay, userData.mediumDelay, userData.highDelay),
109
- endTime
110
- }
111
-
112
- days.push(deviceDayData)
113
- }
114
- }
115
-
116
- return days
117
- }
118
-
119
- async function exportDelayedStartReportToPDF (userData, reportData) {
120
- console.log('exportDelayedStartReportToPDF')
121
-
122
- const timezone = userData.user.attributes.timezone
123
- const translations = getTranslations(userData)
124
- const lang = userData.user.attributes.lang || (isClientSide() && navigator.language)
125
- const reportDataRows = reportData.devices
126
-
127
- const headers = [
128
- translations.report.group,
129
- translations.report.vehicle,
130
- translations.report.driver,
131
- translations.report.day,
132
- translations.report.startDate,
133
- translations.report.startTime,
134
- translations.report.delayDescription,
135
- translations.report.endTime
136
- ]
137
-
138
- if (reportDataRows) {
139
- // eslint-disable-next-line new-cap
140
- const doc = new jsPDF.jsPDF('l')
141
- await headerFromUser(doc, translations.report.titleDelayedStartReport, userData.user)
142
-
143
- doc.setFontSize(13)
144
- doc.text(convertToLocaleString(reportData.from, lang, timezone, userData.user) + ' - ' + convertToLocaleString(reportData.to, lang, timezone, userData.user), 20, 25)
145
-
146
- const data = []
147
- reportDataRows.forEach(function (row) {
148
- const group = userData.groups.find(g => row.groupId === g.id)
149
-
150
- const temp = [
151
- group ? group.name : '',
152
- row.device,
153
- row.driver,
154
- row.weekDay,
155
- convertToLocaleDateString(row.startTime, lang, timezone, userData.user),
156
- convertToLocaleTimeString(row.startTime, lang, timezone, userData.user),
157
- row.delayDescription,
158
- convertToLocaleTimeString(row.endTime, lang, timezone, userData.user)
159
- ]
160
- data.push(temp)
161
- })
162
- const footValues = []
163
-
164
- const style = getStyle(getUserPartner(userData.user))
165
-
166
- addTable(doc, headers, data, footValues, style, 40)
167
- return doc
168
- }
169
- }
170
-
171
- const fileName = 'DelayedStartReport'
172
- async function exportDelayedStartReportToExcel (userData, reportData) {
173
- console.log('Export to Excel')
174
-
175
- const translations = getTranslations(userData)
176
- const timezone = userData.user.attributes.timezone
177
- const lang = userData.user.attributes.lang
178
-
179
- const reportDataRows = reportData.devices
180
-
181
- const settings = {
182
- sheetName: translations.report.titleTripReport, // The name of the sheet
183
- fileName // The name of the spreadsheet
184
- }
185
-
186
- const headers = [
187
- { label: translations.report.group, value: 'group' },
188
- { label: translations.report.vehicle, value: 'name' },
189
- { label: translations.report.driver, value: 'driver' },
190
- { label: translations.report.day, value: 'day' },
191
- { label: translations.report.startDate, value: 'startDate' },
192
- { label: translations.report.startTime, value: 'startTime' },
193
- { label: translations.report.delayDescription, value: 'delayDescription' },
194
- { label: translations.report.endTime, value: 'endTime' }
195
- ]
196
-
197
- let data = []
198
- if (reportDataRows) {
199
- reportDataRows.forEach(row => {
200
- const group = userData.groups.find(g => row.groupId === g.id)
201
- data = data.concat({
202
- group: group ? group.name : '',
203
- name: row.device,
204
- driver: row.driver,
205
- day: row.weekDay,
206
- startDate: convertToLocaleDateString(row.startTime, lang, timezone, userData.user),
207
- startTime: convertToLocaleTimeString(row.startTime, lang, timezone, userData.user),
208
- delayDescription: row.delayDescription,
209
- endTime: convertToLocaleTimeString(row.endTime, lang, timezone, userData.user)
210
- })
211
- })
212
- console.log(data)
213
- return {
214
- headers,
215
- data,
216
- settings
217
- }
218
- }
219
- }
220
-
221
- exports.create = createDelayedStartReport
222
- exports.exportToPDF = exportDelayedStartReportToPDF
223
- exports.exportToExcel = exportDelayedStartReportToExcel
@@ -1,328 +0,0 @@
1
- const traccarHelper = require('../util/traccar')
2
- const { getDriverData, devicesByDriver } = require('../util/driver')
3
- const { getCanDriverStyleMessages, parseCanDriverStyleMessage } = require('../util/xpert')
4
- const { calculateRPMSections } = require('./performance-report')
5
- const { getTranslations, isClientSide, convertToLocaleString, convertMS } = 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
- const { getOverspeedEvents } = require('../speeding-report')
11
- const { calculateConsumption } = require('../util/fuel')
12
- const { getCanAvgConsumption } = require('../fuel-consumption-report')
13
- const automaticReports = require('../automaticReports')
14
-
15
- const distanceCoefficient = 0.5
16
- const consumptionCoefficient = 0.7
17
- const rpmCoefficient = 0.8
18
- const hardBrakingCoefficient = 0.10
19
- const hardAccelerationCoefficient = 0.10
20
- const hardCorneringCoefficient = 0.10
21
- const overspeedCoefficient = 0.15
22
- const geofenceCoefficient = 0.15
23
- const continuesDrivingCoefficient = 0.1
24
- const reverseCoefficient = 0.1
25
- const otherCoefficient = 0.1
26
-
27
- async function create (from, to, userData, traccar) {
28
- const reportData = {
29
- drivers: []
30
- }
31
-
32
- userData.geofences = []
33
- userData.roadSpeedLimits = true
34
-
35
- const { devices, drivers } = await devicesByDriver(traccar, from, to, userData.drivers, userData.devices)
36
- userData.drivers = drivers
37
-
38
- let deviceCount = 0
39
- const driversData = new Map()
40
- const overspeedEvents = await getOverspeedEvents(from, to, userData, devices, userData, traccar)
41
-
42
- const sliced = automaticReports.sliceArray(devices, 5)
43
-
44
- for (const slice of sliced) {
45
- const allInOne = await traccarHelper.getAllInOne(traccar, from, to, slice, true, true, false, false, deviceCount, devices.length)
46
-
47
- const result = []
48
- const requests = []
49
- for (const _chunk of automaticReports.sliceArray(slice.map(d => d.id), 1)) {
50
- requests.push(traccar.reports.reportsEventsGet(from, to, _chunk, null, ['alarm']))
51
- }
52
-
53
- try {
54
- result.push(...(await Promise.all(requests)))
55
- } catch (e) {
56
- console.log(e)
57
- }
58
- const alarmEvents = result.flatMap(d => d.data)
59
-
60
- for (const device of slice) {
61
- const route = allInOne.route.filter(t => t.deviceId === device.id)
62
- const trips = allInOne.trips.filter(t => t.deviceId === device.id)
63
-
64
- const deviceOverspeedEvents = overspeedEvents.find(e => e.device.id === device.id)
65
- const deviceAlarmEvents = alarmEvents.filter(e => e.deviceId === device.id)
66
-
67
- await processDevice(driversData, device, userData, { route, trips }, deviceAlarmEvents, deviceOverspeedEvents)
68
- deviceCount++
69
- }
70
-
71
- console.log('LOADING_MESSAGE:' + slice[0].name)
72
- console.log(`PROGRESS_PERC:${deviceCount / devices.length * 100}`)
73
- }
74
-
75
- const allDriversData = (Array.from(driversData.values())).filter(d => d.distance > 0)
76
- allDriversData.forEach(d => {
77
- const distanceScore = (Math.abs(d.distance - userData.distanceTarget) / userData.distanceTarget) * distanceCoefficient
78
- const rpmScore = ((d.highEngineRPM / 60000) / userData.rpmTarget) * rpmCoefficient
79
- const hardBrakingScore = (d.hardBraking / userData.hardBrakingTarget) * hardBrakingCoefficient
80
- const hardAccelerationScore = (d.hardAcceleration / userData.hardAccelerationTarget) * hardAccelerationCoefficient
81
- const hardCorneringScore = (d.hardCornering / userData.hardCorneringTarget) * hardCorneringCoefficient
82
- const overspeedScore = (d.overspeed / userData.overspeedTarget) * overspeedCoefficient
83
- const consumptionScore = (getCanAvgConsumption(d.distance, d.spentFuel).byKms / userData.fuelConsumptionTarget) * consumptionCoefficient
84
- const geofenceAlarmScore = (d.geofenceAlarm / userData.geofenceTarget) * geofenceCoefficient
85
- const continuesDrivingAlarmScore = (d.continuesDrivingAlarm / userData.continuesDrivingTarget) * continuesDrivingCoefficient
86
- const reverseAlarmScore = (d.reverseAlarm / userData.reverseTarget) * reverseCoefficient
87
- const otherAlarmScore = (d.otherAlarm / userData.otherTarget) * otherCoefficient
88
-
89
- d.avgFuelConsumption = getCanAvgConsumption(d.distance, d.spentFuel).byKms
90
- d.score = distanceScore + rpmScore + hardBrakingScore + hardAccelerationScore +
91
- hardCorneringScore + consumptionScore + overspeedScore + geofenceAlarmScore +
92
- continuesDrivingAlarmScore + reverseAlarmScore + otherAlarmScore
93
- })
94
- allDriversData.sort((a, b) => (a.score > b.score) ? 1 : -1)
95
-
96
- reportData.drivers.push(...allDriversData)
97
-
98
- reportData.target = {
99
- distanceTarget: userData.distanceTarget,
100
- rpmTarget: userData.rpmTarget,
101
- hardBrakingTarget: userData.hardBrakingTarget,
102
- hardAccelerationTarget: userData.hardAccelerationTarget,
103
- hardCorneringTarget: userData.hardCorneringTarget,
104
- fuelConsumptionTarget: userData.fuelConsumptionTarget,
105
- overspeedTarget: userData.overspeedTarget,
106
- geofenceTarget: userData.geofenceTarget,
107
- continuesDrivingTarget: userData.continuesDrivingTarget,
108
- reverseTarget: userData.reverseTarget,
109
- otherTarget: userData.otherTarget
110
- }
111
-
112
- reportData.coefficient = {
113
- distanceCoefficient,
114
- rpmCoefficient,
115
- hardBrakingCoefficient,
116
- hardAccelerationCoefficient,
117
- hardCorneringCoefficient,
118
- consumptionCoefficient,
119
- overspeedCoefficient,
120
- geofenceCoefficient,
121
- continuesDrivingCoefficient,
122
- reverseCoefficient,
123
- otherCoefficient
124
- }
125
-
126
- return reportData
127
- }
128
-
129
- async function processDevice (driversData, device, userData, allInOne, alarmEvents, overspeedEvents) {
130
- for (const d of userData.drivers) {
131
- const { trips, route } = await getDriverData(d, allInOne, userData)
132
- const positionsIds = route.map(p => p.id)
133
- const events = alarmEvents.filter(e => positionsIds.includes(e.positionId))
134
- const driverOverSpeedEvents = overspeedEvents ? overspeedEvents.alerts.filter(e => positionsIds.includes(e.position.id)) : []
135
- const spentFuel = calculateConsumption(device, { trips, route })
136
-
137
- const geofenceAlarm = events.filter(e => e.attributes.alarm === 'la ceinture').length
138
- const continuesDrivingAlarm = events.filter(e => e.attributes.alarm === 'Conduite continue').length
139
- const reverseAlarm = events.filter(e => e.attributes.alarm === 'MARCHE ARIERRE').length
140
- const otherAlarm = events.length - (geofenceAlarm + continuesDrivingAlarm + reverseAlarm)
141
-
142
- let driverData = driversData.get(d.id)
143
- if (!driverData) {
144
- driverData = {
145
- name: d.name,
146
- distance: 0,
147
- highEngineRPM: 0,
148
- hardBraking: 0,
149
- hardAcceleration: 0,
150
- hardCornering: 0,
151
- overspeed: 0,
152
- spentFuel: 0,
153
- geofenceAlarm: 0,
154
- continuesDrivingAlarm: 0,
155
- reverseAlarm: 0,
156
- otherAlarm: 0
157
- }
158
- driversData.set(d.id, driverData)
159
- }
160
-
161
- let highEngineRPM = 0
162
- let hardBraking = 0
163
- let hardAcceleration = 0
164
- let hardCornering = 0
165
- if (route.find(p => p.attributes.rawXpert)) {
166
- const xpertMessages = route.map(p => p.attributes.rawXpert).filter(a => a)
167
- const canDriverStyle = getCanDriverStyleMessages(xpertMessages).map(m => parseCanDriverStyleMessage(m))
168
- highEngineRPM = canDriverStyle.reduce((a, b) => a + b.totalTimeWithHighRpmAndTorque, 0)
169
- hardBraking = canDriverStyle.reduce((a, b) => a + b.totalNumberOfHarshBrakes, 0)
170
- hardAcceleration = canDriverStyle.reduce((a, b) => a + b.totalNumberOfHarshAccelerations, 0)
171
- } else {
172
- const highEngineRPMSections = calculateRPMSections(route, d.attributes.highRPM || 1500)
173
- highEngineRPM = highEngineRPMSections.map(a => a.length > 1
174
- ? a.map((p, index) => index === 0 ? 0 : new Date(p.fixTime).getTime() - new Date(a[index - 1].fixTime).getTime()).reduce((a, b) => a + b, 0)
175
- : 0).reduce((a, b) => a + b, 0)
176
-
177
- hardBraking = route.filter(p => p.attributes.alarm === 'hardBraking').length
178
- hardAcceleration = route.filter(p => p.attributes.alarm === 'hardAcceleration').length
179
- hardCornering = route.filter(p => p.attributes.alarm === 'hardCornering').length
180
- }
181
-
182
- driverData.distance = driverData.distance + trips.filter(t => t.distance > 0).reduce((a, b) => a + b.distance, 0)
183
- driverData.highEngineRPM = driverData.highEngineRPM + highEngineRPM
184
- driverData.hardBraking = driverData.hardBraking + hardBraking
185
- driverData.hardAcceleration = driverData.hardAcceleration + hardAcceleration
186
- driverData.hardCornering = driverData.hardCornering + hardCornering
187
- driverData.overspeed = driverData.overspeed + driverOverSpeedEvents.length
188
- driverData.spentFuel = driverData.spentFuel + spentFuel
189
- driverData.geofenceAlarm = driverData.geofenceAlarm + geofenceAlarm
190
- driverData.continuesDrivingAlarm = driverData.continuesDrivingAlarm + continuesDrivingAlarm
191
- driverData.reverseAlarm = driverData.reverseAlarm + reverseAlarm
192
- driverData.otherAlarm = driverData.otherAlarm + otherAlarm
193
- }
194
- }
195
-
196
- const fileName = 'DriverRankingReport'
197
- async function exportToExcel (userData, reportData) {
198
- console.log('Export to Excel')
199
-
200
- const translations = getTranslations(userData)
201
-
202
- const reportDataRows = reportData.drivers
203
-
204
- const settings = {
205
- sheetName: translations.report.titleDriverRankingReport, // The name of the sheet
206
- fileName // The name of the spreadsheet
207
- }
208
-
209
- const headers = [
210
- { label: translations.report.driver, value: 'name' },
211
- { label: translations.report.distance, value: 'distance' },
212
- { label: translations.report.avgFuelConsumption, value: 'avgFuelConsumption' },
213
- { label: translations.report.highEngineRPM, value: 'highEngineRPM' },
214
- { label: translations.report.hardBraking, value: 'hardBraking' },
215
- { label: translations.report.hardAcceleration, value: 'hardAcceleration' },
216
- { label: translations.report.hardCornering, value: 'hardCornering' },
217
- { label: translations.report.overspeedAlarm, value: 'overspeed' },
218
- { label: translations.report.geofenceAlarm, value: 'geofenceAlarm' },
219
- { label: translations.report.continuesDrivingAlarm, value: 'continuesDrivingAlarm' },
220
- { label: translations.report.reverseAlarm, value: 'reverseAlarm' },
221
- { label: translations.report.otherAlarm, value: 'otherAlarm' },
222
- { label: translations.report.score, value: 'score' }
223
- ]
224
-
225
- let data = []
226
- if (reportDataRows) {
227
- reportDataRows.forEach(row => {
228
- data = data.concat({
229
- name: row.name,
230
- distance: Number(row.distance.toFixed(1)),
231
- avgFuelConsumption: Number(row.avgFuelConsumption.toFixed(2)),
232
- highEngineRPM: convertMS(row.highEngineRPM, false),
233
- hardBraking: row.hardBraking,
234
- hardAcceleration: row.hardAcceleration,
235
- hardCornering: row.hardCornering,
236
- overspeed: row.overspeed,
237
- geofenceAlarm: row.geofenceAlarm,
238
- continuesDrivingAlarm: row.continuesDrivingAlarm,
239
- reverseAlarm: row.reverseAlarm,
240
- otherAlarm: row.otherAlarm,
241
- score: Number(row.score.toFixed(2))
242
- })
243
- })
244
- console.log(data)
245
- return {
246
- headers,
247
- data,
248
- settings
249
- }
250
- }
251
- }
252
-
253
- async function exportToPDF (userData, reportData) {
254
- console.log('exportDelayedStartReportToPDF')
255
-
256
- const timezone = userData.user.attributes.timezone
257
- const translations = getTranslations(userData)
258
- const lang = userData.user.attributes.lang || (isClientSide() && navigator.language)
259
- const reportDataRows = reportData.drivers
260
-
261
- const headers = [
262
- translations.report.driver,
263
- translations.report.distance,
264
- translations.report.avgFuelConsumption,
265
- translations.report.highEngineRPM,
266
- translations.report.hardBraking,
267
- translations.report.hardAcceleration,
268
- translations.report.hardCornering,
269
- translations.report.overspeedAlarm,
270
- translations.report.geofenceAlarm,
271
- translations.report.continuesDrivingAlarm,
272
- translations.report.reverseAlarm,
273
- translations.report.otherAlarm,
274
- translations.report.score
275
- ]
276
-
277
- if (reportDataRows) {
278
- // eslint-disable-next-line new-cap
279
- const doc = new jsPDF.jsPDF('l')
280
- await headerFromUser(doc, translations.report.titleDriverRankingReport, userData.user)
281
-
282
- doc.setFontSize(13)
283
- doc.text(convertToLocaleString(reportData.from, lang, timezone, userData.user) + ' - ' + convertToLocaleString(reportData.to, lang, timezone, userData.user), 20, 25)
284
-
285
- const data = []
286
- reportDataRows.forEach(function (row) {
287
- const temp = [
288
- row.name,
289
- row.distance.toFixed(1),
290
- row.avgFuelConsumption.toFixed(2),
291
- convertMS(row.highEngineRPM, false),
292
- row.hardBraking,
293
- row.hardAcceleration,
294
- row.hardCornering,
295
- row.overspeed,
296
- row.geofenceAlarm,
297
- row.continuesDrivingAlarm,
298
- row.reverseAlarm,
299
- row.otherAlarm,
300
- row.score.toFixed(2)
301
- ]
302
- data.push(temp)
303
- })
304
- const footValues = []
305
-
306
- const style = getStyle(getUserPartner(userData.user))
307
-
308
- addTable(doc, headers, data, footValues, style, 40, {
309
- 1: { halign: 'right' },
310
- 2: { halign: 'right' },
311
- 3: { halign: 'right' },
312
- 4: { halign: 'right' },
313
- 5: { halign: 'right' },
314
- 6: { halign: 'right' },
315
- 7: { halign: 'right' },
316
- 8: { halign: 'right' },
317
- 9: { halign: 'right' },
318
- 10: { halign: 'right' },
319
- 11: { halign: 'right' },
320
- 12: { halign: 'right' }
321
- })
322
- return doc
323
- }
324
- }
325
-
326
- exports.create = create
327
- exports.exportToPDF = exportToPDF
328
- exports.exportToExcel = exportToExcel
@@ -1,61 +0,0 @@
1
- const automaticReports = require('../automaticReports')
2
- const traccarHelper = require('../util/traccar')
3
- const distance = require('@turf/distance')
4
-
5
- async function createGPSJumpReport (from, to, userData, traccar, minDistance) {
6
- let reportData = []
7
-
8
- const devices = userData.devices
9
-
10
- const sliced = automaticReports.sliceArray(devices, 10)
11
- let deviceCount = 0
12
- for (const slice of sliced) {
13
- const allInOne = await traccarHelper.getAllInOne(traccar, from, to, slice, true, false, false, false, deviceCount, devices.length)
14
-
15
- slice.forEach(d => {
16
- const deviceData = getDeviceData(allInOne, d, userData.user, minDistance || userData.minDistance)
17
- reportData = reportData.concat(deviceData)
18
- })
19
-
20
- deviceCount = deviceCount + slice.length
21
- }
22
-
23
- return reportData
24
- }
25
-
26
- function getDeviceData (allInOne, d, user, minDistance) {
27
- const deviceRoute = allInOne.route.filter(t => t.deviceId === d.id)
28
-
29
- return deviceRoute.map((pA, index) => {
30
- if (index < deviceRoute.length - 1) {
31
- const pB = deviceRoute[index + 1]
32
- const distanceValue = distance.default([pA.longitude, pA.latitude], [pB.longitude, pB.latitude], { units: 'meters' })
33
- if ((minDistance * 1000) < distanceValue) {
34
- return {
35
- device: d.name,
36
- dateA: pA.fixTime,
37
- addressA: pA.address,
38
- dateB: pB.fixTime,
39
- addressB: pB.address,
40
- distance: distanceValue
41
- }
42
- }
43
- }
44
- return undefined
45
- }).filter(a => a).sort((a, b) => (a.device > b.device) ? 1 : -1)
46
- }
47
-
48
- async function exportGPSJumpReportToPDF (userData, reportData) {
49
-
50
- }
51
-
52
- async function exportGPSJumpReportToExcel (userData, reportData) {
53
-
54
- }
55
-
56
- exports.createGPSJumpReport = createGPSJumpReport
57
- exports.exportGPSJumpReportToPDF = exportGPSJumpReportToPDF
58
- exports.exportGPSJumpReportToExcel = exportGPSJumpReportToExcel
59
- exports.create = createGPSJumpReport
60
- exports.exportToPDF = exportGPSJumpReportToPDF
61
- exports.exportToExcel = exportGPSJumpReportToExcel