fleetmap-reports 1.0.288 → 1.0.292
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/.idea/aws.xml +17 -0
- package/.idea/codeStyles/Project.xml +7 -0
- package/{fleetmap-reports.iml → .idea/fleetmap-reports.iml} +2 -1
- package/.idea/jsLibraryMappings.xml +1 -1
- package/.idea/modules.xml +1 -1
- package/.idea/vcs.xml +1 -1
- package/lang/enGB.js +12 -2
- package/lang/esCL.js +10 -1
- package/lang/index.js +4 -1
- package/lang/ptBR.js +11 -1
- package/lang/ptPT.js +11 -1
- package/package.json +2 -1
- package/src/activity-report.js +542 -206
- package/src/automaticReports.js +1 -1
- package/src/events-report.js +25 -21
- package/src/here.js +1 -1
- package/src/idle-report.js +285 -0
- package/src/index.js +12 -2
- package/src/index.test.js +18 -25
- package/src/kms-report.js +409 -103
- package/src/location-report.js +22 -18
- package/src/refueling-report.js +11 -1
- package/src/reportStyle.js +26 -0
- package/src/speeding-report.js +239 -180
- package/src/tests/index.js +22 -0
- package/src/trip-report.js +152 -159
- package/src/util/driver.js +5 -13
- package/src/util/pdfDocument.js +58 -0
- package/src/util/traccar.js +72 -0
- package/src/util/trips.js +76 -0
- package/src/util/utils.js +67 -1
- package/src/zone-report.js +22 -23
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const automaticReports = require("../automaticReports");
|
|
2
|
+
|
|
3
|
+
async function getRoute(traccar, from, to, devices){
|
|
4
|
+
const devicesToSlice = devices.slice()
|
|
5
|
+
|
|
6
|
+
const arrayOfArrays = automaticReports.sliceArray(devicesToSlice)
|
|
7
|
+
let requests = []
|
|
8
|
+
for (const a of arrayOfArrays) {
|
|
9
|
+
const promise = traccar.reports.reportsRouteGet(from, to, a.map(d => d.id))
|
|
10
|
+
requests = requests.concat(promise)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const result = await Promise.all(requests)
|
|
14
|
+
return result.map(r => r.data).flat()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function getTrips(traccar, from, to, devices){
|
|
18
|
+
const devicesToSlice = devices.slice()
|
|
19
|
+
const arrayOfArrays = automaticReports.sliceArray(devicesToSlice)
|
|
20
|
+
let requests = []
|
|
21
|
+
for (const a of arrayOfArrays) {
|
|
22
|
+
const promise = traccar.reports.reportsTripsGet(from, to, a.map(d => d.id))
|
|
23
|
+
requests = requests.concat(promise)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const result = await Promise.all(requests)
|
|
27
|
+
return result.map(r => r.data).flat()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function getStops(traccar, from, to, devices){
|
|
31
|
+
const devicesToSlice = devices.slice()
|
|
32
|
+
const arrayOfArrays = automaticReports.sliceArray(devicesToSlice)
|
|
33
|
+
let requests = []
|
|
34
|
+
for (const a of arrayOfArrays) {
|
|
35
|
+
const promise = traccar.reports.reportsStopsGet(from, to, a.map(d => d.id))
|
|
36
|
+
requests = requests.concat(promise)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const result = await Promise.all(requests)
|
|
40
|
+
return result.map(r => r.data).flat()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function getEvents(traccar, from, to, devices, events){
|
|
44
|
+
const devicesToSlice = devices.slice()
|
|
45
|
+
const arrayOfArrays = automaticReports.sliceArray(devicesToSlice)
|
|
46
|
+
let requests = []
|
|
47
|
+
for (const a of arrayOfArrays) {
|
|
48
|
+
const promise = traccar.reports.reportsEventsGet(from, to, a.map(d => d.id), null, events)
|
|
49
|
+
requests = requests.concat(promise)
|
|
50
|
+
}
|
|
51
|
+
const result = await Promise.all(requests)
|
|
52
|
+
return result.map(r => r.data).flat()
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function getSummary(traccar, from, to, devices){
|
|
56
|
+
const devicesToSlice = devices.slice()
|
|
57
|
+
const arrayOfArrays = automaticReports.sliceArray(devicesToSlice)
|
|
58
|
+
let requests = []
|
|
59
|
+
for (const a of arrayOfArrays) {
|
|
60
|
+
const promise = traccar.reports.reportsSummaryGet(from, to, a.map(d => d.id))
|
|
61
|
+
requests = requests.concat(promise)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const result = await Promise.all(requests)
|
|
65
|
+
return result.map(r => r.data).flat()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
exports.getRoute = getRoute
|
|
69
|
+
exports.getTrips = getTrips
|
|
70
|
+
exports.getStops = getStops
|
|
71
|
+
exports.getEvents = getEvents
|
|
72
|
+
exports.getSummary = getSummary
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
const traccar = require("./traccar");
|
|
2
|
+
const {coordsDistance} = require("./utils");
|
|
3
|
+
|
|
4
|
+
const minDistance = 0
|
|
5
|
+
const minAvgSpeed = 0
|
|
6
|
+
|
|
7
|
+
function addNearestPOIs(trips, userData){
|
|
8
|
+
trips.forEach(t => {
|
|
9
|
+
t.totalKms = t.distance / 1000
|
|
10
|
+
|
|
11
|
+
const distance = userData.geofences
|
|
12
|
+
.filter(g => g && g.area.startsWith('CIRCLE'))
|
|
13
|
+
.map(g => {
|
|
14
|
+
const str = g.area.substring('CIRCLE ('.length, g.area.indexOf(','))
|
|
15
|
+
const coord = str.trim().split(' ')
|
|
16
|
+
return {
|
|
17
|
+
p: g,
|
|
18
|
+
distance: Math.round(coordsDistance(parseFloat(coord[1]), parseFloat(coord[0]), t.endLon, t.endLat))
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
const nearestPOIs = distance.filter(a => a.distance < 100).sort((a, b) => (a.distance > b.distance) ? 1 : -1)
|
|
22
|
+
if (nearestPOIs.length > 0) {
|
|
23
|
+
t.endPOIName = nearestPOIs[0].p.name
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function checkTripsKms(traccarInstance, from, to, routeData, tripsData, devices) {
|
|
29
|
+
console.log('checkTripsKms')
|
|
30
|
+
const trips = tripsData.filter(t => t.distance === minDistance && t.averageSpeed > minAvgSpeed)
|
|
31
|
+
if(trips.length > 0) {
|
|
32
|
+
//Vehicles with imported positions. calculate trip distance with route positions
|
|
33
|
+
const route = routeData.length === 0 ? await traccar.getRoute(traccarInstance, from, to, devices) : routeData
|
|
34
|
+
trips.forEach(t => {
|
|
35
|
+
if(t.distance === minDistance && t.averageSpeed > minAvgSpeed) {
|
|
36
|
+
const tripRoute = route.filter(p => p.deviceId === t.deviceId
|
|
37
|
+
&& new Date(p.fixTime).getTime() >= new Date(t.startTime).getTime()
|
|
38
|
+
&& new Date(p.fixTime).getTime() <= new Date(t.endTime).getTime())
|
|
39
|
+
t.distance = tripRoute.reduce((a, b) => a + b.attributes.distance, 0)
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function isInsideTimetable(t, userData){
|
|
46
|
+
const tripStart = new Date(t.startTime)
|
|
47
|
+
const tripEnd = new Date(t.endTime)
|
|
48
|
+
|
|
49
|
+
if((tripStart.getDay() === 0 && userData.weekDays.sunday) ||
|
|
50
|
+
(tripStart.getDay() === 1 && userData.weekDays.monday) ||
|
|
51
|
+
(tripStart.getDay() === 2 && userData.weekDays.tuesday) ||
|
|
52
|
+
(tripStart.getDay() === 3 && userData.weekDays.wednesday) ||
|
|
53
|
+
(tripStart.getDay() === 4 && userData.weekDays.thursday) ||
|
|
54
|
+
(tripStart.getDay() === 5 && userData.weekDays.friday) ||
|
|
55
|
+
(tripStart.getDay() === 6 && userData.weekDays.saturday)) {
|
|
56
|
+
|
|
57
|
+
const startDate = new Date(new Date(tripStart).toISOString().split('T')[0] + ' '+userData.dayHours.startTime)
|
|
58
|
+
const endDate = new Date(new Date(tripStart).toISOString().split('T')[0] + ' '+userData.dayHours.endTime)
|
|
59
|
+
|
|
60
|
+
console.log(tripStart, startDate, endDate)
|
|
61
|
+
|
|
62
|
+
//Trips inside time period
|
|
63
|
+
if(startDate.getTime() < endDate.getTime()) {
|
|
64
|
+
return tripStart.getTime() > startDate.getTime() && tripEnd.getTime() < endDate.getTime()
|
|
65
|
+
} else {
|
|
66
|
+
return (tripStart.getTime() < endDate.getTime() && tripEnd.getTime() < endDate.getTime()) ||
|
|
67
|
+
(tripStart.getTime() > startDate.getTime())
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return false
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
exports.checkTripsKms = checkTripsKms
|
|
75
|
+
exports.isInsideTimetable = isInsideTimetable
|
|
76
|
+
exports.addNearestPOIs = addNearestPOIs
|
package/src/util/utils.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
const axios = require('axios')
|
|
2
2
|
const turf = require('turf')
|
|
3
3
|
|
|
4
4
|
function convertMS(duration, withSeconds) {
|
|
@@ -29,6 +29,72 @@ function coordsDistance(lon1, lat1, lon2, lat2) {
|
|
|
29
29
|
return (turf.distance(from, to, 'meters'))
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
function getDates(startDate, endDate) {
|
|
33
|
+
const dates = []
|
|
34
|
+
let currentDate = new Date(startDate.toISOString().split('T')[0] + ' 12:00 PM')
|
|
35
|
+
const addDays = function (days) {
|
|
36
|
+
const date = new Date(this.valueOf())
|
|
37
|
+
date.setDate(date.getDate() + days)
|
|
38
|
+
return date
|
|
39
|
+
}
|
|
40
|
+
while (currentDate <= endDate) {
|
|
41
|
+
dates.push(currentDate)
|
|
42
|
+
currentDate = addDays.call(currentDate, 1)
|
|
43
|
+
}
|
|
44
|
+
return dates
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function getImgFromUrl(hostname) {
|
|
48
|
+
try {
|
|
49
|
+
const img = new Image()
|
|
50
|
+
img.src = '/img/logos/' + hostname + '.png'
|
|
51
|
+
return img
|
|
52
|
+
} catch (e) {
|
|
53
|
+
const response = await axios.get('https://' + hostname + '/img/logos/' + hostname + '.png', { responseType: 'arraybuffer' })
|
|
54
|
+
return Buffer.from(response.data, 'binary').toString('base64')
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function isClientSide() { return (typeof window !== "undefined") }
|
|
59
|
+
|
|
60
|
+
function convertToLocaleString(value, lang, timezone){
|
|
61
|
+
if(isClientSide()){
|
|
62
|
+
return new Date(value).toLocaleString()
|
|
63
|
+
} else {
|
|
64
|
+
return new Date(value).toLocaleString(lang, {
|
|
65
|
+
timeZone: timezone,
|
|
66
|
+
hour12: false
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function convertToLocaleDateString(value, lang, timezone){
|
|
72
|
+
if(isClientSide){
|
|
73
|
+
return new Date(value).toLocaleDateString()
|
|
74
|
+
} else {
|
|
75
|
+
return new Date(value).toLocaleDateString(lang, {
|
|
76
|
+
timeZone: timezone,
|
|
77
|
+
hour12: false
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function convertToLocaleTimeString(value, lang, timezone){
|
|
83
|
+
if(isClientSide){
|
|
84
|
+
return new Date(value).toLocaleTimeString()
|
|
85
|
+
} else {
|
|
86
|
+
return new Date(value).toLocaleTimeString(lang, {
|
|
87
|
+
timeZone: timezone,
|
|
88
|
+
hour12: false
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
exports.getImgFromUrl = getImgFromUrl
|
|
32
94
|
exports.convertMS = convertMS
|
|
33
95
|
exports.coordsDistance = coordsDistance
|
|
96
|
+
exports.getDates = getDates
|
|
97
|
+
exports.convertToLocaleString = convertToLocaleString
|
|
98
|
+
exports.convertToLocaleDateString = convertToLocaleDateString
|
|
99
|
+
exports.convertToLocaleTimeString = convertToLocaleTimeString
|
|
34
100
|
|
package/src/zone-report.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
const moment = require('moment')
|
|
2
2
|
const messages = require('../lang')
|
|
3
3
|
const automaticReports = require("./automaticReports");
|
|
4
|
-
const {convertMS} = require("./util/utils")
|
|
4
|
+
const {convertMS, convertToLocaleString} = require("./util/utils")
|
|
5
5
|
const jsPDF = require('jspdf')
|
|
6
6
|
require('jspdf-autotable')
|
|
7
|
-
const
|
|
7
|
+
const {headerFromUser} = require("./util/pdfDocument");
|
|
8
|
+
const {getStyle} = require("./reportStyle")
|
|
9
|
+
const {getUserPartner} = require("fleetmap-partners");
|
|
8
10
|
|
|
9
11
|
const fileName = 'ZoneReport'
|
|
10
12
|
|
|
@@ -144,10 +146,11 @@ async function processDevices(from, to, devices, drivers, geofences, data, tracc
|
|
|
144
146
|
return devicesResult
|
|
145
147
|
}
|
|
146
148
|
|
|
147
|
-
function exportZoneReportToPDF(userData, reportData) {
|
|
149
|
+
async function exportZoneReportToPDF(userData, reportData) {
|
|
148
150
|
console.log('Export to PDF')
|
|
149
151
|
|
|
150
152
|
const lang = userData.user.attributes.lang
|
|
153
|
+
const timezone = userData.user.attributes.timezone
|
|
151
154
|
const translations = messages[lang] ? messages[lang] : messages['en-GB']
|
|
152
155
|
|
|
153
156
|
const headers = [
|
|
@@ -160,9 +163,7 @@ function exportZoneReportToPDF(userData, reportData) {
|
|
|
160
163
|
if (reportData.devices) {
|
|
161
164
|
let first = true
|
|
162
165
|
const doc = new jsPDF.jsPDF('l')
|
|
163
|
-
doc.
|
|
164
|
-
doc.text(translations.report.titleActivityReport, 15, 15 )
|
|
165
|
-
|
|
166
|
+
await headerFromUser(doc, translations.report.titleZoneReport, userData.user)
|
|
166
167
|
|
|
167
168
|
reportData.devices.forEach(d => {
|
|
168
169
|
let data = []
|
|
@@ -176,11 +177,11 @@ function exportZoneReportToPDF(userData, reportData) {
|
|
|
176
177
|
first = false
|
|
177
178
|
space = 10
|
|
178
179
|
}
|
|
179
|
-
doc.setFontSize(
|
|
180
|
+
doc.setFontSize(13)
|
|
180
181
|
doc.text(name, 20, space+20 )
|
|
181
|
-
doc.setFontSize(
|
|
182
|
+
doc.setFontSize(11)
|
|
182
183
|
doc.text(group ? translations.report.group + ': ' + group.name : '', 200, space+20 )
|
|
183
|
-
doc.text(
|
|
184
|
+
doc.text(convertToLocaleString(d.from, lang, timezone) + ' - ' + convertToLocaleString(d.to, lang, timezone), 20, space+25 )
|
|
184
185
|
d.geofences.map(a => {
|
|
185
186
|
const temp = [
|
|
186
187
|
geofenceEnter(userData.user, a),
|
|
@@ -196,22 +197,26 @@ function exportZoneReportToPDF(userData, reportData) {
|
|
|
196
197
|
'Total:' + d.geofences.length
|
|
197
198
|
]
|
|
198
199
|
|
|
200
|
+
const style = getStyle(getUserPartner(userData.user))
|
|
199
201
|
doc.autoTable({
|
|
200
202
|
head: [headers],
|
|
201
203
|
body: data,
|
|
202
204
|
foot: [footValues],
|
|
203
205
|
showFoot: 'lastPage',
|
|
204
206
|
headStyles: {
|
|
205
|
-
fillColor:
|
|
206
|
-
textColor:
|
|
207
|
+
fillColor: style.pdfHeaderColor,
|
|
208
|
+
textColor: style.pdfHeaderTextColor,
|
|
209
|
+
fontSize: 10
|
|
207
210
|
},
|
|
208
211
|
bodyStyles: {
|
|
209
|
-
fillColor:
|
|
210
|
-
textColor:
|
|
212
|
+
fillColor: style.pdfBodyColor,
|
|
213
|
+
textColor: style.pdfBodyTextColor,
|
|
214
|
+
fontSize: 8
|
|
211
215
|
},
|
|
212
216
|
footStyles: {
|
|
213
|
-
fillColor:
|
|
214
|
-
textColor:
|
|
217
|
+
fillColor: style.pdfFooterColor,
|
|
218
|
+
textColor: style.pdfFooterTextColor,
|
|
219
|
+
fontSize: 9
|
|
215
220
|
},
|
|
216
221
|
startY: space+35 });
|
|
217
222
|
})
|
|
@@ -267,16 +272,10 @@ function deviceName(device){
|
|
|
267
272
|
}
|
|
268
273
|
|
|
269
274
|
function geofenceEnter(user, row){
|
|
270
|
-
return row.inTime ?
|
|
271
|
-
timeZone: user.attributes.timezone,
|
|
272
|
-
hour12: false
|
|
273
|
-
}) : ''
|
|
275
|
+
return row.inTime ? convertToLocaleString(row.inTime.fixTime, user.attributes.lang, user.attributes.timezone) : ''
|
|
274
276
|
}
|
|
275
277
|
function geofenceExit(user, row){
|
|
276
|
-
return row.outTime ?
|
|
277
|
-
timeZone: user.attributes.timezone,
|
|
278
|
-
hour12: false
|
|
279
|
-
}) : ''
|
|
278
|
+
return row.outTime ? convertToLocaleString(row.outTime.fixTime, user.attributes.lang, user.attributes.timezone) : ''
|
|
280
279
|
}
|
|
281
280
|
|
|
282
281
|
exports.createZoneReport = createZoneReport
|