fleetmap-reports 2.0.358 → 2.0.359

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 (81) hide show
  1. package/package.json +1 -1
  2. package/src/partnerReports/driverranking-report.js +39 -7
  3. package/.claude/worktrees/eager-stonebraker-c08ac7/.eslintrc.js +0 -15
  4. package/.claude/worktrees/eager-stonebraker-c08ac7/lang/enGB.js +0 -309
  5. package/.claude/worktrees/eager-stonebraker-c08ac7/lang/esCL.js +0 -297
  6. package/.claude/worktrees/eager-stonebraker-c08ac7/lang/frFR.json +0 -324
  7. package/.claude/worktrees/eager-stonebraker-c08ac7/lang/index.js +0 -35
  8. package/.claude/worktrees/eager-stonebraker-c08ac7/lang/ptBR.js +0 -301
  9. package/.claude/worktrees/eager-stonebraker-c08ac7/lang/ptPT.js +0 -310
  10. package/.claude/worktrees/eager-stonebraker-c08ac7/package-lock.json +0 -11944
  11. package/.claude/worktrees/eager-stonebraker-c08ac7/package.json +0 -45
  12. package/.claude/worktrees/eager-stonebraker-c08ac7/src/activity-report.js +0 -822
  13. package/.claude/worktrees/eager-stonebraker-c08ac7/src/automaticReports.js +0 -34
  14. package/.claude/worktrees/eager-stonebraker-c08ac7/src/carbone/index.js +0 -13
  15. package/.claude/worktrees/eager-stonebraker-c08ac7/src/custom/vistawasteActivity-report.js +0 -544
  16. package/.claude/worktrees/eager-stonebraker-c08ac7/src/events-report.js +0 -360
  17. package/.claude/worktrees/eager-stonebraker-c08ac7/src/fuel-consumption-report.js +0 -296
  18. package/.claude/worktrees/eager-stonebraker-c08ac7/src/fuel-drop-report.js +0 -128
  19. package/.claude/worktrees/eager-stonebraker-c08ac7/src/here.js +0 -172
  20. package/.claude/worktrees/eager-stonebraker-c08ac7/src/idle-report.js +0 -403
  21. package/.claude/worktrees/eager-stonebraker-c08ac7/src/index.js +0 -244
  22. package/.claude/worktrees/eager-stonebraker-c08ac7/src/kms-report.js +0 -549
  23. package/.claude/worktrees/eager-stonebraker-c08ac7/src/location-report.js +0 -496
  24. package/.claude/worktrees/eager-stonebraker-c08ac7/src/machines-report.js +0 -278
  25. package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/afriquia.js +0 -129
  26. package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/dailyuse-report.js +0 -80
  27. package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/delayedstart-report.js +0 -223
  28. package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/driverranking-report.js +0 -328
  29. package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/gpsjump-report.js +0 -61
  30. package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/performance-report.js +0 -359
  31. package/.claude/worktrees/eager-stonebraker-c08ac7/src/refueling-report.js +0 -345
  32. package/.claude/worktrees/eager-stonebraker-c08ac7/src/reportStyle.js +0 -34
  33. package/.claude/worktrees/eager-stonebraker-c08ac7/src/sensor-report.js +0 -447
  34. package/.claude/worktrees/eager-stonebraker-c08ac7/src/speeding-report.js +0 -663
  35. package/.claude/worktrees/eager-stonebraker-c08ac7/src/stop-report.js +0 -242
  36. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/ActivityReportTemplate.mjml +0 -51
  37. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/EmptyReportTemplate.mjml +0 -25
  38. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/EventsReportTemplate.mjml +0 -75
  39. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/FuelDropReportTemplate.mjml +0 -60
  40. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/IdleReportTemplate.mjml +0 -54
  41. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/KmsReportGroupByDayTemplate.mjml +0 -43
  42. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/KmsReportTemplate.mjml +0 -44
  43. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/LocationReportTemplate.mjml +0 -37
  44. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/RefuelingReportTemplate.mjml +0 -60
  45. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/SensorReportTemplate.mjml +0 -23
  46. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/SpeedingReportTemplate.mjml +0 -80
  47. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/TripReportTemplate.mjml +0 -97
  48. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/ZoneReportTemplate.mjml +0 -52
  49. package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/report.mjml +0 -96
  50. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/activity.test.js +0 -99
  51. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/carbone.test.js +0 -20
  52. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/events.test.js +0 -30
  53. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/fuel.test.js +0 -35
  54. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/idle.test.js +0 -16
  55. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/index.js +0 -24
  56. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/index.test.js +0 -203
  57. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/kms.test.js +0 -74
  58. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/performance.test.js +0 -36
  59. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/positions.test.js +0 -67
  60. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/speeding.test.js +0 -120
  61. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/translations.test.js +0 -21
  62. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/trips.test.js +0 -140
  63. package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/zones.test.js +0 -162
  64. package/.claude/worktrees/eager-stonebraker-c08ac7/src/trip-report.js +0 -641
  65. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/device.js +0 -13
  66. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/driver.js +0 -90
  67. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/fuel.js +0 -102
  68. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/geofence.js +0 -52
  69. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/odoo.js +0 -18
  70. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/parallel.js +0 -64
  71. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/pdfDocument.js +0 -140
  72. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/route.js +0 -78
  73. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/timetable.js +0 -30
  74. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/traccar.js +0 -213
  75. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/traccar.worker.js +0 -49
  76. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/trips.js +0 -270
  77. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/utils.js +0 -358
  78. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/worker.js +0 -14
  79. package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/xpert.js +0 -58
  80. package/.claude/worktrees/eager-stonebraker-c08ac7/src/word/index.js +0 -95
  81. package/.claude/worktrees/eager-stonebraker-c08ac7/src/zone-report.js +0 -904
