fleetmap-reports 1.0.275 → 1.0.276

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.
@@ -1,11 +1,9 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <project version="4">
3
3
  <component name="ChangeListManager">
4
- <list default="true" id="eb665c86-c893-4333-bd2a-721dc27980b9" name="Changes" comment="fix convert date to localeString">
5
- <change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
6
- <change beforePath="$PROJECT_DIR$/src/activity-report.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/activity-report.js" afterDir="false" />
4
+ <list default="true" id="eb665c86-c893-4333-bd2a-721dc27980b9" name="Changes" comment="Add idle report">
7
5
  <change beforePath="$PROJECT_DIR$/src/index.test.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/index.test.js" afterDir="false" />
8
- <change beforePath="$PROJECT_DIR$/src/kms-report.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/kms-report.js" afterDir="false" />
6
+ <change beforePath="$PROJECT_DIR$/src/speeding-report.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/speeding-report.js" afterDir="false" />
9
7
  </list>
10
8
  <option name="SHOW_DIALOG" value="false" />
11
9
  <option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -233,7 +231,9 @@
233
231
  <workItem from="1641921254910" duration="614000" />
234
232
  <workItem from="1641991863387" duration="626000" />
235
233
  <workItem from="1641992769870" duration="96000" />
236
- <workItem from="1641992912450" duration="1045000" />
234
+ <workItem from="1641992912450" duration="1734000" />
235
+ <workItem from="1642001918030" duration="2950000" />
236
+ <workItem from="1642028703547" duration="8996000" />
237
237
  </task>
238
238
  <task id="LOCAL-00001" summary="Fix getStyle">
239
239
  <created>1636983717385</created>
@@ -424,7 +424,21 @@
424
424
  <option name="project" value="LOCAL" />
425
425
  <updated>1641912050985</updated>
426
426
  </task>
427
- <option name="localTasksCounter" value="28" />
427
+ <task id="LOCAL-00028" summary="Fix activity and kms report by driver inside a time period">
428
+ <created>1641994017219</created>
429
+ <option name="number" value="00028" />
430
+ <option name="presentableId" value="LOCAL-00028" />
431
+ <option name="project" value="LOCAL" />
432
+ <updated>1641994017220</updated>
433
+ </task>
434
+ <task id="LOCAL-00029" summary="Add idle report">
435
+ <created>1642039915131</created>
436
+ <option name="number" value="00029" />
437
+ <option name="presentableId" value="LOCAL-00029" />
438
+ <option name="project" value="LOCAL" />
439
+ <updated>1642039915132</updated>
440
+ </task>
441
+ <option name="localTasksCounter" value="30" />
428
442
  <servers />
429
443
  </component>
430
444
  <component name="TypeScriptGeneratedFilesManager">
@@ -454,8 +468,6 @@
454
468
  <option name="oldMeFiltersMigrated" value="true" />
455
469
  </component>
456
470
  <component name="VcsManagerConfiguration">
457
- <MESSAGE value="Fix getStyle in all reports" />
458
- <MESSAGE value="try catch on pdf addImage" />
459
471
  <MESSAGE value="Kms report grouped by day" />
460
472
  <MESSAGE value="Fix pdf logo" />
461
473
  <MESSAGE value="kms report with parallel requests" />
@@ -479,6 +491,8 @@
479
491
  <MESSAGE value="fix trip report" />
480
492
  <MESSAGE value="fix kms report by group" />
481
493
  <MESSAGE value="fix convert date to localeString" />
482
- <option name="LAST_COMMIT_MESSAGE" value="fix convert date to localeString" />
494
+ <MESSAGE value="Fix activity and kms report by driver inside a time period" />
495
+ <MESSAGE value="Add idle report" />
496
+ <option name="LAST_COMMIT_MESSAGE" value="Add idle report" />
483
497
  </component>
484
498
  </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.276",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -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
 
@@ -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')
@@ -394,6 +394,9 @@ async function exportSpeedingReportToPDF(userData, reportData) {
394
394
  footValues.splice(2, 0, '')
395
395
  }
396
396
 
397
+ doc.addFileToVFS("Amiri-Regular.ttf", AmiriRegular());
398
+ doc.addFont("Amiri-Regular.ttf", "Amiri", "normal");
399
+
397
400
  const style = getStyle(getUserPartner(userData.user))
398
401
  doc.autoTable({
399
402
  head: [headers],
@@ -408,7 +411,8 @@ async function exportSpeedingReportToPDF(userData, reportData) {
408
411
  bodyStyles: {
409
412
  fillColor: style.pdfBodyColor,
410
413
  textColor: style.pdfBodyTextColor,
411
- fontSize: 8
414
+ fontSize: 8,
415
+ font: timezone === 'Asia/Qatar' ? "Amiri" : ''
412
416
  },
413
417
  footStyles: {
414
418
  fillColor: style.pdfFooterColor,