This commit is contained in:
wayanrivan
2026-08-05 09:28:06 +07:00
parent 85279d4616
commit cd60b836b5

View File

@ -31,8 +31,8 @@
@if ($user_role == \App\Models\Users::ROLE_VENDOR || $user_role == \App\Models\Users::ROLE_ADMIN) @if ($user_role == \App\Models\Users::ROLE_VENDOR || $user_role == \App\Models\Users::ROLE_ADMIN)
@can('vehicle.create') @can('vehicle.create')
<!-- <div class="col text-end"> <!-- <div class="col text-end">
<button id="btnMdlNewVhc" class="btn btn-sm btn-danger">Add New Vehicle</button> <button id="btnMdlNewVhc" class="btn btn-sm btn-danger">Add New Vehicle</button>
</div> --> </div> -->
@endcan @endcan
{{-- <div class="col-auto text-end ps-0"> {{-- <div class="col-auto text-end ps-0">
@ -314,6 +314,20 @@
// Timestamp 'start' TIDAK diubah karena itu waktu kejadian sebenarnya — // Timestamp 'start' TIDAK diubah karena itu waktu kejadian sebenarnya —
// yang disamakan hanya titik lokasi & odometer supaya laporan terlihat // yang disamakan hanya titik lokasi & odometer supaya laporan terlihat
// kontinu (finish trip N == start trip N+1). // kontinu (finish trip N == start trip N+1).
//
// PENTING: perbandingan koordinat dilakukan secara NUMERIK (parseFloat +
// hitung jarak meter via getDistanceMeters), BUKAN string mentah.
// Ini supaya kasus seperti berikut tetap terdeteksi & diperbaiki:
// - km/odometer sudah nyambung (finish trip N == start trip N+1)
// TAPI titik GPS-nya beda beberapa meter (drift GPS), sehingga
// salah satu titik "masuk" radius site tertentu (mis. "Bank BNU")
// dan yang lain tidak -> teks lokasi jadi kelihatan "loncat"
// walau kendaraan sebenarnya di tempat yang sama.
// Toleransi 0 meter berarti: kalau titiknya tidak PERSIS sama,
// selalu disamakan dengan finish sebelumnya. Ini paling aman untuk
// laporan (finish trip N akan selalu == start trip N+1).
const TRIP_CONTINUITY_TOLERANCE_METERS = 0; // >>> ADDED
function normalizeTripContinuity(rows) { // >>> ADDED function normalizeTripContinuity(rows) { // >>> ADDED
if (!Array.isArray(rows) || rows.length === 0) return rows; if (!Array.isArray(rows) || rows.length === 0) return rows;
@ -333,14 +347,54 @@
const prev = groupRows[i - 1]; const prev = groupRows[i - 1];
const curr = groupRows[i]; const curr = groupRows[i];
const locMismatch = (prev.finish_lat_long || '').trim() !== (curr.start_lat_long || '') // 1) Cek mismatch km/odometer
.trim();
const kmMismatch = Number(prev.finishMileage) !== Number(curr.startMileage); const kmMismatch = Number(prev.finishMileage) !== Number(curr.startMileage);
if (locMismatch || kmMismatch) { // 2) Cek mismatch koordinat GPS -- HANYA kalau datanya tersedia,
// karena banyak data (seperti contoh Anda) punya
// start_lat_long/finish_lat_long = null untuk semua baris.
const prevCoord = parseLatLong(prev.finish_lat_long);
const currCoord = parseLatLong(curr.start_lat_long);
let coordMismatch = false;
if (prevCoord.lat !== null && currCoord.lat !== null) {
const distMeters = getDistanceMeters(
prevCoord.lat, prevCoord.lng,
currCoord.lat, currCoord.lng
);
coordMismatch = distMeters > TRIP_CONTINUITY_TOLERANCE_METERS;
}
// 3) Cek mismatch TEKS lokasi (startLoc vs finishLoc). Ini penting
// karena saat lat_long null, satu-satunya sumber lokasi yang
// dipakai untuk render adalah field teks ini (lihat kolom
// Start/Finish -> prioritas 2: row.startLoc / row.finishLoc).
// Tanpa cek ini, kasus seperti "Estrada Suai - Maliana, Cendana"
// vs "Bank BNU, Estrada Suai - Maliana, Cendana" tidak akan
// terdeteksi sebagai mismatch walau km-nya sudah nyambung.
const prevFinishText = (prev.finishLoc || '').trim();
const currStartText = (curr.startLoc || '').trim();
const textMismatch = prevFinishText !== currStartText;
if (kmMismatch || coordMismatch || textMismatch) {
curr.start_lat_long = prev.finish_lat_long; curr.start_lat_long = prev.finish_lat_long;
curr.startLoc = prev.finishLoc; curr.startLoc = prev.finishLoc;
curr.startMileage = prev.finishMileage; curr.startMileage = prev.finishMileage;
// Hitung ulang Distance (kolom 'mileage') dari selisih odometer
// yang baru (finishMileage - startMileage yang sudah disinkronkan),
// supaya kolom Distance tetap konsisten dengan kolom Start(km)/Finish(km)
// yang tampil di tabel. Sebelumnya 'mileage' berasal dari GPS track
// mentah, yang bisa beda dengan selisih odometer setelah normalisasi ini.
//
// - Kalau hasilnya minus (finishMileage < startMileage, misal odometer
// sempat reset/kebalik), jadikan positif (absolute value).
// - Lalu bulatkan ke bilangan bulat terdekat: desimal >= 0.5 dibulatkan
// ke atas, desimal < 0.5 dibulatkan ke bawah (standard round-half-up;
// Math.round sudah berlaku demikian untuk angka positif).
const rawDiff = Number(curr.finishMileage) - Number(curr.startMileage);
if (!isNaN(rawDiff)) {
curr.mileage = Math.round(Math.abs(rawDiff));
}
} }
} }
}); });
@ -600,7 +654,8 @@
locationLabel = formatSiteLabel(nearestSite); locationLabel = formatSiteLabel(nearestSite);
} else if (row.startLoc) { } else if (row.startLoc) {
// Prioritas 2: startLoc sudah ada dari API // Prioritas 2: startLoc sudah ada dari API
locationLabel = Helper.shortenText(decodeURIComponent(row.startLoc), 255); locationLabel = Helper.shortenText(decodeURIComponent(row
.startLoc), 255);
} else if (type === 'export') { } else if (type === 'export') {
// Export bersifat sinkron, tidak bisa menunggu hasil geocode background // Export bersifat sinkron, tidak bisa menunggu hasil geocode background
locationLabel = '-'; locationLabel = '-';
@ -630,7 +685,8 @@
if (nearestSite) { if (nearestSite) {
locationLabel = formatSiteLabel(nearestSite); locationLabel = formatSiteLabel(nearestSite);
} else if (row.finishLoc) { } else if (row.finishLoc) {
locationLabel = Helper.shortenText(decodeURIComponent(row.finishLoc), 255); locationLabel = Helper.shortenText(decodeURIComponent(row
.finishLoc), 255);
} else if (type === 'export') { } else if (type === 'export') {
locationLabel = '-'; locationLabel = '-';
} else { } else {