@@ -1,90 +0,0 @@
1
- const traccar = require('./traccar')
2
- const automaticReports = require('../automaticReports')
3
- const traccarHelper = require('./traccar')
4
- const { isInsideTimetable, isPartialInsideTimetable } = require('./trips')
5
-
6
- // get devices used by each driver between two dates
7
- async function devicesByDriver (traccarInstance, from, to, drivers, devices) {
8
- const eventsData = await traccar.getEvents(traccarInstance, from, to, devices, ['driverChanged'])
9
- const driverUniqueIdsToProcess = new Set(eventsData.map(e => e.attributes.driverUniqueId))
10
- const driversToProcess = drivers.filter(d => driverUniqueIdsToProcess.has(d.uniqueId))
11
-
12
- const deviceIdsToProcess = new Set(eventsData.map(e => e.deviceId))
13
- const devicesToProcess = devices.filter(d => deviceIdsToProcess.has(d.id))
14
-
15
- return { devices: devicesToProcess, drivers: driversToProcess }
16
- }
17
-
18
- async function reportByDriver (devices, traccar, from, to, userData, processor, allInOneData = { route: true, trips: true, stops: true, summary: false }) {
19
- const report = { drivers: [] }
20
-
21
- const sliced = automaticReports.sliceArray(devices, 5)
22
-
23
- let deviceCount = 0
24
- for (const slice of sliced) {
25
- const allInOne = await traccarHelper.getAllInOne(traccar, from, to, slice, allInOneData.route, allInOneData.trips, allInOneData.stops, allInOneData.summary, deviceCount, devices.length)
26
- const results = await processor(from, to, userData, { trips: allInOne.trips, route: allInOne.route, stops: allInOne.stops })
27
- report.drivers.push(...results)
28
- deviceCount = deviceCount + slice.length
29
- }
30
-
31
- return report
32
- }
33
-
34
- function getDriverUniqueIdTimeline (driverUniqueIdTimeline, driverUniqueId, date) {
35
- if (!driverUniqueIdTimeline) {
36
- return undefined
37
- }
38
-
39
- return driverUniqueIdTimeline.find(d => d.uniqueId === driverUniqueId &&
40
- (!d.startDate || new Date(d.startDate) <= new Date(date)) &&
41
- (!d.endDate || new Date(d.endDate) >= new Date(date)))
42
- }
43
-
44
- function getDriverName (driverUniqueId, date, userData) {
45
- if (driverUniqueId) {
46
- const timeline = getDriverUniqueIdTimeline(userData.driverUniqueIdTimeline, driverUniqueId, date)
47
-
48
- if (timeline) {
49
- return timeline.driverName
50
- }
51
-
52
- const driver = userData.drivers ? userData.drivers.find(d => !d.uniqueId.localeCompare(driverUniqueId, undefined, { sensitivity: 'base' })) : undefined
53
-
54
- return driver
55
- ? driver.name + ' ' + ((driver.attributes && driver.attributes.notes) || '')
56
- : driverUniqueId
57
- }
58
-
59
- return ''
60
- }
61
-
62
- async function getDriverData (d, data, userData) {
63
- const route = data.route ? data.route.filter(p => !d.uniqueId.localeCompare(p.attributes.driverUniqueId, undefined, { sensitivity: 'base' })) : undefined
64
- const trips = data.trips ? data.trips.filter(t => !d.uniqueId.localeCompare(t.driverUniqueId, undefined, { sensitivity: 'base' })) : undefined
65
- const events = data.events ? data.events.filter(e => e.position && !d.uniqueId.localeCompare(e.position.attributes.driverUniqueId, undefined, { sensitivity: 'base' })) : undefined
66
-
67
- const filteredTrips = []
68
- if (trips) {
69
- for (const t of trips) {
70
- if (userData.allWeek ||
71
- !userData.weekDays ||
72
- isInsideTimetable(t, userData) ||
73
- await isPartialInsideTimetable(undefined, t, userData, route)) {
74
- filteredTrips.push(t)
75
- }
76
- }
77
- }
78
-
79
- return {
80
- route,
81
- trips: filteredTrips,
82
- events
83
- }
84
- }
85
-
86
- exports.getDriverData = getDriverData
87
- exports.getDriverName = getDriverName
88
- exports.getDriverUniqueIdTimeline = getDriverUniqueIdTimeline
89
- exports.devicesByDriver = devicesByDriver
90
- exports.reportByDriver = reportByDriver
@@ -1,102 +0,0 @@
1
- function calculateFuelDiff (a, b) {
2
- return b - a
3
- }
4
-
5
- function getRefuelingLiters (d, position, diff) {
6
- if (position.protocol === 'teltonika' && !position.attributes.io89) {
7
- return diff
8
- }
9
- return Math.round(diff * d.attributes.fuel_tank_capacity / 100)
10
- }
11
-
12
- function calculateTotalFuelFromSensor(trips, stops, positions, device, firstStopIndex) {
13
- const lastStopIndex = firstStopIndex + trips.length - 1
14
- const lastStop = stops.length > lastStopIndex ? stops[lastStopIndex] : null
15
- const firstTripStart = new Date(trips[0].startTime).getTime()
16
- const lastEndTime = lastStop ? new Date(lastStop.endTime).getTime() : new Date(trips[trips.length - 1].endTime).getTime()
17
-
18
- const rangePositions = positions.filter(p => {
19
- const t = new Date(p.fixTime).getTime()
20
- return t >= firstTripStart && t <= lastEndTime && p.attributes.fuel != null
21
- })
22
-
23
- if (rangePositions.length < 2) return 0
24
-
25
- const invertedSensor = device.attributes.fuel_low_threshold > device.attributes.fuel_high_threshold
26
- const sensorRange = Math.abs(device.attributes.fuel_high_threshold - device.attributes.fuel_low_threshold)
27
- const refuelThreshold = sensorRange * 0.2
28
-
29
- let totalRawConsumption = 0
30
- let segmentStartFuel = rangePositions[0].attributes.fuel
31
-
32
- for (let i = 1; i < rangePositions.length; i++) {
33
- const prev = rangePositions[i - 1]
34
- const curr = rangePositions[i]
35
- // refuel = significant increase for normal sensor, significant decrease for inverted
36
- const fuelChange = invertedSensor
37
- ? prev.attributes.fuel - curr.attributes.fuel
38
- : curr.attributes.fuel - prev.attributes.fuel
39
-
40
- if (fuelChange > refuelThreshold) {
41
- const segmentRawDiff = invertedSensor
42
- ? prev.attributes.fuel - segmentStartFuel
43
- : segmentStartFuel - prev.attributes.fuel
44
- if (segmentRawDiff > 0) totalRawConsumption += segmentRawDiff
45
- segmentStartFuel = curr.attributes.fuel
46
- }
47
- }
48
-
49
- const lastFuel = rangePositions[rangePositions.length - 1].attributes.fuel
50
- const lastSegmentRawDiff = invertedSensor
51
- ? lastFuel - segmentStartFuel
52
- : segmentStartFuel - lastFuel
53
- if (lastSegmentRawDiff > 0) totalRawConsumption += lastSegmentRawDiff
54
-
55
- if (totalRawConsumption <= 0) return 0
56
- return (totalRawConsumption / sensorRange) * device.attributes.fuel_tank_capacity
57
- }
58
-
59
-
60
- function calculateConsumption (d, data) {
61
- let fuelConsumption = 0
62
- const withFuelUsed = data.route && data.route.find(p => p.attributes.fuelUsed)
63
- if (data.summary && withFuelUsed) {
64
- fuelConsumption = calculateSpentFuel(data.summary.spentFuel, d, withFuelUsed)
65
- } else if (data.trips && data.stops) {
66
- fuelConsumption = data.trips.reduce((a, b) => a + calculateSpentFuel(b.spentFuel, d, withFuelUsed), 0) + data.stops.reduce((a, b) => a + calculateSpentFuel(b.spentFuel, d, withFuelUsed), 0)
67
- } else if (data.route && data.route.length > 1 && data.route[0].attributes.fuelUsed) {
68
- fuelConsumption = data.route[data.route.length - 1].attributes.fuelUsed - data.route[0].attributes.fuelUsed
69
- } else if (data.summary) {
70
- fuelConsumption = data.summary.spentFuel
71
- }
72
- return fuelConsumption > 0 ? fuelConsumption : 0
73
- }
74
-
75
- function calculateSpentFuel (value, device, withFuelUsed) {
76
- if (!value) { return value }
77
-
78
- if (device.attributes.xpert) {
79
- return withFuelUsed ? value : (value * device.attributes.fuel_tank_capacity) / 100
80
- }
81
-
82
- const { fuel_low_threshold, fuel_high_threshold, fuel_tank_capacity } = device.attributes
83
- if (fuel_low_threshold != null && fuel_high_threshold != null && fuel_tank_capacity) {
84
- const sensorRange = Math.abs(fuel_high_threshold - fuel_low_threshold)
85
- const rawFuel = fuel_low_threshold > fuel_high_threshold
86
- ? (value < 0 ? Math.abs(value) : 0)
87
- : value
88
- return rawFuel > 0 ? (rawFuel / sensorRange) * fuel_tank_capacity : 0
89
- }
90
-
91
- return value > 0 ? value : 0
92
- }
93
-
94
- function useOdooFuelData (d, route) {
95
- return route && route.length && !route[0].attributes.fuel && d.attributes.odooId
96
- }
97
-
98
- exports.calculateFuelDiff = calculateFuelDiff
99
- exports.getRefuelingLiters = getRefuelingLiters
100
- exports.calculateConsumption = calculateConsumption
101
- exports.useOdooFuelData = useOdooFuelData
102
- exports.calculateTotalFuelFromSensor = calculateTotalFuelFromSensor
@@ -1,52 +0,0 @@
1
- const turf = require('@turf/helpers')
2
- const inside = require('@turf/boolean-point-in-polygon')
3
- const { coordsDistance } = require('./utils')
4
- const booleanPointInPolygon = require('@turf/boolean-point-in-polygon')
5
- const distance = require('@turf/distance')
6
- const pointToLineDistance = require('@turf/point-to-line-distance')
7
-
8
- exports.insideGeofence = function insideGeofence (position, geofence) {
9
- const coords = geofence.area.slice(9, geofence.area.length - 2).split(',')
10
- const coords2 = coords.map(c => {
11
- return c.trim().split(' ').map(a => parseFloat(a))
12
- })
13
- const pt = turf.point([parseFloat(position.latitude), parseFloat(position.longitude)])
14
- const poly = turf.polygon([coords2])
15
-
16
- return inside.default(pt, poly)
17
- }
18
-
19
- exports.getNearestPOI = (position, geofences) => getNearestPOIs(position.longitude, position.latitude, geofences)[0]
20
- function getNearestPOIs (long, lat, geofences) {
21
- const distance = geofences
22
- .filter(g => g && g.area && g.area.startsWith('CIRCLE'))
23
- .map(g => {
24
- const str = g.area.substring('CIRCLE ('.length, g.area.indexOf(','))
25
- const radius = g.area.substring(g.area.indexOf(',') + 1, g.area.indexOf(')'))
26
- const coord = str.trim().split(' ')
27
- return {
28
- p: g,
29
- distance: Math.round(coordsDistance(parseFloat(coord[1]), parseFloat(coord[0]), long, lat)),
30
- r: parseFloat(radius)
31
- }
32
- })
33
- return distance.filter(a => a.distance < a.r).sort((a, b) => (a.distance > b.distance) ? 1 : -1)
34
- }
35
- exports.getNearestPOIs = getNearestPOIs
36
-
37
- exports.loadGroupsData = async function loadGroupsData (userData, traccarInstance) {
38
- for (const g of userData.groups) {
39
- g.geofenceIds = (await traccarInstance.geofences.geofencesGet(undefined, undefined, undefined, g.id, undefined, undefined).then(r => r.data)).map(g => g.id)
40
- }
41
- }
42
-
43
- exports.checkGeofenceIn = function checkGeofenceIn (p, g) {
44
- switch (g.geometry.type) {
45
- case 'Polygon':
46
- return booleanPointInPolygon.default(p, g)
47
- case 'Point':
48
- return distance.default(p, g, { units: 'meters' }) <= g.properties.distance
49
- case 'LineString':
50
- return pointToLineDistance.default(p, g, { units: 'meters' }) < (g.properties.geofence.attributes.polylineDistance || 25)
51
- }
52
- }
@@ -1,18 +0,0 @@
1
-
2
- async function getOdooFuelServices (traccar, from, to) {
3
- const url = `/odoo/reports/refuelingServices?startDate=${from.toDateString()}&endDate=${to.toDateString()}`
4
-
5
- try {
6
- const { data } = await traccar.axios.get(url, {
7
- jar: traccar.cookieJar,
8
- withCredentials: true
9
- })
10
-
11
- return data
12
- } catch (e) {
13
- console.log(e)
14
- return []
15
- }
16
- }
17
-
18
- exports.getOdooFuelServices = getOdooFuelServices
@@ -1,64 +0,0 @@
1
- const { sliceArray } = require('../automaticReports')
2
- const path = require('path')
3
-
4
- exports.parallel = (report, method, toSlice, ...args) => {
5
- const cluster = require('cluster')
6
- const numCPUs = require('os').cpus().length
7
- return new Promise((resolve, reject) => {
8
- if (cluster.isPrimary) {
9
- console.log('parallel with', numCPUs, 'cpus', 'toSlice len', toSlice.length)
10
- cluster.setupPrimary({ exec: path.resolve(__dirname, 'worker.js') })
11
- const sliced = toSlice.length > (numCPUs - 1) ? sliceArray(toSlice, toSlice.length / (numCPUs - 1)) : [toSlice]
12
- console.log('sliced in', sliced.length)
13
- const _result = []
14
- let done = 0
15
- let workerCount = 0
16
- if (!sliced.length) {
17
- console.error(report, method, 'got sliced length', sliced.length, toSlice)
18
- reject(new Error('0 to process'))
19
- }
20
- sliced.forEach((slice) => {
21
- if (!slice.length) {
22
- console.error(report, method, 'got empty slice', slice)
23
- reject(new Error('got empty slice'))
24
- }
25
- try {
26
- console.log('forking worker', workerCount++, report, method, slice.length)
27
- const worker = cluster.fork()
28
- worker.on('message', ({ result }) => {
29
- console.log('received result from worker', worker.process.pid)
30
- _result.push(result)
31
- if (++done === sliced.length) {
32
- resolve(_result.flat())
33
- }
34
- })
35
- worker.on('error', (e) => {
36
- console.error(e)
37
- reject(new Error(`Worker ${worker.process.pid} error ${e.message}`))
38
- reject(e)
39
- })
40
- worker.on('exit', (code, signal) => {
41
- if (code !== 0) {
42
- reject(new Error(`Worker ${worker.process.pid} exited with code ${code} and signal ${signal}`))
43
- }
44
- })
45
- worker.send({
46
- report,
47
- method,
48
- args: [slice, ...args]
49
- })
50
- console.log('sent to worker', worker.process.pid)
51
- } catch (e) {
52
- console.error(report, method, 'worker', workerCount, 'numCPUs', numCPUs)
53
- reject(e)
54
- }
55
- })
56
- cluster.on('exit', (worker, code, signal) => {
57
- console.log('worker died', worker.process.pid, code, signal)
58
- if (signal === 'SIGKILL') {
59
- reject(new Error(`Worker died ${worker.process.pid}, code ${code} signal ${signal}`))
60
- }
61
- })
62
- }
63
- })
64
- }