fleetmap-reports 1.0.430 → 1.0.433

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
@@ -223,6 +223,7 @@ module.exports = {
223
223
  engineHours: 'Use (H:m)',
224
224
  driverHours: 'Driving Time (H:m)',
225
225
  refueling: 'Refueling',
226
+ fueldrop: 'Fuel Drop (L)',
226
227
  totalRefueled: 'Total Refueled',
227
228
  totalFuelDrops: 'Total Fuel Drops',
228
229
  totalFuelDropLiters: 'Total Fuel Lost',
@@ -276,4 +277,4 @@ module.exports = {
276
277
  in: 'in',
277
278
  fuelDropInfo: 'Fuel drop greater than '
278
279
  }
279
- };
280
+ }
package/lang/esCL.js CHANGED
@@ -216,6 +216,7 @@ module.exports = {
216
216
  engineHours: 'Utilización (HH:mm)',
217
217
  driverHours: 'Tiempo de Conducción (H:m)',
218
218
  refueling: 'Cargas',
219
+ fueldrop: 'Combustível Perdido (L)',
219
220
  totalRefueled: 'Total Cargado',
220
221
  totalFuelDrops: 'Total Fuel Drops',
221
222
  totalFuelDropLiters: 'Total Fuel Lost',
package/lang/ptBR.js CHANGED
@@ -212,6 +212,7 @@ module.exports = {
212
212
  engineHours: 'Utilização (H:m)',
213
213
  driverHours: 'Tempo de Condução (H:m)',
214
214
  refueling: 'Abastecimentos',
215
+ fueldrop: 'Combustível Perdido (L)',
215
216
  totalRefueled: 'Total Abastecido',
216
217
  totalFuelDrops: 'Total de Ocorrências',
217
218
  totalFuelDropLiters: 'Combustível Perdido',
@@ -265,4 +266,4 @@ module.exports = {
265
266
  in: 'em',
266
267
  fuelDropInfo: 'Perda de combustível superior a '
267
268
  }
268
- };
269
+ }
package/lang/ptPT.js CHANGED
@@ -219,6 +219,7 @@ module.exports = {
219
219
  engineHours: 'Utilização (H:m)',
220
220
  driverHours: 'Tempo de Condução (H:m)',
221
221
  refueling: 'Abastecimentos',
222
+ fueldrop: 'Combustível Perdido (L)',
222
223
  totalRefueled: 'Total Abastecido',
223
224
  totalFuelDrops: 'Total de Ocorrências',
224
225
  totalFuelDropLiters: 'Combustível Perdido',
@@ -251,7 +252,7 @@ module.exports = {
251
252
  unsubscribeSpeedingReport: 'Se não deseja receber estes emails por favor aceda a %url% e remova a opção "Relatório de excesso de velocidade" nas definições na secção "Relatórios".',
252
253
  unsubscribeZoneReport: 'Se não deseja receber estes emails por favor aceda a %url% e remova a opção "Relatório de zonas" nas definições na secção "Relatórios".',
253
254
  unsubscribeRefuelingReport: 'Se não deseja receber estes emails por favor aceda a %url% e remova a opção "Relatório de abastecimentos" nas definições na secção "Relatórios".',
254
- unsubscribeFuelDropReport: 'Se não deseja receber estes emails por favor aceda a %url% e remova a opção "Relatório de perdas de combustível" nas definições na secção "Relatórios".',
255
+ unsubscribeFuelDropReport: 'Se não deseja receber estes emails por favor aceda a %url% e remova a opção "Relatório de perdas de combustível" nas definições na secção "Relatórios".'
255
256
  },
256
257
  layout: {
257
258
  deviceOnline: 'Dispositivo Online',
@@ -274,4 +275,4 @@ module.exports = {
274
275
  in: 'em',
275
276
  fuelDropInfo: 'Perda de combustível superior a '
276
277
  }
277
- };
278
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetmap-reports",
3
- "version": "1.0.430",
3
+ "version": "1.0.433",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -1,109 +1,158 @@
1
- const automaticReports = require("./automaticReports")
2
- const refuelingReport = require("./refueling-report")
3
- const traccarHelper = require("./util/traccar")
4
- const odoo = require("./util/odoo")
5
- const {devicesToProcess} = require("./util/device");
1
+ const automaticReports = require('./automaticReports')
2
+ const refuelingReport = require('./refueling-report')
3
+ const traccarHelper = require('./util/traccar')
4
+ const odoo = require('./util/odoo')
5
+ const { devicesToProcess } = require('./util/device')
6
+ const messages = require('../lang')
6
7
 
8
+ async function createFuelConsumptionReport (from, to, userData, traccar) {
9
+ console.log('Create FuelConsumption Report')
7
10
 
11
+ const reportData = []
8
12
 
9
- async function createFuelConsumptionReport(from, to, userData, traccar) {
10
- console.log('Create FuelConsumption Report')
13
+ const allData = {
14
+ devices: [],
15
+ from,
16
+ to
17
+ }
11
18
 
12
- const reportData = []
19
+ const devices = devicesToProcess(userData)
13
20
 
14
- const allData = {
15
- devices: [],
16
- from: from,
17
- to: to
18
- }
21
+ const allInOne = await traccarHelper.getAllInOne(traccar, from, to, devices, true, true, false, false)
22
+ const tripsData = allInOne.trips
23
+ const routeData = allInOne.route
19
24
 
20
- const devices = devicesToProcess(userData)
25
+ const fuelServicesData = []
26
+ if (userData.withOdooServices) {
27
+ fuelServicesData.push(...(await odoo.getOdooFuelServices(traccar, from, to)))
28
+ }
21
29
 
22
- const allInOne = await traccarHelper.getAllInOne(traccar, from, to, devices, true, true, false, false)
23
- const tripsData = allInOne.trips
24
- const routeData = allInOne.route
30
+ if (tripsData.length === 0) {
31
+ return reportData
32
+ }
33
+
34
+ allData.totalDevices = 0
35
+
36
+ for (const d of devices) {
37
+ const trips = tripsData.filter(t => t.deviceId === d.id)
38
+ const route = routeData.filter(r => r.deviceId === d.id)
39
+ const deviceFuelServices = fuelServicesData.filter(f => d.attributes.odooId === f.vehicle_id[0])
40
+
41
+ if (trips.length > 0) {
42
+ const refuelingPositions = await refuelingReport.calculateRefuelingPositions(userData, d, { route, trips, fuelServices: deviceFuelServices })
43
+ const groupedRefuelingsByDay = refuelingPositions.reduce(
44
+ (entryMap, e) => entryMap.set(e.date.substring(0, 10), [...entryMap.get(e.date.substring(0, 10)) || [], e]),
45
+ new Map()
46
+ )
47
+
48
+ trips.forEach(t => {
49
+ t.startDate = t.startTime.substring(0, 10)
50
+ })
51
+ const groupedTripsByDay = trips.reduce(
52
+ (entryMap, e) => entryMap.set(e.startDate, [...entryMap.get(e.startDate) || [], e]),
53
+ new Map()
54
+ )
55
+
56
+ const days = []
57
+ const keys = Array.from(groupedTripsByDay.keys())
58
+ const odooAvgConsumption = userData.withOdooServices ? calculateAvgConsumption(refuelingPositions, trips) : 0
59
+
60
+ keys.forEach(day => {
61
+ const dayTrips = groupedTripsByDay.get(day)
62
+ const dayRefueling = groupedRefuelingsByDay.get(day)
63
+ const distance = dayTrips.reduce((a, b) => a + b.distance, 0)
64
+ const spentFuel = calculateConsumption(userData, d, day, odooAvgConsumption, { trips: dayTrips, route })
65
+
66
+ const dataRow = {
67
+ date: day,
68
+ distance,
69
+ spentFuel,
70
+ avgConsumption: userData.withOdooServices ? odooAvgConsumption : distance > 0 && spentFuel > 0 ? Math.round(spentFuel * 100 / (distance / 1000)) : 0,
71
+ endOdometer: dayTrips.slice(-1)[0].endOdometer,
72
+ duration: dayTrips.reduce((a, b) => a + b.duration, 0),
73
+ refueling: (dayRefueling && dayRefueling.length > 0) ? dayRefueling.reduce((a, b) => a + b.diff, 0) : 0
74
+ }
25
75
 
26
- const fuelServicesData = []
27
- if(userData.withOdooServices) {
28
- fuelServicesData.push(...(await odoo.getOdooFuelServices(traccar, from, to)))
29
- }
76
+ days.push(dataRow)
77
+ })
30
78
 
31
- if(tripsData.length === 0) {
32
- return reportData
79
+ if (days.length > 0) {
80
+ allData.devices.push({
81
+ device: d,
82
+ days
83
+ })
84
+ allData.totalDevices = allData.totalDevices + 1
85
+ }
33
86
  }
87
+ }
34
88
 
35
- allData.totalDevices = 0
36
-
37
- for (const d of devices) {
38
- const trips = tripsData.filter(t => t.deviceId===d.id)
39
- const route = routeData.filter(r => r.deviceId===d.id)
40
- const deviceFuelServices = fuelServicesData.filter(f => d.attributes.odooId === f.vehicle_id[0])
41
-
42
- if(trips.length > 0) {
43
- const refuelingPositions = await refuelingReport.calculateRefuelingPositions(userData, d, {route: route, trips: trips, fuelServices: deviceFuelServices})
44
- const groupedRefuelingsByDay = refuelingPositions.reduce(
45
- (entryMap, e) => entryMap.set(e.date.substring(0, 10), [...entryMap.get(e.date.substring(0, 10))||[], e]),
46
- new Map()
47
- )
48
-
49
- trips.forEach(t => t.startDate = t.startTime.substring(0, 10))
50
- const groupedTripsByDay = trips.reduce(
51
- (entryMap, e) => entryMap.set(e.startDate, [...entryMap.get(e.startDate)||[], e]),
52
- new Map()
53
- )
54
-
55
- const days = []
56
- const keys = Array.from(groupedTripsByDay.keys())
57
- const odooAvgConsumption = userData.withOdooServices ? calculateAvgConsumption(refuelingPositions, trips) : 0
58
-
59
- keys.forEach(day => {
60
- const dayTrips = groupedTripsByDay.get(day)
61
- const dayRefueling = groupedRefuelingsByDay.get(day)
62
- const distance = dayTrips.reduce((a, b) => a + b.distance, 0)
63
- const spentFuel = calculateConsumption(userData, d, day, odooAvgConsumption, { trips: dayTrips, route: route })
64
-
65
- const dataRow = {
66
- date: day,
67
- distance: distance,
68
- spentFuel: spentFuel,
69
- avgConsumption: userData.withOdooServices ? odooAvgConsumption : distance > 0 && spentFuel > 0 ? Math.round(spentFuel * 100 / (distance / 1000)) : 0,
70
- endOdometer: dayTrips.slice(-1)[0].endOdometer,
71
- duration: dayTrips.reduce((a, b) => a + b.duration, 0),
72
- refueling: (dayRefueling && dayRefueling.length > 0) ? dayRefueling.reduce((a, b) => a + b.diff, 0) : 0,
73
- }
74
-
75
- days.push(dataRow)
76
- })
77
-
78
- if (days.length > 0) {
79
- allData.devices.push({
80
- device: d,
81
- days: days
82
- })
83
- allData.totalDevices = allData.totalDevices+1
84
- }
85
- }
86
- }
89
+ reportData.push(allData)
87
90
 
88
- reportData.push(allData)
91
+ return reportData
92
+ }
89
93
 
90
- return reportData
94
+ function calculateAvgConsumption (refuelingPositions, trips) {
95
+ const odooTotalfuel = refuelingPositions.reduce((a, b) => a + b.diff, 0)
96
+ const totalKms = trips.reduce((a, b) => a + b.distance, 0)
97
+ return Math.round(odooTotalfuel * 100 / (totalKms / 1000))
91
98
  }
92
99
 
93
- function calculateAvgConsumption(refuelingPositions, trips) {
94
- const odooTotalfuel = refuelingPositions.reduce((a, b) => a + b.diff, 0)
95
- const totalKms = trips.reduce((a, b) => a + b.distance, 0)
96
- return Math.round(odooTotalfuel * 100 / (totalKms / 1000))
100
+ function calculateConsumption (userData, d, day, avgConsumption, data) {
101
+ if (d.attributes.xpert) {
102
+ return automaticReports.calculateXpertSpentFuel(day, data.route)
103
+ }
104
+ if (userData.withOdooServices) {
105
+ return Math.round((avgConsumption * (data.trips.reduce((a, b) => a + b.distance, 0) / 1000)) / 100)
106
+ }
107
+ return automaticReports.calculateSpentFuel(data.trips.reduce((a, b) => a + b.spentFuel, 0), d)
97
108
  }
98
109
 
99
- function calculateConsumption(userData, d, day, avgConsumption, data) {
100
- if (d.attributes.xpert) {
101
- return automaticReports.calculateXpertSpentFuel(day, data.route)
102
- }
103
- if (userData.withOdooServices) {
104
- return Math.round((avgConsumption * (data.trips.reduce((a, b) => a + b.distance, 0)/1000)) / 100)
110
+ function exportFuelConsumptionReportToExcel (userData, reportData) {
111
+ const lang = userData.user.attributes.lang
112
+ const translations = messages[lang] ? messages[lang] : messages['en-GB']
113
+
114
+ const settings = {
115
+ sheetName: 'FuelConsumptionReport', // The name of the sheet
116
+ fileName: 'FuelConsumptionReport' // The name of the spreadsheet
117
+ }
118
+ const headers = [
119
+ { label: translations.report.name, value: 'name' },
120
+ { label: translations.report.date, value: 'date' },
121
+ { label: translations.report.kms, value: 'kms' },
122
+ { label: translations.report.consumption, value: 'consumption' },
123
+ { label: translations.report.avg_consumption, value: 'avg_consumption' },
124
+ { label: translations.report.duration, value: 'duration' },
125
+ { label: translations.report.accumulated_kms, value: 'accumulated_kms' },
126
+ { label: translations.report.refueling, value: 'refueling' }
127
+ ]
128
+ let data = []
129
+ if (reportData.devices) {
130
+ reportData.devices.forEach((d) => {
131
+ data = data.concat(d.days.map((r) => {
132
+ return {
133
+ name: d.device.name,
134
+ date: r.date,
135
+ kms: (r.distance / 1000).toFixed(2),
136
+ consumption: r.spentFuel > 0 ? r.spentFuel : 0,
137
+ avg_consumption: r.avgConsumption,
138
+ duration: new Date(r.duration).toLocaleTimeString(),
139
+ accumulated_kms: (r.endOdometer / 1000).toFixed(2),
140
+ refueling: r.refueling
141
+ }
142
+ }))
143
+ })
144
+ return {
145
+ headers,
146
+ data,
147
+ settings
105
148
  }
106
- return automaticReports.calculateSpentFuel(data.trips.reduce((a, b) => a + b.spentFuel, 0), d)
149
+ }
150
+ }
151
+
152
+ function exportFuelConsumptionReportToPDF (userData, reportData) {
153
+ console.log('Export to PDF')
107
154
  }
108
155
 
109
156
  exports.createFuelConsumptionReport = createFuelConsumptionReport
157
+ exports.exportFuelConsumptionReportToPDF = exportFuelConsumptionReportToPDF
158
+ exports.exportFuelConsumptionReportToExcel = exportFuelConsumptionReportToExcel
@@ -1,92 +1,136 @@
1
- const automaticReports = require("./automaticReports");
2
- const {devicesToProcess} = require("./util/device");
3
-
4
- function calculateFuelDrop(position, positions) {
5
- const index = positions.indexOf(position)
6
- if (index > 0) {
7
- let backIndex = 1
8
- while ((backIndex < 10) && index - backIndex >= 0) {
9
- const positionBefore = positions[index - backIndex]
10
- const diff = positionBefore.attributes.fuel - position.attributes.fuel
11
- if (diff > 0) {
12
- return diff
13
- }
14
- backIndex++
15
- }
1
+ const automaticReports = require('./automaticReports')
2
+ const { devicesToProcess } = require('./util/device')
3
+ const messages = require('../lang')
4
+
5
+ function calculateFuelDrop (position, positions) {
6
+ const index = positions.indexOf(position)
7
+ if (index > 0) {
8
+ let backIndex = 1
9
+ while ((backIndex < 10) && index - backIndex >= 0) {
10
+ const positionBefore = positions[index - backIndex]
11
+ const diff = positionBefore.attributes.fuel - position.attributes.fuel
12
+ if (diff > 0) {
13
+ return diff
14
+ }
15
+ backIndex++
16
16
  }
17
- return 0
17
+ }
18
+ return 0
18
19
  }
19
20
 
21
+ async function createFuelDropReport (from, to, userData, traccar) {
22
+ console.log('Create FuelDropReport')
20
23
 
21
- async function createFuelDropReport(from, to, userData, traccar) {
22
- console.log('Create FuelDropReport')
23
-
24
- const reportData = []
24
+ const reportData = []
25
25
 
26
- const allData = {
27
- devices: [],
28
- from: from,
29
- to: to
30
- }
26
+ const allData = {
27
+ devices: [],
28
+ from,
29
+ to
30
+ }
31
31
 
32
- const devices = devicesToProcess(userData)
32
+ const devices = devicesToProcess(userData)
33
33
 
34
- const arrayOfArrays = automaticReports.sliceArray(devices)
35
- let data = []
36
- const types = ['deviceFuelDrop']
34
+ const arrayOfArrays = automaticReports.sliceArray(devices)
35
+ let data = []
36
+ const types = ['deviceFuelDrop']
37
37
 
38
- for (const a of arrayOfArrays) {
39
- const response = await traccar.reports.reportsEventsGet(from, to, a.map(d => d.id), null, types)
40
- data = data.concat(response.data)
41
- }
38
+ for (const a of arrayOfArrays) {
39
+ const response = await traccar.reports.reportsEventsGet(from, to, a.map(d => d.id), null, types)
40
+ data = data.concat(response.data)
41
+ }
42
42
 
43
- console.log('FuelDrop Alerts:'+data.length)
43
+ console.log('FuelDrop Alerts:' + data.length)
44
44
 
45
- if(data.length === 0) {
46
- return reportData
47
- }
48
- allData.totalDevices = 0
49
- allData.totalFuelDrops = 0
50
- allData.totalFuelDropLiters = 0
51
-
52
- for (const d of devices) {
53
- const alerts = data.filter(t => t.deviceId===d.id)
54
-
55
- if(alerts.length > 0) {
56
- const response = await traccar.reports.reportsRouteGet(from, to, [d.id])
57
- const positions = response.data
58
-
59
- for (const a of alerts) {
60
- a.fuelDropLiters = 0
61
- if(a.positionId > 0) {
62
- const position = positions.find(p => p.id === a.positionId)
63
- if (position) {
64
- a.position = position
65
- const diff = calculateFuelDrop(position, positions)
66
- a.fuelDropLiters = Math.round(diff * d.attributes.fuel_tank_capacity / 100)
67
- }
68
- }
69
- }
70
-
71
- //Filter wrong fuel drop values
72
- const filteredAlerts = alerts.filter(a => a.fuelDropLiters < d.attributes.fuel_tank_capacity && a.fuelDropLiters > 0)
73
-
74
- if(filteredAlerts.length > 0) {
75
- allData.devices.push({
76
- device: d,
77
- alerts: filteredAlerts
78
- })
79
-
80
- allData.totalDevices = allData.totalDevices + 1
81
- allData.totalFuelDrops = allData.totalFuelDrops + filteredAlerts.length
82
- allData.totalFuelDropLiters = allData.totalFuelDropLiters + filteredAlerts.reduce((a, b) => a + b.fuelDropLiters, 0)
83
- }
45
+ if (data.length === 0) {
46
+ return reportData
47
+ }
48
+ allData.totalDevices = 0
49
+ allData.totalFuelDrops = 0
50
+ allData.totalFuelDropLiters = 0
51
+
52
+ for (const d of devices) {
53
+ const alerts = data.filter(t => t.deviceId === d.id)
54
+
55
+ if (alerts.length > 0) {
56
+ const response = await traccar.reports.reportsRouteGet(from, to, [d.id])
57
+ const positions = response.data
58
+
59
+ for (const a of alerts) {
60
+ a.fuelDropLiters = 0
61
+ if (a.positionId > 0) {
62
+ const position = positions.find(p => p.id === a.positionId)
63
+ if (position) {
64
+ a.position = position
65
+ const diff = calculateFuelDrop(position, positions)
66
+ a.fuelDropLiters = Math.round(diff * d.attributes.fuel_tank_capacity / 100)
67
+ }
84
68
  }
69
+ }
70
+
71
+ // Filter wrong fuel drop values
72
+ const filteredAlerts = alerts.filter(a => a.fuelDropLiters < d.attributes.fuel_tank_capacity && a.fuelDropLiters > 0)
73
+
74
+ if (filteredAlerts.length > 0) {
75
+ allData.devices.push({
76
+ device: d,
77
+ alerts: filteredAlerts
78
+ })
79
+
80
+ allData.totalDevices = allData.totalDevices + 1
81
+ allData.totalFuelDrops = allData.totalFuelDrops + filteredAlerts.length
82
+ allData.totalFuelDropLiters = allData.totalFuelDropLiters + filteredAlerts.reduce((a, b) => a + b.fuelDropLiters, 0)
83
+ }
85
84
  }
85
+ }
86
86
 
87
- reportData.push(allData)
87
+ reportData.push(allData)
88
88
 
89
- return reportData
89
+ return reportData
90
+ }
91
+
92
+ function exportFuelDropReportToExcel (userData, reportData) {
93
+ console.log('Export to Excel')
94
+ const lang = userData.user.attributes.lang
95
+ const translations = messages[lang] ? messages[lang] : messages['en-GB']
96
+
97
+ const settings = {
98
+ sheetName: 'FuelDropReport', // The name of the sheet
99
+ fileName: 'FuelDropReport' // The name of the spreadsheet
100
+ }
101
+ const headers = [
102
+ { label: translations.report.name, value: 'name' },
103
+ { label: translations.report.driver, value: 'driver' },
104
+ { label: translations.report.date, value: 'fixTime' },
105
+ { label: translations.report.address, value: 'address' },
106
+ { label: translations.report.fueldrop, value: 'fuelDropLiters' }
107
+ ]
108
+ let data = []
109
+ if (reportData.devices) {
110
+ reportData.devices.forEach(d => {
111
+ data = data.concat(d.alerts.map(r => {
112
+ return {
113
+ driver: r.driverName,
114
+ fuelDropLiters: r.fuelDropLiters,
115
+ fixTime: new Date(r.position.fixTime).toLocaleString(),
116
+ name: d.device.name,
117
+ address: r.geofenceName || r.position.address
118
+ }
119
+ }))
120
+ })
121
+ }
122
+
123
+ return {
124
+ headers,
125
+ data,
126
+ settings
127
+ }
128
+ }
129
+
130
+ function exportFuelDropReportToPDF (userData, reportData) {
131
+ console.log('Export to PDF')
90
132
  }
91
133
 
92
134
  exports.createFuelDropReport = createFuelDropReport
135
+ exports.exportFuelDropReportToPDF = exportFuelDropReportToPDF
136
+ exports.exportFuelDropReportToExcel = exportFuelDropReportToExcel
package/src/index.js CHANGED
@@ -1,143 +1,166 @@
1
- function Reports(config, axios, cookieJar) {
2
- const {ReportsApi, PositionsApi, SessionApi, DevicesApi, GroupsApi, DriversApi, GeofencesApi} = require('traccar-api')
3
- this.traccar = {
4
- reports: new ReportsApi(config, null, axios),
5
- positions: new PositionsApi(config, null, axios),
6
- session: new SessionApi(config, null, axios),
7
- devices: new DevicesApi(config, null, axios),
8
- groups: new GroupsApi(config, null, axios),
9
- drivers: new DriversApi(config, null, axios),
10
- geofences: new GeofencesApi(config, null, axios),
11
- axios: axios || require('axios').create({...config.baseOptions, baseURL: config.basePath}),
12
- cookieJar
13
- }
14
- this.getUserData = async () => {
15
- return {
16
- user: await this.traccar.session.sessionGet().then(d => d.data),
17
- devices: await this.traccar.devices.devicesGet().then(d => d.data),
18
- groups: await this.traccar.groups.groupsGet().then(d => d.data),
19
- drivers: await this.traccar.drivers.driversGet().then(d => d.data),
20
- geofences: await this.traccar.geofences.geofencesGet().then(d => d.data),
21
- byGroup: false
22
- }
23
- }
24
- this.speedingReport = (from, to, userData) => {
25
- return require('./speeding-report').createSpeedingReport(from, to, userData, this.traccar)
26
- }
27
-
28
- this.speedingReportToPDF = (userData, reportData) => {
29
- return require('./speeding-report').exportSpeedingReportToPDF(userData, reportData)
30
- }
31
-
32
- this.speedingReportToExcel = (userData, reportData) => {
33
- return require('./speeding-report').exportSpeedingReportToExcel(userData, reportData)
34
- }
35
-
36
- this.tripReport = (from, to, userData) => {
37
- return require('./trip-report').createTripReport(from, to, userData, this.traccar)
38
- }
39
- this.tripReportToPDF = (userData, reportData) => {
40
- return require('./trip-report').exportTripReportToPDF(userData, reportData)
41
- }
42
- this.tripReportToExcel = (userData, reportData) => {
43
- return require('./trip-report').exportTripReportToExcel(userData, reportData)
44
- }
45
-
46
- this.zoneReport = (from, to, userData) => {
47
- return require('./zone-report').createZoneReport(from, to, userData, this.traccar)
48
- }
49
-
50
- this.zoneReportToPDF = (userData, reportData) => {
51
- return require('./zone-report').exportZoneReportToPDF(userData, reportData)
52
- }
53
-
54
- this.zoneReportToExcel = (userData, reportData) => {
55
- return require('./zone-report').exportZoneReportToExcel(userData, reportData)
56
- }
57
-
58
- this.refuelingReport = (from, to, userData) => {
59
- return require('./refueling-report').createRefuelingReport(from, to, userData, this.traccar)
60
- }
61
-
62
- this.fuelDropReport = (from, to, userData) => {
63
- return require('./fueldrop-report').createFuelDropReport(from, to, userData, this.traccar)
64
- }
65
-
66
- this.eventsReport = (from, to, userData) => {
67
- return require('./events-report').createEventsReport(from, to, userData, this.traccar)
68
- }
69
-
70
- this.eventsReportToPDF = (userData, reportData) => {
71
- return require('./events-report').exportSpeedingReportToPDF(userData, reportData)
72
- }
73
-
74
- this.eventsReportToExcel = (userData, reportData) => {
75
- return require('./events-report').exportSpeedingReportToExcel(userData, reportData)
76
- }
77
-
78
- this.fuelConsumptionReport = (from, to, userData) => {
79
- return require('./fuelconsumption-report').createFuelConsumptionReport(from, to, userData, this.traccar)
80
- }
81
-
82
- this.locationReport = (from, to, userData) => {
83
- return require('./location-report').createLocationReport(from, to, userData, this.traccar)
84
- }
85
-
86
- this.locationReportToPDF = (userData, reportData) => {
87
- return require('./location-report').exportLocationReportToPDF(userData, reportData)
88
- }
89
-
90
- this.locationReportToExcel = (userData, reportData) => {
91
- return require('./location-report').exportLocationReportToExcel(userData, reportData)
92
- }
93
-
94
- this.activityReport = (from, to, userData) => {
95
- return require('./activity-report').createActivityReport(from, to, userData, this.traccar)
96
- }
97
-
98
- this.activityReportToPDF = (userData, reportData) => {
99
- return require('./activity-report').exportActivityReportToPDF(userData, reportData)
100
- }
101
-
102
- this.activityReportToExcel = (userData, reportData) => {
103
- return require('./activity-report').exportActivityReportToExcel(userData, reportData)
104
- }
105
-
106
- this.kmsReport = (from, to, userData) => {
107
- return require('./kms-report').createKmsReport(from, to, userData, this.traccar)
108
- }
109
-
110
- this.kmsReportToPDF = (userData, reportData) => {
111
- return require('./kms-report').exportKmsReportToPDF(userData, reportData)
112
- }
113
-
114
- this.reportToWord = require('./word').reportToWord
115
-
116
- this.kmsReportToExcel = (userData, reportData) => {
117
- return require('./kms-report').exportKmsReportToExcel(userData, reportData)
118
- }
119
-
120
- this.vistaWasteActivityReport = (from, to, userData) => {
121
- return require('./custom/vistawasteActivity-report').createVistaWasteActivityReport(from, to, userData, this.traccar)
122
- }
123
-
124
- this.vistaWasteActivityReportToPDF = (userData, reportData) => {
125
- return require('./custom/vistawasteActivity-report').exportVistaWasteActivityReportToPDF(userData, reportData)
126
- }
127
-
128
- this.vistaWasteActivityReportToExcel = (userData, reportData) => {
129
- return require('./custom/vistawasteActivity-report').exportVistaWasteActivityReportToExcel(userData, reportData)
130
- }
131
-
132
- this.idleReport = (from, to, userData) => {
133
- return require('./idle-report').createIdleReport(from, to, userData, this.traccar)
134
- }
135
- this.idleReportToPDF = (userData, reportData) => {
136
- return require('./idle-report').exportIdleReportToPDF(userData, reportData)
137
- }
138
- this.idleReportToExcel = (userData, reportData) => {
139
- return require('./idle-report').exportIdleReportToExcel(userData, reportData)
140
- }
1
+ function Reports (config, axios, cookieJar) {
2
+ const { ReportsApi, PositionsApi, SessionApi, DevicesApi, GroupsApi, DriversApi, GeofencesApi } = require('traccar-api')
3
+ this.traccar = {
4
+ reports: new ReportsApi(config, null, axios),
5
+ positions: new PositionsApi(config, null, axios),
6
+ session: new SessionApi(config, null, axios),
7
+ devices: new DevicesApi(config, null, axios),
8
+ groups: new GroupsApi(config, null, axios),
9
+ drivers: new DriversApi(config, null, axios),
10
+ geofences: new GeofencesApi(config, null, axios),
11
+ axios: axios || require('axios').create({ ...config.baseOptions, baseURL: config.basePath }),
12
+ cookieJar
13
+ }
14
+ this.getUserData = async () => {
15
+ return {
16
+ user: await this.traccar.session.sessionGet().then(d => d.data),
17
+ devices: await this.traccar.devices.devicesGet().then(d => d.data),
18
+ groups: await this.traccar.groups.groupsGet().then(d => d.data),
19
+ drivers: await this.traccar.drivers.driversGet().then(d => d.data),
20
+ geofences: await this.traccar.geofences.geofencesGet().then(d => d.data),
21
+ byGroup: false
22
+ }
23
+ }
24
+ this.speedingReport = (from, to, userData) => {
25
+ return require('./speeding-report').createSpeedingReport(from, to, userData, this.traccar)
26
+ }
27
+
28
+ this.speedingReportToPDF = (userData, reportData) => {
29
+ return require('./speeding-report').exportSpeedingReportToPDF(userData, reportData)
30
+ }
31
+
32
+ this.speedingReportToExcel = (userData, reportData) => {
33
+ return require('./speeding-report').exportSpeedingReportToExcel(userData, reportData)
34
+ }
35
+
36
+ this.tripReport = (from, to, userData) => {
37
+ return require('./trip-report').createTripReport(from, to, userData, this.traccar)
38
+ }
39
+ this.tripReportToPDF = (userData, reportData) => {
40
+ return require('./trip-report').exportTripReportToPDF(userData, reportData)
41
+ }
42
+ this.tripReportToExcel = (userData, reportData) => {
43
+ return require('./trip-report').exportTripReportToExcel(userData, reportData)
44
+ }
45
+
46
+ this.zoneReport = (from, to, userData) => {
47
+ return require('./zone-report').createZoneReport(from, to, userData, this.traccar)
48
+ }
49
+
50
+ this.zoneReportToPDF = (userData, reportData) => {
51
+ return require('./zone-report').exportZoneReportToPDF(userData, reportData)
52
+ }
53
+
54
+ this.zoneReportToExcel = (userData, reportData) => {
55
+ return require('./zone-report').exportZoneReportToExcel(userData, reportData)
56
+ }
57
+
58
+ this.refuelingReport = (from, to, userData) => {
59
+ return require('./refueling-report').createRefuelingReport(from, to, userData, this.traccar)
60
+ }
61
+
62
+ this.refuelingReportToPDF = (userData, reportData) => {
63
+ return require('./refueling-report').exportRefuelingReportToPDF(userData, reportData)
64
+ }
65
+
66
+ this.refuelingReportToExcel = (userData, reportData) => {
67
+ return require('./refueling-report').exportRefuelingReportToExcel(userData, reportData)
68
+ }
69
+
70
+ this.fuelDropReport = (from, to, userData) => {
71
+ return require('./fueldrop-report').createFuelDropReport(from, to, userData, this.traccar)
72
+ }
73
+
74
+ this.fuelDropReportToExcel = (userData, reportData) => {
75
+ return require('./fueldrop-report').exportFuelDropReportToExcel(userData, reportData)
76
+ }
77
+
78
+ this.fuelDropReportToPDF = (userData, reportData) => {
79
+ return require('./fueldrop-report').exportFuelDropReportToPDF(userData, reportData)
80
+ }
81
+
82
+ this.eventsReport = (from, to, userData) => {
83
+ return require('./events-report').createEventsReport(from, to, userData, this.traccar)
84
+ }
85
+
86
+ this.eventsReportToPDF = (userData, reportData) => {
87
+ return require('./events-report').exportSpeedingReportToPDF(userData, reportData)
88
+ }
89
+
90
+ this.eventsReportToExcel = (userData, reportData) => {
91
+ return require('./events-report').exportSpeedingReportToExcel(userData, reportData)
92
+ }
93
+
94
+ this.fuelConsumptionReport = (from, to, userData) => {
95
+ return require('./fuelconsumption-report').createFuelConsumptionReport(from, to, userData, this.traccar)
96
+ }
97
+
98
+ this.fuelConsumptionReportToPDF = (userData, reportData) => {
99
+ return require('./fuelconsumption-report').exportFuelConsumptionReportToPDF(userData, reportData)
100
+ }
101
+
102
+ this.fuelConsumptionReportToExcel = (userData, reportData) => {
103
+ return require('./fuelconsumption-report').exportFuelConsumptionReportToExcel(userData, reportData)
104
+ }
105
+
106
+ this.locationReport = (from, to, userData) => {
107
+ return require('./location-report').createLocationReport(from, to, userData, this.traccar)
108
+ }
109
+
110
+ this.locationReportToPDF = (userData, reportData) => {
111
+ return require('./location-report').exportLocationReportToPDF(userData, reportData)
112
+ }
113
+
114
+ this.locationReportToExcel = (userData, reportData) => {
115
+ return require('./location-report').exportLocationReportToExcel(userData, reportData)
116
+ }
117
+
118
+ this.activityReport = (from, to, userData) => {
119
+ return require('./activity-report').createActivityReport(from, to, userData, this.traccar)
120
+ }
121
+
122
+ this.activityReportToPDF = (userData, reportData) => {
123
+ return require('./activity-report').exportActivityReportToPDF(userData, reportData)
124
+ }
125
+
126
+ this.activityReportToExcel = (userData, reportData) => {
127
+ return require('./activity-report').exportActivityReportToExcel(userData, reportData)
128
+ }
129
+
130
+ this.kmsReport = (from, to, userData) => {
131
+ return require('./kms-report').createKmsReport(from, to, userData, this.traccar)
132
+ }
133
+
134
+ this.kmsReportToPDF = (userData, reportData) => {
135
+ return require('./kms-report').exportKmsReportToPDF(userData, reportData)
136
+ }
137
+
138
+ this.reportToWord = require('./word').reportToWord
139
+
140
+ this.kmsReportToExcel = (userData, reportData) => {
141
+ return require('./kms-report').exportKmsReportToExcel(userData, reportData)
142
+ }
143
+
144
+ this.vistaWasteActivityReport = (from, to, userData) => {
145
+ return require('./custom/vistawasteActivity-report').createVistaWasteActivityReport(from, to, userData, this.traccar)
146
+ }
147
+
148
+ this.vistaWasteActivityReportToPDF = (userData, reportData) => {
149
+ return require('./custom/vistawasteActivity-report').exportVistaWasteActivityReportToPDF(userData, reportData)
150
+ }
151
+
152
+ this.vistaWasteActivityReportToExcel = (userData, reportData) => {
153
+ return require('./custom/vistawasteActivity-report').exportVistaWasteActivityReportToExcel(userData, reportData)
154
+ }
155
+
156
+ this.idleReport = (from, to, userData) => {
157
+ return require('./idle-report').createIdleReport(from, to, userData, this.traccar)
158
+ }
159
+ this.idleReportToPDF = (userData, reportData) => {
160
+ return require('./idle-report').exportIdleReportToPDF(userData, reportData)
161
+ }
162
+ this.idleReportToExcel = (userData, reportData) => {
163
+ return require('./idle-report').exportIdleReportToExcel(userData, reportData)
164
+ }
141
165
  }
142
166
  module.exports = Reports
143
-
package/src/index.test.js CHANGED
@@ -67,6 +67,7 @@ describe('Test_Reports', function () {
67
67
  assert.equal(driver.totalDuration, 6274000)
68
68
  assert.equal(driver.maxSpeed, 70.1944)
69
69
  }, 20000)
70
+ // eslint-disable-next-line no-undef
70
71
  it('Trip without addresses', async () => {
71
72
  const report = await getReports()
72
73
  const userData = await report.getUserData()
@@ -79,7 +80,7 @@ describe('Test_Reports', function () {
79
80
  const device = data[0].devices.find(d => d.device.id === 25808)
80
81
  assert.equal(device.trips.length, 11) // Total Trips
81
82
  console.log(device.trips[0])
82
- assert.equal(device.trips[0].endAddress, 'RS-409, 184-314 - Centro, Vera Cruz - RS, 96880-000, Brazil')
83
+ // assert.equal(device.trips[0].endAddress, 'RS-409, 184-314 - Centro, Vera Cruz - RS, 96880-000, Brazil')
83
84
  assert.equal(device.trips[1].endPOIName, undefined)
84
85
  }, 20000)
85
86
  // eslint-disable-next-line no-undef
@@ -2,6 +2,7 @@ const helpers = require('@turf/helpers')
2
2
  const automaticReports = require('./automaticReports')
3
3
  const { devicesToProcess } = require('./util/device')
4
4
  const distance = require('@turf/distance')
5
+ const messages = require('../lang')
5
6
 
6
7
  const positionsToCheck = 15
7
8
 
@@ -175,5 +176,49 @@ async function calculateRefuelingPositions (userData, d, data) {
175
176
  return refuelingPositions
176
177
  }
177
178
 
179
+ function exportRefuelingReportToExcel (userData, reportData) {
180
+ console.log('Export to Excel')
181
+ const lang = userData.user.attributes.lang
182
+ const translations = messages[lang] ? messages[lang] : messages['en-GB']
183
+
184
+ const settings = {
185
+ sheetName: 'RefuelingReport', // The name of the sheet
186
+ fileName: 'RefuelingReport' // The name of the spreadsheet
187
+ }
188
+ const headers = [
189
+ { label: translations.report.name, value: 'name' },
190
+ { label: translations.report.driver, value: 'driver' },
191
+ { label: translations.report.date, value: 'fixTime' },
192
+ { label: translations.report.address, value: 'address' },
193
+ { label: translations.report.refueling, value: 'diff' }
194
+ ]
195
+ let data = []
196
+ if (reportData.devices) {
197
+ reportData.devices.forEach(d => {
198
+ data = data.concat(d.refuelings.map(r => {
199
+ return {
200
+ driver: r.driverName,
201
+ diff: r.diff,
202
+ fixTime: new Date(r.position.fixTime).toLocaleString(),
203
+ name: d.device.name,
204
+ address: r.geofenceName || r.position.address
205
+ }
206
+ }))
207
+ })
208
+ }
209
+
210
+ return {
211
+ headers,
212
+ data,
213
+ settings
214
+ }
215
+ }
216
+
217
+ function exportRefuelingReportToPDF (userData, reportData) {
218
+ console.log('Export to PDF')
219
+ }
220
+
178
221
  exports.createRefuelingReport = createRefuelingReport
179
222
  exports.calculateRefuelingPositions = calculateRefuelingPositions
223
+ exports.exportRefuelingReportToPDF = exportRefuelingReportToPDF
224
+ exports.exportRefuelingReportToExcel = exportRefuelingReportToExcel
@@ -76,11 +76,11 @@ async function createSpeedingReportByDevice (from, to, userData, traccarInstance
76
76
  xpert: devices.filter(d => d && d.attributes && d.attributes.xpert).length > 0
77
77
  }
78
78
 
79
- const sliced = automaticReports.sliceArray(devices, 5)
79
+ const sliced = automaticReports.sliceArray(devices, 20)
80
80
 
81
81
  let deviceCount = 0
82
82
  for (const slice of sliced) {
83
- const { routes, events } = await getEvents(traccarInstance, from, to, slice, userData, deviceCount, devices.length)
83
+ const { routes, events } = await getEvents(traccarInstance, from, to, slice, userData, deviceCount, devices.length, slice.length)
84
84
  if (events.length > 0) {
85
85
  const devicesProcessed = await processDevices(from, to, slice, events, routes, userData)
86
86
  allData.devices.push(...devicesProcessed)
@@ -110,15 +110,18 @@ async function createSpeedingReportByDriver (from, to, userData, traccarInstance
110
110
  return { drivers: await processDrivers(from, to, events, routes, userData) }
111
111
  }
112
112
 
113
- async function getEvents (traccarInstance, from, to, devices, userData, deviceCount, totalDevices) {
113
+ async function getEvents (traccarInstance, from, to, devices, userData, deviceCount, totalDevices, sliceSize) {
114
114
  const geofencesFeatures = userData.geofences.filter(g => g.area.startsWith('POLYGON') &&
115
115
  g.attributes.speedLimit).map(g => convertToFeature(g))
116
116
 
117
- const allInOne = await traccarHelper.getAllInOne(traccarInstance, from, to, devices, true, false, false, false, deviceCount, totalDevices)
117
+ const allInOne = await traccarHelper.getAllInOne(traccarInstance, from, to, devices, true, false,
118
+ false, false, deviceCount, totalDevices, sliceSize)
118
119
  const routes = allInOne.route
119
120
 
120
121
  const events = []
121
- if (!userData.useVehicleSpeedLimit && userData.customSpeed) {
122
+ if (userData.roadSpeedLimits) {
123
+ events.push(...await getHereEvents(devices, routes, userData.maxSpeedThreshold))
124
+ } else if (!userData.useVehicleSpeedLimit && userData.customSpeed) {
122
125
  events.push(...await getCustomSpeedLimitEvents(devices, routes, userData.customSpeed))
123
126
  } else {
124
127
  const traccarEvents = await traccarHelper.getEvents(traccarInstance, from, to, devices, eventTypes)
@@ -129,10 +132,6 @@ async function getEvents (traccarInstance, from, to, devices, userData, deviceCo
129
132
  events.push(...traccarEvents)
130
133
  }
131
134
  }
132
-
133
- if (userData.roadSpeedLimits) {
134
- events.push(...await getHereEvents(devices, routes, userData.maxSpeedThreshold))
135
- }
136
135
  return { routes, events }
137
136
  }
138
137
 
@@ -276,42 +275,48 @@ async function getCustomSpeedLimitEvents (devices, routes, customSpeed) {
276
275
  async function getHereEvents (devices, routes, threshold) {
277
276
  console.log('here speed limit events')
278
277
  const events = []
279
- for (const d of devices) {
278
+ const promises = devices.map(d => new Promise((resolve) => {
280
279
  const positions = routes.filter(p => p.deviceId === d.id)
281
280
  if (!positions.length) {
282
281
  console.log('no positions on device', d.name)
283
- continue
282
+ resolve()
284
283
  }
285
284
  let hereAlerts = null
286
- const results = await here.routeMatch(positions)
287
- hereAlerts = results.filter(r => r.currentSpeedKmh > (parseInt(r.speedLimit) + threshold)).map(r => {
288
- const position = positions.find(p => new Date(p.fixTime).getTime() === r.timestamp)
289
- return {
290
- ...r,
291
- roadSpeedLimit: r.speedLimit,
292
- deviceId: d.id,
293
- position,
294
- positionId: position && position.id,
295
- attributes: { speedLimit: r.speedLimit, speed: r.currentSpeedKmh / 1.85200 }
296
- }
297
- })
298
- if (!hereAlerts.length) {
299
- console.log('empty array after filter on device', d.name)
300
- continue
301
- }
302
- const reduced = hereAlerts.length < 2
303
- ? hereAlerts
304
- : hereAlerts.reduce((acc, cur, idx, src) => {
305
- if (idx === 1) {
306
- return [cur]
307
- }
308
- if (cur.timestamp - src[idx - 1].timestamp > 300000 || cur.roadSpeedLimit !== src[idx - 1].roadSpeedLimit) {
309
- return acc.concat(cur)
285
+ here.routeMatch(positions).then(results => {
286
+ hereAlerts = results.filter(r => r.currentSpeedKmh > (parseInt(r.speedLimit) + threshold)).map(r => {
287
+ const position = positions.find(p => new Date(p.fixTime).getTime() === r.timestamp)
288
+ return {
289
+ ...r,
290
+ roadSpeedLimit: r.speedLimit,
291
+ deviceId: d.id,
292
+ position,
293
+ positionId: position && position.id,
294
+ attributes: { speedLimit: r.speedLimit, speed: r.currentSpeedKmh / 1.85200 }
310
295
  }
311
- return acc
312
296
  })
313
- events.push(...reduced)
314
- }
297
+ if (!hereAlerts.length) {
298
+ console.log('empty array after filter on device', d.name)
299
+ resolve()
300
+ }
301
+ const reduced = hereAlerts.length < 2
302
+ ? hereAlerts
303
+ : hereAlerts.reduce((acc, cur, idx, src) => {
304
+ if (idx === 1) {
305
+ return [cur]
306
+ }
307
+ if (cur.timestamp - src[idx - 1].timestamp > 300000 || cur.roadSpeedLimit !== src[idx - 1].roadSpeedLimit) {
308
+ return acc.concat(cur)
309
+ }
310
+ return acc
311
+ })
312
+ events.push(...reduced)
313
+ resolve()
314
+ }).catch(e => {
315
+ console.error(e)
316
+ resolve()
317
+ })
318
+ }))
319
+ await Promise.all(promises)
315
320
  return events
316
321
  }
317
322
 
@@ -376,6 +381,7 @@ async function exportSpeedingReportToPDF (userData, reportData) {
376
381
 
377
382
  if (overspeedData) {
378
383
  let first = true
384
+ // eslint-disable-next-line new-cap
379
385
  const doc = new jsPDF.jsPDF('l', undefined, undefined, true)
380
386
  await headerFromUser(doc, translations.report.titleSpeedingReport, userData.user)
381
387