fleetmap-reports 1.0.275 → 1.0.279

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.
@@ -0,0 +1,7 @@
1
+ <component name="ProjectCodeStyleConfiguration">
2
+ <code_scheme name="Project" version="173">
3
+ <ScalaCodeStyleSettings>
4
+ <option name="MULTILINE_STRING_CLOSING_QUOTES_ON_NEW_LINE" value="true" />
5
+ </ScalaCodeStyleSettings>
6
+ </code_scheme>
7
+ </component>
@@ -0,0 +1,5 @@
1
+ <component name="ProjectCodeStyleConfiguration">
2
+ <state>
3
+ <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
4
+ </state>
5
+ </component>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="JavaScriptLibraryMappings">
4
+ <file url="file://$PROJECT_DIR$" libraries="{Node.js Core}" />
5
+ </component>
6
+ </project>
package/lang/enGB.js CHANGED
@@ -182,6 +182,7 @@ module.exports = {
182
182
  titleEventsReport: 'Events Report',
183
183
  titleActivityReport: 'Activity Report',
184
184
  titleKmsReport: 'Kms Report',
185
+ titleIdleReport: 'Idle Report',
185
186
  from: 'From',
186
187
  to: 'to',
187
188
  headerStartAddress: 'Start address',
package/lang/esCL.js CHANGED
@@ -176,6 +176,7 @@ module.exports = {
176
176
  titleEventsReport: 'Informe de Eventos',
177
177
  titleActivityReport: 'Activity Report',
178
178
  titleKmsReport: 'Informe de Kms',
179
+ titleIdleReport: 'Relatórios de Ralenti',
179
180
  from: 'De',
180
181
  to: 'a',
181
182
  headerStartAddress: 'Lugar de início',
package/lang/ptBR.js CHANGED
@@ -172,6 +172,7 @@ module.exports = {
172
172
  titleEventsReport: 'Relatório de Eventos',
173
173
  titleActivityReport: 'Relatório de Actividade',
174
174
  titleKmsReport: 'Relatórios de Kms',
175
+ titleIdleReport: 'Relatórios de Ralenti',
175
176
  from: 'De',
176
177
  to: 'a',
177
178
  headerStartAddress: 'Local de início',
package/lang/ptPT.js CHANGED
@@ -178,6 +178,7 @@ module.exports = {
178
178
  titleEventsReport: 'Relatório de Eventos',
179
179
  titleActivityReport: 'Relatório de Actividade',
180
180
  titleKmsReport: 'Relatórios de Kms',
181
+ titleIdleReport: 'Relatórios de Ralenti',
181
182
  from: 'De',
182
183
  to: 'a',
183
184
  headerStartAddress: 'Local de início',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetmap-reports",
3
- "version": "1.0.275",
3
+ "version": "1.0.279",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
package/src/here.js CHANGED
@@ -100,7 +100,6 @@ exports.routeMatch = async (rows) => {
100
100
  const csv = generateCSV(rows)
101
101
  const response = await axios.post(calcRoute, csv, { headers: { 'Content-Type': 'application/binary' }})
102
102
  const hereData = response.data
103
- console.dir(hereData, {depth: null})
104
103
  const route = hereData.response.route[0]
105
104
  const results = []
106
105
  const wayPoints = route.waypoint
@@ -0,0 +1,285 @@
1
+ const traccar = require("./util/traccar");
2
+ const messages = require("../lang");
3
+ const jsPDF = require("jspdf");
4
+ const {headerFromUser, AmiriRegular} = require("./util/pdfDocument");
5
+ const {convertToLocaleString, convertMS} = require("./util/utils");
6
+ const {getStyle} = require("./reportStyle");
7
+ const {getUserPartner} = require("fleetmap-partners");
8
+
9
+
10
+ let traccarInstance
11
+ let userData
12
+
13
+ const fileName = 'IdleReport'
14
+
15
+ async function createIdleReport(from, to, reportUserData, traccar) {
16
+ console.log('Create IdleReport')
17
+ userData = reportUserData
18
+ traccarInstance = traccar
19
+ const reportData = []
20
+
21
+ if (userData.byGroup) {
22
+ console.log("ByGroup")
23
+ const allData = await createTripReportByGroup(from, to)
24
+ reportData.push(...allData)
25
+ } else {
26
+ console.log("ByDevice")
27
+ const report = await createTripReportByDevice(from, to)
28
+ reportData.push(report)
29
+ }
30
+
31
+ return reportData
32
+ }
33
+
34
+ async function createTripReportByGroup(from, to) {
35
+ const reportData = []
36
+ for (const g of userData.groups) {
37
+ const devices = userData.devices.filter(d => d.groupId === g.id)
38
+ console.log(g.name + ' devices:' + devices.length)
39
+ if(devices.length > 0) {
40
+ const groupData = {
41
+ devices: [],
42
+ group: g,
43
+ from: from,
44
+ to: to
45
+ }
46
+
47
+ const response = await traccarInstance.reports.reportsRouteGet(from, to, null, [g.id])
48
+ const routes = response.data
49
+
50
+ devices.sort((a, b) => (a.name > b.name) ? 1 : -1)
51
+
52
+ if (routes.length > 0) {
53
+ console.log('Routes:' + routes.length)
54
+ groupData.devices = processDevices(from, to, devices, routes)
55
+
56
+ reportData.push(groupData)
57
+ }
58
+ }
59
+ }
60
+
61
+ const groupIds = userData.groups.map(g => g.id)
62
+ const withoutGroupDevices = userData.devices.filter(d => !groupIds.includes(d.groupId))
63
+
64
+ const allData = await createTripReportByDevice(from, to, withoutGroupDevices)
65
+ reportData.push(allData)
66
+
67
+ return reportData
68
+ }
69
+
70
+ async function createTripReportByDevice(from, to) {
71
+ const devices = userData.devices
72
+ const allData = {
73
+ devices: [],
74
+ from: from,
75
+ to: to
76
+ }
77
+
78
+ devices.sort((a, b) => (a.name > b.name) ? 1 : -1)
79
+
80
+ const devicesToSlice = devices.slice()
81
+ const route = await traccar.getRoute(traccarInstance, from, to, devicesToSlice)
82
+
83
+ console.log('Route:' + route.length)
84
+
85
+ if (route.length > 0) {
86
+ allData.devices = processDevices(from, to, devices, route)
87
+ }
88
+
89
+ return allData
90
+ }
91
+
92
+ function processDevices(from, to, devices, routes) {
93
+ const devicesResult = []
94
+
95
+ devices.forEach(d => {
96
+ const route = routes.filter(p => p.deviceId === d.id)
97
+
98
+ const idleEvents = []
99
+ let inIdle = false
100
+ route.forEach(p => {
101
+ if(p.attributes.ignition && p.speed === 0){
102
+ if(!inIdle) {
103
+ const idleEvent = {
104
+ position: p,
105
+ idleTime: 0
106
+ }
107
+ idleEvents.push(idleEvent)
108
+ inIdle = true
109
+ }
110
+ } else if(inIdle) {
111
+ const currentIdleEvent = idleEvents[idleEvents.length-1]
112
+ currentIdleEvent.idleTime = new Date(p.fixTime) - new Date(currentIdleEvent.position.fixTime)
113
+ inIdle = false
114
+ }
115
+ })
116
+
117
+ if(idleEvents.length) {
118
+ const deviceData = {
119
+ device: d,
120
+ idleEvents: idleEvents
121
+ }
122
+ devicesResult.push(deviceData)
123
+ }
124
+ })
125
+
126
+ return devicesResult
127
+ }
128
+
129
+ async function exportIdleReportToPDF(userData, reportData) {
130
+ console.log('Export to PDF')
131
+
132
+ const lang = userData.user.attributes.lang
133
+ const timezone = userData.user.attributes.timezone
134
+ const translations = messages[lang] ? messages[lang] : messages['en-GB']
135
+
136
+ const idleData = userData.byDriver ? reportData.drivers : reportData.devices
137
+
138
+ const headers = [
139
+ translations.report.date,
140
+ translations.report.address,
141
+ translations.report.duration
142
+ ]
143
+
144
+ if (userData.byDriver) {
145
+ headers.push(translations.report.vehicle)
146
+ } else {
147
+ headers.push(translations.report.driver)
148
+ }
149
+
150
+ if (idleData) {
151
+ let first = true
152
+ const doc = new jsPDF.jsPDF('l');
153
+ await headerFromUser(doc, translations.report.titleIdleReport, userData.user)
154
+
155
+ idleData.forEach(d => {
156
+ try {
157
+ let data = []
158
+
159
+ const name = userData.byDriver ? d.driver.name : deviceName(d.device)
160
+ const group = userData.byDriver ? userData.groups.find(g => g.drivers.includes(d.id)) : userData.groups.find(g => d.device.groupId === g.id)
161
+
162
+ let space = 0
163
+ if(!first) {
164
+ doc.addPage()
165
+ } else {
166
+ first = false
167
+ space = 10
168
+ }
169
+ doc.setFontSize(13)
170
+ doc.text(name, 20, space+20 )
171
+ doc.setFontSize(11)
172
+ doc.text(group ? translations.report.group + ': ' + group.name : '', 150, space+20 )
173
+ doc.text(convertToLocaleString(reportData.from, lang, timezone) + ' - ' + convertToLocaleString(reportData.to, lang, timezone), 20, space+25 )
174
+
175
+ d.idleEvents.map(a => {
176
+ const temp = [
177
+ getIdleEventDate(a, userData.user),
178
+ a.position.address,
179
+ convertMS(a.idleTime, true),
180
+ userData.byDriver ? a.deviceName : a.driver
181
+ ]
182
+
183
+ data.push(temp)
184
+ })
185
+
186
+ const footValues = [
187
+ 'Total:' + d.idleEvents.length,
188
+ '',
189
+ convertMS(d.idleEvents.reduce((a, b) => a + b.idleTime, 0), true)
190
+ ]
191
+
192
+ if(userData.roadSpeedLimits){
193
+ footValues.splice(2, 0, '')
194
+ }
195
+
196
+ doc.addFileToVFS("Amiri-Regular.ttf", AmiriRegular());
197
+ doc.addFont("Amiri-Regular.ttf", "Amiri", "normal");
198
+
199
+ const style = getStyle(getUserPartner(userData.user))
200
+ doc.autoTable({
201
+ head: [headers],
202
+ body: data,
203
+ foot: [footValues],
204
+ showFoot: 'lastPage',
205
+ headStyles: {
206
+ fillColor: style.pdfHeaderColor,
207
+ textColor: style.pdfHeaderTextColor,
208
+ fontSize: 10
209
+ },
210
+ bodyStyles: {
211
+ fillColor: style.pdfBodyColor,
212
+ textColor: style.pdfBodyTextColor,
213
+ fontSize: 8,
214
+ font: timezone === 'Asia/Qatar' ? "Amiri" : ''
215
+
216
+ },
217
+ footStyles: {
218
+ fillColor: style.pdfFooterColor,
219
+ textColor: style.pdfFooterTextColor,
220
+ fontSize: 9
221
+ },
222
+ startY: space+35 });
223
+ } catch (e) {
224
+ console.error(e, 'moving on...')
225
+ }
226
+ })
227
+
228
+ return doc
229
+ }
230
+ }
231
+
232
+ function exportIdleReportToExcel(userData, reportData) {
233
+ console.log('Export to Excel')
234
+
235
+ const lang = userData.user.attributes.lang
236
+ const translations = messages[lang] ? messages[lang] : messages['en-GB']
237
+
238
+ const idleData = userData.byDriver ? reportData.drivers : reportData.devices
239
+
240
+ const settings = {
241
+ sheetName: translations.report.titleIdleReport.substring(0, 31), // The name of the sheet
242
+ fileName: fileName, // The name of the spreadsheet
243
+ }
244
+ const headers = [
245
+ userData.byDriver ? {label: translations.report.driver, value:'driver'} : {label: translations.report.vehicle, value:'name'},
246
+ {label: translations.report.date, value:'fixTime'},
247
+ {label: translations.report.address, value:'address'},
248
+ {label: translations.report.duration, value:'duration'},
249
+ userData.byDriver ? {label: translations.report.vehicle, value:'name'} : {label: translations.report.driver, value:'driver'}
250
+ ]
251
+
252
+ let data = []
253
+ if (idleData) {
254
+ idleData.forEach(d => {
255
+ data = data.concat([{}])
256
+ data = data.concat(d.idleEvents.map(a => {
257
+ return {
258
+ driver: userData.byDriver ? d.driver.name : a.driver,
259
+ duration: convertMS(a.idleTime, true),
260
+ fixTime: getIdleEventDate(a, userData.user),
261
+ name: userData.byDriver ? a.deviceName : d.device.name,
262
+ address: a.position.address + (a.geofenceName ? ' - ' + a.geofenceName : '')
263
+ }
264
+ }))
265
+ })
266
+ console.log(data)
267
+ return {
268
+ headers,
269
+ data,
270
+ settings
271
+ }
272
+ }
273
+ }
274
+
275
+ function deviceName(device){
276
+ return device.name + (device.attributes.license_plate ? ', ' +device.attributes.license_plate : '') + (device.model ? ', ' + device.model : '')
277
+ }
278
+
279
+ function getIdleEventDate(row, user) {
280
+ return convertToLocaleString(row.position.fixTime, user.attributes.lang, user.attributes.timezone)
281
+ }
282
+
283
+ exports.createIdleReport = createIdleReport;
284
+ exports.exportIdleReportToPDF = exportIdleReportToPDF;
285
+ exports.exportIdleReportToExcel = exportIdleReportToExcel;
package/src/index.js CHANGED
@@ -124,6 +124,16 @@ function Reports(config, axios) {
124
124
  this.vistaWasteActivityReportToExcel = (userData, reportData) => {
125
125
  return require('./custom/vistawasteActivity-report').exportVistaWasteActivityReportToExcel(userData, reportData)
126
126
  }
127
+
128
+ this.idleReport = (from, to, userData) => {
129
+ return require('./idle-report').createIdleReport(from, to, userData, this.traccar)
130
+ }
131
+ this.idleReportToPDF = (userData, reportData) => {
132
+ return require('./idle-report').exportIdleReportToPDF(userData, reportData)
133
+ }
134
+ this.idleReportToExcel = (userData, reportData) => {
135
+ return require('./idle-report').exportIdleReportToExcel(userData, reportData)
136
+ }
127
137
  }
128
138
  module.exports = Reports
129
139
 
package/src/index.test.js CHANGED
@@ -1,60 +1,20 @@
1
1
  const {getReports} = require("./tests");
2
2
 
3
- describe('Reports', function() {
3
+ describe('speedingReport', function() {
4
4
  this.timeout(500000)
5
5
  it('test speeding', async () => {
6
6
  const report = await getReports()
7
7
  const userData = await report.getUserData()
8
8
 
9
- const reportData = await report.speedingReport(new Date(2021, 2, 30, 0, 0, 0, 0),
9
+ await report.speedingReport(new Date(2021, 2, 30, 0, 0, 0, 0),
10
10
  new Date(2021, 2, 30, 23, 59, 59, 0),
11
11
  userData)
12
-
13
- console.log(reportData)
14
-
15
- })
16
- it('test trip report', async () => {
17
- const report = await getReports()
18
- const userData = await report.getUserData()
19
- userData.byGroup = true
20
- const reportData = await report.tripReport(new Date(2021, 2, 30, 0, 0, 0, 0),
21
- new Date(2021, 2, 30, 23, 59, 59, 0),
22
- userData)
23
-
24
- console.log(reportData)
25
-
26
- })
27
- it('test event report', async () => {
28
- const report = await getReports()
29
- const userData = await report.getUserData()
30
- userData.eventTypes = []
31
- const reportData = await report.eventsReport(new Date(2021, 10, 20, 0, 0, 0, 0),
32
- new Date(2021, 10, 30, 23, 59, 59, 0),
33
- userData)
34
-
35
- console.log(reportData)
36
-
37
12
  })
38
13
  it('test kmsReport by day', async () => {
39
14
  const reports = await getReports()
40
15
  const userData = await reports.getUserData()
41
16
  userData.groupByDay = true
42
- const reportData = await reports.kmsReport(new Date(2021, 10, 1), new Date(2021, 10, 3),
43
- userData)
44
-
45
- console.log(reportData)
46
-
47
- await reports.kmsReportToPDF(userData, reportData[0])
48
- })
49
- it('test locationReport by day', async () => {
50
- const reports = await getReports()
51
- const userData = await reports.getUserData()
52
- userData.groupByDay = true
53
- const reportData = await reports.locations(new Date(2021, 10, 1), new Date(2021, 10, 3),
17
+ await reports.kmsReport(new Date(2021, 9), new Date(2021, 10),
54
18
  userData)
55
-
56
- console.log(reportData)
57
-
58
- await reports.kmsReportToPDF(userData, reportData[0])
59
19
  })
60
20
  })
@@ -1,7 +1,7 @@
1
1
  const messages = require('../lang')
2
2
  const jsPDF = require('jspdf')
3
3
  const {convertMS, convertToLocaleString} = require("./util/utils")
4
- const {headerFromUser} = require("./util/pdfDocument")
4
+ const {headerFromUser, AmiriRegular} = require("./util/pdfDocument")
5
5
  require('jspdf-autotable')
6
6
  const { parse } = require('wkt')
7
7
  const turf = require('turf')
@@ -205,7 +205,7 @@ async function findEventsPosition(from, to, devices, events, routes){
205
205
  }
206
206
 
207
207
  async function getCustomSpeedLimitEvents(devices, routes){
208
- console.log('calculate custom speed limit events')
208
+ console.log('custom speed limit events')
209
209
  const events = []
210
210
  const maxSpeed = userData.customSpeed / 1.85200
211
211
 
@@ -235,12 +235,15 @@ async function getCustomSpeedLimitEvents(devices, routes){
235
235
  }
236
236
 
237
237
  async function getHereEvents(devices, routes, threshold){
238
- console.log('calculate custom speed limit events')
238
+ console.log('here speed limit events')
239
239
  const events = []
240
+ const hereData = {}
241
+ await Promise.all(devices.map(d =>
242
+ here.routeMatch(routes.filter(p => p.deviceId === d.id)).then(r => d.results = r)
243
+ ))
240
244
  for (const d of devices) {
241
- const positions = routes.filter(p => p.deviceId === d.id)
242
245
  try {
243
- const results = await here.routeMatch(positions)
246
+ const results = d.results
244
247
  const hereAlerts = results.filter(r => r.currentSpeedKmh > (parseInt(r.speedLimit) + threshold)).map(r => {
245
248
  const position = positions.find(p => new Date(p.fixTime).getTime() === r.timestamp)
246
249
  return {
@@ -263,7 +266,7 @@ async function getHereEvents(devices, routes, threshold){
263
266
  })
264
267
  events.push(...reduced)
265
268
  } catch (e) {
266
- //console.error(e)
269
+ console.error(e)
267
270
  }
268
271
  }
269
272
  return events
@@ -394,6 +397,9 @@ async function exportSpeedingReportToPDF(userData, reportData) {
394
397
  footValues.splice(2, 0, '')
395
398
  }
396
399
 
400
+ doc.addFileToVFS("Amiri-Regular.ttf", AmiriRegular());
401
+ doc.addFont("Amiri-Regular.ttf", "Amiri", "normal");
402
+
397
403
  const style = getStyle(getUserPartner(userData.user))
398
404
  doc.autoTable({
399
405
  head: [headers],
@@ -408,7 +414,8 @@ async function exportSpeedingReportToPDF(userData, reportData) {
408
414
  bodyStyles: {
409
415
  fillColor: style.pdfBodyColor,
410
416
  textColor: style.pdfBodyTextColor,
411
- fontSize: 8
417
+ fontSize: 8,
418
+ font: timezone === 'Asia/Qatar' ? "Amiri" : ''
412
419
  },
413
420
  footStyles: {
414
421
  fillColor: style.pdfFooterColor,