fleetmap-reports 2.0.357 → 2.0.358
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/.claude/worktrees/eager-stonebraker-c08ac7/.eslintrc.js +15 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/lang/enGB.js +309 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/lang/esCL.js +297 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/lang/frFR.json +324 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/lang/index.js +35 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/lang/ptBR.js +301 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/lang/ptPT.js +310 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/package-lock.json +11944 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/package.json +45 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/activity-report.js +822 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/automaticReports.js +34 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/carbone/index.js +13 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/custom/vistawasteActivity-report.js +544 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/events-report.js +360 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/fuel-consumption-report.js +296 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/fuel-drop-report.js +128 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/here.js +172 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/idle-report.js +403 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/index.js +244 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/kms-report.js +549 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/location-report.js +496 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/machines-report.js +278 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/afriquia.js +129 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/dailyuse-report.js +80 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/delayedstart-report.js +223 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/driverranking-report.js +328 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/gpsjump-report.js +61 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/partnerReports/performance-report.js +359 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/refueling-report.js +345 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/reportStyle.js +34 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/sensor-report.js +447 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/speeding-report.js +663 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/stop-report.js +242 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/ActivityReportTemplate.mjml +51 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/EmptyReportTemplate.mjml +25 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/EventsReportTemplate.mjml +75 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/FuelDropReportTemplate.mjml +60 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/IdleReportTemplate.mjml +54 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/KmsReportGroupByDayTemplate.mjml +43 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/KmsReportTemplate.mjml +44 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/LocationReportTemplate.mjml +37 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/RefuelingReportTemplate.mjml +60 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/SensorReportTemplate.mjml +23 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/SpeedingReportTemplate.mjml +80 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/TripReportTemplate.mjml +97 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/ZoneReportTemplate.mjml +52 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/templates/report.mjml +96 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/activity.test.js +99 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/carbone.test.js +20 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/events.test.js +30 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/fuel.test.js +35 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/idle.test.js +16 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/index.js +24 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/index.test.js +203 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/kms.test.js +74 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/performance.test.js +36 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/positions.test.js +67 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/speeding.test.js +120 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/translations.test.js +21 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/trips.test.js +140 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/tests/zones.test.js +162 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/trip-report.js +641 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/device.js +13 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/driver.js +90 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/fuel.js +102 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/geofence.js +52 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/odoo.js +18 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/parallel.js +64 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/pdfDocument.js +140 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/route.js +78 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/timetable.js +30 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/traccar.js +213 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/traccar.worker.js +49 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/trips.js +270 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/utils.js +358 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/worker.js +14 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/util/xpert.js +58 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/word/index.js +95 -0
- package/.claude/worktrees/eager-stonebraker-c08ac7/src/zone-report.js +904 -0
- package/lang/enGB.js +18 -0
- package/lang/esCL.js +18 -0
- package/lang/frFR.json +7 -1
- package/lang/ptBR.js +18 -0
- package/lang/ptPT.js +18 -0
- package/package.json +1 -1
- package/src/partnerReports/driverranking-report.js +149 -49
- package/src/util/pdfDocument.js +2 -1
package/lang/enGB.js
CHANGED
|
@@ -193,7 +193,25 @@ module.exports = {
|
|
|
193
193
|
titleIdleReport: 'Idle Report',
|
|
194
194
|
titleMachinesReport: 'Machines Report',
|
|
195
195
|
titleStopReport: 'Stop Report',
|
|
196
|
+
titleDriverRankingReport: 'Driver Ranking Report',
|
|
196
197
|
titleSensorReport: 'Sensor Report',
|
|
198
|
+
rank: 'Rank',
|
|
199
|
+
grade: 'Grade',
|
|
200
|
+
safetyScore: 'Safety',
|
|
201
|
+
efficiencyScore: 'Efficiency',
|
|
202
|
+
complianceScore: 'Compliance',
|
|
203
|
+
score: 'Overall Score',
|
|
204
|
+
avgFuelConsumption: 'Avg. L/100km',
|
|
205
|
+
highEngineRPM: 'High RPM',
|
|
206
|
+
hardBraking: 'Hard Braking',
|
|
207
|
+
hardAcceleration: 'Hard Acceleration',
|
|
208
|
+
hardCornering: 'Hard Cornering',
|
|
209
|
+
overspeedAlarm: 'Speeding',
|
|
210
|
+
geofenceAlarm: 'Seatbelt',
|
|
211
|
+
continuesDrivingAlarm: 'Continuous Driving',
|
|
212
|
+
reverseAlarm: 'Reverse Gear',
|
|
213
|
+
otherAlarm: 'Other',
|
|
214
|
+
detailedMetrics: 'Detailed metrics',
|
|
197
215
|
from: 'From',
|
|
198
216
|
to: 'to',
|
|
199
217
|
headerStartAddress: 'Start address',
|
package/lang/esCL.js
CHANGED
|
@@ -183,7 +183,25 @@ module.exports = {
|
|
|
183
183
|
titleIdleReport: 'Informe de Ralenti',
|
|
184
184
|
titleMachinesReport: 'Informe de Maquinas',
|
|
185
185
|
titleStopReport: 'Informe de Paradas',
|
|
186
|
+
titleDriverRankingReport: 'Informe de Ranking de Conductores',
|
|
186
187
|
titleSensorReport: 'Informe de Sensores',
|
|
188
|
+
rank: 'Posición',
|
|
189
|
+
grade: 'Calificación',
|
|
190
|
+
safetyScore: 'Seguridad',
|
|
191
|
+
efficiencyScore: 'Eficiencia',
|
|
192
|
+
complianceScore: 'Cumplimiento',
|
|
193
|
+
score: 'Puntuación General',
|
|
194
|
+
avgFuelConsumption: 'Consumo Prom. L/100km',
|
|
195
|
+
highEngineRPM: 'RPM Alto',
|
|
196
|
+
hardBraking: 'Frenado Brusco',
|
|
197
|
+
hardAcceleration: 'Aceleración Brusca',
|
|
198
|
+
hardCornering: 'Giro Brusco',
|
|
199
|
+
overspeedAlarm: 'Exceso de Velocidad',
|
|
200
|
+
geofenceAlarm: 'Cinturón de Seguridad',
|
|
201
|
+
continuesDrivingAlarm: 'Conducción Continua',
|
|
202
|
+
reverseAlarm: 'Marcha Atrás',
|
|
203
|
+
otherAlarm: 'Otros',
|
|
204
|
+
detailedMetrics: 'Métricas detalladas',
|
|
187
205
|
from: 'De',
|
|
188
206
|
to: 'a',
|
|
189
207
|
headerStartAddress: 'Lugar de início',
|
package/lang/frFR.json
CHANGED
|
@@ -297,7 +297,13 @@
|
|
|
297
297
|
"geofenceAlarm": "Ceinture",
|
|
298
298
|
"continuesDrivingAlarm": "Cond. Continue",
|
|
299
299
|
"reverseAlarm": "Marche Arriere",
|
|
300
|
-
"otherAlarm": "Other"
|
|
300
|
+
"otherAlarm": "Other",
|
|
301
|
+
"rank": "Rang",
|
|
302
|
+
"grade": "Note",
|
|
303
|
+
"safetyScore": "Sécurité",
|
|
304
|
+
"efficiencyScore": "Efficacité",
|
|
305
|
+
"complianceScore": "Conformité",
|
|
306
|
+
"detailedMetrics": "Métriques détaillées"
|
|
301
307
|
},
|
|
302
308
|
"layout": {
|
|
303
309
|
"deviceOnline": "Appareil en ligne",
|
package/lang/ptBR.js
CHANGED
|
@@ -185,7 +185,25 @@ module.exports = {
|
|
|
185
185
|
titleIdleReport: 'Relatórios de Ralenti',
|
|
186
186
|
titleMachinesReport: 'Relatório de Máquinas',
|
|
187
187
|
titleStopReport: 'Relatório de Paragens',
|
|
188
|
+
titleDriverRankingReport: 'Relatório de Ranking de Motoristas',
|
|
188
189
|
titleSensorReport: 'Relatório de Sensores',
|
|
190
|
+
rank: 'Posição',
|
|
191
|
+
grade: 'Nota',
|
|
192
|
+
safetyScore: 'Segurança',
|
|
193
|
+
efficiencyScore: 'Eficiência',
|
|
194
|
+
complianceScore: 'Conformidade',
|
|
195
|
+
score: 'Pontuação Geral',
|
|
196
|
+
avgFuelConsumption: 'Consumo Médio L/100km',
|
|
197
|
+
highEngineRPM: 'RPM Alta',
|
|
198
|
+
hardBraking: 'Frenagem Brusca',
|
|
199
|
+
hardAcceleration: 'Aceleração Brusca',
|
|
200
|
+
hardCornering: 'Curva Brusca',
|
|
201
|
+
overspeedAlarm: 'Excesso de Velocidade',
|
|
202
|
+
geofenceAlarm: 'Cinto de Segurança',
|
|
203
|
+
continuesDrivingAlarm: 'Condução Contínua',
|
|
204
|
+
reverseAlarm: 'Marcha à Ré',
|
|
205
|
+
otherAlarm: 'Outros',
|
|
206
|
+
detailedMetrics: 'Métricas detalhadas',
|
|
189
207
|
from: 'De',
|
|
190
208
|
to: 'a',
|
|
191
209
|
headerStartAddress: 'Local de início',
|
package/lang/ptPT.js
CHANGED
|
@@ -191,7 +191,25 @@ module.exports = {
|
|
|
191
191
|
titleIdleReport: 'Relatórios de Ralenti',
|
|
192
192
|
titleMachinesReport: 'Relatório de Máquinas',
|
|
193
193
|
titleStopReport: 'Relatório de Paragens',
|
|
194
|
+
titleDriverRankingReport: 'Relatório de Ranking de Condutores',
|
|
194
195
|
titleSensorReport: 'Relatório de Sensores',
|
|
196
|
+
rank: 'Posição',
|
|
197
|
+
grade: 'Nota',
|
|
198
|
+
safetyScore: 'Segurança',
|
|
199
|
+
efficiencyScore: 'Eficiência',
|
|
200
|
+
complianceScore: 'Conformidade',
|
|
201
|
+
score: 'Pontuação Geral',
|
|
202
|
+
avgFuelConsumption: 'Consumo Médio L/100km',
|
|
203
|
+
highEngineRPM: 'RPM Alto',
|
|
204
|
+
hardBraking: 'Travagem Brusca',
|
|
205
|
+
hardAcceleration: 'Aceleração Brusca',
|
|
206
|
+
hardCornering: 'Curva Brusca',
|
|
207
|
+
overspeedAlarm: 'Excesso de Velocidade',
|
|
208
|
+
geofenceAlarm: 'Cinto de Segurança',
|
|
209
|
+
continuesDrivingAlarm: 'Condução Contínua',
|
|
210
|
+
reverseAlarm: 'Marcha-atrás',
|
|
211
|
+
otherAlarm: 'Outros',
|
|
212
|
+
detailedMetrics: 'Métricas detalhadas',
|
|
195
213
|
from: 'De',
|
|
196
214
|
to: 'a',
|
|
197
215
|
headerStartAddress: 'Local de início',
|
package/package.json
CHANGED
|
@@ -24,6 +24,39 @@ const continuesDrivingCoefficient = 0.1
|
|
|
24
24
|
const reverseCoefficient = 0.1
|
|
25
25
|
const otherCoefficient = 0.1
|
|
26
26
|
|
|
27
|
+
const grades = [
|
|
28
|
+
{ min: 90, grade: 'A' },
|
|
29
|
+
{ min: 75, grade: 'B' },
|
|
30
|
+
{ min: 60, grade: 'C' },
|
|
31
|
+
{ min: 40, grade: 'D' },
|
|
32
|
+
{ min: -Infinity, grade: 'F' }
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
// Converts a "the lower the better" metric into a 0-100 score (100 = met target, 0 = twice the target or worse)
|
|
36
|
+
function goodnessScore (actual, target) {
|
|
37
|
+
if (!target || target <= 0) {
|
|
38
|
+
return 100
|
|
39
|
+
}
|
|
40
|
+
return Math.max(0, Math.min(100, 100 * (1 - (actual / target))))
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Same as goodnessScore, but for metrics where deviating from the target in either direction is bad (e.g. distance)
|
|
44
|
+
function deviationScore (actual, target) {
|
|
45
|
+
if (!target || target <= 0) {
|
|
46
|
+
return 100
|
|
47
|
+
}
|
|
48
|
+
return Math.max(0, Math.min(100, 100 * (1 - (Math.abs(actual - target) / target))))
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function weightedAverage (metrics) {
|
|
52
|
+
const totalWeight = metrics.reduce((sum, m) => sum + m.weight, 0)
|
|
53
|
+
return metrics.reduce((sum, m) => sum + (m.value * m.weight), 0) / totalWeight
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function toGrade (score) {
|
|
57
|
+
return grades.find(g => score >= g.min).grade
|
|
58
|
+
}
|
|
59
|
+
|
|
27
60
|
async function create (from, to, userData, traccar) {
|
|
28
61
|
const reportData = {
|
|
29
62
|
drivers: []
|
|
@@ -74,24 +107,30 @@ async function create (from, to, userData, traccar) {
|
|
|
74
107
|
|
|
75
108
|
const allDriversData = (Array.from(driversData.values())).filter(d => d.distance > 0)
|
|
76
109
|
allDriversData.forEach(d => {
|
|
77
|
-
const distanceScore = (Math.abs(d.distance - userData.distanceTarget) / userData.distanceTarget) * distanceCoefficient
|
|
78
|
-
const rpmScore = ((d.highEngineRPM / 60000) / userData.rpmTarget) * rpmCoefficient
|
|
79
|
-
const hardBrakingScore = (d.hardBraking / userData.hardBrakingTarget) * hardBrakingCoefficient
|
|
80
|
-
const hardAccelerationScore = (d.hardAcceleration / userData.hardAccelerationTarget) * hardAccelerationCoefficient
|
|
81
|
-
const hardCorneringScore = (d.hardCornering / userData.hardCorneringTarget) * hardCorneringCoefficient
|
|
82
|
-
const overspeedScore = (d.overspeed / userData.overspeedTarget) * overspeedCoefficient
|
|
83
|
-
const consumptionScore = (getCanAvgConsumption(d.distance, d.spentFuel).byKms / userData.fuelConsumptionTarget) * consumptionCoefficient
|
|
84
|
-
const geofenceAlarmScore = (d.geofenceAlarm / userData.geofenceTarget) * geofenceCoefficient
|
|
85
|
-
const continuesDrivingAlarmScore = (d.continuesDrivingAlarm / userData.continuesDrivingTarget) * continuesDrivingCoefficient
|
|
86
|
-
const reverseAlarmScore = (d.reverseAlarm / userData.reverseTarget) * reverseCoefficient
|
|
87
|
-
const otherAlarmScore = (d.otherAlarm / userData.otherTarget) * otherCoefficient
|
|
88
|
-
|
|
89
110
|
d.avgFuelConsumption = getCanAvgConsumption(d.distance, d.spentFuel).byKms
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
111
|
+
|
|
112
|
+
d.safetyScore = weightedAverage([
|
|
113
|
+
{ value: goodnessScore(d.hardBraking, userData.hardBrakingTarget), weight: hardBrakingCoefficient },
|
|
114
|
+
{ value: goodnessScore(d.hardAcceleration, userData.hardAccelerationTarget), weight: hardAccelerationCoefficient },
|
|
115
|
+
{ value: goodnessScore(d.hardCornering, userData.hardCorneringTarget), weight: hardCorneringCoefficient },
|
|
116
|
+
{ value: goodnessScore(d.overspeed, userData.overspeedTarget), weight: overspeedCoefficient },
|
|
117
|
+
{ value: goodnessScore(d.reverseAlarm, userData.reverseTarget), weight: reverseCoefficient }
|
|
118
|
+
])
|
|
119
|
+
d.efficiencyScore = weightedAverage([
|
|
120
|
+
{ value: deviationScore(d.distance, userData.distanceTarget), weight: distanceCoefficient },
|
|
121
|
+
{ value: goodnessScore(d.avgFuelConsumption, userData.fuelConsumptionTarget), weight: consumptionCoefficient },
|
|
122
|
+
{ value: goodnessScore(d.highEngineRPM / 60000, userData.rpmTarget), weight: rpmCoefficient }
|
|
123
|
+
])
|
|
124
|
+
d.complianceScore = weightedAverage([
|
|
125
|
+
{ value: goodnessScore(d.geofenceAlarm, userData.geofenceTarget), weight: geofenceCoefficient },
|
|
126
|
+
{ value: goodnessScore(d.continuesDrivingAlarm, userData.continuesDrivingTarget), weight: continuesDrivingCoefficient },
|
|
127
|
+
{ value: goodnessScore(d.otherAlarm, userData.otherTarget), weight: otherCoefficient }
|
|
128
|
+
])
|
|
129
|
+
d.overallScore = (d.safetyScore + d.efficiencyScore + d.complianceScore) / 3
|
|
130
|
+
d.grade = toGrade(d.overallScore)
|
|
93
131
|
})
|
|
94
|
-
allDriversData.sort((a, b) =>
|
|
132
|
+
allDriversData.sort((a, b) => b.overallScore - a.overallScore)
|
|
133
|
+
allDriversData.forEach((d, index) => { d.rank = index + 1 })
|
|
95
134
|
|
|
96
135
|
reportData.drivers.push(...allDriversData)
|
|
97
136
|
|
|
@@ -207,7 +246,13 @@ async function exportToExcel (userData, reportData) {
|
|
|
207
246
|
}
|
|
208
247
|
|
|
209
248
|
const headers = [
|
|
249
|
+
{ label: translations.report.rank, value: 'rank' },
|
|
210
250
|
{ label: translations.report.driver, value: 'name' },
|
|
251
|
+
{ label: translations.report.grade, value: 'grade' },
|
|
252
|
+
{ label: translations.report.score, value: 'overallScore' },
|
|
253
|
+
{ label: translations.report.safetyScore, value: 'safetyScore' },
|
|
254
|
+
{ label: translations.report.efficiencyScore, value: 'efficiencyScore' },
|
|
255
|
+
{ label: translations.report.complianceScore, value: 'complianceScore' },
|
|
211
256
|
{ label: translations.report.distance, value: 'distance' },
|
|
212
257
|
{ label: translations.report.avgFuelConsumption, value: 'avgFuelConsumption' },
|
|
213
258
|
{ label: translations.report.highEngineRPM, value: 'highEngineRPM' },
|
|
@@ -218,16 +263,21 @@ async function exportToExcel (userData, reportData) {
|
|
|
218
263
|
{ label: translations.report.geofenceAlarm, value: 'geofenceAlarm' },
|
|
219
264
|
{ label: translations.report.continuesDrivingAlarm, value: 'continuesDrivingAlarm' },
|
|
220
265
|
{ label: translations.report.reverseAlarm, value: 'reverseAlarm' },
|
|
221
|
-
{ label: translations.report.otherAlarm, value: 'otherAlarm' }
|
|
222
|
-
{ label: translations.report.score, value: 'score' }
|
|
266
|
+
{ label: translations.report.otherAlarm, value: 'otherAlarm' }
|
|
223
267
|
]
|
|
224
268
|
|
|
225
269
|
let data = []
|
|
226
270
|
if (reportDataRows) {
|
|
227
271
|
reportDataRows.forEach(row => {
|
|
228
272
|
data = data.concat({
|
|
273
|
+
rank: row.rank,
|
|
229
274
|
name: row.name,
|
|
230
|
-
|
|
275
|
+
grade: row.grade,
|
|
276
|
+
overallScore: Math.round(row.overallScore),
|
|
277
|
+
safetyScore: Math.round(row.safetyScore),
|
|
278
|
+
efficiencyScore: Math.round(row.efficiencyScore),
|
|
279
|
+
complianceScore: Math.round(row.complianceScore),
|
|
280
|
+
distance: Number((row.distance / 1000).toFixed(1)),
|
|
231
281
|
avgFuelConsumption: Number(row.avgFuelConsumption.toFixed(2)),
|
|
232
282
|
highEngineRPM: convertMS(row.highEngineRPM, false),
|
|
233
283
|
hardBraking: row.hardBraking,
|
|
@@ -237,11 +287,9 @@ async function exportToExcel (userData, reportData) {
|
|
|
237
287
|
geofenceAlarm: row.geofenceAlarm,
|
|
238
288
|
continuesDrivingAlarm: row.continuesDrivingAlarm,
|
|
239
289
|
reverseAlarm: row.reverseAlarm,
|
|
240
|
-
otherAlarm: row.otherAlarm
|
|
241
|
-
score: Number(row.score.toFixed(2))
|
|
290
|
+
otherAlarm: row.otherAlarm
|
|
242
291
|
})
|
|
243
292
|
})
|
|
244
|
-
console.log(data)
|
|
245
293
|
return {
|
|
246
294
|
headers,
|
|
247
295
|
data,
|
|
@@ -250,15 +298,33 @@ async function exportToExcel (userData, reportData) {
|
|
|
250
298
|
}
|
|
251
299
|
}
|
|
252
300
|
|
|
301
|
+
const gradeColors = {
|
|
302
|
+
A: { fill: [200, 236, 204], text: [30, 110, 40] },
|
|
303
|
+
B: { fill: [223, 240, 196], text: [66, 110, 30] },
|
|
304
|
+
C: { fill: [255, 236, 179], text: [153, 101, 0] },
|
|
305
|
+
D: { fill: [255, 205, 178], text: [166, 74, 0] },
|
|
306
|
+
F: { fill: [255, 205, 210], text: [153, 0, 20] }
|
|
307
|
+
}
|
|
308
|
+
|
|
253
309
|
async function exportToPDF (userData, reportData) {
|
|
254
|
-
console.log('
|
|
310
|
+
console.log('exportDriverRankingReportToPDF')
|
|
255
311
|
|
|
256
312
|
const timezone = userData.user.attributes.timezone
|
|
257
313
|
const translations = getTranslations(userData)
|
|
258
314
|
const lang = userData.user.attributes.lang || (isClientSide() && navigator.language)
|
|
259
315
|
const reportDataRows = reportData.drivers
|
|
260
316
|
|
|
261
|
-
const
|
|
317
|
+
const scoreboardHeaders = [
|
|
318
|
+
translations.report.rank,
|
|
319
|
+
translations.report.driver,
|
|
320
|
+
translations.report.grade,
|
|
321
|
+
translations.report.score,
|
|
322
|
+
translations.report.safetyScore,
|
|
323
|
+
translations.report.efficiencyScore,
|
|
324
|
+
translations.report.complianceScore
|
|
325
|
+
]
|
|
326
|
+
|
|
327
|
+
const detailHeaders = [
|
|
262
328
|
translations.report.driver,
|
|
263
329
|
translations.report.distance,
|
|
264
330
|
translations.report.avgFuelConsumption,
|
|
@@ -270,8 +336,7 @@ async function exportToPDF (userData, reportData) {
|
|
|
270
336
|
translations.report.geofenceAlarm,
|
|
271
337
|
translations.report.continuesDrivingAlarm,
|
|
272
338
|
translations.report.reverseAlarm,
|
|
273
|
-
translations.report.otherAlarm
|
|
274
|
-
translations.report.score
|
|
339
|
+
translations.report.otherAlarm
|
|
275
340
|
]
|
|
276
341
|
|
|
277
342
|
if (reportDataRows) {
|
|
@@ -282,30 +347,66 @@ async function exportToPDF (userData, reportData) {
|
|
|
282
347
|
doc.setFontSize(13)
|
|
283
348
|
doc.text(convertToLocaleString(reportData.from, lang, timezone, userData.user) + ' - ' + convertToLocaleString(reportData.to, lang, timezone, userData.user), 20, 25)
|
|
284
349
|
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
row.hardCornering,
|
|
295
|
-
row.overspeed,
|
|
296
|
-
row.geofenceAlarm,
|
|
297
|
-
row.continuesDrivingAlarm,
|
|
298
|
-
row.reverseAlarm,
|
|
299
|
-
row.otherAlarm,
|
|
300
|
-
row.score.toFixed(2)
|
|
301
|
-
]
|
|
302
|
-
data.push(temp)
|
|
303
|
-
})
|
|
304
|
-
const footValues = []
|
|
350
|
+
const scoreboardData = reportDataRows.map(row => [
|
|
351
|
+
row.rank,
|
|
352
|
+
row.name,
|
|
353
|
+
row.grade,
|
|
354
|
+
Math.round(row.overallScore),
|
|
355
|
+
Math.round(row.safetyScore),
|
|
356
|
+
Math.round(row.efficiencyScore),
|
|
357
|
+
Math.round(row.complianceScore)
|
|
358
|
+
])
|
|
305
359
|
|
|
306
360
|
const style = getStyle(getUserPartner(userData.user))
|
|
307
361
|
|
|
308
|
-
addTable(doc,
|
|
362
|
+
addTable(doc, scoreboardHeaders, scoreboardData, [], style, 40, {
|
|
363
|
+
0: { halign: 'center' },
|
|
364
|
+
2: { halign: 'center' },
|
|
365
|
+
3: { halign: 'right' },
|
|
366
|
+
4: { halign: 'right' },
|
|
367
|
+
5: { halign: 'right' },
|
|
368
|
+
6: { halign: 'right' }
|
|
369
|
+
}, (cellData) => {
|
|
370
|
+
if (cellData.section !== 'body') {
|
|
371
|
+
return
|
|
372
|
+
}
|
|
373
|
+
const row = reportDataRows[cellData.row.index]
|
|
374
|
+
if (!row) {
|
|
375
|
+
return
|
|
376
|
+
}
|
|
377
|
+
if (cellData.column.index === 0) {
|
|
378
|
+
cellData.cell.styles.fontStyle = row.rank <= 3 ? 'bold' : 'normal'
|
|
379
|
+
}
|
|
380
|
+
if (cellData.column.index === 2 || cellData.column.index === 3) {
|
|
381
|
+
const colors = gradeColors[row.grade]
|
|
382
|
+
cellData.cell.styles.fillColor = colors.fill
|
|
383
|
+
cellData.cell.styles.textColor = colors.text
|
|
384
|
+
cellData.cell.styles.fontStyle = 'bold'
|
|
385
|
+
}
|
|
386
|
+
})
|
|
387
|
+
|
|
388
|
+
const detailData = reportDataRows.map(row => [
|
|
389
|
+
row.name,
|
|
390
|
+
(row.distance / 1000).toFixed(1),
|
|
391
|
+
row.avgFuelConsumption.toFixed(2),
|
|
392
|
+
convertMS(row.highEngineRPM, false),
|
|
393
|
+
row.hardBraking,
|
|
394
|
+
row.hardAcceleration,
|
|
395
|
+
row.hardCornering,
|
|
396
|
+
row.overspeed,
|
|
397
|
+
row.geofenceAlarm,
|
|
398
|
+
row.continuesDrivingAlarm,
|
|
399
|
+
row.reverseAlarm,
|
|
400
|
+
row.otherAlarm
|
|
401
|
+
])
|
|
402
|
+
|
|
403
|
+
const detailStartY = doc.lastAutoTable.finalY + 12
|
|
404
|
+
doc.setFontSize(10)
|
|
405
|
+
doc.setFont('helvetica', 'bold')
|
|
406
|
+
doc.text(translations.report.detailedMetrics, 15, detailStartY - 4)
|
|
407
|
+
doc.setFont('helvetica', 'normal')
|
|
408
|
+
|
|
409
|
+
addTable(doc, detailHeaders, detailData, [], { ...style, bodyFontSize: 7, headerFontSize: 8 }, detailStartY, {
|
|
309
410
|
1: { halign: 'right' },
|
|
310
411
|
2: { halign: 'right' },
|
|
311
412
|
3: { halign: 'right' },
|
|
@@ -316,8 +417,7 @@ async function exportToPDF (userData, reportData) {
|
|
|
316
417
|
8: { halign: 'right' },
|
|
317
418
|
9: { halign: 'right' },
|
|
318
419
|
10: { halign: 'right' },
|
|
319
|
-
11: { halign: 'right' }
|
|
320
|
-
12: { halign: 'right' }
|
|
420
|
+
11: { halign: 'right' }
|
|
321
421
|
})
|
|
322
422
|
return doc
|
|
323
423
|
}
|
package/src/util/pdfDocument.js
CHANGED
|
@@ -61,7 +61,7 @@ async function headerFromUser (doc, title, user, orientation = 'l') {
|
|
|
61
61
|
return header(doc, title, partner && partner.host, getStyle(partner), orientation)
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
function addTable (doc, headers, data, footValues, style, startY, columnStyles = {}) {
|
|
64
|
+
function addTable (doc, headers, data, footValues, style, startY, columnStyles = {}, didParseCell) {
|
|
65
65
|
doc.autoTable({
|
|
66
66
|
head: [headers],
|
|
67
67
|
body: data,
|
|
@@ -97,6 +97,7 @@ function addTable (doc, headers, data, footValues, style, startY, columnStyles =
|
|
|
97
97
|
})
|
|
98
98
|
})
|
|
99
99
|
},
|
|
100
|
+
...(didParseCell ? { didParseCell } : {}),
|
|
100
101
|
columnStyles,
|
|
101
102
|
startY
|
|
102
103
|
})
|