feat: Implement GPS reports functionality including vehicle trips, trip details, and abnormalities.

This commit is contained in:
Pringgosutono
2025-12-16 07:59:50 +07:00
parent 20b081a5c0
commit c3abd60868
3 changed files with 502 additions and 17 deletions

View File

@ -6,19 +6,15 @@ use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Validator;
use Auth;
use App\Responses;
use App\Helper;
use Maatwebsite\Excel\Facades\Excel;
use Maatwebsite\Excel\Concerns\FromArray;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithStyles;
use Maatwebsite\Excel\Concerns\WithCustomStartCell;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use Carbon\Carbon;
use App\Models\UserLogs;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Support\Facades\Log;
class ReportsController extends Controller
{
@ -160,9 +156,9 @@ class ReportsController extends Controller
// // RETURN 1 - LIST
// if($req->type != 'report'){
$apiResp = Responses::success("success list vehicles report");
$apiResp["data"] = $list;
return new Response($apiResp, $apiResp["meta"]["code"]);
$apiResp = Responses::success("success list vehicles report");
$apiResp["data"] = $list;
return new Response($apiResp, $apiResp["meta"]["code"]);
// }
// // RETURN 2 - REPORT
@ -232,8 +228,8 @@ class ReportsController extends Controller
// return Excel::download($export, 'trip_report.xlsx');
// }
} catch (\Exception $e) {
$apiResp = Responses::error($e->getMessage());
return new Response($apiResp, $apiResp["meta"]["code"]);
$apiResp = Responses::error($e->getMessage());
return new Response($apiResp, $apiResp["meta"]["code"]);
// return Responses::json(Responses::SERVER_ERROR, 'An error occurred while generating the report.', (object)[]);
}
}
@ -356,16 +352,128 @@ class ReportsController extends Controller
// // RETURN 1 - LIST
// if($req->type != 'report'){
$apiResp = Responses::success("success list abnormalities report");
$apiResp["data"] = $list;
return new Response($apiResp, $apiResp["meta"]["code"]);
$apiResp = Responses::success("success list abnormalities report");
$apiResp["data"] = $list;
return new Response($apiResp, $apiResp["meta"]["code"]);
// }
} catch (\Exception $e) {
$apiResp = Responses::error($e->getMessage());
return new Response($apiResp, $apiResp["meta"]["code"]);
$apiResp = Responses::error($e->getMessage());
return new Response($apiResp, $apiResp["meta"]["code"]);
// return Responses::json(Responses::SERVER_ERROR, 'An error occurred while generating the report.', (object)[]);
}
}
public function api_view_trip_detail(Request $req, $token)
{
// token = base64_encode(tgl0 + '|' + tgl1 + '|' + nopol1 + '|' + now_unix())
// $token = "1759686805|1759693045|B.10-517|1765845676";
$token = base64_decode($token);
$token = explode('|', $token);
$tgl0 = (int) $token[0] ?? null;
$tgl1 = (int) $token[1] ?? null;
$nopol1 = $token[2] ?? null;
$now = (int) $token[3] ?? null;
$isMoreThanOneHour = time() - $now > 60 * 60;
if ($tgl0 == null || $tgl1 == null || $nopol1 == null || $now == null || $isMoreThanOneHour) {
$apiResp = Responses::bad_request("Invalid token");
return new Response($apiResp, $apiResp["meta"]["code"]);
}
// get vid by nopol1
$vid = DB::select("SELECT id FROM t_vehicles WHERE nopol1 = ?", [$nopol1]);
if (count($vid) == 0) {
$apiResp = Responses::bad_request("Vehicle not found");
return new Response($apiResp, $apiResp["meta"]["code"]);
}
$vid = $vid[0]->id;
$d = [$vid, $tgl0, $tgl1];
$list = DB::select("SELECT
t.crt_d, t.latitude, t.longitude, t.speed,
tgta.fulladdress,
t.pre_milleage, t.vhc_milleage, fuel_count
FROM
t_gps_tracks t
left join t_gps_tracks_address tgta on tgta.master_id = t.id
WHERE
t.vhc_id = ?
and t.latitude IS NOT NULL
AND t.longitude IS NOT NULL
AND t.action = 'location'
AND t.crt_d BETWEEN ? AND ?
ORDER BY t.crt_d asc
", $d);
if (count($list) == 0) {
$apiResp = Responses::not_found("Track not found");
return new Response($apiResp, $apiResp["meta"]["code"]);
}
$start = [
'time' => $list[0]->crt_d,
'fulladdress' => urldecode($list[0]->fulladdress),
'mileage' => $list[0]->vhc_milleage,
];
$finish = [
'time' => $list[count($list) - 1]->crt_d,
'fulladdress' => urldecode($list[count($list) - 1]->fulladdress),
'mileage' => $list[count($list) - 1]->vhc_milleage,
];
$t0 = Carbon::createFromTimestamp($list[0]->crt_d);
$t1 = Carbon::createFromTimestamp($list[count($list) - 1]->crt_d);
$diff = $t1->diff($t0);
$hours = $diff->h + ($diff->days * 24); // include days converted to hours
$minutes = $diff->i;
$duration = "{$hours} hour" . ($hours > 1 ? 's' : '') . " {$minutes} minute" . ($minutes > 1 ? 's' : '');
$distance = $list[count($list) - 1]->vhc_milleage - $list[0]->vhc_milleage;
$fuel_consumed = $list[count($list) - 1]->fuel_count - $list[0]->fuel_count;
$data = [
'nopol1' => $nopol1,
'vid' => $vid,
'tgl0' => $tgl0,
'tgl1' => $tgl1,
'list' => $list,
'start' => $start,
'finish' => $finish,
'duration' => $duration,
'distance' => $distance,
'fuel_consumed' => $fuel_consumed,
];
// dd($list);
return view('menu_v1.reports.view_trip_detail', $data);
}
public function decryptText(string $ciphertext = "FqujI/06YPCpCSP0Xlt6bA==")
{
$secret = "Mg3Xt1169cRNJWX6HG12DVkgmAXINVuq";
$iv_str = "Mg3Xt1169cRNJWX6";
// Derive key and IV exactly as the web tool does
$md5 = md5($secret, true); // 16-byte raw binary MD5
$key = $md5 . $md5; // 32 bytes → AES-256 key
$iv = substr($md5, 0, 16); // IV = first 16 bytes of MD5
$data = base64_decode($ciphertext, true);
if ($data === false) {
return 'Invalid Base64';
}
$plaintext = openssl_decrypt(
$data,
'aes-256-cbc',
$key,
0,
$iv
);
if ($plaintext === false) {
return 'Decryption failed: ' . openssl_error_string();
}
return $plaintext; // → "1764833739"
}
}