Compare commits
57 Commits
c97dd332f0
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 8b833e7295 | |||
| 0b79bd665c | |||
| 81efe25ce2 | |||
| fbbcf86509 | |||
| 18897186e0 | |||
| 136db1a158 | |||
| f4202ce146 | |||
| a2c821d4bd | |||
| 1331e4a46e | |||
| 111c3e35a1 | |||
| 4b5cb88e4a | |||
| 0284d25af4 | |||
| a92d0c632f | |||
| 77e5b345b7 | |||
| a3f42315e4 | |||
| 65f7cc1ebf | |||
| e1153c375d | |||
| 0fe1cac8bf | |||
| 0621b14b77 | |||
| 08776e5a1b | |||
| b3a2467629 | |||
| dae0954891 | |||
| d013eb6dd1 | |||
| 8445a18416 | |||
| d1f90af6f6 | |||
| f6d11ce5e9 | |||
| 993b529331 | |||
| 5c687fc24f | |||
| bc92ed5234 | |||
| 5d585a6e26 | |||
| 64235d08f5 | |||
| 85d29d4142 | |||
| 620486de25 | |||
| 48fe5e3ef6 | |||
| e49309f709 | |||
| 36ec099cd9 | |||
| c7e0b57ad6 | |||
| a101b55279 | |||
| c075457053 | |||
| 0217c1c947 | |||
| ff5b411178 | |||
| 14f5246c86 | |||
| ccd7b19ff5 | |||
| c492711d83 | |||
| 3ad22e0cf5 | |||
| cf6594a5da | |||
| 64d7ce4f65 | |||
| f906c80835 | |||
| 5cbf7600ae | |||
| 79596192d3 | |||
| f257a1b7f2 | |||
| 1f3bf298f8 | |||
| 3e6ea0b3d4 | |||
| db6fe59062 | |||
| 62e45a8777 | |||
| af271871dd | |||
| bc6a88e1db |
1
.gitignore
vendored
1
.gitignore
vendored
@ -13,3 +13,4 @@ npm-debug.log
|
||||
yarn-error.log
|
||||
.vscode
|
||||
.DS_Store
|
||||
.sql
|
||||
@ -9,6 +9,7 @@ class Helper
|
||||
const EARTH_RADIUS_M = 6371000;
|
||||
const EARTH_RADIUS_KM = 6371;
|
||||
const EARTH_RADIUS_MILES = 3959; // 3958.756 || 3959 || 3963
|
||||
const TIMEFIX = 25200;
|
||||
|
||||
/**
|
||||
* Calculates the great-circle distance between two points, with
|
||||
|
||||
@ -13,6 +13,7 @@ use App\Models\Users;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use App\Models\UserLogs;
|
||||
|
||||
class LoginController extends Controller
|
||||
{
|
||||
@ -143,6 +144,12 @@ class LoginController extends Controller
|
||||
// return $req->wantsJson()
|
||||
// ? new JsonResponse([], 204)
|
||||
// : redirect(route('view_dashboard'));
|
||||
$log = [
|
||||
"module" => "Auth",
|
||||
"action" => "Login",
|
||||
"desc" => "User login",
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
|
||||
if ($req->wantsJson()) {
|
||||
return new JsonResponse([], 204);
|
||||
@ -173,7 +180,14 @@ class LoginController extends Controller
|
||||
public function logout(Request $req)
|
||||
{
|
||||
$user = Auth::user();
|
||||
if ($user->role == Users::ROLE_ADMIN) {
|
||||
$log = [
|
||||
"module" => "Auth",
|
||||
"action" => "Logout",
|
||||
"desc" => "User logout",
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
|
||||
if ($user->role == Users::ROLE_ADMIN) {
|
||||
$this->guard()->logout();
|
||||
$req->session()->invalidate();
|
||||
$req->session()->regenerateToken();
|
||||
|
||||
@ -12,6 +12,8 @@ use App\Responses;
|
||||
use App\Helper;
|
||||
use App\Models\Clients;
|
||||
use App\Models\Users;
|
||||
use App\Models\UserLogs;
|
||||
use Auth;
|
||||
|
||||
class ClientController extends Controller
|
||||
{
|
||||
@ -25,6 +27,13 @@ class ClientController extends Controller
|
||||
$data = [
|
||||
"disc_types" => Clients::select2DiscountTypes(),
|
||||
];
|
||||
|
||||
$log = [
|
||||
"module" => "Company",
|
||||
"action" => "View",
|
||||
"desc" => "Open Company Menu",
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return view("menu_v1.clients", $data);
|
||||
}
|
||||
|
||||
@ -250,6 +259,13 @@ class ClientController extends Controller
|
||||
$apiResp = Responses::created("success add new client");
|
||||
|
||||
DB::commit();
|
||||
|
||||
$log = [
|
||||
"module" => "Company",
|
||||
"action" => "Create",
|
||||
"desc" => "Add new company: ".$req->cname,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
Storage::disk("public")->delete($url_clogo);
|
||||
@ -481,6 +497,13 @@ class ClientController extends Controller
|
||||
DB::commit();
|
||||
|
||||
$apiResp = Responses::success("success update client");
|
||||
|
||||
$log = [
|
||||
"module" => "Company",
|
||||
"action" => "Update",
|
||||
"desc" => "Update company: ".$req->cname,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
Storage::disk("public")->delete($url_clogo);
|
||||
@ -541,6 +564,13 @@ class ClientController extends Controller
|
||||
DB::commit();
|
||||
|
||||
$apiResp = Responses::success("success delete client");
|
||||
|
||||
$log = [
|
||||
"module" => "Company",
|
||||
"action" => "Delete",
|
||||
"desc" => "Delete company: ".$client[0]->c_name,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
|
||||
232
app/Http/Controllers/ConfDistributionController.php
Normal file
232
app/Http/Controllers/ConfDistributionController.php
Normal file
@ -0,0 +1,232 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
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 Hidehalo\Nanoid\Client as Nanoid;
|
||||
use Hidehalo\Nanoid\GeneratorInterface as NanoidInterface;
|
||||
use App\Responses;
|
||||
use App\Helper;
|
||||
use App\Models\ConfRates;
|
||||
use App\Models\ConfTruckTypes;
|
||||
use App\Models\Vehicles;
|
||||
use App\Models\UserLogs;
|
||||
use Auth;
|
||||
|
||||
class ConfDistributionController extends Controller
|
||||
{
|
||||
/**
|
||||
* View
|
||||
*/
|
||||
|
||||
public function view_distribution_category(Request $req)
|
||||
{
|
||||
$data = [];
|
||||
|
||||
$log = [
|
||||
"module" => "Distribution Category",
|
||||
"action" => "View",
|
||||
"desc" => "Open Distribution Category menu",
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return view("menu_v1.configs.distribution_category", $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* API
|
||||
*/
|
||||
|
||||
public function api_add_distribution_category(Request $req)
|
||||
{
|
||||
try {
|
||||
$now = time();
|
||||
// new or edit
|
||||
$tipe = $req->tipe ?? "new";
|
||||
|
||||
$input = [
|
||||
"dc_code" => $req->dc_code,
|
||||
"dc_name" => $req->dc_name,
|
||||
];
|
||||
$rulesInput = [
|
||||
"dc_code" => "required|string|max:10",
|
||||
"dc_name" => "required|string|max:100",
|
||||
];
|
||||
|
||||
// validasi input
|
||||
$isValidInput = Validator::make($input, $rulesInput);
|
||||
if (!$isValidInput->passes()) {
|
||||
$apiResp = Responses::bad_input($isValidInput->messages()->first());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
if($tipe == "new"){
|
||||
$uniqCode = DB::select("SELECT * FROM t_conf_distribution_category WHERE dc_code = ?", [$req->dc_code]);
|
||||
}
|
||||
if($tipe == "edit"){
|
||||
$uniqCode = DB::select("SELECT * FROM t_conf_distribution_category WHERE dc_code = ? AND id != ?", [$req->dc_code, $req->id]);
|
||||
}
|
||||
if (count($uniqCode) > 0) {
|
||||
$apiResp = Responses::bad_request("type code has been used");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
$insD = [
|
||||
"dc_code" => $req->dc_code,
|
||||
"dc_name" => $req->dc_name,
|
||||
"crt" => $now,
|
||||
"crt_by" => $req->auth->uid,
|
||||
"updt" => $now,
|
||||
"updt_by" => $req->auth->uid,
|
||||
];
|
||||
// $insQ = DB::insert("INSERT
|
||||
// INTO t_conf_distribution_category (dc_code, dc_name, crt, crt_by, updt, updt_by)
|
||||
// VALUES (?, ?, ?, ?, ?, ?)
|
||||
// ", array_values($insD));
|
||||
$insQ = DB::insert("INSERT into t_conf_distribution_category set
|
||||
dc_code = ?,
|
||||
dc_name = ?,
|
||||
crt = ?,
|
||||
crt_by = ?,
|
||||
updt = ?,
|
||||
updt_by = ?
|
||||
on duplicate key update
|
||||
dc_code = values(dc_code),
|
||||
dc_name = values(dc_name),
|
||||
updt = values(updt),
|
||||
updt_by = values(updt_by)
|
||||
", array_values($insD));
|
||||
|
||||
|
||||
$apiResp = Responses::created("success " . ($tipe == "new" ? "add new" : "edit") . " distribution category");
|
||||
|
||||
DB::commit();
|
||||
|
||||
$log = [
|
||||
"module" => "Distribution Category",
|
||||
"action" => "".($tipe == "new" ? "Create" : "Update")."",
|
||||
"desc" => "".($tipe == "new" ? "Add new" : "Update")." distribution category: ".$req->dc_name,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
$apiResp = Responses::error($e->getMessage());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
|
||||
public function api_list_distribution_category(Request $req)
|
||||
{
|
||||
try {
|
||||
$now = time();
|
||||
|
||||
$list = DB::select("SELECT * FROM t_conf_distribution_category WHERE dlt IS NULL ORDER BY dc_code ASC");
|
||||
foreach ($list as $key => $row) {
|
||||
$list[$key]->DT_RowIndex = $key + 1;
|
||||
$list[$key]->action = "-";
|
||||
}
|
||||
|
||||
$apiResp = Responses::success("success list distribution category");
|
||||
$apiResp["count"] = count($list);
|
||||
$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"]);
|
||||
}
|
||||
}
|
||||
|
||||
public function api_show_distribution_category(Request $req, $id)
|
||||
{
|
||||
try {
|
||||
$input = [
|
||||
"id" => $id,
|
||||
];
|
||||
$rulesInput = [
|
||||
"id" => "required|integer|not_in:0",
|
||||
];
|
||||
|
||||
// validasi input
|
||||
$isValidInput = Validator::make($input, $rulesInput);
|
||||
if (!$isValidInput->passes()) {
|
||||
$apiResp = Responses::bad_input($isValidInput->messages()->first());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
$dtl = DB::select("SELECT * FROM t_conf_distribution_category WHERE id = ? AND dlt IS NULL limit 1", [$id]);
|
||||
if (count($dtl) < 1) {
|
||||
$apiResp = Responses::not_found("truck type not found");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
$apiResp = Responses::success("success get detail vehicle type");
|
||||
$apiResp["data"] = $dtl[0];
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
$apiResp = Responses::error($e->getMessage());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function api_del_distribution_category(Request $req, $id)
|
||||
{
|
||||
try {
|
||||
$now = time();
|
||||
|
||||
$input = [
|
||||
"id" => $id,
|
||||
];
|
||||
$rulesInput = [
|
||||
"id" => "required|integer|not_in:0",
|
||||
];
|
||||
|
||||
// validasi input
|
||||
$isValidInput = Validator::make($input, $rulesInput);
|
||||
if (!$isValidInput->passes()) {
|
||||
$apiResp = Responses::bad_input($isValidInput->messages()->first());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
$dtl = DB::select("SELECT * FROM t_conf_distribution_category WHERE id = ? AND dlt IS NULL limit 1", [$id]);
|
||||
if (count($dtl) < 1) {
|
||||
$apiResp = Responses::not_found("vehicle type not found");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
$updtQ = DB::update("UPDATE t_conf_distribution_category
|
||||
SET
|
||||
dlt = ?,
|
||||
dlt_by = ?,
|
||||
updt = ?,
|
||||
updt_by = ?
|
||||
WHERE id = ? AND dlt IS NULL
|
||||
", [1, $req->user()->id, $now, $req->user()->id, $id]);
|
||||
|
||||
DB::commit();
|
||||
|
||||
$apiResp = Responses::success("success delete vehicle type");
|
||||
|
||||
$log = [
|
||||
"module" => "Distribution Category",
|
||||
"action" => "Delete",
|
||||
"desc" => "Delete distribution category: ".$dtl[0]->dc_name,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, "Delete distribution category: ".$dtl[0]->dc_name);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
$apiResp = Responses::error($e->getMessage());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
233
app/Http/Controllers/ConfPoolController.php
Normal file
233
app/Http/Controllers/ConfPoolController.php
Normal file
@ -0,0 +1,233 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
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 Hidehalo\Nanoid\Client as Nanoid;
|
||||
use Hidehalo\Nanoid\GeneratorInterface as NanoidInterface;
|
||||
use App\Responses;
|
||||
use App\Helper;
|
||||
use App\Models\ConfRates;
|
||||
use App\Models\ConfTruckTypes;
|
||||
use App\Models\Vehicles;
|
||||
use App\Models\UserLogs;
|
||||
use Auth;
|
||||
|
||||
class ConfPoolController extends Controller
|
||||
{
|
||||
/**
|
||||
* View
|
||||
*/
|
||||
|
||||
public function view_pool(Request $req)
|
||||
{
|
||||
$data = [];
|
||||
|
||||
|
||||
$log = [
|
||||
"module" => "Pool",
|
||||
"action" => "View",
|
||||
"desc" => "Open Pool menu",
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return view("menu_v1.configs.pool", $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* API
|
||||
*/
|
||||
|
||||
public function api_add_pool(Request $req)
|
||||
{
|
||||
try {
|
||||
$now = time();
|
||||
// new or edit
|
||||
$tipe = $req->tipe ?? "new";
|
||||
|
||||
$input = [
|
||||
"pool_code" => $req->pool_code,
|
||||
"pool_name" => $req->pool_name,
|
||||
];
|
||||
$rulesInput = [
|
||||
"pool_code" => "required|string|max:10",
|
||||
"pool_name" => "required|string|max:100",
|
||||
];
|
||||
|
||||
// validasi input
|
||||
$isValidInput = Validator::make($input, $rulesInput);
|
||||
if (!$isValidInput->passes()) {
|
||||
$apiResp = Responses::bad_input($isValidInput->messages()->first());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
if($tipe == "new"){
|
||||
$uniqCode = DB::select("SELECT * FROM t_conf_pool WHERE pool_code = ?", [$req->pool_code]);
|
||||
}
|
||||
if($tipe == "edit"){
|
||||
$uniqCode = DB::select("SELECT * FROM t_conf_pool WHERE pool_code = ? AND id != ?", [$req->pool_code, $req->id]);
|
||||
}
|
||||
if (count($uniqCode) > 0) {
|
||||
$apiResp = Responses::bad_request("type code has been used");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
$insD = [
|
||||
"pool_code" => $req->pool_code,
|
||||
"pool_name" => $req->pool_name,
|
||||
"crt" => $now,
|
||||
"crt_by" => $req->auth->uid,
|
||||
"updt" => $now,
|
||||
"updt_by" => $req->auth->uid,
|
||||
];
|
||||
// $insQ = DB::insert("INSERT
|
||||
// INTO t_conf_pool (pool_code, pool_name, crt, crt_by, updt, updt_by)
|
||||
// VALUES (?, ?, ?, ?, ?, ?)
|
||||
// ", array_values($insD));
|
||||
$insQ = DB::insert("INSERT into t_conf_pool set
|
||||
pool_code = ?,
|
||||
pool_name = ?,
|
||||
crt = ?,
|
||||
crt_by = ?,
|
||||
updt = ?,
|
||||
updt_by = ?
|
||||
on duplicate key update
|
||||
pool_code = values(pool_code),
|
||||
pool_name = values(pool_name),
|
||||
updt = values(updt),
|
||||
updt_by = values(updt_by)
|
||||
", array_values($insD));
|
||||
|
||||
|
||||
$apiResp = Responses::created("success " . ($tipe == "new" ? "add new" : "edit") . " distribution category");
|
||||
|
||||
DB::commit();
|
||||
|
||||
$log = [
|
||||
"module" => "Pool",
|
||||
"action" => "".($tipe == "new" ? "Create" : "Update")."",
|
||||
"desc" => "".($tipe == "new" ? "Add new" : "Update")." pool: ".$req->pool_name,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
$apiResp = Responses::error($e->getMessage());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
|
||||
public function api_list_pool(Request $req)
|
||||
{
|
||||
try {
|
||||
$now = time();
|
||||
|
||||
$list = DB::select("SELECT * FROM t_conf_pool WHERE dlt IS NULL ORDER BY pool_code ASC");
|
||||
foreach ($list as $key => $row) {
|
||||
$list[$key]->DT_RowIndex = $key + 1;
|
||||
$list[$key]->action = "-";
|
||||
}
|
||||
|
||||
$apiResp = Responses::success("success list distribution category");
|
||||
$apiResp["count"] = count($list);
|
||||
$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"]);
|
||||
}
|
||||
}
|
||||
|
||||
public function api_show_pool(Request $req, $id)
|
||||
{
|
||||
try {
|
||||
$input = [
|
||||
"id" => $id,
|
||||
];
|
||||
$rulesInput = [
|
||||
"id" => "required|integer|not_in:0",
|
||||
];
|
||||
|
||||
// validasi input
|
||||
$isValidInput = Validator::make($input, $rulesInput);
|
||||
if (!$isValidInput->passes()) {
|
||||
$apiResp = Responses::bad_input($isValidInput->messages()->first());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
$dtl = DB::select("SELECT * FROM t_conf_pool WHERE id = ? AND dlt IS NULL limit 1", [$id]);
|
||||
if (count($dtl) < 1) {
|
||||
$apiResp = Responses::not_found("truck type not found");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
$apiResp = Responses::success("success get detail vehicle type");
|
||||
$apiResp["data"] = $dtl[0];
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
$apiResp = Responses::error($e->getMessage());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function api_del_pool(Request $req, $id)
|
||||
{
|
||||
try {
|
||||
$now = time();
|
||||
|
||||
$input = [
|
||||
"id" => $id,
|
||||
];
|
||||
$rulesInput = [
|
||||
"id" => "required|integer|not_in:0",
|
||||
];
|
||||
|
||||
// validasi input
|
||||
$isValidInput = Validator::make($input, $rulesInput);
|
||||
if (!$isValidInput->passes()) {
|
||||
$apiResp = Responses::bad_input($isValidInput->messages()->first());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
$dtl = DB::select("SELECT * FROM t_conf_pool WHERE id = ? AND dlt IS NULL limit 1", [$id]);
|
||||
if (count($dtl) < 1) {
|
||||
$apiResp = Responses::not_found("vehicle type not found");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
$updtQ = DB::update("UPDATE t_conf_pool
|
||||
SET
|
||||
dlt = ?,
|
||||
dlt_by = ?,
|
||||
updt = ?,
|
||||
updt_by = ?
|
||||
WHERE id = ? AND dlt IS NULL
|
||||
", [1, $req->user()->id, $now, $req->user()->id, $id]);
|
||||
|
||||
DB::commit();
|
||||
|
||||
$apiResp = Responses::success("success delete vehicle type");
|
||||
|
||||
$log = [
|
||||
"module" => "Pool",
|
||||
"action" => "Delete",
|
||||
"desc" => "Delete pool: ".$dtl[0]->pool_name,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
$apiResp = Responses::error($e->getMessage());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -15,6 +15,8 @@ use App\Helper;
|
||||
use App\Models\ConfRates;
|
||||
use App\Models\ConfTruckTypes;
|
||||
use App\Models\Vehicles;
|
||||
use App\Models\UserLogs;
|
||||
use Auth;
|
||||
|
||||
class ConfTruckTypeController extends Controller
|
||||
{
|
||||
@ -26,6 +28,12 @@ class ConfTruckTypeController extends Controller
|
||||
{
|
||||
$data = [];
|
||||
|
||||
$log = [
|
||||
"module" => "Vehicle Type",
|
||||
"action" => "View",
|
||||
"desc" => "Open Vehicle Type menu",
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return view("menu_v1.configs.truck_types", $data);
|
||||
}
|
||||
|
||||
@ -163,6 +171,14 @@ class ConfTruckTypeController extends Controller
|
||||
$apiResp = Responses::created("success add new vehicle type");
|
||||
|
||||
DB::commit();
|
||||
|
||||
|
||||
$log = [
|
||||
"module" => "Vehicle Type",
|
||||
"action" => "Create",
|
||||
"desc" => "Add new vehicle type: ".$req->type_name,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
@ -256,6 +272,13 @@ class ConfTruckTypeController extends Controller
|
||||
$apiResp = Responses::created("success update vehicle type");
|
||||
|
||||
DB::commit();
|
||||
|
||||
$log = [
|
||||
"module" => "Vehicle Type",
|
||||
"action" => "Update",
|
||||
"desc" => "Update vehicle type: ".$req->type_name,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
@ -310,6 +333,13 @@ class ConfTruckTypeController extends Controller
|
||||
DB::commit();
|
||||
|
||||
$apiResp = Responses::success("success delete vehicle type");
|
||||
|
||||
$log = [
|
||||
"module" => "Vehicle Type",
|
||||
"action" => "Delete",
|
||||
"desc" => "Delete vehicle type: ".$truckType[0]->name,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
|
||||
@ -11,6 +11,8 @@ use App\Responses;
|
||||
use App\Helper;
|
||||
use App\Models\Devices;
|
||||
use App\Models\Vehicles;
|
||||
use App\Models\UserLogs;
|
||||
use Auth;
|
||||
|
||||
class DevicesController extends Controller
|
||||
{
|
||||
@ -20,6 +22,13 @@ class DevicesController extends Controller
|
||||
$data = [
|
||||
"vhcs" => $vhcs,
|
||||
];
|
||||
|
||||
$log = [
|
||||
"module" => "Device",
|
||||
"action" => "View",
|
||||
"desc" => "Open Device menu",
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return view("menu_v1.configs.devices", $data);
|
||||
}
|
||||
|
||||
@ -202,6 +211,13 @@ class DevicesController extends Controller
|
||||
$apiResp = Responses::created("success add new device");
|
||||
|
||||
DB::commit();
|
||||
|
||||
$log = [
|
||||
"module" => "Device",
|
||||
"action" => "Create",
|
||||
"desc" => "Add new device: ".$device_id,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
@ -354,6 +370,13 @@ class DevicesController extends Controller
|
||||
$apiResp = Responses::created("success update device");
|
||||
|
||||
DB::commit();
|
||||
|
||||
$log = [
|
||||
"module" => "Device",
|
||||
"action" => "Update",
|
||||
"desc" => "Edit device: ".$device_id,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
@ -403,6 +426,13 @@ class DevicesController extends Controller
|
||||
DB::commit();
|
||||
|
||||
$apiResp = Responses::success("success delete device");
|
||||
|
||||
$log = [
|
||||
"module" => "Device",
|
||||
"action" => "Delete",
|
||||
"desc" => "Delete device : ".$device[0]->device_id,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
|
||||
@ -16,6 +16,7 @@ use App\Models\Drivers;
|
||||
use App\Models\DriversDetail;
|
||||
use App\Models\Users;
|
||||
use App\Models\DrvPhoneDevices;
|
||||
use App\Models\UserLogs;
|
||||
|
||||
class DriversController extends Controller
|
||||
{
|
||||
@ -252,6 +253,13 @@ class DriversController extends Controller
|
||||
$apiResp = Responses::created("success add new driver");
|
||||
|
||||
DB::commit();
|
||||
|
||||
$log = [
|
||||
"module" => "Driver",
|
||||
"action" => "View",
|
||||
"desc" => "Add new driver: ".$req->fullname,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
Storage::disk("public")->delete($url_ktp);
|
||||
@ -451,6 +459,13 @@ class DriversController extends Controller
|
||||
DB::commit();
|
||||
|
||||
$apiResp = Responses::success("success update driver");
|
||||
|
||||
$log = [
|
||||
"module" => "Driver",
|
||||
"action" => "Update",
|
||||
"desc" => "Edit driver: ".$req->fullname,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
Storage::disk("public")->delete($url_ktp);
|
||||
@ -501,6 +516,13 @@ class DriversController extends Controller
|
||||
DB::commit();
|
||||
|
||||
$apiResp = Responses::success("success delete driver");
|
||||
|
||||
$log = [
|
||||
"module" => "Driver",
|
||||
"action" => "Delete",
|
||||
"desc" => "Delete driver : ".$driver[0]->fullname,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
|
||||
@ -30,12 +30,21 @@ use App\Models\Finance;
|
||||
use App\Models\OrdersCheckpoints;
|
||||
use App\Models\OrdersInvoices;
|
||||
use App\Models\OrdersDriversUploads;
|
||||
use App\Models\UserLogs;
|
||||
use Auth;
|
||||
|
||||
class MenuController extends Controller
|
||||
{
|
||||
public function view_dashboard(Request $req)
|
||||
{
|
||||
$data = [
|
||||
$log = [
|
||||
"module" => "Dashboard",
|
||||
"action" => "View",
|
||||
"desc" => "Open Dashboard menu",
|
||||
];
|
||||
UserLogs::insert($req->auth->uid, $log);
|
||||
|
||||
$data = [
|
||||
"client_group" => Clients::getClientById($req->auth->client_group_id),
|
||||
];
|
||||
|
||||
@ -45,12 +54,20 @@ class MenuController extends Controller
|
||||
$data["client_group"] = null;
|
||||
}
|
||||
|
||||
|
||||
return view("menu_v1.dashboard", $data);
|
||||
}
|
||||
|
||||
public function view_drivers(Request $req)
|
||||
{
|
||||
$data = [
|
||||
$log = [
|
||||
"module" => "Driver",
|
||||
"action" => "View",
|
||||
"desc" => "Open Driver menu",
|
||||
];
|
||||
UserLogs::insert($req->auth->uid, $log);
|
||||
|
||||
$data = [
|
||||
"bloods" => Helper::listBloods(),
|
||||
"relationships" => Drivers::listRelationships(),
|
||||
"vendors" => Users::listUsersByRole(Users::ROLE_VENDOR),
|
||||
@ -61,7 +78,17 @@ class MenuController extends Controller
|
||||
|
||||
public function view_vehicles(Request $req)
|
||||
{
|
||||
$data = [
|
||||
$log = [
|
||||
"module" => "Vehicle",
|
||||
"action" => "View",
|
||||
"desc" => "Open Vehicle menu",
|
||||
];
|
||||
UserLogs::insert($req->auth->uid, $log);
|
||||
|
||||
$listPool = DB::select("SELECT * FROM t_conf_pool WHERE dlt IS NULL ORDER BY pool_code ASC");
|
||||
$listDistribution = DB::select("SELECT * FROM t_conf_distribution_category WHERE dlt IS NULL ORDER BY dc_code ASC");
|
||||
|
||||
$data = [
|
||||
// 'cats' => Vehicles::listCats(), // default Truck
|
||||
"brands" => Vehicles::listBrands(),
|
||||
"types" => Vehicles::listTypes(),
|
||||
@ -73,6 +100,8 @@ class MenuController extends Controller
|
||||
"is_idle_yes" => 1,
|
||||
"is_available" => Devices::IS_AVAIL,
|
||||
]),
|
||||
"listPool" => $listPool,
|
||||
"listDistribution" => $listDistribution
|
||||
];
|
||||
// dd($data);
|
||||
return view("menu_v1.vehicles", $data);
|
||||
@ -84,6 +113,13 @@ class MenuController extends Controller
|
||||
|
||||
public function view_transactions()
|
||||
{
|
||||
$log = [
|
||||
"module" => "Transactions",
|
||||
"action" => "View",
|
||||
"desc" => "Open Transactions menu",
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
|
||||
$data = [
|
||||
"availOrdToMerge" => Finance::availOrdToMerge(),
|
||||
];
|
||||
@ -169,6 +205,14 @@ class MenuController extends Controller
|
||||
}
|
||||
public function view_transactions_view(Request $req)
|
||||
{
|
||||
$log = [
|
||||
"module" => "Transactions",
|
||||
"action" => "View",
|
||||
"desc" => "Open Transactions menu",
|
||||
];
|
||||
UserLogs::insert($req->auth->uid, $log);
|
||||
|
||||
|
||||
$codes = explode(",", $req->code);
|
||||
$limit = count($codes);
|
||||
if ($limit > 2) {
|
||||
@ -330,6 +374,13 @@ class MenuController extends Controller
|
||||
|
||||
public function view_logs_gps()
|
||||
{
|
||||
$log = [
|
||||
"module" => "Logs GPS",
|
||||
"action" => "View",
|
||||
"desc" => "Open Logs GPS menu",
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
|
||||
return view("menu_v1.configs.index_logs_gps");
|
||||
}
|
||||
|
||||
|
||||
369
app/Http/Controllers/ReportsController.php
Normal file
369
app/Http/Controllers/ReportsController.php
Normal file
@ -0,0 +1,369 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
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;
|
||||
|
||||
class ReportsController extends Controller
|
||||
{
|
||||
public function view_report_vehicle_trips(Request $req)
|
||||
{
|
||||
$q = "SELECT id, nopol1 from t_vehicles WHERE dlt is null order by nopol1";
|
||||
$listNopol = DB::select($q);
|
||||
|
||||
$data = [
|
||||
'listNopol' => $listNopol,
|
||||
];
|
||||
|
||||
$log = [
|
||||
"module" => "Vehicle Trips Report",
|
||||
"action" => "View",
|
||||
"desc" => "Open Vehicle Trips Report menu",
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return view('menu_v1.reports.vehicle_trips', $data);
|
||||
}
|
||||
public function api_report_vehicle_trips_list(Request $req)
|
||||
{
|
||||
// $TIMEFIX = Helper::TIMEFIX;
|
||||
// Validate input
|
||||
// date in unix datetime format
|
||||
// dd($req->type);
|
||||
$rules = [
|
||||
// 'from_date' => 'required|date',
|
||||
// 'to_date' => 'required|date|after_or_equal:from_date',
|
||||
'type' => 'nullable|in:report,list', // enum "report", "list". nullable default "list"
|
||||
];
|
||||
|
||||
$isValidInput = Validator::make($req->all(), $rules);
|
||||
if (!$isValidInput->passes()) {
|
||||
$apiResp = Responses::bad_input($isValidInput->messages()->first());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
// $from_date = $req->input('from_date');
|
||||
// $to_date = $req->input('to_date');
|
||||
$from_date = $req->input('from_date') - Helper::TIMEFIX;
|
||||
$to_date = $req->input('to_date') - Helper::TIMEFIX;
|
||||
$vid = $req->input('vid');
|
||||
// $from_date = 1756054800;
|
||||
// $to_date = 1756745940;
|
||||
|
||||
// get month year
|
||||
$date = Carbon::createFromTimestamp($from_date);
|
||||
$yymm = $date->format('ym');
|
||||
|
||||
try {
|
||||
// $list = DB::select("WITH
|
||||
// gaps AS (
|
||||
// SELECT
|
||||
// -- previous gap since previous row > 1 hour (3600s)
|
||||
// CASE
|
||||
// WHEN (crt_d - LAG(crt_d, 1, NULL) OVER (PARTITION BY vhc_id ORDER BY crt_d)) > 3600
|
||||
// THEN 1 ELSE 0
|
||||
// END AS isStop,
|
||||
// t.*
|
||||
// FROM tracks_2509 t
|
||||
// WHERE
|
||||
// t.latitude IS NOT NULL
|
||||
// AND t.longitude IS NOT NULL
|
||||
// AND t.action = 'location'
|
||||
// AND t.crt_d BETWEEN ? AND ?
|
||||
// )
|
||||
// , trips AS (
|
||||
// SELECT
|
||||
// -- mark the start of a trip when ignition=4 and previous ignition <> 4
|
||||
// CASE
|
||||
// WHEN ignition = 4
|
||||
// AND LAG(ignition, 1, 0) OVER (PARTITION BY vhc_id ORDER BY crt_d) <> 4
|
||||
// or LAG(isStop, 1, 0) over (PARTITION BY vhc_id ORDER BY crt_d) = 1
|
||||
// THEN 1 ELSE 0
|
||||
// END AS trip_start,
|
||||
// g.*
|
||||
// FROM gaps g
|
||||
// )
|
||||
// , numbered AS (
|
||||
// SELECT
|
||||
// *,
|
||||
// -- assign a trip_id by cumulative sum of trip_start
|
||||
// SUM(trip_start) OVER (PARTITION BY vhc_id ORDER BY crt_d) AS trip_id
|
||||
// FROM trips
|
||||
// where
|
||||
// ignition = 4
|
||||
// and isStop = 0
|
||||
// ),
|
||||
// agg AS (
|
||||
// SELECT
|
||||
// COUNT(*) AS row_count,
|
||||
// v.name,
|
||||
// v.nopol1,
|
||||
// vhc_id,
|
||||
// -- trip_id,
|
||||
// ROW_NUMBER() OVER (PARTITION BY v.id ORDER BY MIN(a.crt_d)) AS trip_id,
|
||||
// SUM(pre_milleage) AS mileage,
|
||||
// MIN(a.crt_d) AS start,
|
||||
// MAX(a.crt_d) AS finish,
|
||||
// MIN(a.vhc_milleage) AS startMileage,
|
||||
// MAX(a.vhc_milleage) AS finishMileage,
|
||||
// (SELECT fulladdress FROM t_gps_tracks_address WHERE master_id = MIN(a.id) LIMIT 1) AS startLoc,
|
||||
// (SELECT fulladdress FROM t_gps_tracks_address WHERE master_id = MAX(a.id) LIMIT 1) AS finishLoc
|
||||
// FROM t_vehicles v
|
||||
// LEFT JOIN numbered a ON a.vhc_id = v.id
|
||||
// WHERE
|
||||
// v.dlt is null and trip_id != 0
|
||||
// and if(? , v.id = ? , 1=1)
|
||||
// GROUP BY v.id, a.trip_id
|
||||
// HAVING COUNT(*) > 1
|
||||
// )
|
||||
// SELECT
|
||||
// *,
|
||||
// SUM(mileage) OVER (PARTITION BY agg.id) AS total_mileage,
|
||||
// COUNT(trip_id) OVER (PARTITION BY agg.id) AS total_trip,
|
||||
// tvd.pool_code, tvd.dc_code
|
||||
// FROM agg agg
|
||||
// join t_vehicles_detail tvd on tvd.vid = agg.vhc_id
|
||||
// ORDER BY agg.id, trip_id
|
||||
// ", [$from_date, $to_date, $vid, $vid]);
|
||||
|
||||
$list = DB::select("WITH TotalMileage AS (
|
||||
SELECT id, SUM(mileage) AS total_mileage, count(*) total_trip
|
||||
FROM trips
|
||||
WHERE start BETWEEN ? AND ?
|
||||
GROUP BY id
|
||||
)
|
||||
SELECT
|
||||
t.*,
|
||||
tm.total_mileage, total_trip,
|
||||
ROW_NUMBER() OVER (PARTITION BY t.id ORDER BY t.start) AS trip_id
|
||||
FROM trips t
|
||||
JOIN TotalMileage tm ON t.id = tm.id
|
||||
WHERE
|
||||
t.start BETWEEN ? AND ?
|
||||
and if(? , t.id = ? , 1=1)
|
||||
", [$from_date, $to_date, $from_date, $to_date, $vid, $vid]);
|
||||
|
||||
// // RETURN 1 - LIST
|
||||
// if($req->type != 'report'){
|
||||
$apiResp = Responses::success("success list vehicles report");
|
||||
$apiResp["data"] = $list;
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
// }
|
||||
|
||||
// // RETURN 2 - REPORT
|
||||
// if($req->type == 'report'){
|
||||
// $headings = ['Name', 'License Plate', 'Number of Trip', 'Total Mileage'];
|
||||
|
||||
// $export = new class($list, $headings) implements FromArray, WithHeadings {
|
||||
// private $list;
|
||||
// private $headings;
|
||||
|
||||
// public function __construct($list, $headings)
|
||||
// {
|
||||
// $this->list = $list;
|
||||
// $this->headings = $headings;
|
||||
// }
|
||||
|
||||
// public function array(): array
|
||||
// {
|
||||
// return array_map(function ($item) {
|
||||
// return [
|
||||
// $item->name,
|
||||
// $item->nopol1,
|
||||
// $item->numOfTrip,
|
||||
// $item->total_milleage,
|
||||
// ];
|
||||
// }, $this->list);
|
||||
// }
|
||||
|
||||
// public function headings(): array
|
||||
// {
|
||||
// return $this->headings;
|
||||
// }
|
||||
|
||||
// // Start table from A3
|
||||
// public function startCell(): string
|
||||
// {
|
||||
// return 'A3';
|
||||
// }
|
||||
|
||||
// // Add title & border styling
|
||||
// public function styles(Worksheet $sheet)
|
||||
// {
|
||||
// $tgl0 = date('d-m-Y', $GLOBALS['from_date']);
|
||||
// $tgl1 = date('d-m-Y', $GLOBALS['to_date']);
|
||||
|
||||
// // Title in A1
|
||||
// $sheet->setCellValue('A1', 'Vehicle Trip Report $tgl0 until $tgl1');
|
||||
// $sheet->getStyle('A1')->getFont()->setBold(true)->setSize(16);
|
||||
// $sheet->getStyle('A1')->getAlignment()->setHorizontal('center');
|
||||
// $sheet->mergeCells('A1:D1'); // Merge across 4 columns
|
||||
|
||||
// // Get last row
|
||||
// $lastRow = $this->list->count() + 3; // 3 = heading row
|
||||
// $range = "A3:D{$lastRow}";
|
||||
|
||||
// // Add borders
|
||||
// $sheet->getStyle($range)->getBorders()->getAllBorders()
|
||||
// ->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
|
||||
|
||||
// // Bold headings
|
||||
// $sheet->getStyle('A3:D3')->getFont()->setBold(true);
|
||||
|
||||
// return [];
|
||||
// }
|
||||
// };
|
||||
|
||||
// return Excel::download($export, 'trip_report.xlsx');
|
||||
// }
|
||||
} catch (\Exception $e) {
|
||||
$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 view_report_trip_detail(Request $req)
|
||||
{
|
||||
$vid = $req->vid;
|
||||
$tgl0 = $req->tgl0;
|
||||
$tgl1 = $req->tgl1;
|
||||
$nopol1 = $req->nopol1;
|
||||
|
||||
$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
|
||||
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);
|
||||
|
||||
$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;
|
||||
|
||||
$data = [
|
||||
'nopol1' => $nopol1,
|
||||
'vid' => $vid,
|
||||
'tgl0' => $tgl0,
|
||||
'tgl1' => $tgl1,
|
||||
'list' => $list,
|
||||
'start' => $start,
|
||||
'finish' => $finish,
|
||||
'duration' => $duration,
|
||||
'distance' => $distance,
|
||||
];
|
||||
// dd($list);
|
||||
return view('menu_v1.reports._trip_detail', $data);
|
||||
}
|
||||
|
||||
public function view_report_abnormalities(Request $req)
|
||||
{
|
||||
$q = "select id, nopol1 from t_vehicles WHERE dlt is null order by nopol1";
|
||||
$listNopol = DB::select($q);
|
||||
|
||||
$data = [
|
||||
'listNopol' => $listNopol,
|
||||
];
|
||||
|
||||
$log = [
|
||||
"module" => "Abnormalities Report",
|
||||
"action" => "View",
|
||||
"desc" => "Open Abnormalities Report menu",
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return view('menu_v1.reports.abnormalities', $data);
|
||||
}
|
||||
public function api_report_abnormalities_list(Request $req)
|
||||
{
|
||||
// Validate input
|
||||
$rules = [
|
||||
// 'from_date' => 'required|date',
|
||||
// 'to_date' => 'required|date|after_or_equal:from_date',
|
||||
'type' => 'nullable|in:report,list', // enum "report", "list". nullable default "list"
|
||||
];
|
||||
|
||||
$isValidInput = Validator::make($req->all(), $rules);
|
||||
if (!$isValidInput->passes()) {
|
||||
$apiResp = Responses::bad_input($isValidInput->messages()->first());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
$from_date = $req->input('from_date') - Helper::TIMEFIX;
|
||||
$to_date = $req->input('to_date') - Helper::TIMEFIX;
|
||||
$vid = $req->input('vid');
|
||||
|
||||
try {
|
||||
$list = DB::select("SELECT
|
||||
tv.name, tv.nopol1,
|
||||
t.crt_d, t.speed, tgta.fulladdress,
|
||||
tvd.speed_limit, tvd.pool_code, tvd.dc_code
|
||||
from
|
||||
t_gps_tracks t
|
||||
left join t_vehicles tv on tv.id = t.vhc_id
|
||||
left join t_vehicles_detail tvd on tvd.vid = tv.id
|
||||
left join t_gps_tracks_address tgta on tgta.master_id = t.id
|
||||
WHERE
|
||||
t.action = 'location'
|
||||
and t.speed != 0
|
||||
AND t.crt_d BETWEEN ? AND ?
|
||||
and if(? , tv.id = ? , 1=1)
|
||||
-- and t.speed > tvd.speed_limit
|
||||
having t.speed >= tvd.speed_limit
|
||||
ORDER BY t.crt_d
|
||||
", [$from_date, $to_date, $vid, $vid]);
|
||||
|
||||
// // RETURN 1 - LIST
|
||||
// if($req->type != 'report'){
|
||||
$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"]);
|
||||
// return Responses::json(Responses::SERVER_ERROR, 'An error occurred while generating the report.', (object)[]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@ -15,14 +14,12 @@ use App\Models\Clients;
|
||||
use App\Models\Vehicles;
|
||||
use App\Models\Banks;
|
||||
use App\Models\UsersMenuPermissions;
|
||||
use Spatie\Permission\PermissionRegistrar;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Models\UserLogs;
|
||||
|
||||
class RolesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function view(Request $req)
|
||||
{
|
||||
$permissions = \Spatie\Permission\Models\Permission::all();
|
||||
@ -35,17 +32,20 @@ class RolesController extends Controller
|
||||
"vehicles" => Vehicles::getVehicles(),
|
||||
"banks" => Banks::listBanks(["is_active" => Banks::IS_ACTIVE]),
|
||||
"permission" => $permissions->groupBy(function ($perm) {
|
||||
return explode(".", $perm->name)[0]; // ambil modul: user, transaction, dst
|
||||
return explode(".", $perm->name)[0];
|
||||
}),
|
||||
];
|
||||
|
||||
$log = [
|
||||
"module" => "Role",
|
||||
"action" => "View",
|
||||
"desc" => "Open Role menu",
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
|
||||
return view("menu_v1.roles", $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* API
|
||||
*/
|
||||
|
||||
public function api_list(Request $req)
|
||||
{
|
||||
try {
|
||||
@ -69,16 +69,9 @@ class RolesController extends Controller
|
||||
public function api_show(Request $req, $uid)
|
||||
{
|
||||
try {
|
||||
$now = time();
|
||||
$input = ["uid" => $uid];
|
||||
$rulesInput = ["uid" => "required|integer|not_in:0"];
|
||||
|
||||
$input = [
|
||||
"uid" => $uid,
|
||||
];
|
||||
$rulesInput = [
|
||||
"uid" => "required|integer|not_in:0",
|
||||
];
|
||||
|
||||
// validasi input
|
||||
$isValidInput = Validator::make($input, $rulesInput);
|
||||
if (!$isValidInput->passes()) {
|
||||
$apiResp = Responses::bad_input($isValidInput->messages()->first());
|
||||
@ -88,7 +81,6 @@ class RolesController extends Controller
|
||||
$role = DB::table("roles")
|
||||
->where("roles.id", $uid)
|
||||
->get();
|
||||
|
||||
if (count($role) < 1) {
|
||||
$apiResp = Responses::not_found("role not found");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
@ -96,7 +88,7 @@ class RolesController extends Controller
|
||||
|
||||
$permissions = DB::table("role_has_permissions")
|
||||
->where("role_id", $uid)
|
||||
->pluck("permission_id") // ambil array [1, 6, ...]
|
||||
->pluck("permission_id")
|
||||
->toArray();
|
||||
$role[0]->permissions = $permissions;
|
||||
|
||||
@ -113,24 +105,36 @@ class RolesController extends Controller
|
||||
{
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
// Users::addUser($data);
|
||||
|
||||
$role_id = DB::table("roles")->insertGetId([
|
||||
"name" => $req->name,
|
||||
"guard_name" => "web",
|
||||
"created_at" => date("Y-m-d H:i:s"),
|
||||
"updated_at" => date("Y-m-d H:i:s"),
|
||||
"created_at" => now(),
|
||||
"updated_at" => now(),
|
||||
]);
|
||||
|
||||
$role_has_permissions = [];
|
||||
foreach ($req->permissions as $_permission) {
|
||||
array_push($role_has_permissions, ["permission_id" => $_permission, "role_id" => $role_id]);
|
||||
$role_has_permissions[] = [
|
||||
"permission_id" => $_permission,
|
||||
"role_id" => $role_id,
|
||||
];
|
||||
}
|
||||
|
||||
DB::table("role_has_permissions")->insert($role_has_permissions);
|
||||
|
||||
$apiResp = Responses::created("success add new role");
|
||||
DB::commit();
|
||||
|
||||
app()[PermissionRegistrar::class]->forgetCachedPermissions();
|
||||
|
||||
$apiResp = Responses::created("success add new role");
|
||||
|
||||
$log = [
|
||||
"module" => "Role",
|
||||
"action" => "Create",
|
||||
"desc" => "Add new role : ".$req->name,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
@ -147,7 +151,7 @@ class RolesController extends Controller
|
||||
DB::table("roles")
|
||||
->where("id", $req->uid)
|
||||
->update([
|
||||
"name" => $req->name, // ganti sesuai field yang mau diubah
|
||||
"name" => $req->name,
|
||||
"updated_at" => now(),
|
||||
]);
|
||||
|
||||
@ -164,9 +168,18 @@ class RolesController extends Controller
|
||||
}
|
||||
DB::table("role_has_permissions")->insert($role_has_permissions);
|
||||
|
||||
DB::commit();
|
||||
|
||||
app()[PermissionRegistrar::class]->forgetCachedPermissions();
|
||||
|
||||
$apiResp = Responses::created("success update role");
|
||||
|
||||
DB::commit();
|
||||
$log = [
|
||||
"module" => "Role",
|
||||
"action" => "Update",
|
||||
"desc" => "Update role : ".$req->name,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
@ -178,19 +191,9 @@ class RolesController extends Controller
|
||||
public function api_del(Request $req)
|
||||
{
|
||||
try {
|
||||
$now = time();
|
||||
$input = ["uid" => $req->uid];
|
||||
$rulesInput = ["uid" => "required|integer|not_in:0"];
|
||||
|
||||
$input = [
|
||||
"uid" => $req->uid,
|
||||
];
|
||||
$rulesInput = [
|
||||
"uid" => "required|integer|not_in:0",
|
||||
];
|
||||
$data = [
|
||||
"id" => $req->uid,
|
||||
];
|
||||
|
||||
// validasi input
|
||||
$isValidInput = Validator::make($input, $rulesInput);
|
||||
if (!$isValidInput->passes()) {
|
||||
$apiResp = Responses::bad_input($isValidInput->messages()->first());
|
||||
@ -201,7 +204,7 @@ class RolesController extends Controller
|
||||
->where("id", $req->uid)
|
||||
->get();
|
||||
if (count($role) < 1) {
|
||||
$apiResp = Responses::not_found("user not found");
|
||||
$apiResp = Responses::not_found("role not found");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
@ -210,14 +213,22 @@ class RolesController extends Controller
|
||||
DB::table("role_has_permissions")
|
||||
->where("role_id", $req->uid)
|
||||
->delete();
|
||||
|
||||
DB::table("roles")
|
||||
->where("id", $req->uid)
|
||||
->delete();
|
||||
|
||||
DB::commit();
|
||||
|
||||
app()[PermissionRegistrar::class]->forgetCachedPermissions();
|
||||
|
||||
$apiResp = Responses::created("success delete role");
|
||||
|
||||
DB::commit();
|
||||
$log = [
|
||||
"module" => "Role",
|
||||
"action" => "Delete",
|
||||
"desc" => "Delete role : ".$role[0]->name,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
@ -229,10 +240,9 @@ class RolesController extends Controller
|
||||
public function api_search(Request $req)
|
||||
{
|
||||
try {
|
||||
$now = time();
|
||||
$roles = Users::arrRoles();
|
||||
$statuses = Users::arrStatus();
|
||||
DB::beginTransaction();
|
||||
|
||||
$roles = Users::arrRoles();
|
||||
$input = [
|
||||
"name" => $req->name,
|
||||
"roles" => $req->roles,
|
||||
@ -242,41 +252,32 @@ class RolesController extends Controller
|
||||
"roles" => "nullable|integer|not_in:0",
|
||||
];
|
||||
|
||||
// validasi input
|
||||
$isValidInput = Validator::make($input, $rulesInput);
|
||||
if (!$isValidInput->passes()) {
|
||||
$apiResp = Responses::bad_input($isValidInput->messages()->first());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
if ($req->roles) {
|
||||
if (in_array($req->roles, $roles)) {
|
||||
} else {
|
||||
$apiResp = Responses::bad_request("role not valid");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
$users = Users::likeName($req->name, $req->roles);
|
||||
} else {
|
||||
$users = Users::likeName($req->name);
|
||||
if ($req->roles && !in_array($req->roles, $roles)) {
|
||||
$apiResp = Responses::bad_request("role not valid");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
$users = $req->roles ? Users::likeName($req->name, $req->roles) : Users::likeName($req->name);
|
||||
|
||||
if (count($users) < 1) {
|
||||
$apiResp = Responses::not_found("user not found");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
foreach ($users as $k => $v) {
|
||||
// remove from array but no reindex array
|
||||
// unset($users[$k]);
|
||||
// remove from array and reindex array
|
||||
// array_splice($users, $k, 1);
|
||||
unset($users[$k]->password);
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
$apiResp = Responses::success("success search user by name");
|
||||
$apiResp["data"] = $users;
|
||||
|
||||
DB::commit();
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
|
||||
287
app/Http/Controllers/RolesController_bak.php
Executable file
287
app/Http/Controllers/RolesController_bak.php
Executable file
@ -0,0 +1,287 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Validator;
|
||||
use App\Responses;
|
||||
use App\Helper;
|
||||
use App\Models\Users;
|
||||
use App\Models\Clients;
|
||||
use App\Models\Vehicles;
|
||||
use App\Models\Banks;
|
||||
use App\Models\UsersMenuPermissions;
|
||||
|
||||
class RolesController_bak extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function view(Request $req)
|
||||
{
|
||||
$permissions = \Spatie\Permission\Models\Permission::all();
|
||||
|
||||
$data = [
|
||||
"roles" => Users::listRoles($req->auth->role),
|
||||
"pernus" => UsersMenuPermissions::listPermissionsMenus([
|
||||
"is_active" => UsersMenuPermissions::IS_ACTIVE,
|
||||
]),
|
||||
"vehicles" => Vehicles::getVehicles(),
|
||||
"banks" => Banks::listBanks(["is_active" => Banks::IS_ACTIVE]),
|
||||
"permission" => $permissions->groupBy(function ($perm) {
|
||||
return explode(".", $perm->name)[0]; // ambil modul: user, transaction, dst
|
||||
}),
|
||||
];
|
||||
|
||||
return view("menu_v1.roles", $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* API
|
||||
*/
|
||||
|
||||
public function api_list(Request $req)
|
||||
{
|
||||
try {
|
||||
$list = DB::table("roles")->get();
|
||||
foreach ($list as $key => $row) {
|
||||
$list[$key]->DT_RowIndex = $key + 1;
|
||||
$list[$key]->count_trx = 0;
|
||||
$list[$key]->action = "-";
|
||||
}
|
||||
|
||||
$apiResp = Responses::success("success list users");
|
||||
$apiResp["data"] = $list;
|
||||
$apiResp["count"] = count($list);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
$apiResp = Responses::error($e->getMessage());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
|
||||
public function api_show(Request $req, $uid)
|
||||
{
|
||||
try {
|
||||
$now = time();
|
||||
|
||||
$input = [
|
||||
"uid" => $uid,
|
||||
];
|
||||
$rulesInput = [
|
||||
"uid" => "required|integer|not_in:0",
|
||||
];
|
||||
|
||||
// validasi input
|
||||
$isValidInput = Validator::make($input, $rulesInput);
|
||||
if (!$isValidInput->passes()) {
|
||||
$apiResp = Responses::bad_input($isValidInput->messages()->first());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
$role = DB::table("roles")
|
||||
->where("roles.id", $uid)
|
||||
->get();
|
||||
|
||||
if (count($role) < 1) {
|
||||
$apiResp = Responses::not_found("role not found");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
$permissions = DB::table("role_has_permissions")
|
||||
->where("role_id", $uid)
|
||||
->pluck("permission_id") // ambil array [1, 6, ...]
|
||||
->toArray();
|
||||
$role[0]->permissions = $permissions;
|
||||
|
||||
$apiResp = Responses::success("success get detail role");
|
||||
$apiResp["data"] = $role[0];
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
$apiResp = Responses::error($e->getMessage());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
|
||||
public function api_add(Request $req)
|
||||
{
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
// Users::addUser($data);
|
||||
|
||||
$role_id = DB::table("roles")->insertGetId([
|
||||
"name" => $req->name,
|
||||
"guard_name" => "web",
|
||||
"created_at" => date("Y-m-d H:i:s"),
|
||||
"updated_at" => date("Y-m-d H:i:s"),
|
||||
]);
|
||||
|
||||
$role_has_permissions = [];
|
||||
foreach ($req->permissions as $_permission) {
|
||||
array_push($role_has_permissions, ["permission_id" => $_permission, "role_id" => $role_id]);
|
||||
}
|
||||
|
||||
DB::table("role_has_permissions")->insert($role_has_permissions);
|
||||
|
||||
$apiResp = Responses::created("success add new role");
|
||||
DB::commit();
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
$apiResp = Responses::error($e->getMessage());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
|
||||
public function api_edit(Request $req)
|
||||
{
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
DB::table("roles")
|
||||
->where("id", $req->uid)
|
||||
->update([
|
||||
"name" => $req->name, // ganti sesuai field yang mau diubah
|
||||
"updated_at" => now(),
|
||||
]);
|
||||
|
||||
DB::table("role_has_permissions")
|
||||
->where("role_id", $req->uid)
|
||||
->delete();
|
||||
|
||||
$role_has_permissions = [];
|
||||
foreach ($req->permissions as $pid) {
|
||||
$role_has_permissions[] = [
|
||||
"role_id" => $req->uid,
|
||||
"permission_id" => $pid,
|
||||
];
|
||||
}
|
||||
DB::table("role_has_permissions")->insert($role_has_permissions);
|
||||
|
||||
$apiResp = Responses::created("success update role");
|
||||
|
||||
DB::commit();
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
$apiResp = Responses::error($e->getMessage());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
|
||||
public function api_del(Request $req)
|
||||
{
|
||||
try {
|
||||
$now = time();
|
||||
|
||||
$input = [
|
||||
"uid" => $req->uid,
|
||||
];
|
||||
$rulesInput = [
|
||||
"uid" => "required|integer|not_in:0",
|
||||
];
|
||||
$data = [
|
||||
"id" => $req->uid,
|
||||
];
|
||||
|
||||
// validasi input
|
||||
$isValidInput = Validator::make($input, $rulesInput);
|
||||
if (!$isValidInput->passes()) {
|
||||
$apiResp = Responses::bad_input($isValidInput->messages()->first());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
$role = DB::table("roles")
|
||||
->where("id", $req->uid)
|
||||
->get();
|
||||
if (count($role) < 1) {
|
||||
$apiResp = Responses::not_found("user not found");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
DB::table("role_has_permissions")
|
||||
->where("role_id", $req->uid)
|
||||
->delete();
|
||||
|
||||
DB::table("roles")
|
||||
->where("id", $req->uid)
|
||||
->delete();
|
||||
|
||||
$apiResp = Responses::created("success delete role");
|
||||
|
||||
DB::commit();
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
$apiResp = Responses::error($e->getMessage());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
|
||||
public function api_search(Request $req)
|
||||
{
|
||||
try {
|
||||
$now = time();
|
||||
$roles = Users::arrRoles();
|
||||
$statuses = Users::arrStatus();
|
||||
|
||||
$input = [
|
||||
"name" => $req->name,
|
||||
"roles" => $req->roles,
|
||||
];
|
||||
$rulesInput = [
|
||||
"name" => "required|string|max:125",
|
||||
"roles" => "nullable|integer|not_in:0",
|
||||
];
|
||||
|
||||
// validasi input
|
||||
$isValidInput = Validator::make($input, $rulesInput);
|
||||
if (!$isValidInput->passes()) {
|
||||
$apiResp = Responses::bad_input($isValidInput->messages()->first());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
if ($req->roles) {
|
||||
if (in_array($req->roles, $roles)) {
|
||||
} else {
|
||||
$apiResp = Responses::bad_request("role not valid");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
$users = Users::likeName($req->name, $req->roles);
|
||||
} else {
|
||||
$users = Users::likeName($req->name);
|
||||
}
|
||||
|
||||
if (count($users) < 1) {
|
||||
$apiResp = Responses::not_found("user not found");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
foreach ($users as $k => $v) {
|
||||
// remove from array but no reindex array
|
||||
// unset($users[$k]);
|
||||
// remove from array and reindex array
|
||||
// array_splice($users, $k, 1);
|
||||
unset($users[$k]->password);
|
||||
}
|
||||
|
||||
$apiResp = Responses::success("success search user by name");
|
||||
$apiResp["data"] = $users;
|
||||
|
||||
DB::commit();
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
$apiResp = Responses::error($e->getMessage());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,19 +24,11 @@ class TrackController extends Controller
|
||||
$now = time();
|
||||
$input = [];
|
||||
$rulesInput = [];
|
||||
|
||||
// validasi input
|
||||
// $isValidInput = Validator::make($input, $rulesInput);
|
||||
// if (!$isValidInput->passes()) {
|
||||
// $apiResp = Responses::bad_input($isValidInput->messages()->first());
|
||||
// return new Response($apiResp, $apiResp['meta']['code']);
|
||||
// }
|
||||
$filter = [
|
||||
"get_order_data" => 1,
|
||||
];
|
||||
if ($req->cptid) {
|
||||
$filter["company"] = $req->cptid;
|
||||
// $filter["company"] = 1;
|
||||
}
|
||||
|
||||
if ($req->auth->is_tracking === Users::IS_TRACK_VHC_YES) {
|
||||
@ -75,7 +67,6 @@ class TrackController extends Controller
|
||||
$filter["vids"][] = $v->vhc_id;
|
||||
}
|
||||
} elseif ($req->auth->role === Users::ROLE_SPECIAL_TRACKING) {
|
||||
// $filter['vid'] = 0;
|
||||
$filter["company"] = $req->auth->client_group_id;
|
||||
} else {
|
||||
$filter["vid"] = 0;
|
||||
@ -88,8 +79,7 @@ class TrackController extends Controller
|
||||
// dd($list);
|
||||
foreach ($list as $key => $row) {
|
||||
$list[$key]->DT_RowIndex = $key + 1;
|
||||
// $list[$key]->mileage_km = '-';
|
||||
$list[$key]->track_schedule = $row->track_sch_h . "/" . $row->track_sch_d; // combine track_sch_h + track_sch_d
|
||||
|
||||
$list[$key]->is_track_holiday_text =
|
||||
$list[$key]->is_track_holiday == Vehicles::ENABLED_TRACK_HOLIDAY ? "Enabled" : "Disabled";
|
||||
$list[$key]->alert_zones = "-";
|
||||
@ -141,21 +131,28 @@ class TrackController extends Controller
|
||||
}
|
||||
|
||||
$filter = [
|
||||
"limit" => 500,
|
||||
"limit" => 10000,
|
||||
];
|
||||
// default 500, jika ada filter date maka max 5K
|
||||
// default 10000, jika ada filter date maka max 100K
|
||||
if (
|
||||
$req->start_date != null &&
|
||||
$req->start_date != "" &&
|
||||
($req->end_date != null && $req->end_date != "")
|
||||
($req->end_date != null && //
|
||||
$req->end_date != "")
|
||||
) {
|
||||
$filter["start_date"] = $req->start_date;
|
||||
$filter["end_date"] = $req->end_date;
|
||||
|
||||
$filter["start_date"] = strtotime(gmdate("Y-m-d H:i:s", $req->start_date));
|
||||
$filter["end_date"] = strtotime(gmdate("Y-m-d H:i:s", $req->end_date));
|
||||
// $filter["start_date"] = strtotime(gmdate("Y-m-d H:i:s", $req->start_date));
|
||||
// $filter["end_date"] = strtotime(gmdate("Y-m-d H:i:s", $req->end_date));
|
||||
|
||||
$filter["limit"] = 5000;
|
||||
$filter["limit"] = 100000;
|
||||
} else {
|
||||
$todayStart = strtotime(gmdate("Y-m-d 00:00:00"));
|
||||
$todayEnd = strtotime(gmdate("Y-m-d 23:59:59"));
|
||||
|
||||
$filter["start_date"] = $todayStart;
|
||||
$filter["end_date"] = $todayEnd;
|
||||
}
|
||||
|
||||
$list = Tracks::lastMoveTracks($req->vid, $filter);
|
||||
|
||||
71
app/Http/Controllers/UserLogsController.php
Normal file
71
app/Http/Controllers/UserLogsController.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
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 Hidehalo\Nanoid\Client as Nanoid;
|
||||
use Hidehalo\Nanoid\GeneratorInterface as NanoidInterface;
|
||||
use App\Responses;
|
||||
use App\Helper;
|
||||
use App\Models\ConfRates;
|
||||
use App\Models\ConfTruckTypes;
|
||||
use App\Models\Vehicles;
|
||||
use App\Models\UserLogs;
|
||||
use Auth;
|
||||
use App\Models\Users;
|
||||
|
||||
class UserLogsController extends Controller
|
||||
{
|
||||
/**
|
||||
* View
|
||||
*/
|
||||
|
||||
public function view_user_logs(Request $req)
|
||||
{
|
||||
$users = Users::listUsers();
|
||||
$data = [
|
||||
"users" => $users,
|
||||
];
|
||||
|
||||
$log = [
|
||||
"module" => "User Logs",
|
||||
"action" => "View",
|
||||
"desc" => "Open User Logs menu",
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return view("menu_v1.userLogs", $data);
|
||||
}
|
||||
public function api_user_logs(Request $req)
|
||||
{
|
||||
try {
|
||||
$tgl0 = $req->tgl0;
|
||||
$tgl1 = $req->tgl1;
|
||||
$userId = $req->userId;
|
||||
|
||||
$d = [$tgl0, $tgl1, $userId, $userId];
|
||||
$list = DB::select("SELECT
|
||||
a.*, b.email
|
||||
FROM t_user_log a
|
||||
join t_users b on a.userId = b.id
|
||||
WHERE
|
||||
a.crt BETWEEN ? AND ?
|
||||
and if(? , a.userId = ? , 1=1)
|
||||
order by a.crt desc
|
||||
", $d);
|
||||
|
||||
$apiResp = Responses::success("success user logs");
|
||||
$apiResp["data"] = $list;
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
$apiResp = Responses::error($e->getMessage());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -15,6 +15,8 @@ use App\Models\Clients;
|
||||
use App\Models\Vehicles;
|
||||
use App\Models\Banks;
|
||||
use App\Models\UsersMenuPermissions;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Models\UserLogs;
|
||||
|
||||
class UsersController extends Controller
|
||||
{
|
||||
@ -50,6 +52,13 @@ class UsersController extends Controller
|
||||
$data["clients"] = Clients::select2Client($req->auth->client_group_id);
|
||||
}
|
||||
|
||||
$log = [
|
||||
"module" => "User",
|
||||
"action" => "View",
|
||||
"desc" => "Open User menu",
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
|
||||
return view("menu_v1.users", $data);
|
||||
}
|
||||
|
||||
@ -173,6 +182,7 @@ class UsersController extends Controller
|
||||
"bank_acc_number" => $req->bank_acc_number,
|
||||
"bank_acc_name" => $req->bank_acc_name,
|
||||
"status" => $req->status,
|
||||
"status_sms" => $req->status_sms,
|
||||
"is_tracking" => $req->is_tracking,
|
||||
"vehicles" => $req->vehicles,
|
||||
"is_vdr_bcng" => $req->is_vdr_bcng,
|
||||
@ -195,6 +205,7 @@ class UsersController extends Controller
|
||||
"bank_acc_number" => "nullable|numeric",
|
||||
"bank_acc_name" => "nullable|string|max:255",
|
||||
"status" => "required|integer|not_in:0",
|
||||
"status_sms" => "required|integer",
|
||||
"is_tracking" => "nullable|numeric",
|
||||
"vehicles" => "nullable|array",
|
||||
"is_vdr_bcng" => "nullable|numeric",
|
||||
@ -219,20 +230,20 @@ class UsersController extends Controller
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
if ($req->roles == Users::ROLE_VENDOR) {
|
||||
if (!$req->bank_id) {
|
||||
$apiResp = Responses::bad_request("bank wajib diisi");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
if (!$req->bank_acc_number) {
|
||||
$apiResp = Responses::bad_request("nomor rekening wajib diisi");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
if (!$req->bank_acc_name) {
|
||||
$apiResp = Responses::bad_request("nama pemilik rekening wajib diisi");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
// if ($req->roles == Users::ROLE_VENDOR) {
|
||||
// if (!$req->bank_id) {
|
||||
// $apiResp = Responses::bad_request("bank wajib diisi");
|
||||
// return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
// }
|
||||
// if (!$req->bank_acc_number) {
|
||||
// $apiResp = Responses::bad_request("nomor rekening wajib diisi");
|
||||
// return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
// }
|
||||
// if (!$req->bank_acc_name) {
|
||||
// $apiResp = Responses::bad_request("nama pemilik rekening wajib diisi");
|
||||
// return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
// }
|
||||
// }
|
||||
|
||||
if ($req->clients) {
|
||||
$clients = Clients::getClientById($req->clients);
|
||||
@ -294,6 +305,7 @@ class UsersController extends Controller
|
||||
"crt_by" => $req->auth->uid,
|
||||
"updt" => $now,
|
||||
"updt_by" => $req->auth->uid,
|
||||
"status_sms" => $req->status_sms,
|
||||
];
|
||||
if ($req->roles == Users::ROLE_CHECKER) {
|
||||
// $data['chk_type'] = $req->chk_type;
|
||||
@ -325,6 +337,14 @@ class UsersController extends Controller
|
||||
$apiResp = Responses::created("success add new user");
|
||||
|
||||
DB::commit();
|
||||
|
||||
$log = [
|
||||
"module" => "User",
|
||||
"action" => "Create",
|
||||
"desc" => "Add new user : ".$req->email,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
@ -352,6 +372,7 @@ class UsersController extends Controller
|
||||
"bank_acc_number" => $req->bank_acc_number,
|
||||
"bank_acc_name" => $req->bank_acc_name,
|
||||
"is_vdr_bcng" => $req->is_vdr_bcng,
|
||||
"status_sms" => $req->status_sms,
|
||||
];
|
||||
$rulesInput = [
|
||||
"uid" => "required|integer|not_in:0",
|
||||
@ -365,6 +386,7 @@ class UsersController extends Controller
|
||||
"bank_acc_number" => "nullable|numeric",
|
||||
"bank_acc_name" => "nullable|string|max:255",
|
||||
"is_vdr_bcng" => "nullable|numeric",
|
||||
"status_sms" => "required|integer",
|
||||
];
|
||||
$data = [
|
||||
"id" => $req->uid,
|
||||
@ -440,6 +462,7 @@ class UsersController extends Controller
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
$data["status_sms"] = $req->status_sms;
|
||||
|
||||
// validasi input
|
||||
$isValidInput = Validator::make($input, $rulesInput);
|
||||
@ -454,25 +477,6 @@ class UsersController extends Controller
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
if ($req->roles == Users::ROLE_VENDOR) {
|
||||
if (!$req->bank_id) {
|
||||
$apiResp = Responses::bad_request("bank wajib diisi");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
if (!$req->bank_branch_name) {
|
||||
$apiResp = Responses::bad_request("bank kcp wajib diisi");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
if (!$req->bank_acc_number) {
|
||||
$apiResp = Responses::bad_request("nomor rekening wajib diisi");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
if (!$req->bank_acc_name) {
|
||||
$apiResp = Responses::bad_request("nama pemilik rekening wajib diisi");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
|
||||
$uniqEmail = Users::getUserByEmail($req->email);
|
||||
if (count($uniqEmail) > 0) {
|
||||
$notSameUser = 1;
|
||||
@ -499,19 +503,6 @@ class UsersController extends Controller
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
// $uniqCPhone = Clients::getClientByPhone($req->phone);
|
||||
// if (count($uniqCPhone) > 0) {
|
||||
// $notSameUser = 1;
|
||||
// foreach ($uniqCPhone as $key => $row) {
|
||||
// if ($row->id == $getUser[0]->client_id) {
|
||||
// $notSameUser = 0;
|
||||
// }
|
||||
// }
|
||||
// if ($notSameUser) {
|
||||
// $apiResp = Responses::bad_request('phone has been used');
|
||||
// return (new Response($apiResp, $apiResp['meta']['code']));
|
||||
// }
|
||||
// }
|
||||
|
||||
$vhcs = null;
|
||||
if ($req->is_tracking == Users::IS_TRACK_VHC_YES) {
|
||||
@ -531,17 +522,6 @@ class UsersController extends Controller
|
||||
$data["is_tracking"] = $req->is_tracking;
|
||||
$data["vhcs"] = $vhcs;
|
||||
|
||||
if ($req->roles == Users::ROLE_VENDOR) {
|
||||
$data["bank_id"] = $req->bank_id;
|
||||
$data["bank_code"] = $req->bank_code;
|
||||
$data["bank_name"] = $req->bank_name;
|
||||
$data["bank_short_name"] = $req->bank_short;
|
||||
$data["bank_branch_name"] = $req->bank_branch_name;
|
||||
$data["bank_acc_number"] = $req->bank_acc_number;
|
||||
$data["bank_acc_name"] = $req->bank_acc_name;
|
||||
$data["is_vdr_bcng"] = $req->is_vdr_bcng;
|
||||
}
|
||||
|
||||
$data["updt"] = $now;
|
||||
$data["updt_by"] = $req->auth->uid;
|
||||
|
||||
@ -551,15 +531,158 @@ class UsersController extends Controller
|
||||
|
||||
Users::updateUser($req->uid, $data);
|
||||
|
||||
DB::table("model_has_roles")
|
||||
->where("model_id", $req->uid)
|
||||
->delete();
|
||||
|
||||
if ($req->roles) {
|
||||
DB::table("model_has_roles")
|
||||
->where("model_id", $req->uid)
|
||||
->delete();
|
||||
|
||||
DB::table("model_has_roles")->insert([
|
||||
"role_id" => $req->roles,
|
||||
"model_type" => "App\\User", // atau 'App\User' tergantung struktur kamu
|
||||
"model_id" => $req->uid, // ID user-nya
|
||||
"model_type" => "App\\User",
|
||||
"model_id" => $req->uid,
|
||||
]);
|
||||
}
|
||||
|
||||
$apiResp = Responses::created("success update user");
|
||||
|
||||
DB::commit();
|
||||
|
||||
$log = [
|
||||
"module" => "User",
|
||||
"action" => "Update",
|
||||
"desc" => "Update user : ".$req->email,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
$apiResp = Responses::error($e->getMessage());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
public function api_edit_user_profile(Request $req)
|
||||
{
|
||||
try {
|
||||
$now = time();
|
||||
$roles = Users::arrRoles();
|
||||
$statuses = Users::arrStatus();
|
||||
|
||||
$input = [
|
||||
"uid" => $req->uid,
|
||||
"is_tracking" => $req->is_tracking,
|
||||
"vehicles" => $req->vehicles,
|
||||
"bank_id" => $req->bank_id,
|
||||
"bank_code" => $req->bank_code,
|
||||
"bank_short" => $req->bank_short,
|
||||
"bank_name" => $req->bank_name,
|
||||
"bank_kcp" => $req->bank_branch_name,
|
||||
"bank_acc_number" => $req->bank_acc_number,
|
||||
"bank_acc_name" => $req->bank_acc_name,
|
||||
"is_vdr_bcng" => $req->is_vdr_bcng,
|
||||
];
|
||||
$rulesInput = [
|
||||
"uid" => "required|integer|not_in:0",
|
||||
"is_tracking" => "nullable|numeric",
|
||||
"vehicles" => "nullable|array",
|
||||
"bank_id" => "nullable|integer|not_in:0",
|
||||
"bank_code" => "nullable|numeric",
|
||||
"bank_short" => "nullable|string",
|
||||
"bank_name" => "nullable|string",
|
||||
"bank_kcp" => "nullable|string",
|
||||
"bank_acc_number" => "nullable|numeric",
|
||||
"bank_acc_name" => "nullable|string|max:255",
|
||||
"is_vdr_bcng" => "nullable|numeric",
|
||||
];
|
||||
$data = [
|
||||
"id" => $req->uid,
|
||||
];
|
||||
|
||||
if ($req->first_name) {
|
||||
$input["first_name"] = $req->first_name;
|
||||
$rulesInput["first_name"] = "required|string|max:125";
|
||||
$data["first_name"] = $req->first_name;
|
||||
}
|
||||
if ($req->last_name) {
|
||||
$input["last_name"] = $req->last_name;
|
||||
$rulesInput["last_name"] = "required|string|max:125";
|
||||
$data["last_name"] = $req->last_name ?? null;
|
||||
}
|
||||
if ($req->email) {
|
||||
$input["email"] = $req->email;
|
||||
$rulesInput["email"] = "required|email";
|
||||
$data["email"] = $req->email;
|
||||
}
|
||||
if ($req->phone) {
|
||||
$input["phone"] = $req->phone;
|
||||
$rulesInput["phone"] = "required|integer|not_in:0";
|
||||
$data["phone"] = $req->phone;
|
||||
$data["phone_code"] = Users::DEFAULT_PHONE_CODE;
|
||||
}
|
||||
if ($req->fulladdress) {
|
||||
$input["fulladdress"] = $req->fulladdress;
|
||||
$rulesInput["fulladdress"] = "required|string|min:45";
|
||||
$data["fulladdress"] = $req->fulladdress;
|
||||
}
|
||||
if ($req->password) {
|
||||
$input["password"] = $req->password;
|
||||
$rulesInput["password"] = "required|string";
|
||||
$data["password"] = Hash::make($req->password);
|
||||
}
|
||||
|
||||
// validasi input
|
||||
$isValidInput = Validator::make($input, $rulesInput);
|
||||
if (!$isValidInput->passes()) {
|
||||
$apiResp = Responses::bad_input($isValidInput->messages()->first());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
$getUser = Users::getUserById($req->uid);
|
||||
if (count($getUser) < 1) {
|
||||
$apiResp = Responses::not_found("user not found");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
|
||||
$uniqEmail = Users::getUserByEmail($req->email);
|
||||
if (count($uniqEmail) > 0) {
|
||||
$notSameUser = 1;
|
||||
foreach ($uniqEmail as $key => $row) {
|
||||
if ($row->id == $req->uid) {
|
||||
$notSameUser = 0;
|
||||
}
|
||||
}
|
||||
if ($notSameUser) {
|
||||
$apiResp = Responses::bad_request("email has been used");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
$uniqPhone = Users::getUserByPhone($req->phone);
|
||||
if (count($uniqPhone) > 0) {
|
||||
$notSameUser = 1;
|
||||
foreach ($uniqPhone as $key => $row) {
|
||||
if ($row->id == $req->uid) {
|
||||
$notSameUser = 0;
|
||||
}
|
||||
}
|
||||
if ($notSameUser) {
|
||||
$apiResp = Responses::bad_request("phone has been used");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
Users::updateUser($req->uid, $data);
|
||||
|
||||
if ($req->roles) {
|
||||
DB::table("model_has_roles")
|
||||
->where("model_id", $req->uid)
|
||||
->delete();
|
||||
|
||||
DB::table("model_has_roles")->insert([
|
||||
"role_id" => $req->roles,
|
||||
"model_type" => "App\\User",
|
||||
"model_id" => $req->uid,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -612,6 +735,14 @@ class UsersController extends Controller
|
||||
$apiResp = Responses::created("success delete user");
|
||||
|
||||
DB::commit();
|
||||
|
||||
$log = [
|
||||
"module" => "User",
|
||||
"action" => "Delete",
|
||||
"desc" => "Delete user : ".$getUser[0]->email,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
@ -678,4 +809,38 @@ class UsersController extends Controller
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
|
||||
public function view_user_logs1(Request $req)
|
||||
{
|
||||
$id = $req->id;
|
||||
|
||||
$user = Users::getUserById($id)[0];
|
||||
$data = [
|
||||
'user' => $user
|
||||
];
|
||||
// dd($dtl);
|
||||
return view('menu_v1._userLogs', $data);
|
||||
}
|
||||
public function api_user_logs1(Request $req)
|
||||
{
|
||||
try {
|
||||
$id = $req->id;
|
||||
$tgl0 = $req->tgl0;
|
||||
$tgl1 = $req->tgl1;
|
||||
|
||||
$d = [$id, $tgl0, $tgl1];
|
||||
$list = DB::select("SELECT * FROM t_user_log
|
||||
WHERE userId = ? AND crt BETWEEN ? AND ?
|
||||
order by crt desc
|
||||
", $d);
|
||||
|
||||
$apiResp = Responses::success("success user logs");
|
||||
$apiResp["data"] = $list;
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
$apiResp = Responses::error($e->getMessage());
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ use App\Models\Vehicles;
|
||||
use App\Models\Devices;
|
||||
use App\Models\VehiclesDetail;
|
||||
use App\Models\Users;
|
||||
use App\Models\UserLogs;
|
||||
|
||||
class VehiclesController extends Controller
|
||||
{
|
||||
@ -152,6 +153,8 @@ class VehiclesController extends Controller
|
||||
"tax_exp" => $req->tax_exp,
|
||||
// "kir_exp" => $req->kir_exp,
|
||||
// "vendor_id" => $req->vendor_id,
|
||||
"dc_code" => $req->dc_code,
|
||||
"pool_code" => $req->pool_code,
|
||||
];
|
||||
$rulesInput = [
|
||||
"front_vehicle_photo" => "required|string",
|
||||
@ -184,6 +187,8 @@ class VehiclesController extends Controller
|
||||
"tax_exp" => "required|date_format:Y-m-d",
|
||||
// "kir_exp" => "required|date_format:Y-m-d",
|
||||
// "vendor_id" => "nullable|integer|not_in:0",
|
||||
"dc_code" => "nullable|string",
|
||||
"pool_code" => "nullable|string",
|
||||
];
|
||||
|
||||
if ($req->auth->role == Users::ROLE_VENDOR) {
|
||||
@ -235,7 +240,7 @@ class VehiclesController extends Controller
|
||||
"nopol1" => strtoupper($req->nopol1),
|
||||
// "nopol2" => strtoupper($req->nopol2),
|
||||
// "nopol3" => strtoupper($req->nopol3),
|
||||
"sum_milleage" => $req->sum_milleage ?? 0,
|
||||
"sum_milleage" => $req->mileage ?? 0,
|
||||
"c_did" => $req->d_current ?? 0,
|
||||
"a_did" => $req->d_assign ?? 0,
|
||||
"is_track_holiday" => Vehicles::DEFAULT_TRACK_HOLIDAY,
|
||||
@ -249,6 +254,7 @@ class VehiclesController extends Controller
|
||||
"crt_by" => $req->auth->uid,
|
||||
"updt" => $now,
|
||||
"updt_by" => $req->auth->uid,
|
||||
|
||||
];
|
||||
// dd($insVhc);
|
||||
if ($req->model_id) {
|
||||
@ -316,13 +322,24 @@ class VehiclesController extends Controller
|
||||
"regis_year" => $req->regis_year,
|
||||
"tax_exp" => $req->tax_exp,
|
||||
"kir_exp" => $req->kir_exp,
|
||||
"dc_code" => $req->dc_code,
|
||||
"pool_code" => $req->pool_code,
|
||||
|
||||
];
|
||||
VehiclesDetail::addDetail($insDetail);
|
||||
|
||||
$apiResp = Responses::created("success add new vehicle");
|
||||
|
||||
DB::commit();
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
|
||||
$log = [
|
||||
"module" => "Vehicle",
|
||||
"action" => "Create",
|
||||
"desc" => "Add new vehicle: ".$req->vhc_name,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
Storage::disk("public")->delete($url_fvhc);
|
||||
Storage::disk("public")->delete($url_stnk);
|
||||
@ -353,6 +370,7 @@ class VehiclesController extends Controller
|
||||
"type_id" => $req->type_id,
|
||||
"model_id" => $req->model_id,
|
||||
"speed_limit" => $req->speed_limit,
|
||||
"sum_milleage" => $req->mileage,
|
||||
"fuel_capacity" => $req->fuel_capacity,
|
||||
"fuel_drop_treshold" => $req->fuel_drop_treshold,
|
||||
"max_pressure" => $req->max_pressure,
|
||||
@ -374,6 +392,8 @@ class VehiclesController extends Controller
|
||||
"tax_exp" => $req->tax_exp,
|
||||
// "kir_exp" => $req->kir_exp,
|
||||
// "vendor_id" => $req->vendor_id,
|
||||
"dc_code" => $req->dc_code,
|
||||
"pool_code" => $req->pool_code,
|
||||
];
|
||||
$rulesInput = [
|
||||
"vid" => "required|integer|not_in:0",
|
||||
@ -386,6 +406,7 @@ class VehiclesController extends Controller
|
||||
"type_id" => "required|integer",
|
||||
"model_id" => "nullable|integer",
|
||||
"speed_limit" => "required|numeric",
|
||||
"sum_milleage" => "required|numeric",
|
||||
// "fuel_capacity" => "required|numeric",
|
||||
// "fuel_drop_treshold" => "required|numeric",
|
||||
// "max_pressure" => "required|numeric",
|
||||
@ -407,6 +428,8 @@ class VehiclesController extends Controller
|
||||
"tax_exp" => "required|date_format:Y-m-d",
|
||||
// "kir_exp" => "required|date_format:Y-m-d",
|
||||
// "vendor_id" => "nullable|integer|not_in:0",
|
||||
"dc_code" => "nullable|string",
|
||||
"pool_code" => "nullable|string",
|
||||
];
|
||||
|
||||
if ($req->auth->role == Users::ROLE_VENDOR) {
|
||||
@ -495,7 +518,7 @@ class VehiclesController extends Controller
|
||||
"nopol3" => strtoupper($req->nopol3),
|
||||
"c_did" => $req->d_current ?? 0,
|
||||
"a_did" => $req->d_assign ?? 0,
|
||||
"sum_milleage" => $req->sum_milleage ?? 0,
|
||||
"sum_milleage" => $req->mileage ?? 0,
|
||||
"is_track_holiday" => Vehicles::DEFAULT_TRACK_HOLIDAY,
|
||||
"track_sch_d" => Vehicles::DEFAULT_TRACK_SCH_D,
|
||||
"track_sch_h" => Vehicles::DEFAULT_TRACK_SCH_H,
|
||||
@ -561,6 +584,8 @@ class VehiclesController extends Controller
|
||||
"regis_year" => $req->regis_year,
|
||||
"tax_exp" => $req->tax_exp,
|
||||
"kir_exp" => $req->kir_exp,
|
||||
"dc_code" => $req->dc_code,
|
||||
"pool_code" => $req->pool_code,
|
||||
];
|
||||
if ($req->fvhc_base64) {
|
||||
$updtDetail["fvhc_img"] = $url_fvhc;
|
||||
@ -573,6 +598,13 @@ class VehiclesController extends Controller
|
||||
DB::commit();
|
||||
|
||||
$apiResp = Responses::success("success update vehicle");
|
||||
|
||||
$log = [
|
||||
"module" => "Vehicle",
|
||||
"action" => "Update",
|
||||
"desc" => "Update vehicle: ".$req->vhc_name,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
Storage::disk("public")->delete($url_fvhc);
|
||||
@ -630,6 +662,13 @@ class VehiclesController extends Controller
|
||||
DB::commit();
|
||||
|
||||
$apiResp = Responses::success("success delete vehicle");
|
||||
|
||||
$log = [
|
||||
"module" => "Vehicle",
|
||||
"action" => "Delete",
|
||||
"desc" => "Delete vehicle: ".$vehicle[0]->name,
|
||||
];
|
||||
UserLogs::insert(Auth::user()->id, $log);
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
|
||||
@ -17,6 +17,8 @@ use App\Models\Orders;
|
||||
use App\Models\OrdersDrops;
|
||||
// use App\Models\OrdersPckDrop;
|
||||
use App\Models\OrdersAItems;
|
||||
use App\Models\UserLogs;
|
||||
|
||||
|
||||
class ZoneController extends Controller
|
||||
{
|
||||
@ -25,8 +27,14 @@ class ZoneController extends Controller
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function view_zone()
|
||||
public function view_zone(Request $req)
|
||||
{
|
||||
$log = [
|
||||
"module" => "Zone",
|
||||
"action" => "View",
|
||||
"desc" => "Open Zone menu",
|
||||
];
|
||||
UserLogs::insert($req->auth->uid, $log);
|
||||
return view("menu_v1.zone");
|
||||
}
|
||||
|
||||
@ -355,6 +363,13 @@ class ZoneController extends Controller
|
||||
|
||||
$apiResp = Responses::created("success add new zone");
|
||||
|
||||
$log = [
|
||||
"module" => "Zone",
|
||||
"action" => "Create",
|
||||
"desc" => "Add Zone ".$req->zone_name,
|
||||
];
|
||||
UserLogs::insert($req->auth->uid, $log);
|
||||
|
||||
DB::commit();
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
} catch (\Exception $e) {
|
||||
@ -481,7 +496,14 @@ class ZoneController extends Controller
|
||||
|
||||
Zone::updateZone($zid, $updtZone);
|
||||
|
||||
DB::commit();
|
||||
$log = [
|
||||
"module" => "Zone",
|
||||
"action" => "Update",
|
||||
"desc" => "Update Zone ".$req->zone_name,
|
||||
];
|
||||
UserLogs::insert($req->auth->uid, $log);
|
||||
|
||||
DB::commit();
|
||||
|
||||
$apiResp = Responses::success("success update zone");
|
||||
return new Response($apiResp, $apiResp["meta"]["code"]);
|
||||
@ -524,6 +546,13 @@ class ZoneController extends Controller
|
||||
"dlt_by" => $req->auth->uid,
|
||||
]);
|
||||
|
||||
$log = [
|
||||
"module" => "Zone",
|
||||
"action" => "Delete ",
|
||||
"desc" => "Delete Zone ".$zone[0]->name,
|
||||
];
|
||||
UserLogs::insert($req->auth->uid, $log);
|
||||
|
||||
DB::commit();
|
||||
|
||||
$apiResp = Responses::success("success delete zone");
|
||||
|
||||
@ -49,104 +49,331 @@ class Tracks extends Model
|
||||
* device sudah sampai dilokasi pengantaran dan dimatikan, ketika dipakai lagi data tracking yang lama kelihatan dan loncat
|
||||
* untuk mengatasi itu di service_tracking juga perlu validasi tambahan, entah seperti apa caranya
|
||||
*/
|
||||
|
||||
// public static function listCurrentTracks($filter = [])
|
||||
// {
|
||||
// $now = time();
|
||||
// $params = [];
|
||||
|
||||
// $query = "SELECT";
|
||||
// $query .=
|
||||
// " v.id as vid,v.device_id,v.name as vhc_name,c.name as vhc_cat_name,t.name as vhc_type_name";
|
||||
// $query .= " ,v.nopol1,v.nopol2,v.nopol3,vd.fvhc_img";
|
||||
// $query .= " ,v.is_track_holiday,v.track_sch_d,v.track_sch_h,vd.speed_limit,v.crt as vhc_crt";
|
||||
// $query .= " ,client.id as client_group_id,client.c_name as client_group_name";
|
||||
// $query .= " ,tr.ignition,tr.stts_engine,tr.stts_gps,tr.stts_gsm";
|
||||
// $query .= " ,tr.pre_milleage,tr.sum_milleage,tr.vhc_milleage,v.sum_milleage AS vhc_sum_milleage_1";
|
||||
|
||||
// // FRO
|
||||
// // $query .= " ,(SELECT SUM(pre_milleage) FROM " . self::T_TRACKS . " WHERE vhc_id = v.id LIMIT 1) as vhc_sum_milleage";
|
||||
|
||||
// // $query .= " ,(SELECT crt_s FROM " . self::T_TRACKS . " WHERE stts_engine = " . self::STTS_EN_IDLING . " AND vhc_id = v.id AND crt_s >= (
|
||||
// // SELECT crt_s FROM " . self::T_TRACKS . " WHERE stts_engine IN (" . self::STTS_EN_STOPING . "," . self::STTS_EN_MOVING . ") AND vhc_id = v.id AND crt_s <= tr.crt_s ORDER BY id DESC LIMIT 1
|
||||
// // ) ORDER BY id ASC LIMIT 1) as lst_idle_at";
|
||||
|
||||
// // $query .= " ,(SELECT crt_s FROM " . self::T_TRACKS . " WHERE stts_engine = " . self::STTS_EN_STOPING . " AND vhc_id = v.id AND crt_s >= (
|
||||
// // SELECT crt_s FROM " . self::T_TRACKS . " WHERE stts_engine IN (" . self::STTS_EN_IDLING . "," . self::STTS_EN_MOVING . ") AND vhc_id = v.id AND crt_s <= tr.crt_s ORDER BY id DESC LIMIT 1
|
||||
// // ) ORDER BY id ASC LIMIT 1) as lst_stop_at";
|
||||
|
||||
// $query .=
|
||||
// " ,tr.id AS lst_master_id,tr.latitude AS lst_lat,tr.longitude AS lst_lng,tr.speed AS lst_speed,tr.orientation AS lst_orientation";
|
||||
// $query .= " ,tr.crt AS lst_loc_crt,tr.crt_d AS lst_loc_crt_d,tr.crt_s AS lst_loc_crt_s";
|
||||
// $query .=
|
||||
// " ,tr_addr.master_id AS lst_addr_master_id,tr_addr.country_text AS lst_country_text,tr_addr.state_text AS lst_state_text,tr_addr.city_text AS lst_city_text";
|
||||
// $query .=
|
||||
// " ,tr_addr.district_text AS lst_district_text,tr_addr.village_text AS lst_village_text,tr_addr.postcode AS lst_postcode";
|
||||
// $query .= " ,tr_addr.streets AS lst_streets,tr_addr.fulladdress AS lst_fulladdress";
|
||||
|
||||
// // FRO
|
||||
// // $query .= " ,(SELECT COUNT(id) FROM " . self::T_TRACKS . " WHERE vhc_id = v.id AND action = 'heartbeat' AND crt BETWEEN ".($now-(10*60))." AND ".$now." LIMIT 1) as lst_heartbeat"; // heartbeat last data on further 10 minutes
|
||||
|
||||
// if (isset($filter["active_rates"])) {
|
||||
// $query .=
|
||||
// ",rate.vdr_id as rate_vdr_id,rate.vhc_type as rate_vhc_type,rate.origin_prov as rate_origin_prov,rate.dest_city as rate_dest_city,rate.dest_district as rate_dest_district";
|
||||
// $query .=
|
||||
// ",rate.fast_time as rate_fast_time,rate.long_time as rate_long_time,rate.sell_kg as rate_sell_kg,rate.sell_cbm as rate_sell_cbm,rate.sell_ftl as rate_sell_ftl";
|
||||
// }
|
||||
// if (isset($filter["get_order_data"])) {
|
||||
// $query .=
|
||||
// ",ord.id as ord_id,ord.code as ord_code,ord.status as ord_stts,ord.crt as ord_crt,ord_pck.pck_name as ord_pck_name,ord_pck.pck_addr as ord_pck_addr,ord_drop.drop_name as ord_drop_name,ord_drop.drop_addr as ord_drop_addr";
|
||||
// $query .=
|
||||
// ",(SELECT nmKotamadyaKel FROM t_region WHERE kodeKab = ord_pck.pck_ktid LIMIT 1) ord_pck_ktname, (SELECT nmKotamadyaKel FROM t_region WHERE kodeKab = ord_drop.drop_ktid LIMIT 1) ord_drop_ktname";
|
||||
// $query .=
|
||||
// ",ord_drv.drv_name as ord_drv_name,ord_drv.drv_phone_val as ord_drv_phone_val,ord_drv.drv_phone2_val as ord_drv_phone2_val,ord_drv.drv_addr as ord_drv_addr";
|
||||
// $query .= ",ord_c.c_name as ord_c_name,ord_c.c_pt_name as ord_c_pt_name";
|
||||
// }
|
||||
// $query .= " FROM t_vehicles AS v";
|
||||
// $query .= " INNER JOIN t_vehicles_detail AS vd ON v.id = vd.vid";
|
||||
// $query .= " INNER JOIN t_vehicles_types AS t ON v.type_id = t.id";
|
||||
// $query .= " INNER JOIN t_vehicles_cats AS c ON v.cat_id = c.id";
|
||||
// $query .= " LEFT JOIN t_users AS vendor ON v.vendor_id = vendor.id";
|
||||
// $query .= " LEFT JOIN t_clients AS client ON vendor.client_group_id = client.id";
|
||||
// // get last updated row from many rows
|
||||
// // $query .= " LEFT JOIN ( SELECT MAX(crt) max_crt, device_id FROM " . self::T_TRACKS . " WHERE latitude is not null AND longitude is not null GROUP BY device_id ORDER BY crt DESC ) AS tr1 ON (v.device_id = tr1.device_id)"; // cara lama berlaku utk gps tracker saja
|
||||
// // // $query .= " LEFT JOIN ( SELECT MAX(crt) max_crt, device_id, vhc_id FROM " . self::T_TRACKS . " WHERE latitude is not null AND longitude is not null GROUP BY vhc_id ORDER BY crt DESC ) AS tr1 ON (v.id = tr1.vhc_id)"; // support gps tracker dan smartphone / apapun yang mempunyai device_id(IMEI)
|
||||
// // $query .= " LEFT JOIN " . self::T_TRACKS . " AS tr ON (tr.crt = tr1.max_crt)";
|
||||
// // get last updated tracking from updated table realtime
|
||||
// // $query .= " LEFT JOIN db_trucking.t_gps_tracks_rltm AS tr ON tr.vhc_id = v.id";
|
||||
// $query .= " LEFT JOIN t_gps_tracks_rltm AS tr ON tr.vhc_id = v.id";
|
||||
// // $query .= " LEFT JOIN " . self::T_TRACKS_ADDR . " AS tr_addr ON tr.id = tr_addr.master_id";
|
||||
|
||||
// //FRO
|
||||
// $query .=
|
||||
// " LEFT JOIN " .
|
||||
// self::T_TRACKS_ADDR .
|
||||
// " AS tr_addr ON tr.latitude = tr_addr.lat and tr.longitude = tr_addr.lng";
|
||||
|
||||
// if (isset($filter["active_rates"])) {
|
||||
// // $query .= " INNER JOIN t_conf_rates as rate ON v.type_id = rate.vhc_type";
|
||||
// $query .= " INNER JOIN t_conf_rates as rate ON v.vendor_id = rate.vdr_id";
|
||||
// }
|
||||
// if (isset($filter["get_order_data"])) {
|
||||
// // the old way => only 1 order 1 vehicle
|
||||
// $query .= " LEFT JOIN t_orders as ord ON v.ord_id = ord.id";
|
||||
// $query .= " LEFT JOIN t_orders_pickups as ord_pck ON v.ord_id = ord_pck.ord_id";
|
||||
// $query .= " LEFT JOIN t_orders_drops as ord_drop ON v.ord_id = ord_drop.ord_id";
|
||||
// $query .= " LEFT JOIN t_orders_drivers as ord_drv ON v.ord_id = ord_drv.ord_id";
|
||||
// $query .= " LEFT JOIN t_orders_clients as ord_c ON v.ord_id = ord_c.ord_id";
|
||||
|
||||
// // the new way => can handle 2 order in 1 vehicle
|
||||
// // $query .= " LEFT JOIN t_orders_vehicles as ord_vhc ON v.id = ord_vhc.vhc_id";
|
||||
// // $query .= " LEFT JOIN t_orders as ord ON ord_vhc.ord_id = ord.id";
|
||||
// // $query .= " LEFT JOIN t_orders_pickups as ord_pck ON ord_vhc.ord_id = ord_pck.ord_id";
|
||||
// // $query .= " LEFT JOIN t_orders_drops as ord_drop ON ord_vhc.ord_id = ord_drop.ord_id";
|
||||
// // $query .= " LEFT JOIN t_orders_drivers as ord_drv ON ord_vhc.ord_id = ord_drv.ord_id";
|
||||
// // $query .= " LEFT JOIN t_orders_clients as ord_c ON ord_vhc.ord_id = ord_c.ord_id";
|
||||
// }
|
||||
// $query .= " WHERE v.dlt is null";
|
||||
// // $query .= " AND tr.action IN ('location','alarm')"; // kalo gamau ngambil data heartbeat(idling)
|
||||
// // $query .= " AND tr.device_id = v.device_id"; // cara lama berlaku utk gps tracker saja
|
||||
// // $query .= " AND tr.vhc_id = v.id"; // support gps tracker dan smartphone / apapun yang mempunyai device_id(IMEI) // bikin lemot
|
||||
// $query .= " AND tr.latitude != 0 AND tr.latitude is not null";
|
||||
// if (isset($filter["status"])) {
|
||||
// $query .= " AND v.status = ?";
|
||||
// $params[] = $filter["status"];
|
||||
// }
|
||||
// if (isset($filter["is_in_ord"])) {
|
||||
// $query .= " AND v.is_in_ord = ?";
|
||||
// $params[] = $filter["is_in_ord"];
|
||||
// }
|
||||
// if (isset($filter["nopol1"]) && isset($filter["nopol2"]) && isset($filter["nopol3"])) {
|
||||
// $query .= " AND v.nopol1 = ? AND v.nopol2 = ? AND v.nopol3 = ?";
|
||||
// array_push($params, $filter["nopol1"], $filter["nopol2"], $filter["nopol3"]);
|
||||
// }
|
||||
// if (isset($filter["vid"])) {
|
||||
// $query .= " AND v.id = ?";
|
||||
// $params[] = $filter["vid"];
|
||||
// }
|
||||
// if (isset($filter["vids"])) {
|
||||
// if ($filter["vids"] && count($filter["vids"]) > 0) {
|
||||
// $binds_vids = "";
|
||||
// foreach ($filter["vids"] as $k => $v) {
|
||||
// $binds_vids .= "?,";
|
||||
// $params[] = $v;
|
||||
// }
|
||||
// if (substr($binds_vids, -1) === ",") {
|
||||
// $binds_vids = substr($binds_vids, 0, -1);
|
||||
// }
|
||||
// $query .= " AND v.id IN ($binds_vids)";
|
||||
// } else {
|
||||
// $query .= " AND v.id = ?";
|
||||
// $params[] = 0;
|
||||
// }
|
||||
// }
|
||||
// if (isset($filter["own_by_vdr_id"])) {
|
||||
// $query .= " AND v.vendor_id = ?";
|
||||
// $params[] = $filter["own_by_vdr_id"];
|
||||
// }
|
||||
// if (isset($filter["active_rates"])) {
|
||||
// // v1
|
||||
// // $query .= " AND rate.vdr_id != 0 AND rate.dest_city != 0 AND rate.dest_district != 0";
|
||||
// // $query .= " AND rate.origin_prov = ? AND (rate.dest_city = ? OR rate.dest_district = ?) AND rate.sell_kg = ? AND rate.sell_cbm = ? AND rate.long_time = ?";
|
||||
// // array_push($params, $filter['active_rates']->origin_prov, $filter['active_rates']->dest_city, $filter['active_rates']->dest_district, $filter['active_rates']->sell_kg, $filter['active_rates']->sell_cbm, $filter['active_rates']->long_time);
|
||||
// // v2
|
||||
// $query .=
|
||||
// " AND rate.vdr_id != 0 AND rate.dest_city != 0 AND rate.is_active = " . ConfRates::IS_ACTIVE;
|
||||
// $query .=
|
||||
// " AND rate.origin_prov = ? AND (rate.dest_city = ? OR rate.dest_district = ?) AND rate.sell_ftl = ? AND rate.long_time = ?";
|
||||
// array_push(
|
||||
// $params,
|
||||
// $filter["active_rates"]->origin_prov,
|
||||
// $filter["active_rates"]->dest_city,
|
||||
// $filter["active_rates"]->dest_district,
|
||||
// $filter["active_rates"]->sell_ftl,
|
||||
// $filter["active_rates"]->long_time
|
||||
// );
|
||||
// }
|
||||
// if (isset($filter["prefer_truck_type"])) {
|
||||
// $query .= " AND v.type_id = ?";
|
||||
// $params[] = $filter["prefer_truck_type"];
|
||||
// }
|
||||
// if (isset($filter["get_order_data"])) {
|
||||
// if (isset($filter["client_id"])) {
|
||||
// $query .= " AND ord_c.c_id = ?";
|
||||
// $params[] = $filter["client_id"];
|
||||
// }
|
||||
// // $query .= " AND ord.status IN (22,4)";
|
||||
// }
|
||||
// if (isset($filter["company"])) {
|
||||
// $query .= " AND client.id = ?";
|
||||
// $params[] = $filter["company"];
|
||||
// }
|
||||
|
||||
// // $query .= " AND v.id = 70";
|
||||
|
||||
// $query .= " GROUP BY v.id";
|
||||
// $query .= " ORDER BY tr.crt_d DESC";
|
||||
// $query .= " LIMIT 500;";
|
||||
|
||||
// // dd($query);
|
||||
|
||||
// $list = DB::select($query, $params);
|
||||
// foreach ($list as $_list) {
|
||||
// $_query =
|
||||
// " SELECT SUM(pre_milleage) as vhc_sum_milleage FROM " . self::T_TRACKS . " WHERE vhc_id = ?";
|
||||
// $_query = DB::select($_query, [$_list->vid]);
|
||||
// $_list->vhc_sum_milleage = $_query[0]->vhc_sum_milleage;
|
||||
|
||||
// $_query =
|
||||
// "
|
||||
// SELECT
|
||||
// crt_s as lst_idle_at
|
||||
// FROM
|
||||
// " .
|
||||
// self::T_TRACKS .
|
||||
// "
|
||||
// WHERE
|
||||
// stts_engine = " .
|
||||
// self::STTS_EN_IDLING .
|
||||
// "
|
||||
// AND vhc_id = ?
|
||||
// AND crt_s >= (
|
||||
// SELECT
|
||||
// crt_s
|
||||
// FROM
|
||||
// " .
|
||||
// self::T_TRACKS .
|
||||
// "
|
||||
// WHERE
|
||||
// stts_engine IN (
|
||||
// " .
|
||||
// self::STTS_EN_STOPING .
|
||||
// ",
|
||||
// " .
|
||||
// self::STTS_EN_MOVING .
|
||||
// ")
|
||||
// AND vhc_id = ?
|
||||
// AND crt_s <= ?
|
||||
// ORDER BY
|
||||
// id DESC
|
||||
// LIMIT 1
|
||||
// )
|
||||
// ORDER BY
|
||||
// id ASC
|
||||
// LIMIT 1";
|
||||
// $_query = DB::select($_query, [$_list->vid, $_list->vid, $_list->lst_loc_crt_s]);
|
||||
// $_list->lst_idle_at = count($_query) == 0 ? "" : $_query[0]->lst_idle_at;
|
||||
|
||||
// $_query =
|
||||
// "SELECT crt_s as lst_stop_at FROM " .
|
||||
// self::T_TRACKS .
|
||||
// " WHERE stts_engine = " .
|
||||
// self::STTS_EN_STOPING .
|
||||
// " AND vhc_id = ? AND crt_s >= (
|
||||
// SELECT crt_s FROM " .
|
||||
// self::T_TRACKS .
|
||||
// " WHERE stts_engine IN (" .
|
||||
// self::STTS_EN_IDLING .
|
||||
// "," .
|
||||
// self::STTS_EN_MOVING .
|
||||
// ") AND vhc_id = ? AND crt_s <= ? ORDER BY id DESC LIMIT 1
|
||||
// ) ORDER BY id ASC LIMIT 1 ";
|
||||
// $_query = DB::select($_query, [$_list->vid, $_list->vid, $_list->lst_loc_crt_s]);
|
||||
// $_list->lst_stop_at = count($_query) == 0 ? "" : $_query[0]->lst_stop_at;
|
||||
|
||||
// $_query =
|
||||
// " SELECT COUNT(id) as lst_heartbeat FROM " .
|
||||
// self::T_TRACKS .
|
||||
// " WHERE vhc_id = ? AND action = 'heartbeat' AND crt BETWEEN " .
|
||||
// ($now - 10 * 60) .
|
||||
// " AND " .
|
||||
// $now .
|
||||
// " LIMIT 1";
|
||||
// $_query = DB::select($_query, [$_list->vid]);
|
||||
// $_list->lst_heartbeat = count($_query) == 0 ? "" : $_query[0]->lst_heartbeat;
|
||||
// }
|
||||
// // em
|
||||
// return $list;
|
||||
// }
|
||||
public static function listCurrentTracks($filter = [])
|
||||
{
|
||||
$now = time();
|
||||
$params = [];
|
||||
|
||||
$query = "SELECT";
|
||||
$query .=
|
||||
" v.id as vid,v.device_id,v.name as vhc_name,c.name as vhc_cat_name,t.name as vhc_type_name";
|
||||
$query .= " ,v.nopol1,v.nopol2,v.nopol3,vd.fvhc_img";
|
||||
$query .= " ,v.is_track_holiday,v.track_sch_d,v.track_sch_h,vd.speed_limit,v.crt as vhc_crt";
|
||||
$query .= " ,client.id as client_group_id,client.c_name as client_group_name";
|
||||
$query .= " ,tr.ignition,tr.stts_engine,tr.stts_gps,tr.stts_gsm";
|
||||
$query .= " ,tr.pre_milleage,tr.sum_milleage,tr.vhc_milleage,v.sum_milleage AS vhc_sum_milleage_1";
|
||||
|
||||
// FRO
|
||||
// $query .= " ,(SELECT SUM(pre_milleage) FROM " . self::T_TRACKS . " WHERE vhc_id = v.id LIMIT 1) as vhc_sum_milleage";
|
||||
|
||||
// $query .= " ,(SELECT crt_s FROM " . self::T_TRACKS . " WHERE stts_engine = " . self::STTS_EN_IDLING . " AND vhc_id = v.id AND crt_s >= (
|
||||
// SELECT crt_s FROM " . self::T_TRACKS . " WHERE stts_engine IN (" . self::STTS_EN_STOPING . "," . self::STTS_EN_MOVING . ") AND vhc_id = v.id AND crt_s <= tr.crt_s ORDER BY id DESC LIMIT 1
|
||||
// ) ORDER BY id ASC LIMIT 1) as lst_idle_at";
|
||||
|
||||
// $query .= " ,(SELECT crt_s FROM " . self::T_TRACKS . " WHERE stts_engine = " . self::STTS_EN_STOPING . " AND vhc_id = v.id AND crt_s >= (
|
||||
// SELECT crt_s FROM " . self::T_TRACKS . " WHERE stts_engine IN (" . self::STTS_EN_IDLING . "," . self::STTS_EN_MOVING . ") AND vhc_id = v.id AND crt_s <= tr.crt_s ORDER BY id DESC LIMIT 1
|
||||
// ) ORDER BY id ASC LIMIT 1) as lst_stop_at";
|
||||
|
||||
$query .=
|
||||
" ,tr.id AS lst_master_id,tr.latitude AS lst_lat,tr.longitude AS lst_lng,tr.speed AS lst_speed,tr.orientation AS lst_orientation";
|
||||
$query .= " ,tr.crt AS lst_loc_crt,tr.crt_d AS lst_loc_crt_d,tr.crt_s AS lst_loc_crt_s";
|
||||
$query .=
|
||||
" ,tr_addr.master_id AS lst_addr_master_id,tr_addr.country_text AS lst_country_text,tr_addr.state_text AS lst_state_text,tr_addr.city_text AS lst_city_text";
|
||||
$query .=
|
||||
" ,tr_addr.district_text AS lst_district_text,tr_addr.village_text AS lst_village_text,tr_addr.postcode AS lst_postcode";
|
||||
$query .= " ,tr_addr.streets AS lst_streets,tr_addr.fulladdress AS lst_fulladdress";
|
||||
|
||||
// FRO
|
||||
// $query .= " ,(SELECT COUNT(id) FROM " . self::T_TRACKS . " WHERE vhc_id = v.id AND action = 'heartbeat' AND crt BETWEEN ".($now-(10*60))." AND ".$now." LIMIT 1) as lst_heartbeat"; // heartbeat last data on further 10 minutes
|
||||
$query = "SELECT
|
||||
v.id as vid, v.device_id, v.name as vhc_name, c.name as vhc_cat_name, t.name as vhc_type_name,
|
||||
v.nopol1, v.nopol2, v.nopol3, vd.fvhc_img,
|
||||
v.is_track_holiday, v.track_sch_d, v.track_sch_h, vd.speed_limit, v.crt as vhc_crt,
|
||||
client.id as client_group_id, client.c_name as client_group_name,
|
||||
tr.ignition, tr.stts_engine, tr.stts_gps, tr.stts_gsm,
|
||||
tr.pre_milleage, tr.sum_milleage, tr.vhc_milleage, v.sum_milleage AS vhc_sum_milleage_1,
|
||||
tr.id AS lst_master_id, tr.latitude AS lst_lat, tr.longitude AS lst_lng,
|
||||
tr.speed AS lst_speed, tr.orientation AS lst_orientation,
|
||||
tr.crt AS lst_loc_crt, tr.crt_d AS lst_loc_crt_d, tr.crt_s AS lst_loc_crt_s,
|
||||
tr_addr.master_id AS lst_addr_master_id, tr_addr.country_text AS lst_country_text,
|
||||
tr_addr.state_text AS lst_state_text, tr_addr.city_text AS lst_city_text,
|
||||
tr_addr.district_text AS lst_district_text, tr_addr.village_text AS lst_village_text,
|
||||
tr_addr.postcode AS lst_postcode, tr_addr.streets AS lst_streets,
|
||||
tr_addr.fulladdress AS lst_fulladdress";
|
||||
|
||||
if (isset($filter["active_rates"])) {
|
||||
$query .=
|
||||
",rate.vdr_id as rate_vdr_id,rate.vhc_type as rate_vhc_type,rate.origin_prov as rate_origin_prov,rate.dest_city as rate_dest_city,rate.dest_district as rate_dest_district";
|
||||
$query .=
|
||||
",rate.fast_time as rate_fast_time,rate.long_time as rate_long_time,rate.sell_kg as rate_sell_kg,rate.sell_cbm as rate_sell_cbm,rate.sell_ftl as rate_sell_ftl";
|
||||
$query .= ",
|
||||
rate.vdr_id as rate_vdr_id, rate.vhc_type as rate_vhc_type,
|
||||
rate.origin_prov as rate_origin_prov, rate.dest_city as rate_dest_city,
|
||||
rate.dest_district as rate_dest_district, rate.fast_time as rate_fast_time,
|
||||
rate.long_time as rate_long_time, rate.sell_kg as rate_sell_kg,
|
||||
rate.sell_cbm as rate_sell_cbm, rate.sell_ftl as rate_sell_ftl";
|
||||
}
|
||||
|
||||
if (isset($filter["get_order_data"])) {
|
||||
$query .=
|
||||
",ord.id as ord_id,ord.code as ord_code,ord.status as ord_stts,ord.crt as ord_crt,ord_pck.pck_name as ord_pck_name,ord_pck.pck_addr as ord_pck_addr,ord_drop.drop_name as ord_drop_name,ord_drop.drop_addr as ord_drop_addr";
|
||||
$query .=
|
||||
",(SELECT nmKotamadyaKel FROM t_region WHERE kodeKab = ord_pck.pck_ktid LIMIT 1) ord_pck_ktname, (SELECT nmKotamadyaKel FROM t_region WHERE kodeKab = ord_drop.drop_ktid LIMIT 1) ord_drop_ktname";
|
||||
$query .=
|
||||
",ord_drv.drv_name as ord_drv_name,ord_drv.drv_phone_val as ord_drv_phone_val,ord_drv.drv_phone2_val as ord_drv_phone2_val,ord_drv.drv_addr as ord_drv_addr";
|
||||
$query .= ",ord_c.c_name as ord_c_name,ord_c.c_pt_name as ord_c_pt_name";
|
||||
$query .= ",
|
||||
ord.id as ord_id, ord.code as ord_code, ord.status as ord_stts, ord.crt as ord_crt,
|
||||
ord_pck.pck_name as ord_pck_name, ord_pck.pck_addr as ord_pck_addr,
|
||||
ord_drop.drop_name as ord_drop_name, ord_drop.drop_addr as ord_drop_addr,
|
||||
(SELECT nmKotamadyaKel FROM t_region WHERE kodeKab = ord_pck.pck_ktid LIMIT 1) AS ord_pck_ktname,
|
||||
(SELECT nmKotamadyaKel FROM t_region WHERE kodeKab = ord_drop.drop_ktid LIMIT 1) AS ord_drop_ktname,
|
||||
ord_drv.drv_name as ord_drv_name, ord_drv.drv_phone_val as ord_drv_phone_val,
|
||||
ord_drv.drv_phone2_val as ord_drv_phone2_val, ord_drv.drv_addr as ord_drv_addr,
|
||||
ord_c.c_name as ord_c_name, ord_c.c_pt_name as ord_c_pt_name";
|
||||
}
|
||||
$query .= " FROM t_vehicles AS v";
|
||||
$query .= " INNER JOIN t_vehicles_detail AS vd ON v.id = vd.vid";
|
||||
$query .= " INNER JOIN t_vehicles_types AS t ON v.type_id = t.id";
|
||||
$query .= " INNER JOIN t_vehicles_cats AS c ON v.cat_id = c.id";
|
||||
$query .= " LEFT JOIN t_users AS vendor ON v.vendor_id = vendor.id";
|
||||
$query .= " LEFT JOIN t_clients AS client ON vendor.client_group_id = client.id";
|
||||
// get last updated row from many rows
|
||||
// $query .= " LEFT JOIN ( SELECT MAX(crt) max_crt, device_id FROM " . self::T_TRACKS . " WHERE latitude is not null AND longitude is not null GROUP BY device_id ORDER BY crt DESC ) AS tr1 ON (v.device_id = tr1.device_id)"; // cara lama berlaku utk gps tracker saja
|
||||
// // $query .= " LEFT JOIN ( SELECT MAX(crt) max_crt, device_id, vhc_id FROM " . self::T_TRACKS . " WHERE latitude is not null AND longitude is not null GROUP BY vhc_id ORDER BY crt DESC ) AS tr1 ON (v.id = tr1.vhc_id)"; // support gps tracker dan smartphone / apapun yang mempunyai device_id(IMEI)
|
||||
// $query .= " LEFT JOIN " . self::T_TRACKS . " AS tr ON (tr.crt = tr1.max_crt)";
|
||||
// get last updated tracking from updated table realtime
|
||||
// $query .= " LEFT JOIN db_trucking.t_gps_tracks_rltm AS tr ON tr.vhc_id = v.id";
|
||||
$query .= " LEFT JOIN t_gps_tracks_rltm AS tr ON tr.vhc_id = v.id";
|
||||
// $query .= " LEFT JOIN " . self::T_TRACKS_ADDR . " AS tr_addr ON tr.id = tr_addr.master_id";
|
||||
|
||||
//FRO
|
||||
$query .=
|
||||
" LEFT JOIN " .
|
||||
" FROM t_vehicles AS v
|
||||
INNER JOIN t_vehicles_detail AS vd ON v.id = vd.vid
|
||||
INNER JOIN t_vehicles_types AS t ON v.type_id = t.id
|
||||
INNER JOIN t_vehicles_cats AS c ON v.cat_id = c.id
|
||||
LEFT JOIN t_users AS vendor ON v.vendor_id = vendor.id
|
||||
LEFT JOIN t_clients AS client ON vendor.client_group_id = client.id
|
||||
LEFT JOIN t_gps_tracks_rltm AS tr ON tr.vhc_id = v.id
|
||||
LEFT JOIN " .
|
||||
self::T_TRACKS_ADDR .
|
||||
" AS tr_addr ON tr.latitude = tr_addr.lat and tr.longitude = tr_addr.lng";
|
||||
" AS tr_addr ON tr.latitude = tr_addr.lat AND tr.longitude = tr_addr.lng";
|
||||
|
||||
if (isset($filter["active_rates"])) {
|
||||
// $query .= " INNER JOIN t_conf_rates as rate ON v.type_id = rate.vhc_type";
|
||||
$query .= " INNER JOIN t_conf_rates as rate ON v.vendor_id = rate.vdr_id";
|
||||
}
|
||||
if (isset($filter["get_order_data"])) {
|
||||
// the old way => only 1 order 1 vehicle
|
||||
$query .= " LEFT JOIN t_orders as ord ON v.ord_id = ord.id";
|
||||
$query .= " LEFT JOIN t_orders_pickups as ord_pck ON v.ord_id = ord_pck.ord_id";
|
||||
$query .= " LEFT JOIN t_orders_drops as ord_drop ON v.ord_id = ord_drop.ord_id";
|
||||
$query .= " LEFT JOIN t_orders_drivers as ord_drv ON v.ord_id = ord_drv.ord_id";
|
||||
$query .= " LEFT JOIN t_orders_clients as ord_c ON v.ord_id = ord_c.ord_id";
|
||||
|
||||
// the new way => can handle 2 order in 1 vehicle
|
||||
// $query .= " LEFT JOIN t_orders_vehicles as ord_vhc ON v.id = ord_vhc.vhc_id";
|
||||
// $query .= " LEFT JOIN t_orders as ord ON ord_vhc.ord_id = ord.id";
|
||||
// $query .= " LEFT JOIN t_orders_pickups as ord_pck ON ord_vhc.ord_id = ord_pck.ord_id";
|
||||
// $query .= " LEFT JOIN t_orders_drops as ord_drop ON ord_vhc.ord_id = ord_drop.ord_id";
|
||||
// $query .= " LEFT JOIN t_orders_drivers as ord_drv ON ord_vhc.ord_id = ord_drv.ord_id";
|
||||
// $query .= " LEFT JOIN t_orders_clients as ord_c ON ord_vhc.ord_id = ord_c.ord_id";
|
||||
if (isset($filter["get_order_data"])) {
|
||||
$query .= "
|
||||
LEFT JOIN t_orders as ord ON v.ord_id = ord.id
|
||||
LEFT JOIN t_orders_pickups as ord_pck ON v.ord_id = ord_pck.ord_id
|
||||
LEFT JOIN t_orders_drops as ord_drop ON v.ord_id = ord_drop.ord_id
|
||||
LEFT JOIN t_orders_drivers as ord_drv ON v.ord_id = ord_drv.ord_id
|
||||
LEFT JOIN t_orders_clients as ord_c ON v.ord_id = ord_c.ord_id";
|
||||
}
|
||||
$query .= " WHERE v.dlt is null";
|
||||
// $query .= " AND tr.action IN ('location','alarm')"; // kalo gamau ngambil data heartbeat(idling)
|
||||
// $query .= " AND tr.device_id = v.device_id"; // cara lama berlaku utk gps tracker saja
|
||||
// $query .= " AND tr.vhc_id = v.id"; // support gps tracker dan smartphone / apapun yang mempunyai device_id(IMEI) // bikin lemot
|
||||
$query .= " AND tr.latitude != 0 AND tr.latitude is not null";
|
||||
|
||||
$query .= " WHERE v.dlt IS NULL AND tr.latitude != 0 AND tr.latitude IS NOT NULL";
|
||||
|
||||
if (isset($filter["status"])) {
|
||||
$query .= " AND v.status = ?";
|
||||
$params[] = $filter["status"];
|
||||
@ -155,25 +382,19 @@ class Tracks extends Model
|
||||
$query .= " AND v.is_in_ord = ?";
|
||||
$params[] = $filter["is_in_ord"];
|
||||
}
|
||||
if (isset($filter["nopol1"]) && isset($filter["nopol2"]) && isset($filter["nopol3"])) {
|
||||
if (isset($filter["nopol1"], $filter["nopol2"], $filter["nopol3"])) {
|
||||
$query .= " AND v.nopol1 = ? AND v.nopol2 = ? AND v.nopol3 = ?";
|
||||
array_push($params, $filter["nopol1"], $filter["nopol2"], $filter["nopol3"]);
|
||||
}
|
||||
if (isset($filter["vid"])) {
|
||||
$query .= " AND v.id = ?";
|
||||
$params[] = $filter["vid"];
|
||||
}
|
||||
// if (isset($filter["vid"])) {
|
||||
// $query .= " AND v.id = ?";
|
||||
// $params[] = $filter["vid"];
|
||||
// }
|
||||
if (isset($filter["vids"])) {
|
||||
if ($filter["vids"] && count($filter["vids"]) > 0) {
|
||||
$binds_vids = "";
|
||||
foreach ($filter["vids"] as $k => $v) {
|
||||
$binds_vids .= "?,";
|
||||
$params[] = $v;
|
||||
}
|
||||
if (substr($binds_vids, -1) === ",") {
|
||||
$binds_vids = substr($binds_vids, 0, -1);
|
||||
}
|
||||
$query .= " AND v.id IN ($binds_vids)";
|
||||
$placeholders = rtrim(str_repeat("?,", count($filter["vids"])), ",");
|
||||
$query .= " AND v.id IN ($placeholders)";
|
||||
$params = array_merge($params, $filter["vids"]);
|
||||
} else {
|
||||
$query .= " AND v.id = ?";
|
||||
$params[] = 0;
|
||||
@ -184,11 +405,6 @@ class Tracks extends Model
|
||||
$params[] = $filter["own_by_vdr_id"];
|
||||
}
|
||||
if (isset($filter["active_rates"])) {
|
||||
// v1
|
||||
// $query .= " AND rate.vdr_id != 0 AND rate.dest_city != 0 AND rate.dest_district != 0";
|
||||
// $query .= " AND rate.origin_prov = ? AND (rate.dest_city = ? OR rate.dest_district = ?) AND rate.sell_kg = ? AND rate.sell_cbm = ? AND rate.long_time = ?";
|
||||
// array_push($params, $filter['active_rates']->origin_prov, $filter['active_rates']->dest_city, $filter['active_rates']->dest_district, $filter['active_rates']->sell_kg, $filter['active_rates']->sell_cbm, $filter['active_rates']->long_time);
|
||||
// v2
|
||||
$query .=
|
||||
" AND rate.vdr_id != 0 AND rate.dest_city != 0 AND rate.is_active = " . ConfRates::IS_ACTIVE;
|
||||
$query .=
|
||||
@ -211,110 +427,97 @@ class Tracks extends Model
|
||||
$query .= " AND ord_c.c_id = ?";
|
||||
$params[] = $filter["client_id"];
|
||||
}
|
||||
// $query .= " AND ord.status IN (22,4)";
|
||||
}
|
||||
if (isset($filter["company"])) {
|
||||
$query .= " AND client.id = ?";
|
||||
$params[] = $filter["company"];
|
||||
}
|
||||
|
||||
// $query .= " AND v.id = 70";
|
||||
|
||||
$query .= " GROUP BY v.id";
|
||||
$query .= " ORDER BY tr.crt_d DESC";
|
||||
$query .= " LIMIT 500;";
|
||||
|
||||
// dd($query);
|
||||
$query .= " GROUP BY v.id ORDER BY tr.crt_s DESC LIMIT 500";
|
||||
|
||||
$list = DB::select($query, $params);
|
||||
foreach ($list as $_list) {
|
||||
$_query =
|
||||
" SELECT SUM(pre_milleage) as vhc_sum_milleage FROM " . self::T_TRACKS . " WHERE vhc_id = ?";
|
||||
$_query = DB::select($_query, [$_list->vid]);
|
||||
$_list->vhc_sum_milleage = $_query[0]->vhc_sum_milleage;
|
||||
// dd($list);
|
||||
// Post-processing per row
|
||||
// foreach ($list as $_list) {
|
||||
// $_list->vhc_sum_milleage =
|
||||
// optional(
|
||||
// DB::select(
|
||||
// "SELECT SUM(pre_milleage) as vhc_sum_milleage FROM " .
|
||||
// self::T_TRACKS .
|
||||
// " WHERE vhc_id = ?",
|
||||
// [$_list->vid]
|
||||
// )
|
||||
// )[0]->vhc_sum_milleage ?? "";
|
||||
|
||||
$_query =
|
||||
"
|
||||
SELECT
|
||||
crt_s as lst_idle_at
|
||||
FROM
|
||||
" .
|
||||
self::T_TRACKS .
|
||||
"
|
||||
WHERE
|
||||
stts_engine = " .
|
||||
self::STTS_EN_IDLING .
|
||||
"
|
||||
AND vhc_id = ?
|
||||
AND crt_s >= (
|
||||
SELECT
|
||||
crt_s
|
||||
FROM
|
||||
" .
|
||||
self::T_TRACKS .
|
||||
"
|
||||
WHERE
|
||||
stts_engine IN (
|
||||
" .
|
||||
self::STTS_EN_STOPING .
|
||||
",
|
||||
" .
|
||||
self::STTS_EN_MOVING .
|
||||
")
|
||||
AND vhc_id = ?
|
||||
AND crt_s <= ?
|
||||
ORDER BY
|
||||
id DESC
|
||||
LIMIT 1
|
||||
)
|
||||
ORDER BY
|
||||
id ASC
|
||||
LIMIT 1";
|
||||
$_query = DB::select($_query, [$_list->vid, $_list->vid, $_list->lst_loc_crt_s]);
|
||||
$_list->lst_idle_at = count($_query) == 0 ? "" : $_query[0]->lst_idle_at;
|
||||
// $_list->lst_idle_at =
|
||||
// optional(
|
||||
// DB::select(
|
||||
// "SELECT crt_s FROM " .
|
||||
// self::T_TRACKS .
|
||||
// " WHERE stts_engine = ? AND vhc_id = ? AND crt_s >= (
|
||||
// SELECT crt_s FROM " .
|
||||
// self::T_TRACKS .
|
||||
// " WHERE stts_engine IN (?, ?) AND vhc_id = ? AND crt_s <= ? ORDER BY id DESC LIMIT 1
|
||||
// ) ORDER BY id ASC LIMIT 1",
|
||||
// [
|
||||
// self::STTS_EN_IDLING,
|
||||
// $_list->vid,
|
||||
// self::STTS_EN_STOPING,
|
||||
// self::STTS_EN_MOVING,
|
||||
// $_list->vid,
|
||||
// $_list->lst_loc_crt_s,
|
||||
// ]
|
||||
// )
|
||||
// )[0]->crt_s ?? "";
|
||||
|
||||
$_query =
|
||||
"SELECT crt_s as lst_stop_at FROM " .
|
||||
self::T_TRACKS .
|
||||
" WHERE stts_engine = " .
|
||||
self::STTS_EN_STOPING .
|
||||
" AND vhc_id = ? AND crt_s >= (
|
||||
SELECT crt_s FROM " .
|
||||
self::T_TRACKS .
|
||||
" WHERE stts_engine IN (" .
|
||||
self::STTS_EN_IDLING .
|
||||
"," .
|
||||
self::STTS_EN_MOVING .
|
||||
") AND vhc_id = ? AND crt_s <= ? ORDER BY id DESC LIMIT 1
|
||||
) ORDER BY id ASC LIMIT 1 ";
|
||||
$_query = DB::select($_query, [$_list->vid, $_list->vid, $_list->lst_loc_crt_s]);
|
||||
$_list->lst_stop_at = count($_query) == 0 ? "" : $_query[0]->lst_stop_at;
|
||||
// $_list->lst_stop_at =
|
||||
// optional(
|
||||
// DB::select(
|
||||
// "SELECT crt_s FROM " .
|
||||
// self::T_TRACKS .
|
||||
// " WHERE stts_engine = ? AND vhc_id = ? AND crt_s >= (
|
||||
// SELECT crt_s FROM " .
|
||||
// self::T_TRACKS .
|
||||
// " WHERE stts_engine IN (?, ?) AND vhc_id = ? AND crt_s <= ? ORDER BY id DESC LIMIT 1
|
||||
// ) ORDER BY id ASC LIMIT 1",
|
||||
// [
|
||||
// self::STTS_EN_STOPING,
|
||||
// $_list->vid,
|
||||
// self::STTS_EN_IDLING,
|
||||
// self::STTS_EN_MOVING,
|
||||
// $_list->vid,
|
||||
// $_list->lst_loc_crt_s,
|
||||
// ]
|
||||
// )
|
||||
// )[0]->crt_s ?? "";
|
||||
|
||||
// $_list->lst_heartbeat =
|
||||
// optional(
|
||||
// DB::select(
|
||||
// "SELECT COUNT(id) as lst_heartbeat FROM " .
|
||||
// self::T_TRACKS .
|
||||
// " WHERE vhc_id = ? AND action = 'heartbeat' AND crt BETWEEN ? AND ? LIMIT 1",
|
||||
// [$_list->vid, $now - 600, $now]
|
||||
// )
|
||||
// )[0]->lst_heartbeat ?? "";
|
||||
// }
|
||||
|
||||
$_query =
|
||||
" SELECT COUNT(id) as lst_heartbeat FROM " .
|
||||
self::T_TRACKS .
|
||||
" WHERE vhc_id = ? AND action = 'heartbeat' AND crt BETWEEN " .
|
||||
($now - 10 * 60) .
|
||||
" AND " .
|
||||
$now .
|
||||
" LIMIT 1";
|
||||
$_query = DB::select($_query, [$_list->vid]);
|
||||
$_list->lst_heartbeat = count($_query) == 0 ? "" : $_query[0]->lst_heartbeat;
|
||||
}
|
||||
// em
|
||||
return $list;
|
||||
}
|
||||
|
||||
public static function lastMoveTracks($vid, $filter = [])
|
||||
{
|
||||
// dd($vid, $filter);
|
||||
$now = time();
|
||||
$params = [];
|
||||
$query = "SELECT";
|
||||
$query .= " v.id as vid,v.device_id,v.nopol1,v.nopol2,v.nopol3";
|
||||
$query .= " ,tr.id as master_id,tr.latitude,tr.longitude,tr.speed,tr.orientation";
|
||||
// ,(tr.crt + ( 7 * 3600 )) AS lst_loc_crt
|
||||
// ,(tr.crt_d + ( 7 * 3600 )) AS lst_loc_crt_d
|
||||
$query .= "
|
||||
,(tr.crt + ( 7 * 3600 )) AS lst_loc_crt
|
||||
,(tr.crt_d + ( 7 * 3600 )) AS lst_loc_crt_d
|
||||
,tr.crt AS lst_loc_crt
|
||||
,tr.crt_d AS lst_loc_crt_d
|
||||
,tr.crt_s AS lst_loc_crt_s";
|
||||
$query .= " ,tr.ignition,tr.stts_engine";
|
||||
$query .= " ,tr.pre_milleage,tr.sum_milleage,tr.vhc_milleage,v.sum_milleage AS vhc_sum_milleage_1";
|
||||
@ -340,7 +543,9 @@ class Tracks extends Model
|
||||
|
||||
if (isset($filter["start_date"]) && isset($filter["end_date"])) {
|
||||
$query .= " AND tr.crt_d BETWEEN ? AND ?";
|
||||
array_push($params, $filter["start_date"], $filter["end_date"]);
|
||||
$tgl0 = $filter["start_date"] - Helper::TIMEFIX;
|
||||
$tgl1 = $filter["end_date"] - Helper::TIMEFIX;
|
||||
array_push($params, $tgl0, $tgl1);
|
||||
}
|
||||
|
||||
if (isset($filter["start_at"])) {
|
||||
@ -356,66 +561,95 @@ class Tracks extends Model
|
||||
|
||||
if (isset($filter["limit"])) {
|
||||
$query .= " LIMIT ?";
|
||||
$params[] = $filter["limit"] ?? 1000;
|
||||
$params[] = $filter["limit"] ?? 10000;
|
||||
// $params[] = $filter["limit"];
|
||||
}
|
||||
|
||||
$query .= " ;";
|
||||
$rawTracks = DB::select($query, $params);
|
||||
$rawTracks = collect($rawTracks);
|
||||
// dd($rawTracks->toJson(JSON_PRETTY_PRINT));
|
||||
// dd($rawTracks);
|
||||
|
||||
$filtered = collect();
|
||||
$zeroBlock = collect();
|
||||
$tempBlock = collect();
|
||||
// // filter
|
||||
// $filtered = collect();
|
||||
// $zeroBlock = collect();
|
||||
// $tempBlock = collect();
|
||||
|
||||
$lastIndex = $rawTracks->count() - 1;
|
||||
// $lastIndex = $rawTracks->count() - 1;
|
||||
|
||||
foreach ($rawTracks as $i => $track) {
|
||||
$isZero = $track->speed == 0;
|
||||
// foreach ($rawTracks as $i => $track) {
|
||||
// $isZero = $track->speed == 0;
|
||||
|
||||
if ($i === $lastIndex) {
|
||||
if ($isZero) {
|
||||
$zeroBlock->push($track);
|
||||
} else {
|
||||
if ($zeroBlock->isNotEmpty()) {
|
||||
$tempBlock = $zeroBlock;
|
||||
$tempBlock->push($track);
|
||||
// if ($i === $lastIndex) {
|
||||
// if ($isZero) {
|
||||
// $zeroBlock->push($track);
|
||||
// } else {
|
||||
// if ($zeroBlock->isNotEmpty()) {
|
||||
// $tempBlock = $zeroBlock;
|
||||
// $tempBlock->push($track);
|
||||
|
||||
$zerosOnly = $tempBlock->filter(fn($t) => $t->speed == 0);
|
||||
// $zerosOnly = $tempBlock->filter(fn($t) => $t->speed == 0);
|
||||
|
||||
if ($zerosOnly->count() === 1) {
|
||||
$filtered->push($zerosOnly->first());
|
||||
} elseif ($zerosOnly->count() > 1) {
|
||||
$filtered->push($zerosOnly->first());
|
||||
$filtered->push($zerosOnly->last());
|
||||
}
|
||||
} else {
|
||||
$filtered->push($track);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// if ($zerosOnly->count() === 1) {
|
||||
// $filtered->push($zerosOnly->first());
|
||||
// } elseif ($zerosOnly->count() > 1) {
|
||||
// $filtered->push($zerosOnly->first());
|
||||
// $filtered->push($zerosOnly->last());
|
||||
// }
|
||||
// } else {
|
||||
// $filtered->push($track);
|
||||
// }
|
||||
// }
|
||||
// continue;
|
||||
// }
|
||||
// //
|
||||
// if ($isZero) {
|
||||
// $zeroBlock->push($track);
|
||||
// } else {
|
||||
// if ($zeroBlock->isNotEmpty()) {
|
||||
// $filtered->push($zeroBlock->first());
|
||||
// $zeroBlock = collect();
|
||||
// }
|
||||
// $filtered->push($track);
|
||||
// }
|
||||
// }
|
||||
|
||||
if ($isZero) {
|
||||
$zeroBlock->push($track);
|
||||
} else {
|
||||
if ($zeroBlock->isNotEmpty()) {
|
||||
$filtered->push($zeroBlock->first());
|
||||
$zeroBlock = collect();
|
||||
}
|
||||
$filtered->push($track);
|
||||
}
|
||||
}
|
||||
// if ($zeroBlock->isNotEmpty() && $rawTracks->last()->speed == 0) {
|
||||
// if ($zeroBlock->count() === 1) {
|
||||
// $filtered->push($zeroBlock->first());
|
||||
// } else {
|
||||
// $filtered->push($zeroBlock->first());
|
||||
// $filtered->push($zeroBlock->last());
|
||||
// }
|
||||
// }
|
||||
|
||||
if ($zeroBlock->isNotEmpty() && $rawTracks->last()->speed == 0) {
|
||||
if ($zeroBlock->count() === 1) {
|
||||
$filtered->push($zeroBlock->first());
|
||||
} else {
|
||||
$filtered->push($zeroBlock->first());
|
||||
$filtered->push($zeroBlock->last());
|
||||
}
|
||||
}
|
||||
// grouping by trip
|
||||
$groupTrip = [];
|
||||
$temp = [];
|
||||
|
||||
return $filtered->take(500);
|
||||
// loop from top to bottom
|
||||
foreach ($rawTracks as $item) {
|
||||
if ($item->ignition == 4) {
|
||||
// collect data when ignition is 4
|
||||
$temp[] = $item;
|
||||
} else {
|
||||
// if ignition != 4, save group if exists then reset
|
||||
if (!empty($temp)) {
|
||||
$groupTrip[] = $temp;
|
||||
$temp = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
// add last collected group if any
|
||||
if (!empty($temp)) {
|
||||
$groupTrip[] = $temp;
|
||||
}
|
||||
// dd($groupTrip);
|
||||
|
||||
|
||||
// return $filtered->take(500);
|
||||
return $groupTrip;
|
||||
}
|
||||
|
||||
public static function nearestInCircle($lat, $lng, $rad, $filter = [])
|
||||
|
||||
@ -63,17 +63,6 @@ class Tracks_copy extends Model
|
||||
$query .= " ,tr.ignition,tr.stts_engine,tr.stts_gps,tr.stts_gsm";
|
||||
$query .= " ,tr.pre_milleage,tr.sum_milleage,tr.vhc_milleage,v.sum_milleage AS vhc_sum_milleage_1";
|
||||
|
||||
// FRO
|
||||
// $query .= " ,(SELECT SUM(pre_milleage) FROM " . self::T_TRACKS . " WHERE vhc_id = v.id LIMIT 1) as vhc_sum_milleage";
|
||||
|
||||
// $query .= " ,(SELECT crt_s FROM " . self::T_TRACKS . " WHERE stts_engine = " . self::STTS_EN_IDLING . " AND vhc_id = v.id AND crt_s >= (
|
||||
// SELECT crt_s FROM " . self::T_TRACKS . " WHERE stts_engine IN (" . self::STTS_EN_STOPING . "," . self::STTS_EN_MOVING . ") AND vhc_id = v.id AND crt_s <= tr.crt_s ORDER BY id DESC LIMIT 1
|
||||
// ) ORDER BY id ASC LIMIT 1) as lst_idle_at";
|
||||
|
||||
// $query .= " ,(SELECT crt_s FROM " . self::T_TRACKS . " WHERE stts_engine = " . self::STTS_EN_STOPING . " AND vhc_id = v.id AND crt_s >= (
|
||||
// SELECT crt_s FROM " . self::T_TRACKS . " WHERE stts_engine IN (" . self::STTS_EN_IDLING . "," . self::STTS_EN_MOVING . ") AND vhc_id = v.id AND crt_s <= tr.crt_s ORDER BY id DESC LIMIT 1
|
||||
// ) ORDER BY id ASC LIMIT 1) as lst_stop_at";
|
||||
|
||||
$query .=
|
||||
" ,tr.id AS lst_master_id,tr.latitude AS lst_lat,tr.longitude AS lst_lng,tr.speed AS lst_speed,tr.orientation AS lst_orientation";
|
||||
$query .= " ,tr.crt AS lst_loc_crt,tr.crt_d AS lst_loc_crt_d,tr.crt_s AS lst_loc_crt_s";
|
||||
@ -83,9 +72,6 @@ class Tracks_copy extends Model
|
||||
" ,tr_addr.district_text AS lst_district_text,tr_addr.village_text AS lst_village_text,tr_addr.postcode AS lst_postcode";
|
||||
$query .= " ,tr_addr.streets AS lst_streets,tr_addr.fulladdress AS lst_fulladdress";
|
||||
|
||||
// FRO
|
||||
// $query .= " ,(SELECT COUNT(id) FROM " . self::T_TRACKS . " WHERE vhc_id = v.id AND action = 'heartbeat' AND crt BETWEEN ".($now-(10*60))." AND ".$now." LIMIT 1) as lst_heartbeat"; // heartbeat last data on further 10 minutes
|
||||
|
||||
if (isset($filter["active_rates"])) {
|
||||
$query .=
|
||||
",rate.vdr_id as rate_vdr_id,rate.vhc_type as rate_vhc_type,rate.origin_prov as rate_origin_prov,rate.dest_city as rate_dest_city,rate.dest_district as rate_dest_district";
|
||||
@ -107,45 +93,23 @@ class Tracks_copy extends Model
|
||||
$query .= " INNER JOIN t_vehicles_cats AS c ON v.cat_id = c.id";
|
||||
$query .= " LEFT JOIN t_users AS vendor ON v.vendor_id = vendor.id";
|
||||
$query .= " LEFT JOIN t_clients AS client ON vendor.client_group_id = client.id";
|
||||
// get last updated row from many rows
|
||||
// $query .= " LEFT JOIN ( SELECT MAX(crt) max_crt, device_id FROM " . self::T_TRACKS . " WHERE latitude is not null AND longitude is not null GROUP BY device_id ORDER BY crt DESC ) AS tr1 ON (v.device_id = tr1.device_id)"; // cara lama berlaku utk gps tracker saja
|
||||
// // $query .= " LEFT JOIN ( SELECT MAX(crt) max_crt, device_id, vhc_id FROM " . self::T_TRACKS . " WHERE latitude is not null AND longitude is not null GROUP BY vhc_id ORDER BY crt DESC ) AS tr1 ON (v.id = tr1.vhc_id)"; // support gps tracker dan smartphone / apapun yang mempunyai device_id(IMEI)
|
||||
// $query .= " LEFT JOIN " . self::T_TRACKS . " AS tr ON (tr.crt = tr1.max_crt)";
|
||||
// get last updated tracking from updated table realtime
|
||||
// $query .= " LEFT JOIN db_trucking.t_gps_tracks_rltm AS tr ON tr.vhc_id = v.id";
|
||||
$query .= " LEFT JOIN t_gps_tracks_rltm AS tr ON tr.vhc_id = v.id";
|
||||
// $query .= " LEFT JOIN " . self::T_TRACKS_ADDR . " AS tr_addr ON tr.id = tr_addr.master_id";
|
||||
|
||||
//FRO
|
||||
$query .=
|
||||
" LEFT JOIN " .
|
||||
self::T_TRACKS_ADDR .
|
||||
" AS tr_addr ON tr.latitude = tr_addr.lat and tr.longitude = tr_addr.lng";
|
||||
|
||||
if (isset($filter["active_rates"])) {
|
||||
// $query .= " INNER JOIN t_conf_rates as rate ON v.type_id = rate.vhc_type";
|
||||
$query .= " INNER JOIN t_conf_rates as rate ON v.vendor_id = rate.vdr_id";
|
||||
}
|
||||
if (isset($filter["get_order_data"])) {
|
||||
// the old way => only 1 order 1 vehicle
|
||||
$query .= " LEFT JOIN t_orders as ord ON v.ord_id = ord.id";
|
||||
$query .= " LEFT JOIN t_orders_pickups as ord_pck ON v.ord_id = ord_pck.ord_id";
|
||||
$query .= " LEFT JOIN t_orders_drops as ord_drop ON v.ord_id = ord_drop.ord_id";
|
||||
$query .= " LEFT JOIN t_orders_drivers as ord_drv ON v.ord_id = ord_drv.ord_id";
|
||||
$query .= " LEFT JOIN t_orders_clients as ord_c ON v.ord_id = ord_c.ord_id";
|
||||
|
||||
// the new way => can handle 2 order in 1 vehicle
|
||||
// $query .= " LEFT JOIN t_orders_vehicles as ord_vhc ON v.id = ord_vhc.vhc_id";
|
||||
// $query .= " LEFT JOIN t_orders as ord ON ord_vhc.ord_id = ord.id";
|
||||
// $query .= " LEFT JOIN t_orders_pickups as ord_pck ON ord_vhc.ord_id = ord_pck.ord_id";
|
||||
// $query .= " LEFT JOIN t_orders_drops as ord_drop ON ord_vhc.ord_id = ord_drop.ord_id";
|
||||
// $query .= " LEFT JOIN t_orders_drivers as ord_drv ON ord_vhc.ord_id = ord_drv.ord_id";
|
||||
// $query .= " LEFT JOIN t_orders_clients as ord_c ON ord_vhc.ord_id = ord_c.ord_id";
|
||||
}
|
||||
$query .= " WHERE v.dlt is null";
|
||||
// $query .= " AND tr.action IN ('location','alarm')"; // kalo gamau ngambil data heartbeat(idling)
|
||||
// $query .= " AND tr.device_id = v.device_id"; // cara lama berlaku utk gps tracker saja
|
||||
// $query .= " AND tr.vhc_id = v.id"; // support gps tracker dan smartphone / apapun yang mempunyai device_id(IMEI) // bikin lemot
|
||||
$query .= " AND tr.latitude != 0 AND tr.latitude is not null";
|
||||
if (isset($filter["status"])) {
|
||||
$query .= " AND v.status = ?";
|
||||
@ -184,11 +148,6 @@ class Tracks_copy extends Model
|
||||
$params[] = $filter["own_by_vdr_id"];
|
||||
}
|
||||
if (isset($filter["active_rates"])) {
|
||||
// v1
|
||||
// $query .= " AND rate.vdr_id != 0 AND rate.dest_city != 0 AND rate.dest_district != 0";
|
||||
// $query .= " AND rate.origin_prov = ? AND (rate.dest_city = ? OR rate.dest_district = ?) AND rate.sell_kg = ? AND rate.sell_cbm = ? AND rate.long_time = ?";
|
||||
// array_push($params, $filter['active_rates']->origin_prov, $filter['active_rates']->dest_city, $filter['active_rates']->dest_district, $filter['active_rates']->sell_kg, $filter['active_rates']->sell_cbm, $filter['active_rates']->long_time);
|
||||
// v2
|
||||
$query .=
|
||||
" AND rate.vdr_id != 0 AND rate.dest_city != 0 AND rate.is_active = " . ConfRates::IS_ACTIVE;
|
||||
$query .=
|
||||
@ -211,21 +170,16 @@ class Tracks_copy extends Model
|
||||
$query .= " AND ord_c.c_id = ?";
|
||||
$params[] = $filter["client_id"];
|
||||
}
|
||||
// $query .= " AND ord.status IN (22,4)";
|
||||
}
|
||||
if (isset($filter["company"])) {
|
||||
$query .= " AND client.id = ?";
|
||||
$params[] = $filter["company"];
|
||||
}
|
||||
|
||||
// $query .= " AND v.id = 70";
|
||||
|
||||
$query .= " GROUP BY v.id";
|
||||
$query .= " ORDER BY tr.crt_d DESC";
|
||||
$query .= " LIMIT 500;";
|
||||
|
||||
// dd($query);
|
||||
|
||||
$list = DB::select($query, $params);
|
||||
foreach ($list as $_list) {
|
||||
$_query =
|
||||
@ -301,7 +255,6 @@ class Tracks_copy extends Model
|
||||
$_query = DB::select($_query, [$_list->vid]);
|
||||
$_list->lst_heartbeat = count($_query) == 0 ? "" : $_query[0]->lst_heartbeat;
|
||||
}
|
||||
// em
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
||||
1010
app/Models/Tracks_copy_last.php
Executable file
1010
app/Models/Tracks_copy_last.php
Executable file
File diff suppressed because it is too large
Load Diff
20
app/Models/UserLogs.php
Normal file
20
app/Models/UserLogs.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class UserLogs extends Model
|
||||
{
|
||||
public static function insert($userId, $log)
|
||||
{
|
||||
$now = time();
|
||||
return DB::insert("INSERT into t_user_log
|
||||
set
|
||||
userId = ?,
|
||||
log = ?,
|
||||
crt = ?
|
||||
", [$userId, json_encode($log), $now]);
|
||||
}
|
||||
}
|
||||
@ -17,6 +17,7 @@
|
||||
"laravel/framework": "^9.0.0",
|
||||
"laravel/tinker": "^2.5",
|
||||
"laravel/ui": "^4.0",
|
||||
"maatwebsite/excel": "^3.1",
|
||||
"spatie/laravel-permission": "^6.20",
|
||||
"yajra/laravel-datatables": "^9.0"
|
||||
},
|
||||
|
||||
591
composer.lock
generated
591
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "1d471cd31c444b2d18a5d42b8df9a0ca",
|
||||
"content-hash": "01c0c9e02caa82e92dd9b4d028602130",
|
||||
"packages": [
|
||||
{
|
||||
"name": "asm89/stack-cors",
|
||||
@ -262,6 +262,162 @@
|
||||
],
|
||||
"time": "2024-02-09T16:56:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "composer/pcre",
|
||||
"version": "3.3.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/composer/pcre.git",
|
||||
"reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
|
||||
"reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"phpstan/phpstan": "<1.11.10"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1.12 || ^2",
|
||||
"phpstan/phpstan-strict-rules": "^1 || ^2",
|
||||
"phpunit/phpunit": "^8 || ^9"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"phpstan": {
|
||||
"includes": [
|
||||
"extension.neon"
|
||||
]
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-main": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Composer\\Pcre\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jordi Boggiano",
|
||||
"email": "j.boggiano@seld.be",
|
||||
"homepage": "http://seld.be"
|
||||
}
|
||||
],
|
||||
"description": "PCRE wrapping library that offers type-safe preg_* replacements.",
|
||||
"keywords": [
|
||||
"PCRE",
|
||||
"preg",
|
||||
"regex",
|
||||
"regular expression"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/composer/pcre/issues",
|
||||
"source": "https://github.com/composer/pcre/tree/3.3.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://packagist.com",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/composer",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-11-12T16:29:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "composer/semver",
|
||||
"version": "3.4.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/composer/semver.git",
|
||||
"reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95",
|
||||
"reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.3.2 || ^7.0 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1.11",
|
||||
"symfony/phpunit-bridge": "^3 || ^7"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Composer\\Semver\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nils Adermann",
|
||||
"email": "naderman@naderman.de",
|
||||
"homepage": "http://www.naderman.de"
|
||||
},
|
||||
{
|
||||
"name": "Jordi Boggiano",
|
||||
"email": "j.boggiano@seld.be",
|
||||
"homepage": "http://seld.be"
|
||||
},
|
||||
{
|
||||
"name": "Rob Bast",
|
||||
"email": "rob.bast@gmail.com",
|
||||
"homepage": "http://robbast.nl"
|
||||
}
|
||||
],
|
||||
"description": "Semver library that offers utilities, version constraint parsing and validation.",
|
||||
"keywords": [
|
||||
"semantic",
|
||||
"semver",
|
||||
"validation",
|
||||
"versioning"
|
||||
],
|
||||
"support": {
|
||||
"irc": "ircs://irc.libera.chat:6697/composer",
|
||||
"issues": "https://github.com/composer/semver/issues",
|
||||
"source": "https://github.com/composer/semver/tree/3.4.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://packagist.com",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/composer",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-08-20T19:15:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dflydev/dot-access-data",
|
||||
"version": "v3.0.3",
|
||||
@ -706,6 +862,67 @@
|
||||
],
|
||||
"time": "2025-03-06T22:45:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ezyang/htmlpurifier",
|
||||
"version": "v4.18.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ezyang/htmlpurifier.git",
|
||||
"reference": "cb56001e54359df7ae76dc522d08845dc741621b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/cb56001e54359df7ae76dc522d08845dc741621b",
|
||||
"reference": "cb56001e54359df7ae76dc522d08845dc741621b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"cerdic/css-tidy": "^1.7 || ^2.0",
|
||||
"simpletest/simpletest": "dev-master"
|
||||
},
|
||||
"suggest": {
|
||||
"cerdic/css-tidy": "If you want to use the filter 'Filter.ExtractStyleBlocks'.",
|
||||
"ext-bcmath": "Used for unit conversion and imagecrash protection",
|
||||
"ext-iconv": "Converts text to and from non-UTF-8 encodings",
|
||||
"ext-tidy": "Used for pretty-printing HTML"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"library/HTMLPurifier.composer.php"
|
||||
],
|
||||
"psr-0": {
|
||||
"HTMLPurifier": "library/"
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/library/HTMLPurifier/Language/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-2.1-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Edward Z. Yang",
|
||||
"email": "admin@htmlpurifier.org",
|
||||
"homepage": "http://ezyang.com"
|
||||
}
|
||||
],
|
||||
"description": "Standards compliant HTML filter written in PHP",
|
||||
"homepage": "http://htmlpurifier.org/",
|
||||
"keywords": [
|
||||
"html"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/ezyang/htmlpurifier/issues",
|
||||
"source": "https://github.com/ezyang/htmlpurifier/tree/v4.18.0"
|
||||
},
|
||||
"time": "2024-11-01T03:51:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "fruitcake/laravel-cors",
|
||||
"version": "v2.2.0",
|
||||
@ -2344,6 +2561,272 @@
|
||||
],
|
||||
"time": "2024-09-21T08:32:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "maatwebsite/excel",
|
||||
"version": "3.1.67",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/SpartnerNL/Laravel-Excel.git",
|
||||
"reference": "e508e34a502a3acc3329b464dad257378a7edb4d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/e508e34a502a3acc3329b464dad257378a7edb4d",
|
||||
"reference": "e508e34a502a3acc3329b464dad257378a7edb4d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"composer/semver": "^3.3",
|
||||
"ext-json": "*",
|
||||
"illuminate/support": "5.8.*||^6.0||^7.0||^8.0||^9.0||^10.0||^11.0||^12.0",
|
||||
"php": "^7.0||^8.0",
|
||||
"phpoffice/phpspreadsheet": "^1.30.0",
|
||||
"psr/simple-cache": "^1.0||^2.0||^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/scout": "^7.0||^8.0||^9.0||^10.0",
|
||||
"orchestra/testbench": "^6.0||^7.0||^8.0||^9.0||^10.0",
|
||||
"predis/predis": "^1.1"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"aliases": {
|
||||
"Excel": "Maatwebsite\\Excel\\Facades\\Excel"
|
||||
},
|
||||
"providers": [
|
||||
"Maatwebsite\\Excel\\ExcelServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Maatwebsite\\Excel\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Patrick Brouwers",
|
||||
"email": "patrick@spartner.nl"
|
||||
}
|
||||
],
|
||||
"description": "Supercharged Excel exports and imports in Laravel",
|
||||
"keywords": [
|
||||
"PHPExcel",
|
||||
"batch",
|
||||
"csv",
|
||||
"excel",
|
||||
"export",
|
||||
"import",
|
||||
"laravel",
|
||||
"php",
|
||||
"phpspreadsheet"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/SpartnerNL/Laravel-Excel/issues",
|
||||
"source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.67"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://laravel-excel.com/commercial-support",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/patrickbrouwers",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-08-26T09:13:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "maennchen/zipstream-php",
|
||||
"version": "3.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/maennchen/ZipStream-PHP.git",
|
||||
"reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/aeadcf5c412332eb426c0f9b4485f6accba2a99f",
|
||||
"reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"ext-zlib": "*",
|
||||
"php-64bit": "^8.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"brianium/paratest": "^7.7",
|
||||
"ext-zip": "*",
|
||||
"friendsofphp/php-cs-fixer": "^3.16",
|
||||
"guzzlehttp/guzzle": "^7.5",
|
||||
"mikey179/vfsstream": "^1.6",
|
||||
"php-coveralls/php-coveralls": "^2.5",
|
||||
"phpunit/phpunit": "^11.0",
|
||||
"vimeo/psalm": "^6.0"
|
||||
},
|
||||
"suggest": {
|
||||
"guzzlehttp/psr7": "^2.4",
|
||||
"psr/http-message": "^2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"ZipStream\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Paul Duncan",
|
||||
"email": "pabs@pablotron.org"
|
||||
},
|
||||
{
|
||||
"name": "Jonatan Männchen",
|
||||
"email": "jonatan@maennchen.ch"
|
||||
},
|
||||
{
|
||||
"name": "Jesse Donat",
|
||||
"email": "donatj@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "András Kolesár",
|
||||
"email": "kolesar@kolesar.hu"
|
||||
}
|
||||
],
|
||||
"description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
|
||||
"keywords": [
|
||||
"stream",
|
||||
"zip"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/maennchen/ZipStream-PHP/issues",
|
||||
"source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/maennchen",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-01-27T12:07:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "markbaker/complex",
|
||||
"version": "3.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MarkBaker/PHPComplex.git",
|
||||
"reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
|
||||
"reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
|
||||
"phpcompatibility/php-compatibility": "^9.3",
|
||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
|
||||
"squizlabs/php_codesniffer": "^3.7"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Complex\\": "classes/src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Mark Baker",
|
||||
"email": "mark@lange.demon.co.uk"
|
||||
}
|
||||
],
|
||||
"description": "PHP Class for working with complex numbers",
|
||||
"homepage": "https://github.com/MarkBaker/PHPComplex",
|
||||
"keywords": [
|
||||
"complex",
|
||||
"mathematics"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/MarkBaker/PHPComplex/issues",
|
||||
"source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.2"
|
||||
},
|
||||
"time": "2022-12-06T16:21:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "markbaker/matrix",
|
||||
"version": "3.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MarkBaker/PHPMatrix.git",
|
||||
"reference": "728434227fe21be27ff6d86621a1b13107a2562c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/728434227fe21be27ff6d86621a1b13107a2562c",
|
||||
"reference": "728434227fe21be27ff6d86621a1b13107a2562c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
|
||||
"phpcompatibility/php-compatibility": "^9.3",
|
||||
"phpdocumentor/phpdocumentor": "2.*",
|
||||
"phploc/phploc": "^4.0",
|
||||
"phpmd/phpmd": "2.*",
|
||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
|
||||
"sebastian/phpcpd": "^4.0",
|
||||
"squizlabs/php_codesniffer": "^3.7"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Matrix\\": "classes/src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Mark Baker",
|
||||
"email": "mark@demon-angel.eu"
|
||||
}
|
||||
],
|
||||
"description": "PHP Class for working with matrices",
|
||||
"homepage": "https://github.com/MarkBaker/PHPMatrix",
|
||||
"keywords": [
|
||||
"mathematics",
|
||||
"matrix",
|
||||
"vector"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/MarkBaker/PHPMatrix/issues",
|
||||
"source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.1"
|
||||
},
|
||||
"time": "2022-12-02T22:17:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "monolog/monolog",
|
||||
"version": "2.10.0",
|
||||
@ -2984,6 +3467,112 @@
|
||||
},
|
||||
"time": "2022-03-07T12:52:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpoffice/phpspreadsheet",
|
||||
"version": "1.30.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
|
||||
"reference": "2f39286e0136673778b7a142b3f0d141e43d1714"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/2f39286e0136673778b7a142b3f0d141e43d1714",
|
||||
"reference": "2f39286e0136673778b7a142b3f0d141e43d1714",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"composer/pcre": "^1||^2||^3",
|
||||
"ext-ctype": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-fileinfo": "*",
|
||||
"ext-gd": "*",
|
||||
"ext-iconv": "*",
|
||||
"ext-libxml": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-simplexml": "*",
|
||||
"ext-xml": "*",
|
||||
"ext-xmlreader": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"ext-zip": "*",
|
||||
"ext-zlib": "*",
|
||||
"ezyang/htmlpurifier": "^4.15",
|
||||
"maennchen/zipstream-php": "^2.1 || ^3.0",
|
||||
"markbaker/complex": "^3.0",
|
||||
"markbaker/matrix": "^3.0",
|
||||
"php": "^7.4 || ^8.0",
|
||||
"psr/http-client": "^1.0",
|
||||
"psr/http-factory": "^1.0",
|
||||
"psr/simple-cache": "^1.0 || ^2.0 || ^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "dev-main",
|
||||
"dompdf/dompdf": "^1.0 || ^2.0 || ^3.0",
|
||||
"friendsofphp/php-cs-fixer": "^3.2",
|
||||
"mitoteam/jpgraph": "^10.3",
|
||||
"mpdf/mpdf": "^8.1.1",
|
||||
"phpcompatibility/php-compatibility": "^9.3",
|
||||
"phpstan/phpstan": "^1.1",
|
||||
"phpstan/phpstan-phpunit": "^1.0",
|
||||
"phpunit/phpunit": "^8.5 || ^9.0",
|
||||
"squizlabs/php_codesniffer": "^3.7",
|
||||
"tecnickcom/tcpdf": "^6.5"
|
||||
},
|
||||
"suggest": {
|
||||
"dompdf/dompdf": "Option for rendering PDF with PDF Writer",
|
||||
"ext-intl": "PHP Internationalization Functions",
|
||||
"mitoteam/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers",
|
||||
"mpdf/mpdf": "Option for rendering PDF with PDF Writer",
|
||||
"tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Maarten Balliauw",
|
||||
"homepage": "https://blog.maartenballiauw.be"
|
||||
},
|
||||
{
|
||||
"name": "Mark Baker",
|
||||
"homepage": "https://markbakeruk.net"
|
||||
},
|
||||
{
|
||||
"name": "Franck Lefevre",
|
||||
"homepage": "https://rootslabs.net"
|
||||
},
|
||||
{
|
||||
"name": "Erik Tilt"
|
||||
},
|
||||
{
|
||||
"name": "Adrien Crivelli"
|
||||
}
|
||||
],
|
||||
"description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
|
||||
"homepage": "https://github.com/PHPOffice/PhpSpreadsheet",
|
||||
"keywords": [
|
||||
"OpenXML",
|
||||
"excel",
|
||||
"gnumeric",
|
||||
"ods",
|
||||
"php",
|
||||
"spreadsheet",
|
||||
"xls",
|
||||
"xlsx"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues",
|
||||
"source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.30.0"
|
||||
},
|
||||
"time": "2025-08-10T06:28:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpoption/phpoption",
|
||||
"version": "1.9.3",
|
||||
|
||||
350
public/assets/vendor/printThis.js
vendored
Normal file
350
public/assets/vendor/printThis.js
vendored
Normal file
@ -0,0 +1,350 @@
|
||||
/*
|
||||
* printThis v2.0.0
|
||||
* @desc Printing plug-in for jQuery
|
||||
* @author Jason Day
|
||||
* @author Samuel Rouse
|
||||
*
|
||||
* Resources (based on):
|
||||
* - jPrintArea: http://plugins.jquery.com/project/jPrintArea
|
||||
* - jqPrint: https://github.com/permanenttourist/jquery.jqprint
|
||||
* - Ben Nadal: http://www.bennadel.com/blog/1591-Ask-Ben-Print-Part-Of-A-Web-Page-With-jQuery.htm
|
||||
*
|
||||
* Licensed under the MIT licence:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* (c) Jason Day 2015-2022
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* $("#mySelector").printThis({
|
||||
* debug: false, // show the iframe for debugging
|
||||
* importCSS: true, // import parent page css
|
||||
* importStyle: true, // import style tags
|
||||
* printContainer: true, // grab outer container as well as the contents of the selector
|
||||
* loadCSS: "path/to/my.css", // path to additional css file - use an array [] for multiple
|
||||
* pageTitle: "", // add title to print page
|
||||
* removeInline: false, // remove all inline styles from print elements
|
||||
* removeInlineSelector: "body *", // custom selectors to filter inline styles. removeInline must be true
|
||||
* printDelay: 1000, // variable print delay
|
||||
* header: null, // prefix to html
|
||||
* footer: null, // postfix to html
|
||||
* base: false, // preserve the BASE tag, or accept a string for the URL
|
||||
* formValues: true, // preserve input/form values
|
||||
* canvas: true, // copy canvas elements
|
||||
* doctypeString: '...', // enter a different doctype for older markup
|
||||
* removeScripts: false, // remove script tags from print content
|
||||
* copyTagClasses: true // copy classes from the html & body tag
|
||||
* copyTagStyles: true, // copy styles from html & body tag (for CSS Variables)
|
||||
* beforePrintEvent: null, // callback function for printEvent in iframe
|
||||
* beforePrint: null, // function called before iframe is filled
|
||||
* afterPrint: null // function called before iframe is removed
|
||||
* });
|
||||
*
|
||||
* Notes:
|
||||
* - the loadCSS will load additional CSS (with or without @media print) into the iframe, adjusting layout
|
||||
*/
|
||||
;
|
||||
(function($) {
|
||||
|
||||
function appendContent($el, content) {
|
||||
if (!content) return;
|
||||
|
||||
// Simple test for a jQuery element
|
||||
$el.append(content.jquery ? content.clone() : content);
|
||||
}
|
||||
|
||||
function appendBody($body, $element, opt) {
|
||||
// Clone for safety and convenience
|
||||
// Calls clone(withDataAndEvents = true) to copy form values.
|
||||
var $content = $element.clone(opt.formValues);
|
||||
|
||||
if (opt.formValues) {
|
||||
// Copy original select and textarea values to their cloned counterpart
|
||||
// Makes up for inability to clone select and textarea values with clone(true)
|
||||
copyValues($element, $content, 'select, textarea');
|
||||
}
|
||||
|
||||
if (opt.removeScripts) {
|
||||
$content.find('script').remove();
|
||||
}
|
||||
|
||||
if (opt.printContainer) {
|
||||
// grab $.selector as container
|
||||
$content.appendTo($body);
|
||||
} else {
|
||||
// otherwise just print interior elements of container
|
||||
$content.each(function() {
|
||||
$(this).children().appendTo($body)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Copies values from origin to clone for passed in elementSelector
|
||||
function copyValues(origin, clone, elementSelector) {
|
||||
var $originalElements = origin.find(elementSelector);
|
||||
|
||||
clone.find(elementSelector).each(function(index, item) {
|
||||
$(item).val($originalElements.eq(index).val());
|
||||
});
|
||||
}
|
||||
|
||||
var opt;
|
||||
$.fn.printThis = function(options) {
|
||||
opt = $.extend({}, $.fn.printThis.defaults, options);
|
||||
var $element = this instanceof jQuery ? this : $(this);
|
||||
|
||||
var strFrameName = "printThis-" + (new Date()).getTime();
|
||||
|
||||
if (window.location.hostname !== document.domain && navigator.userAgent.match(/msie/i)) {
|
||||
// Ugly IE hacks due to IE not inheriting document.domain from parent
|
||||
// checks if document.domain is set by comparing the host name against document.domain
|
||||
var iframeSrc = "javascript:document.write(\"<head><script>document.domain=\\\"" + document.domain + "\\\";</s" + "cript></head><body></body>\")";
|
||||
var printI = document.createElement('iframe');
|
||||
printI.name = "printIframe";
|
||||
printI.id = strFrameName;
|
||||
printI.className = "MSIE";
|
||||
document.body.appendChild(printI);
|
||||
printI.src = iframeSrc;
|
||||
|
||||
} else {
|
||||
// other browsers inherit document.domain, and IE works if document.domain is not explicitly set
|
||||
var $frame = $("<iframe id='" + strFrameName + "' name='printIframe' />");
|
||||
$frame.appendTo("body");
|
||||
}
|
||||
|
||||
var $iframe = $("#" + strFrameName);
|
||||
|
||||
// show frame if in debug mode
|
||||
if (!opt.debug) $iframe.css({
|
||||
position: "absolute",
|
||||
width: "0px",
|
||||
height: "0px",
|
||||
left: "-600px",
|
||||
top: "-600px"
|
||||
});
|
||||
|
||||
// before print callback
|
||||
if (typeof opt.beforePrint === "function") {
|
||||
opt.beforePrint();
|
||||
}
|
||||
|
||||
// $iframe.ready() and $iframe.load were inconsistent between browsers
|
||||
setTimeout(function() {
|
||||
|
||||
// Add doctype to fix the style difference between printing and render
|
||||
function setDocType($iframe, doctype){
|
||||
var win, doc;
|
||||
win = $iframe.get(0);
|
||||
win = win.contentWindow || win.contentDocument || win;
|
||||
doc = win.document || win.contentDocument || win;
|
||||
doc.open();
|
||||
doc.write(doctype);
|
||||
doc.close();
|
||||
}
|
||||
|
||||
if (opt.doctypeString){
|
||||
setDocType($iframe, opt.doctypeString);
|
||||
}
|
||||
|
||||
var $doc = $iframe.contents(),
|
||||
$head = $doc.find("head"),
|
||||
$body = $doc.find("body"),
|
||||
$base = $('base'),
|
||||
baseURL;
|
||||
|
||||
// add base tag to ensure elements use the parent domain
|
||||
if (opt.base === true && $base.length > 0) {
|
||||
// take the base tag from the original page
|
||||
baseURL = $base.attr('href');
|
||||
} else if (typeof opt.base === 'string') {
|
||||
// An exact base string is provided
|
||||
baseURL = opt.base;
|
||||
} else {
|
||||
// Use the page URL as the base
|
||||
baseURL = document.location.protocol + '//' + document.location.host;
|
||||
}
|
||||
|
||||
$head.append('<base href="' + baseURL + '">');
|
||||
|
||||
// import page stylesheets
|
||||
if (opt.importCSS) $("link[rel=stylesheet]").each(function() {
|
||||
var href = $(this).attr("href");
|
||||
if (href) {
|
||||
var media = $(this).attr("media") || "all";
|
||||
$head.append("<link type='text/css' rel='stylesheet' href='" + href + "' media='" + media + "'>");
|
||||
}
|
||||
});
|
||||
|
||||
// import style tags
|
||||
if (opt.importStyle) $("style").each(function() {
|
||||
$head.append(this.outerHTML);
|
||||
});
|
||||
|
||||
// add title of the page
|
||||
if (opt.pageTitle) $head.append("<title>" + opt.pageTitle + "</title>");
|
||||
|
||||
// import additional stylesheet(s)
|
||||
if (opt.loadCSS) {
|
||||
if ($.isArray(opt.loadCSS)) {
|
||||
jQuery.each(opt.loadCSS, function(index, value) {
|
||||
$head.append("<link type='text/css' rel='stylesheet' href='" + this + "'>");
|
||||
});
|
||||
} else {
|
||||
$head.append("<link type='text/css' rel='stylesheet' href='" + opt.loadCSS + "'>");
|
||||
}
|
||||
}
|
||||
|
||||
var pageHtml = $('html')[0];
|
||||
|
||||
// CSS VAR in html tag when dynamic apply e.g. document.documentElement.style.setProperty("--foo", bar);
|
||||
$doc.find('html').prop('style', pageHtml.style.cssText);
|
||||
|
||||
// copy 'root' tag classes
|
||||
var tag = opt.copyTagClasses;
|
||||
if (tag) {
|
||||
tag = tag === true ? 'bh' : tag;
|
||||
if (tag.indexOf('b') !== -1) {
|
||||
$body.addClass($('body')[0].className);
|
||||
}
|
||||
if (tag.indexOf('h') !== -1) {
|
||||
$doc.find('html').addClass(pageHtml.className);
|
||||
}
|
||||
}
|
||||
|
||||
// copy ':root' tag classes
|
||||
tag = opt.copyTagStyles;
|
||||
if (tag) {
|
||||
tag = tag === true ? 'bh' : tag;
|
||||
if (tag.indexOf('b') !== -1) {
|
||||
$body.attr('style', $('body')[0].style.cssText);
|
||||
}
|
||||
if (tag.indexOf('h') !== -1) {
|
||||
$doc.find('html').attr('style', pageHtml.style.cssText);
|
||||
}
|
||||
}
|
||||
|
||||
// print header
|
||||
appendContent($body, opt.header);
|
||||
|
||||
if (opt.canvas) {
|
||||
// add canvas data-ids for easy access after cloning.
|
||||
var canvasId = 0;
|
||||
// .addBack('canvas') adds the top-level element if it is a canvas.
|
||||
$element.find('canvas').addBack('canvas').each(function(){
|
||||
$(this).attr('data-printthis', canvasId++);
|
||||
});
|
||||
}
|
||||
|
||||
appendBody($body, $element, opt);
|
||||
|
||||
if (opt.canvas) {
|
||||
// Re-draw new canvases by referencing the originals
|
||||
$body.find('canvas').each(function(){
|
||||
var cid = $(this).data('printthis'),
|
||||
$src = $('[data-printthis="' + cid + '"]');
|
||||
|
||||
this.getContext('2d').drawImage($src[0], 0, 0);
|
||||
|
||||
// Remove the markup from the original
|
||||
if ($.isFunction($.fn.removeAttr)) {
|
||||
$src.removeAttr('data-printthis');
|
||||
} else {
|
||||
$.each($src, function(i, el) {
|
||||
el.removeAttribute('data-printthis');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// remove inline styles
|
||||
if (opt.removeInline) {
|
||||
// Ensure there is a selector, even if it's been mistakenly removed
|
||||
var selector = opt.removeInlineSelector || '*';
|
||||
// $.removeAttr available jQuery 1.7+
|
||||
if ($.isFunction($.removeAttr)) {
|
||||
$body.find(selector).removeAttr("style");
|
||||
} else {
|
||||
$body.find(selector).attr("style", "");
|
||||
}
|
||||
}
|
||||
|
||||
// print "footer"
|
||||
appendContent($body, opt.footer);
|
||||
|
||||
// attach event handler function to beforePrint event
|
||||
function attachOnBeforePrintEvent($iframe, beforePrintHandler) {
|
||||
var win = $iframe.get(0);
|
||||
win = win.contentWindow || win.contentDocument || win;
|
||||
|
||||
if (typeof beforePrintHandler === "function") {
|
||||
if ('matchMedia' in win) {
|
||||
win.matchMedia('print').addListener(function(mql) {
|
||||
if(mql.matches) beforePrintHandler();
|
||||
});
|
||||
} else {
|
||||
win.onbeforeprint = beforePrintHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
attachOnBeforePrintEvent($iframe, opt.beforePrintEvent);
|
||||
|
||||
setTimeout(function() {
|
||||
if ($iframe.hasClass("MSIE")) {
|
||||
// check if the iframe was created with the ugly hack
|
||||
// and perform another ugly hack out of neccessity
|
||||
window.frames["printIframe"].focus();
|
||||
$head.append("<script> window.print(); </s" + "cript>");
|
||||
} else {
|
||||
// proper method
|
||||
if (document.queryCommandSupported("print")) {
|
||||
$iframe[0].contentWindow.document.execCommand("print", false, null);
|
||||
} else {
|
||||
$iframe[0].contentWindow.focus();
|
||||
$iframe[0].contentWindow.print();
|
||||
}
|
||||
}
|
||||
|
||||
// remove iframe after print
|
||||
if (!opt.debug) {
|
||||
setTimeout(function() {
|
||||
$iframe.remove();
|
||||
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// after print callback
|
||||
if (typeof opt.afterPrint === "function") {
|
||||
opt.afterPrint();
|
||||
}
|
||||
|
||||
}, opt.printDelay);
|
||||
|
||||
}, 333);
|
||||
|
||||
};
|
||||
|
||||
// defaults
|
||||
$.fn.printThis.defaults = {
|
||||
debug: false, // show the iframe for debugging
|
||||
importCSS: true, // import parent page css
|
||||
importStyle: true, // import style tags
|
||||
printContainer: true, // print outer container/$.selector
|
||||
loadCSS: "", // path to additional css file - use an array [] for multiple
|
||||
pageTitle: "", // add title to print page
|
||||
removeInline: false, // remove inline styles from print elements
|
||||
removeInlineSelector: "*", // custom selectors to filter inline styles. removeInline must be true
|
||||
printDelay: 1000, // variable print delay
|
||||
header: null, // prefix to html
|
||||
footer: null, // postfix to html
|
||||
base: false, // preserve the BASE tag or accept a string for the URL
|
||||
formValues: true, // preserve input/form values
|
||||
canvas: true, // copy canvas content
|
||||
doctypeString: '<!DOCTYPE html>', // enter a different doctype for older markup
|
||||
removeScripts: false, // remove script tags from print content
|
||||
copyTagClasses: true, // copy classes from the html & body tag
|
||||
copyTagStyles: true, // copy styles from html & body tag (for CSS Variables)
|
||||
beforePrintEvent: null, // callback function for printEvent in iframe
|
||||
beforePrint: null, // function called before iframe is filled
|
||||
afterPrint: null // function called before iframe is removed
|
||||
};
|
||||
})(jQuery);
|
||||
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
set_time_limit(120);
|
||||
set_time_limit(300);
|
||||
/**
|
||||
* Laravel - A PHP Framework For Web Artisans
|
||||
*
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
<link href="{{ asset('assets/vendor/DataTables/datatables.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('assets/css/bootstrap-datepicker.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('assets/css/meus.css') }}" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.min.css" integrity="sha512-f0tzWhCwVFS3WeYaofoLWkTP62ObhewQ1EZn65oSYDZUg1+CyywGKkWzm8BxaJj5HGKI72PnMH9jYyIFz+GH7g==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
<style>
|
||||
.landscape-photo {
|
||||
max-height: max(21vh, 210px);
|
||||
@ -75,6 +76,9 @@
|
||||
<script src="{{ asset('assets/js/moment.min.js') }}"></script>
|
||||
<script src="{{ asset('assets/js/bootstrap-datepicker.min.js') }}"></script>
|
||||
<script src="{{ asset('assets/js/helper.js') }}"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.full.min.js" integrity="sha512-AIOTidJAcHBH2G/oZv9viEGXRqDNmfdPVPYOYKGy3fti0xIplnlgMHUGfuNRzC6FkzIo0iIxgFnr9RikFxK+sw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.34/moment-timezone-with-data.min.js"></script> -->
|
||||
|
||||
<script>
|
||||
const AppState = {
|
||||
user_role: {
|
||||
@ -84,6 +88,8 @@
|
||||
route_segment1: "{{ Request::segment(1) }}",
|
||||
route_segment2: "{{ Request::segment(2) }}",
|
||||
current_company: 0, // cptid
|
||||
// TIMEFIX: new Date().getTimezoneOffset() * -60
|
||||
TIMEFIX: 25200
|
||||
}
|
||||
|
||||
// function startTime() {
|
||||
|
||||
@ -7,9 +7,8 @@
|
||||
@section('customcss')
|
||||
<style>
|
||||
/* .select2-container {
|
||||
z-index: 99999;
|
||||
} */
|
||||
|
||||
z-index: 99999;
|
||||
} */
|
||||
</style>
|
||||
@endsection
|
||||
|
||||
@ -39,13 +38,11 @@
|
||||
<h6>User Infomation</h6>
|
||||
<div class="mb-3">
|
||||
<label for="updt-first_name" class="form-label">Name</label>
|
||||
<input type="text" class="form-control form-control-sm" name="updt-first_name"
|
||||
id="updt-first_name">
|
||||
<input type="text" class="form-control form-control-sm" name="updt-first_name" id="updt-first_name">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="updt-phone" class="form-label">Phone</label>
|
||||
<input type="number" class="form-control form-control-sm" name="updt-phone" id="updt-phone"
|
||||
placeholder="without zero">
|
||||
<input type="number" class="form-control form-control-sm" name="updt-phone" id="updt-phone" placeholder="without zero">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="updt-email" class="form-label">Email</label>
|
||||
@ -53,8 +50,7 @@
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="updt-fulladdress" class="form-label">Address</label>
|
||||
<textarea name="updt-fulladdress" id="updt-fulladdress"
|
||||
class="form-control form-control-sm" rows="3"></textarea>
|
||||
<textarea name="updt-fulladdress" id="updt-fulladdress" class="form-control form-control-sm" rows="3"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
@ -70,15 +66,13 @@
|
||||
<div class="col">
|
||||
<div class="mb-3">
|
||||
<label for="updt-password" class="form-label">Password</label>
|
||||
<input type="password" class="form-control form-control-sm" name="updt-password"
|
||||
id="updt-password">
|
||||
<input type="password" class="form-control form-control-sm" name="updt-password" id="updt-password">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="mb-3">
|
||||
<label for="updt-conf_password" class="form-label">Password Confirmation</label>
|
||||
<input type="password" class="form-control form-control-sm" name="updt-conf_password"
|
||||
id="updt-conf_password">
|
||||
<input type="password" class="form-control form-control-sm" name="updt-conf_password" id="updt-conf_password">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -252,7 +246,7 @@
|
||||
}
|
||||
$('#btnSubmitUpdtUser').attr('disabed', true);
|
||||
$.ajax({
|
||||
url: "{{ route('api_edit_user', '') }}/" + data.uid,
|
||||
url: "{{ route('api_edit_user_profile', '') }}/" + data.uid,
|
||||
method: 'PUT',
|
||||
crossDomain: true,
|
||||
processData: true,
|
||||
@ -291,7 +285,7 @@
|
||||
})
|
||||
});
|
||||
},
|
||||
removeReadOnly: function () {
|
||||
removeReadOnly: function() {
|
||||
$('#updt-first_name').removeAttr('readonly');
|
||||
$('#updt-fulladdress').removeAttr('readonly');
|
||||
$('#updt-phone').removeAttr('readonly');
|
||||
@ -302,7 +296,7 @@
|
||||
});
|
||||
$('#btnSubmitUpdtUser').removeClass('d-none');
|
||||
},
|
||||
addReadOnly: function () {
|
||||
addReadOnly: function() {
|
||||
$('#updt-first_name').attr('readonly', true);
|
||||
$('#updt-fulladdress').attr('readonly', true);
|
||||
$('#updt-phone').attr('readonly', true);
|
||||
|
||||
208
resources/views/menu_v1/_userLogs.blade.php
Normal file
208
resources/views/menu_v1/_userLogs.blade.php
Normal file
@ -0,0 +1,208 @@
|
||||
<style>
|
||||
#map {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
.my-leaflet-map-container img {
|
||||
max-height: none;
|
||||
}
|
||||
.dtl-text{
|
||||
font-size: 11px;
|
||||
}
|
||||
.head-text{
|
||||
font-size: 12px !important;
|
||||
}
|
||||
/* .leaflet-overlay-pane svg {
|
||||
transform: none !important;
|
||||
} */
|
||||
.leaflet-routing-container {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#viewPdf {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 794px;
|
||||
/* height: auto; */
|
||||
max-width: 100%; /* Ensures it is responsive */
|
||||
}
|
||||
/* .modal-dialog{
|
||||
width: 794px;
|
||||
} */
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
<div class="modal-dialog modal-dialog modal-dialog-centered modal-dialog-scrollable modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="mdlDetailTripLabel">{{$user->first_name}} Logs</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
<div class="form-group">
|
||||
<label class="text-muted">From</label>
|
||||
<!-- default today -->
|
||||
<!-- <input class="form-control" id="tgl0" value="02-09-2025 00:00"> -->
|
||||
<input class="form-control" id="tgl0" value="{{ date('d-m-Y 00:00') }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<div class="form-group">
|
||||
<label class="text-muted">To</label>
|
||||
<!-- <input class="form-control" id="tgl1" value="02-09-2025 23:00"> -->
|
||||
<input class="form-control" id="tgl1" value="{{ date('d-m-Y 23:59') }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 d-flex align-items-end">
|
||||
<button class="btn btn-primary" id="submitFilter">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table id="tLogs" class="table table-hover dataTable w-100">
|
||||
<thead>
|
||||
<tr class="">
|
||||
<th class="">Time</th>
|
||||
<th class="">Module</th>
|
||||
<th class="">Description</th>
|
||||
<th class="">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-sm btn-danger" data-bs-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$('.time').each(function () {
|
||||
const unix = parseInt($(this).text().trim()) + AppState.TIMEFIX;
|
||||
$(this).text(moment.unix(unix).format('DD MMM YYYY HH:mm:ss'));
|
||||
});
|
||||
$('#tgl0, #tgl1').datetimepicker({
|
||||
format:'d-m-Y H:i',
|
||||
defaultTime:'00:00',
|
||||
closeOnDateSelect: true,
|
||||
// mask:true
|
||||
});
|
||||
|
||||
$('#submitFilter').on('click', function() {
|
||||
DTable.reload();
|
||||
});
|
||||
// $('#submitFilter').trigger('click');
|
||||
|
||||
const DTable = {
|
||||
table: null,
|
||||
lastAjax: null, // keep track of the last ajax request
|
||||
activate: function() {
|
||||
DTable.reload();
|
||||
},
|
||||
reload: function() {
|
||||
// Abort the last request if it's still running
|
||||
if (DTable.lastAjax) {
|
||||
DTable.lastAjax.abort();
|
||||
}
|
||||
if (DTable.table) {
|
||||
// If table already exists → reload
|
||||
DTable.table.ajax.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
DTable.table = $('#tLogs').DataTable({
|
||||
searching: false, // 🔹 remove search box
|
||||
ordering: false, // 🔹 disable sorting for all columns
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
bLengthChange: true,
|
||||
deferRender: true,
|
||||
destroy: true,
|
||||
ajax: function(data, callback, settings) {
|
||||
// Abort previous
|
||||
if (DTable.lastAjax) {
|
||||
DTable.lastAjax.abort();
|
||||
}
|
||||
|
||||
// Fire new request
|
||||
DTable.lastAjax = $.ajax({
|
||||
url: `{{ route('api_user_logs1') }}?
|
||||
tgl0=${moment($('#tgl0').val(), "DD-MM-YYYY HH:mm").unix()}
|
||||
&tgl1=${moment($('#tgl1').val(), "DD-MM-YYYY HH:mm").unix()}
|
||||
&id={{$user->id}}
|
||||
`,
|
||||
type: 'GET',
|
||||
success: function(json) {
|
||||
callback(json);
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
if (status !== 'abort') {
|
||||
console.error("AJAX error:", error);
|
||||
}
|
||||
},
|
||||
complete: function() {
|
||||
DTable.lastAjax = null;
|
||||
}
|
||||
});
|
||||
},
|
||||
deferRender: true,
|
||||
columns: [
|
||||
{
|
||||
data: 'crt',
|
||||
render: (data, type, row, meta) => {
|
||||
// let addr = row
|
||||
return `
|
||||
${moment.unix(data).format('DD MMM YYYY HH:mm:ss')}<br>
|
||||
`;
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
data: 'log',
|
||||
render: (data, type, row, meta) => {
|
||||
let log = JSON.parse(data);
|
||||
let module = log.module || '-';
|
||||
return module;
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 'log',
|
||||
render: (data, type, row, meta) => {
|
||||
let log = JSON.parse(data);
|
||||
let desc = log.desc || '-';
|
||||
return desc;
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 'log',
|
||||
render: (data, type, row, meta) => {
|
||||
let log = JSON.parse(data);
|
||||
let action = log.action || '-';
|
||||
|
||||
// use badge for action
|
||||
// action = `<span class="badge bg-secondary">${action}</span>`;
|
||||
let badge = '';
|
||||
if (action.toLowerCase() === 'create') {
|
||||
badge = `<span class="badge bg-success">${action}</span>`;
|
||||
} else if (action.toLowerCase() === 'update') {
|
||||
badge = `<span class="badge bg-warning">${action}</span>`;
|
||||
} else if (action.toLowerCase() === 'delete') {
|
||||
badge = `<span class="badge bg-danger">${action}</span>`;
|
||||
} else {
|
||||
badge = `<span class="badge bg-secondary">${action}</span>`;
|
||||
}
|
||||
return badge;
|
||||
}
|
||||
},
|
||||
],
|
||||
paging: false,
|
||||
});
|
||||
},
|
||||
};
|
||||
DTable.activate();
|
||||
});
|
||||
</script>
|
||||
@ -46,6 +46,7 @@
|
||||
<th class="text-end">Type</th>
|
||||
<th class="text-center">Status</th>
|
||||
<th class="text-center">Installation</th>
|
||||
<th class="text-center">Vehicle</th>
|
||||
<th class="text-center">Availability</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -491,6 +492,13 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 'vhc_nopol1',
|
||||
className: 'text-left text-nowrap',
|
||||
visible: true,
|
||||
orderable: true,
|
||||
searchable: true,
|
||||
},
|
||||
{
|
||||
data: 'is_available',
|
||||
className: 'text-center text-nowrap',
|
||||
|
||||
390
resources/views/menu_v1/configs/distribution_category.blade.php
Normal file
390
resources/views/menu_v1/configs/distribution_category.blade.php
Normal file
@ -0,0 +1,390 @@
|
||||
@extends('app.app')
|
||||
|
||||
@section('title')
|
||||
Conf Distribution Categorys
|
||||
@endsection
|
||||
|
||||
@section('customcss')
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid">
|
||||
<div class="content">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="row d-flex align-items-center">
|
||||
<div class="col-3">
|
||||
<p class="card-title text-bold mb-0">Distribution Category</p>
|
||||
</div>
|
||||
@can('config_distribution_category.create')
|
||||
<div class="col text-end">
|
||||
<button id="btnMdlNew" class="btn btn-sm btn-danger">Add New Distribution Category</button>
|
||||
</div>
|
||||
@endcan
|
||||
|
||||
<div class="col-auto text-end ps-0">
|
||||
{{-- <button class="btn btn-sm btn-danger">Upload</button> --}}
|
||||
{{-- <button class="btn btn-sm btn-danger">Download</button> --}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table id="tList" class="table table-hover dataTable w-100">
|
||||
<thead>
|
||||
<tr class="">
|
||||
<th class="">#</th>
|
||||
<th class="text-center">Action</th>
|
||||
<th class="">Code</th>
|
||||
<th class="">Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" data-bs-backdrop="static" data-bs-keyboard="false" id="mdlNew" aria-labelledby="mdlLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog modal-dialog-centered modal-dialog-scrollable">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="mdlLabel">Add New Category</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="fNew">
|
||||
<!--input hidden -->
|
||||
<input type="hidden" name="tipe" id="tipe" value="new">
|
||||
<input type="hidden" name="id" id="id">
|
||||
<div class="mb-3">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<label for="dc_code" class="col-form-label">Code:</label>
|
||||
<input type="text" name="dc_code" id="dc_code" class="form-control" placeholder="Category code, example: VF, VO, etc">
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label for="dc_name" class="col-form-label">Name:</label>
|
||||
<input type="text" name="dc_name" id="dc_name" class="form-control" placeholder="Category name">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
@can('config_distribution_category.delete')
|
||||
<button type="button" id="btnDel" class="btn btn-sm btn-warning">Delete ?</button>
|
||||
@endcan
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
<button id="btnSubmit" type="button" class="btn btn-sm btn-danger">Submit data</button>
|
||||
@can('config_distribution_category.edit')
|
||||
<button id="btnEdit" type="button" class="btn btn-sm btn-danger">Update data</button>
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" data-bs-backdrop="static" data-bs-keyboard="false" id="mdlDel" aria-labelledby="mdlDelLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered modal-sm">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="mdlDelLabel">Delete TruckType</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="d-flex justify-content-center">
|
||||
<p class="mb-0">
|
||||
Are you sure want to delete this Distribution Category
|
||||
<a href="#" class="text-danger">
|
||||
<span id="del-type_name"></span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-sm btn-danger" data-bs-dismiss="modal">Close</button>
|
||||
<button id="btnSubmitDel" type="button" class="btn btn-sm btn-secondary">Yes, delete</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('customjs')
|
||||
<script src="{{ asset('assets/js/load-image.all.min.js') }}"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const State = {
|
||||
file_jimp_worker: "{{ asset('assets/js/worker/jimp.js') }}",
|
||||
storage_lara: "{{ asset('storage') }}/",
|
||||
delay_typing_front: 1000,
|
||||
};
|
||||
|
||||
const Wrapper = {
|
||||
activate: function() {
|
||||
Wrapper.event();
|
||||
DTable.activate();
|
||||
},
|
||||
event: function() {
|
||||
$('#btnMdlNew').on('click', function() {
|
||||
$('#fNew')[0].reset();
|
||||
$('#btnDel').hide();
|
||||
$('#btnEdit').hide();
|
||||
$('#btnSubmit').show();
|
||||
$('#mdlLabel').text('New Distribution Category');
|
||||
$('#dc_code').focus();
|
||||
|
||||
$('#mdlNew').modal('show');
|
||||
});
|
||||
|
||||
$('#btnSubmit, #btnEdit').on('click', function() {
|
||||
let data=$("#fNew").serialize()
|
||||
Wrapper.submitData(data);
|
||||
});
|
||||
|
||||
$('#tList').on('click', '.btnUpdt', function(e) {
|
||||
// console.log("updt klik");
|
||||
const id = $(this).data('id');
|
||||
$.ajax({
|
||||
url: "{{ route('api_conf_show_distribution_category', '') }}/" + id,
|
||||
method: 'GET',
|
||||
crossDomain: true,
|
||||
processData: true,
|
||||
headers: {
|
||||
'x-api-key': Helper.getCookie('_trtk'),
|
||||
},
|
||||
// data: params,
|
||||
success: (data, textStatus, jqXHR) => {
|
||||
console.log("res data", data);
|
||||
|
||||
if (data.meta.type != 'success') {
|
||||
resolve({
|
||||
type: 'fail'
|
||||
});
|
||||
Helper.toast('Warning', 'just now', data.meta.message);
|
||||
return false;
|
||||
}
|
||||
|
||||
// insert value
|
||||
$('#mdlLabel').text('Edit Distribution Category');
|
||||
$('#btnDel').show();
|
||||
$('#btnEdit').show();
|
||||
$('#btnSubmit').hide();
|
||||
|
||||
$('#tipe').val("edit");
|
||||
$('#id').val(id);
|
||||
$('#dc_code').val(data.data.dc_code);
|
||||
$('#dc_name').val(data.data.dc_name);
|
||||
},
|
||||
error: (jqXHR, textStatus, error) => {
|
||||
if (jqXHR.status >= 500) {
|
||||
Helper.toast('Error', 'just now', 'please try again');
|
||||
} else {
|
||||
Helper.toast('Error', 'just now', jqXHR.responseJSON.meta
|
||||
.message);
|
||||
}
|
||||
resolve({
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
$('#mdlNew').modal('show');
|
||||
});
|
||||
|
||||
$('#btnDel').on('click', function(e) {
|
||||
$('#mdlDel').modal('show');
|
||||
});
|
||||
|
||||
$('#btnSubmitDel').on('click', function(e) {
|
||||
const id = $('#id').val()
|
||||
const data = {
|
||||
id: $('#mdlDel').data('id'),
|
||||
};
|
||||
$('#btnSubmitDel').attr('disabed', true);
|
||||
$.ajax({
|
||||
url: "{{ route('api_conf_del_distribution_category', '') }}/" + id,
|
||||
method: 'DELETE',
|
||||
crossDomain: true,
|
||||
processData: true,
|
||||
headers: {
|
||||
'x-api-key': Helper.getCookie('_trtk'),
|
||||
'x-csrf-token': $('meta[name="csrf-token"]').attr('content'),
|
||||
},
|
||||
data: data,
|
||||
success: (data, textStatus, jqXHR) => {
|
||||
$('#btnSubmitDel').removeAttr('disabed');
|
||||
if (data.meta.type != 'success') {
|
||||
resolve({
|
||||
type: 'fail'
|
||||
});
|
||||
Helper.toast('Warning', 'just now', data.meta.message);
|
||||
return false;
|
||||
}
|
||||
Helper.toast('Success', 'just now', 'success delete Distribution Category');
|
||||
$('#mdlDel').modal('hide');
|
||||
$('#mdlNew').modal('hide');
|
||||
$('#tList').DataTable().ajax.reload();
|
||||
resolve({
|
||||
type: 'success'
|
||||
});
|
||||
},
|
||||
error: (jqXHR, textStatus, error) => {
|
||||
$('#btnSubmitDel').removeAttr('disabed');
|
||||
if (jqXHR.status >= 500) {
|
||||
Helper.toast('Error', 'just now', 'Please try again');
|
||||
} else {
|
||||
Helper.toast('Error', 'just now', jqXHR.responseJSON.meta
|
||||
.message);
|
||||
}
|
||||
resolve({
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
$('#mdlDel').on('show.bs.modal', function () {
|
||||
$('#mdlNew').css('opacity', '0.5'); // fade background modal
|
||||
});
|
||||
|
||||
$('#mdlDel').on('hidden.bs.modal', function () {
|
||||
$('#mdlNew').css('opacity', '1');
|
||||
});
|
||||
},
|
||||
submitData: async function(data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (typeof $('#btnSubmit').attr('disabed') != 'undefined') {
|
||||
resolve({
|
||||
type: 'fail'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
$('#btnSubmit').attr('disabed', true);
|
||||
$.ajax({
|
||||
url: "{{ route('api_conf_add_distribution_category') }}",
|
||||
method: 'POST',
|
||||
crossDomain: true,
|
||||
processData: true,
|
||||
headers: {
|
||||
'x-api-key': Helper.getCookie('_trtk'),
|
||||
'x-csrf-token': $('meta[name="csrf-token"]').attr('content'),
|
||||
},
|
||||
data: data,
|
||||
success: (data, textStatus, jqXHR) => {
|
||||
$('#btnSubmit').removeAttr('disabed');
|
||||
if (data.meta.type != 'success') {
|
||||
resolve({
|
||||
type: 'fail'
|
||||
});
|
||||
Helper.toast('Warning', 'just now', data.meta.message);
|
||||
return false;
|
||||
}
|
||||
Helper.toast('Success', 'just now', 'success add new Distribution Category');
|
||||
$('#mdlNew').modal('hide');
|
||||
$('#tList').DataTable().ajax.reload();
|
||||
resolve({
|
||||
type: 'success'
|
||||
});
|
||||
},
|
||||
error: (jqXHR, textStatus, error) => {
|
||||
$('#btnSubmit').removeAttr('disabed');
|
||||
if (jqXHR.status >= 500) {
|
||||
Helper.toast('Error', 'just now', 'Please try again');
|
||||
} else {
|
||||
Helper.toast('Error', 'just now', jqXHR.responseJSON.meta
|
||||
.message);
|
||||
}
|
||||
resolve({
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
};
|
||||
|
||||
const DTable = {
|
||||
activate: function() {
|
||||
DTable.reload();
|
||||
},
|
||||
reload: function() {
|
||||
// $('#tList').DataTable();
|
||||
// if (Driver.Table.firstInitDataTable == 1) { loadTableSkeletonLoading() } else { Driver.Table.firstInitDataTable = 1; }
|
||||
$('#tList').DataTable({
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
bLengthChange: true,
|
||||
deferRender: true,
|
||||
destroy: true,
|
||||
ajax: {
|
||||
url: "{{ route('api_conf_list_distribution_category') }}",
|
||||
type: 'GET',
|
||||
complete: function(jqXHR, textStatus, c) {
|
||||
let count = jqXHR.responseJSON.count;
|
||||
if (typeof count != 'undefined') {
|
||||
$('#count_trucktypes').text(count);
|
||||
}
|
||||
// removeTableSkeletonLoading()
|
||||
},
|
||||
},
|
||||
deferRender: true,
|
||||
columns: [{
|
||||
data: 'DT_RowIndex',
|
||||
className: 'text-end',
|
||||
visible: true,
|
||||
orderable: true,
|
||||
searchable: true,
|
||||
width: "30px"
|
||||
},
|
||||
{
|
||||
data: 'action',
|
||||
className: 'text-center',
|
||||
visible: true,
|
||||
orderable: true,
|
||||
searchable: true,
|
||||
width: "100px",
|
||||
render: function(data, type, row, meta) {
|
||||
let action = `
|
||||
<a href="#" class="text-decoration-none me-1 btnUpdt" data-id="${row.id}" title="Update" data-bs-toggle="tooltip" data-bs-placement="top">
|
||||
<span class="icon ion-eye fz-16"></span>
|
||||
</a>
|
||||
`;
|
||||
return action;
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 'dc_code',
|
||||
className: 'text-left text-nowrap',
|
||||
visible: true,
|
||||
orderable: true,
|
||||
searchable: true,
|
||||
createdCell: function(td, cellData, rowData, row, col) {
|
||||
$(td).attr('data-ttid', rowData.id);
|
||||
$(td).attr('data-type_name', rowData.type_name);
|
||||
},
|
||||
},
|
||||
{
|
||||
data: 'dc_name',
|
||||
className: 'text-left',
|
||||
visible: true,
|
||||
orderable: true,
|
||||
searchable: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Wrapper.activate();
|
||||
</script>
|
||||
@endsection
|
||||
390
resources/views/menu_v1/configs/pool.blade.php
Normal file
390
resources/views/menu_v1/configs/pool.blade.php
Normal file
@ -0,0 +1,390 @@
|
||||
@extends('app.app')
|
||||
|
||||
@section('title')
|
||||
Conf Pools
|
||||
@endsection
|
||||
|
||||
@section('customcss')
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid">
|
||||
<div class="content">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="row d-flex align-items-center">
|
||||
<div class="col-3">
|
||||
<p class="card-title text-bold mb-0">Pool / Area</p>
|
||||
</div>
|
||||
@can('config_pool.create')
|
||||
<div class="col text-end">
|
||||
<button id="btnMdlNew" class="btn btn-sm btn-danger">Add New Pool</button>
|
||||
</div>
|
||||
@endcan
|
||||
|
||||
<div class="col-auto text-end ps-0">
|
||||
{{-- <button class="btn btn-sm btn-danger">Upload</button> --}}
|
||||
{{-- <button class="btn btn-sm btn-danger">Download</button> --}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table id="tList" class="table table-hover dataTable w-100">
|
||||
<thead>
|
||||
<tr class="">
|
||||
<th class="">#</th>
|
||||
<th class="text-center">Action</th>
|
||||
<th class="">Code</th>
|
||||
<th class="">Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" data-bs-backdrop="static" data-bs-keyboard="false" id="mdlNew" aria-labelledby="mdlLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog modal-dialog-centered modal-dialog-scrollable">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="mdlLabel">Add New Pool</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="fNew">
|
||||
<!--input hidden -->
|
||||
<input type="hidden" name="tipe" id="tipe" value="new">
|
||||
<input type="hidden" name="id" id="id">
|
||||
<div class="mb-3">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<label for="pool_code" class="col-form-label">Code:</label>
|
||||
<input type="text" name="pool_code" id="pool_code" class="form-control" placeholder="Pool code, example: VF, VO, etc">
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label for="pool_name" class="col-form-label">Name:</label>
|
||||
<input type="text" name="pool_name" id="pool_name" class="form-control" placeholder="Pool name">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
@can('config_pool.delete')
|
||||
<button type="button" id="btnDel" class="btn btn-sm btn-warning">Delete ?</button>
|
||||
@endcan
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
<button id="btnSubmit" type="button" class="btn btn-sm btn-danger">Submit data</button>
|
||||
@can('config_pool.edit')
|
||||
<button id="btnEdit" type="button" class="btn btn-sm btn-danger">Update data</button>
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" data-bs-backdrop="static" data-bs-keyboard="false" id="mdlDel" aria-labelledby="mdlDelLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered modal-sm">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="mdlDelLabel">Delete TruckType</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="d-flex justify-content-center">
|
||||
<p class="mb-0">
|
||||
Are you sure want to delete this Pool
|
||||
<a href="#" class="text-danger">
|
||||
<span id="del-type_name"></span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-sm btn-danger" data-bs-dismiss="modal">Close</button>
|
||||
<button id="btnSubmitDel" type="button" class="btn btn-sm btn-secondary">Yes, delete</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('customjs')
|
||||
<script src="{{ asset('assets/js/load-image.all.min.js') }}"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const State = {
|
||||
file_jimp_worker: "{{ asset('assets/js/worker/jimp.js') }}",
|
||||
storage_lara: "{{ asset('storage') }}/",
|
||||
delay_typing_front: 1000,
|
||||
};
|
||||
|
||||
const Wrapper = {
|
||||
activate: function() {
|
||||
Wrapper.event();
|
||||
DTable.activate();
|
||||
},
|
||||
event: function() {
|
||||
$('#btnMdlNew').on('click', function() {
|
||||
$('#fNew')[0].reset();
|
||||
$('#btnDel').hide();
|
||||
$('#btnEdit').hide();
|
||||
$('#btnSubmit').show();
|
||||
$('#mdlLabel').text('New Pool');
|
||||
$('#pool_code').focus();
|
||||
|
||||
$('#mdlNew').modal('show');
|
||||
});
|
||||
|
||||
$('#btnSubmit, #btnEdit').on('click', function() {
|
||||
let data=$("#fNew").serialize()
|
||||
Wrapper.submitData(data);
|
||||
});
|
||||
|
||||
$('#tList').on('click', '.btnUpdt', function(e) {
|
||||
// console.log("updt klik");
|
||||
const id = $(this).data('id');
|
||||
$.ajax({
|
||||
url: "{{ route('api_conf_show_pool', '') }}/" + id,
|
||||
method: 'GET',
|
||||
crossDomain: true,
|
||||
processData: true,
|
||||
headers: {
|
||||
'x-api-key': Helper.getCookie('_trtk'),
|
||||
},
|
||||
// data: params,
|
||||
success: (data, textStatus, jqXHR) => {
|
||||
console.log("res data", data);
|
||||
|
||||
if (data.meta.type != 'success') {
|
||||
resolve({
|
||||
type: 'fail'
|
||||
});
|
||||
Helper.toast('Warning', 'just now', data.meta.message);
|
||||
return false;
|
||||
}
|
||||
|
||||
// insert value
|
||||
$('#mdlLabel').text('Edit Pool');
|
||||
$('#btnDel').show();
|
||||
$('#btnEdit').show();
|
||||
$('#btnSubmit').hide();
|
||||
|
||||
$('#tipe').val("edit");
|
||||
$('#id').val(id);
|
||||
$('#pool_code').val(data.data.pool_code);
|
||||
$('#pool_name').val(data.data.pool_name);
|
||||
},
|
||||
error: (jqXHR, textStatus, error) => {
|
||||
if (jqXHR.status >= 500) {
|
||||
Helper.toast('Error', 'just now', 'please try again');
|
||||
} else {
|
||||
Helper.toast('Error', 'just now', jqXHR.responseJSON.meta
|
||||
.message);
|
||||
}
|
||||
resolve({
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
$('#mdlNew').modal('show');
|
||||
});
|
||||
|
||||
$('#btnDel').on('click', function(e) {
|
||||
$('#mdlDel').modal('show');
|
||||
});
|
||||
|
||||
$('#btnSubmitDel').on('click', function(e) {
|
||||
const id = $('#id').val()
|
||||
const data = {
|
||||
id: $('#mdlDel').data('id'),
|
||||
};
|
||||
$('#btnSubmitDel').attr('disabed', true);
|
||||
$.ajax({
|
||||
url: "{{ route('api_conf_del_pool', '') }}/" + id,
|
||||
method: 'DELETE',
|
||||
crossDomain: true,
|
||||
processData: true,
|
||||
headers: {
|
||||
'x-api-key': Helper.getCookie('_trtk'),
|
||||
'x-csrf-token': $('meta[name="csrf-token"]').attr('content'),
|
||||
},
|
||||
data: data,
|
||||
success: (data, textStatus, jqXHR) => {
|
||||
$('#btnSubmitDel').removeAttr('disabed');
|
||||
if (data.meta.type != 'success') {
|
||||
resolve({
|
||||
type: 'fail'
|
||||
});
|
||||
Helper.toast('Warning', 'just now', data.meta.message);
|
||||
return false;
|
||||
}
|
||||
Helper.toast('Success', 'just now', 'success delete Pool');
|
||||
$('#mdlDel').modal('hide');
|
||||
$('#mdlNew').modal('hide');
|
||||
$('#tList').DataTable().ajax.reload();
|
||||
resolve({
|
||||
type: 'success'
|
||||
});
|
||||
},
|
||||
error: (jqXHR, textStatus, error) => {
|
||||
$('#btnSubmitDel').removeAttr('disabed');
|
||||
if (jqXHR.status >= 500) {
|
||||
Helper.toast('Error', 'just now', 'Please try again');
|
||||
} else {
|
||||
Helper.toast('Error', 'just now', jqXHR.responseJSON.meta
|
||||
.message);
|
||||
}
|
||||
resolve({
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
$('#mdlDel').on('show.bs.modal', function () {
|
||||
$('#mdlNew').css('opacity', '0.5'); // fade background modal
|
||||
});
|
||||
|
||||
$('#mdlDel').on('hidden.bs.modal', function () {
|
||||
$('#mdlNew').css('opacity', '1');
|
||||
});
|
||||
},
|
||||
submitData: async function(data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (typeof $('#btnSubmit').attr('disabed') != 'undefined') {
|
||||
resolve({
|
||||
type: 'fail'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
$('#btnSubmit').attr('disabed', true);
|
||||
$.ajax({
|
||||
url: "{{ route('api_conf_add_pool') }}",
|
||||
method: 'POST',
|
||||
crossDomain: true,
|
||||
processData: true,
|
||||
headers: {
|
||||
'x-api-key': Helper.getCookie('_trtk'),
|
||||
'x-csrf-token': $('meta[name="csrf-token"]').attr('content'),
|
||||
},
|
||||
data: data,
|
||||
success: (data, textStatus, jqXHR) => {
|
||||
$('#btnSubmit').removeAttr('disabed');
|
||||
if (data.meta.type != 'success') {
|
||||
resolve({
|
||||
type: 'fail'
|
||||
});
|
||||
Helper.toast('Warning', 'just now', data.meta.message);
|
||||
return false;
|
||||
}
|
||||
Helper.toast('Success', 'just now', 'success add new Pool');
|
||||
$('#mdlNew').modal('hide');
|
||||
$('#tList').DataTable().ajax.reload();
|
||||
resolve({
|
||||
type: 'success'
|
||||
});
|
||||
},
|
||||
error: (jqXHR, textStatus, error) => {
|
||||
$('#btnSubmit').removeAttr('disabed');
|
||||
if (jqXHR.status >= 500) {
|
||||
Helper.toast('Error', 'just now', 'Please try again');
|
||||
} else {
|
||||
Helper.toast('Error', 'just now', jqXHR.responseJSON.meta
|
||||
.message);
|
||||
}
|
||||
resolve({
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
};
|
||||
|
||||
const DTable = {
|
||||
activate: function() {
|
||||
DTable.reload();
|
||||
},
|
||||
reload: function() {
|
||||
// $('#tList').DataTable();
|
||||
// if (Driver.Table.firstInitDataTable == 1) { loadTableSkeletonLoading() } else { Driver.Table.firstInitDataTable = 1; }
|
||||
$('#tList').DataTable({
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
bLengthChange: true,
|
||||
deferRender: true,
|
||||
destroy: true,
|
||||
ajax: {
|
||||
url: "{{ route('api_conf_list_pool') }}",
|
||||
type: 'GET',
|
||||
complete: function(jqXHR, textStatus, c) {
|
||||
let count = jqXHR.responseJSON.count;
|
||||
if (typeof count != 'undefined') {
|
||||
$('#count_trucktypes').text(count);
|
||||
}
|
||||
// removeTableSkeletonLoading()
|
||||
},
|
||||
},
|
||||
deferRender: true,
|
||||
columns: [{
|
||||
data: 'DT_RowIndex',
|
||||
className: 'text-end',
|
||||
visible: true,
|
||||
orderable: true,
|
||||
searchable: true,
|
||||
width: "30px"
|
||||
},
|
||||
{
|
||||
data: 'action',
|
||||
className: 'text-center',
|
||||
visible: true,
|
||||
orderable: true,
|
||||
searchable: true,
|
||||
width: "100px",
|
||||
render: function(data, type, row, meta) {
|
||||
let action = `
|
||||
<a href="#" class="text-decoration-none me-1 btnUpdt" data-id="${row.id}" title="Update" data-bs-toggle="tooltip" data-bs-placement="top">
|
||||
<span class="icon ion-eye fz-16"></span>
|
||||
</a>
|
||||
`;
|
||||
return action;
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 'pool_code',
|
||||
className: 'text-left text-nowrap',
|
||||
visible: true,
|
||||
orderable: true,
|
||||
searchable: true,
|
||||
createdCell: function(td, cellData, rowData, row, col) {
|
||||
$(td).attr('data-ttid', rowData.id);
|
||||
$(td).attr('data-type_name', rowData.type_name);
|
||||
},
|
||||
},
|
||||
{
|
||||
data: 'pool_name',
|
||||
className: 'text-left',
|
||||
visible: true,
|
||||
orderable: true,
|
||||
searchable: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Wrapper.activate();
|
||||
</script>
|
||||
@endsection
|
||||
3541
resources/views/menu_v1/dashboard.blade copy.php
Normal file
3541
resources/views/menu_v1/dashboard.blade copy.php
Normal file
File diff suppressed because it is too large
Load Diff
@ -21,6 +21,10 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.leaflet-routing-container {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#openLeftSideBar1Mobile {
|
||||
display: none;
|
||||
}
|
||||
@ -268,6 +272,7 @@
|
||||
<p class="text-bold mb-0">Engine Status</p>
|
||||
<p id="infoVehicles-engineStatus" class="text-muted mb-0">Idling</p>
|
||||
</li>
|
||||
|
||||
{{-- <li class="list-group-item p-1 px-2">
|
||||
<p class="text-bold mb-0">Durasi Berhenti (<span id="infoVehicles-idlingUnit">min</span>)</p>
|
||||
<p id="infoVehicles-idlingDuration" class="text-muted mb-0">2946</p>
|
||||
@ -402,12 +407,15 @@
|
||||
<div>
|
||||
<div class="mb-2">
|
||||
<label class="text-muted">From</label>
|
||||
<input class="form-control" type="date" id="historyStartDate">
|
||||
<input class="form-control" id="historyStartDate">
|
||||
<!-- <input class="form-control" id="historyStartDate" value="11-08-2025 00:00"> -->
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="mb-2">
|
||||
<label class="text-muted">To</label>
|
||||
<input class="form-control" type="date" id="historyEndDate">
|
||||
<input class="form-control" id="historyEndDate">
|
||||
<!-- <input class="form-control" id="historyEndDate" value="11-08-2025 23:00"> -->
|
||||
</div>
|
||||
<button class="btn btn-primary btn-sm w-100 mb-3" id="historySearch">Search</button>
|
||||
</div>
|
||||
<div id="infoMove-plots" class="infoMove-plots">
|
||||
{{-- <a href="#" class="plotMove-item">
|
||||
@ -434,6 +442,11 @@
|
||||
<span id="c_vhc_zone">-</span>
|
||||
</div>
|
||||
<div class="col-auto text-start align-items-center d-flex">
|
||||
<a href="javascript:void(0);" class="mb-0 text-bold text-dark me-2" id="filterVhcMarker" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Marker Info">
|
||||
<span class="ion-android-pin me-2 text-muted" style="font-size: 17px"></span>
|
||||
</a>
|
||||
</div>
|
||||
{{-- <div class="col-auto text-start align-items-center d-flex">
|
||||
<a href="javascript:void(0);" class="mb-0 text-bold text-dark" id="filterVhcGps" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Vehicle GPS Filter">
|
||||
<span class="ion-pinpoint me-1 text-muted" style="font-size: 17px"></span>
|
||||
</a>
|
||||
@ -444,15 +457,15 @@
|
||||
<span class="ion-android-wifi me-1 text-muted" style="font-size: 17px"></span>
|
||||
</a>
|
||||
<span id="c_vhc_gsm">-</span>
|
||||
</div>
|
||||
</div> --}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="">
|
||||
<div class="col text-end align-items-center d-flex">
|
||||
<a href="javascript:void(0);" class="mb-0 text-bold text-dark me-2" id="filterVhcMarker" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Marker Info">
|
||||
{{-- <a href="javascript:void(0);" class="mb-0 text-bold text-dark me-2" id="filterVhcMarker" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Marker Info">
|
||||
<span class="ion-android-pin me-2 text-muted" style="font-size: 17px"></span>
|
||||
</a>
|
||||
</a> --}}
|
||||
<a href="javascript:void(0);" class="text-decoration-none text-dark fz-18" id="closeRightSideBar1">
|
||||
<span class="icon ion-ios-arrow-right"></span>
|
||||
</a>
|
||||
@ -504,6 +517,13 @@
|
||||
<span class="badge p-1 ps-3 pe-3 bg-danger me-2">Stopped</span>
|
||||
<span class="badge p-1 ps-3 pe-3 bg-warning me-2">Idling</span>
|
||||
<span class="badge p-1 ps-3 pe-3 bg-success">Moving</span>
|
||||
</div>
|
||||
<div class="col text-end" id="tripInfo">
|
||||
<span class="badge p-1 ps-3 pe-3 bg-info me-2" style="background-color:#C0392B !important;">Trip 1</span>
|
||||
<span class="badge p-1 ps-3 pe-3 bg-info me-2" style="background-color:#2980B9 !important;">Trip 2</span>
|
||||
<span class="badge p-1 ps-3 pe-3 bg-info me-2" style="background-color:#27AE60 !important;">Trip 3</span>
|
||||
<span class="badge p-1 ps-3 pe-3 bg-info me-2" style="background-color:#D35400 !important;">Trip 4</span>
|
||||
<span class="badge p-1 ps-3 pe-3 bg-info me-2" style="background-color:#F39C12 !important;">Trip 5</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -514,9 +534,12 @@
|
||||
<script src="{{ asset('assets/vendor/leaflet-1.7.1/leaflet-src.js') }}"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js" integrity="sha512-ozq8xQKq6urvuU6jNgkfqAmT7jKN2XumbrX1JiB3TnF7tI48DPI4Gy1GXKD/V3EExgAs1V+pRO7vwtS1LHg0Gw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/leaflet-rotatedmarker@0.2.0/leaflet.rotatedMarker.min.js"></script>
|
||||
{{-- <script src="https://unpkg.com/leaflet-routing-machine@3.2.12/dist/leaflet-routing-machine.js"></script> --}}
|
||||
<script src="https://unpkg.com/leaflet-routing-machine@3.2.12/dist/leaflet-routing-machine.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
||||
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
const State = {
|
||||
isDrawPolygon: 0,
|
||||
timingRouteAnimation: 100,
|
||||
@ -732,6 +755,13 @@
|
||||
$('#rightSideBar1').addClass('d-none');
|
||||
$('#openRightSideBar1').removeClass('d-none');
|
||||
}
|
||||
|
||||
$('#historyStartDate, #historyEndDate').datetimepicker({
|
||||
format:'d-m-Y H:i',
|
||||
defaultTime:'00:00',
|
||||
closeOnDateSelect: true,
|
||||
// mask:true
|
||||
});
|
||||
},
|
||||
calcIdlingDur: function(lst_idle_unix, lst_speed) {
|
||||
let now = moment();
|
||||
@ -755,19 +785,19 @@
|
||||
};
|
||||
},
|
||||
calcPeriodeDate: function(startDate, endDate) {
|
||||
if (startDate.format('YYYY-MM-DD') === 'Invalid date') {
|
||||
if (startDate.format('YYYY-MM-DD HH:mm') === 'Invalid date') {
|
||||
Helper.toast('Warning', 'just now', 'Start date of the period is not valid');
|
||||
return {
|
||||
isValid: false
|
||||
};
|
||||
}
|
||||
if (endDate.format('YYYY-MM-DD') === 'Invalid date') {
|
||||
if (endDate.format('YYYY-MM-DD HH:mm') === 'Invalid date') {
|
||||
Helper.toast('Warning', 'just now', 'End date of the period is not valid');
|
||||
return {
|
||||
isValid: false
|
||||
};
|
||||
}
|
||||
endDate.add(23, 'hour').add(59, 'minutes').add(59, 'seconds');
|
||||
// endDate.add(23, 'hour').add(59, 'minutes').add(59, 'seconds');
|
||||
const duration = moment.duration(endDate.diff(startDate));
|
||||
const diffDays = duration.days();
|
||||
if (diffDays > 30) {
|
||||
@ -809,7 +839,7 @@
|
||||
// Leaflet.map = L.map('map').setView([-7.1451449, 109.9776078], 8); // centering javanese province
|
||||
// Leaflet.map = L.map('map').setView([-7.8241413, 112.9071746], 9); // centering east java province
|
||||
// Leaflet.map = L.map('map').setView([-6.2106272, 106.8477106], 9); // centering east java province
|
||||
Leaflet.map = L.map('map').setView([-8.90507, 125.9945732], 10); // centering east java province
|
||||
Leaflet.map = L.map('map').setView([-8.90507, 125.9945732], 10); // centering timor leste
|
||||
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
|
||||
attribution: 'Map data © <a href="https://www.mapbox.com/feedback/">Mapbox</a> © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
|
||||
// maxZoom: 20,
|
||||
@ -882,6 +912,11 @@
|
||||
if (locs.constructor === Array) {
|
||||
let circles = [];
|
||||
for (let i = 0; i < locs.length; i++) {
|
||||
// invisible circle
|
||||
if(locs[i].options?.markerOpacity == 0){
|
||||
locs[i].options.opacity = 0
|
||||
locs[i].options.fill = false
|
||||
}
|
||||
let circle = L.circle([locs[i].lat, locs[i].lng], locs[i]?.options);
|
||||
circle.bindPopup(locs[i]?.label || '');
|
||||
circle.bindTooltip(locs[i]?.label || '');
|
||||
@ -909,6 +944,120 @@
|
||||
if (cb) cb(polyline);
|
||||
return polyline;
|
||||
},
|
||||
addRoutes: async function(locs = [], cb = null) {
|
||||
let latLngs = [];
|
||||
for (let i = 0; i < locs.length; i++) {
|
||||
latLngs.push([locs[i].lat, locs[i].lng]);
|
||||
}
|
||||
|
||||
function chunkArray(arr, size) {
|
||||
const result = [];
|
||||
for (let i = 0; i < arr.length; i += size) {
|
||||
result.push(arr.slice(i, i + size));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function fetchOsrm(points) {
|
||||
const coords = points;
|
||||
const hints = ";".repeat(points.length - 1);
|
||||
|
||||
const body = {
|
||||
coordinates: coords,
|
||||
overview: "false",
|
||||
alternatives: "true",
|
||||
steps: "true",
|
||||
hints: hints
|
||||
};
|
||||
|
||||
let config = {
|
||||
method: 'post',
|
||||
maxBodyLength: Infinity,
|
||||
url: 'https://brilianapps.britimorleste.tl/osrm-backend/post-route/v1/driving/',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: body
|
||||
};
|
||||
|
||||
return axios.request(config)
|
||||
.then((response) => {
|
||||
return response.data;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Error:", err.message);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
function decodeOSRMGeometry(encoded) {
|
||||
const coordinates = [];
|
||||
let index = 0, lat = 0, lng = 0;
|
||||
|
||||
while (index < encoded.length) {
|
||||
let result = 1, shift = 0, b;
|
||||
do {
|
||||
b = encoded.charCodeAt(index++) - 63 - 1;
|
||||
result += b << shift;
|
||||
shift += 5;
|
||||
} while (b >= 0x1f);
|
||||
lat += (result & 1 ? ~(result >> 1) : result >> 1);
|
||||
|
||||
result = 1;
|
||||
shift = 0;
|
||||
do {
|
||||
b = encoded.charCodeAt(index++) - 63 - 1;
|
||||
result += b << shift;
|
||||
shift += 5;
|
||||
} while (b >= 0x1f);
|
||||
lng += (result & 1 ? ~(result >> 1) : result >> 1);
|
||||
|
||||
coordinates.push([lat / 1e5, lng / 1e5]);
|
||||
}
|
||||
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
async function getCoordinates(points) {
|
||||
const chunkSize = 500;
|
||||
const chunks = chunkArray(points, chunkSize); // Split the points array into chunks of 500
|
||||
let allCoords = [];
|
||||
|
||||
for (const chunk of chunks) {
|
||||
const osrm = await fetchOsrm(chunk); // Fetch OSRM data for each chunk
|
||||
|
||||
if (!osrm) {
|
||||
console.log("OSRM failed for chunk");
|
||||
return;
|
||||
}
|
||||
|
||||
const coords = osrm.routes[0].legs.flatMap(leg =>
|
||||
leg.steps.flatMap(step =>
|
||||
decodeOSRMGeometry(step.geometry)
|
||||
)
|
||||
);
|
||||
|
||||
allCoords = allCoords.concat(coords); // Combine the result
|
||||
}
|
||||
|
||||
// Now add the polyline to the map
|
||||
return L.polyline(allCoords, {
|
||||
color: locs[0]?.options?.color,
|
||||
weight: 3,
|
||||
opacity: 0.8
|
||||
}).addTo(Leaflet.map);
|
||||
// map.fitBounds(allCoords.map(c => L.latLng(c[0], c[1])));
|
||||
}
|
||||
|
||||
// Usage: Pass the array of coordinates to the function
|
||||
const routes = await getCoordinates(latLngs);
|
||||
|
||||
// optionally fit bounds
|
||||
// Leaflet.map.fitBounds(coords.map(c => L.latLng(c[0], c[1])));
|
||||
|
||||
if (cb) cb(routes);
|
||||
return routes;
|
||||
},
|
||||
// start custom polylines
|
||||
addCustomPolylines: function(locs = [], cb = null) {
|
||||
const radius = 0.5 /* corner smooth radius, keep value in range 0 - 0.5 to avoid artifacts */
|
||||
@ -1072,6 +1221,7 @@
|
||||
if (cb) cb();
|
||||
}
|
||||
} else if (type == 'eventRemoveRouteStartEnd') {
|
||||
// console.log('clear route eventRemoveRouteStartEnd');
|
||||
if (State.eventRemoveRouteStartEnd) {
|
||||
window.dispatchEvent(State.eventRemoveRouteStartEnd);
|
||||
if (cb) cb();
|
||||
@ -1246,14 +1396,15 @@
|
||||
$('#infoMovement').addClass('d-none');
|
||||
} else if (type == State.stts_filterDetail.lastMove) { // last movement
|
||||
$('#infoVehicles').addClass('d-none');
|
||||
$('#infoDriver').addClass('d-none');
|
||||
// $('#infoDriver').addClass('d-none');
|
||||
$('#infoJob').addClass('d-none');
|
||||
$('#infoMovement').removeClass('d-none');
|
||||
$('#infoMovement').addClass('d-block');
|
||||
if (State.inShowVid) {
|
||||
let cache = !(State.inShowVid != State.loadedLastMoveVid);
|
||||
Trucks.bundleShowRouteTruck(cache); // jika data yang diload sebelumnya beda, maka tidak mengambil dari cache
|
||||
Trucks.bundleShowRouteTruck(cache, false); // jika data yang diload sebelumnya beda, maka tidak mengambil dari cache
|
||||
}
|
||||
// Menu.clearListMovements();
|
||||
}
|
||||
},
|
||||
eventListVehicle: function() {
|
||||
@ -1296,48 +1447,14 @@
|
||||
});
|
||||
},
|
||||
showToListMovement: function(obj) {
|
||||
/**
|
||||
* fix DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains
|
||||
* because of string Cawang–Pluit
|
||||
* solution: https://stackoverflow.com/questions/23223718/failed-to-execute-btoa-on-window-the-string-to-be-encoded-contains-characte
|
||||
* window.btoa( unescape(encodeURIComponent(str) ) is deprecated => window.btoa(encodeURIComponent(str))
|
||||
*/
|
||||
// <p class="text-muted mb-0">${(obj?.city_text || obj?.state_text || 'address')} - ${(obj?.postcode || 'postcode')}</p>
|
||||
// <p class="text-muted mb-0">${moment.unix(obj?.lst_loc_crt).format('DD MMM YYYY HH:mm')}</p> // yang ini mix
|
||||
|
||||
// <p class="text-success mb-0">Device Time: ${moment.unix(obj?.lst_loc_crt_d).format('DD MMM YYYY HH:mm')}</p>
|
||||
// <p class="text-danger mb-0">Server Time: ${moment.unix(obj?.lst_loc_crt_s).format('DD MMM YYYY HH:mm')}</p>
|
||||
// <p class="${(obj.pre_milleage >= 3) ? 'text-warning' : 'text-muted'} mb-0">Pre Milleage: ${(obj.pre_milleage).toFixed(3)} Km</p>
|
||||
|
||||
// $('#infoMove-plots').append(`
|
||||
// <a href="#" class="plotMove-item" data-obj="${window.btoa( encodeURIComponent( JSON.stringify(obj) ) )}">
|
||||
// <li class="list-group-item p-1 px-2">
|
||||
// <p class="text-bold mb-0">${obj.key_index}</p>
|
||||
// <p class="text-bold mb-0">Time: ${moment.unix(obj?.lst_loc_crt_d).format('DD MMM YYYY HH:mm')}</p>
|
||||
// <p class="text-muted mb-0">Speed: ${(typeof obj.speed != 'undefined') ? obj.speed : '0'}</p>
|
||||
// <p class="text-muted mb-0">${Number(obj.latitude).toFixed(5)} - ${Number(obj.longitude).toFixed(6)}</p>
|
||||
// <p class="text-muted mb-0">${Helper.shortenText(decodeURIComponent(obj?.fulladdress || 'address'), 25)}</p>
|
||||
// </li>
|
||||
// </a>
|
||||
// `);
|
||||
let arrIdx = Helper.getIndexReversedSequence(obj.key_index - 1, Trucks.last_move.length - 1);
|
||||
// +7
|
||||
// $('#infoMove-plots').append(`
|
||||
// <a href="#" class="plotMove-item" data-obj="${window.btoa( encodeURIComponent( JSON.stringify(obj) ) )}">
|
||||
// <li class="list-group-item p-1 px-2">
|
||||
// <p class="text-bold mb-0">${arrIdx + 1}</p>
|
||||
// <p class="text-bold mb-0">Time: ${moment.unix(obj?.lst_loc_crt_d).format('DD MMM YYYY HH:mm:ss')}</p>
|
||||
// <p class="text-muted mb-0">${Number(obj.latitude).toFixed(5)} - ${Number(obj.longitude).toFixed(6)}</p>
|
||||
// <p class="text-muted mb-2">${Helper.shortenText(decodeURIComponent(obj?.fulladdress || 'address'), 255)}</p>
|
||||
// <p class="mb-0">Current speed: ${Number(obj.speed)}km/h</p>
|
||||
// </li>
|
||||
// </a>
|
||||
// `);
|
||||
const unix = parseInt(obj?.lst_loc_crt_d) + AppState.TIMEFIX;
|
||||
|
||||
$('#infoMove-plots').append(`
|
||||
<a href="#" class="plotMove-item" data-obj="${window.btoa( encodeURIComponent( JSON.stringify(obj) ) )}">
|
||||
<li class="list-group-item p-1 px-2">
|
||||
<p class="text-bold mb-0">${arrIdx + 1}</p>
|
||||
<p class="text-bold mb-0">Time: ${moment.unix(obj?.lst_loc_crt_d).format('DD MMM YYYY HH:mm:ss')}</p>
|
||||
<p class="text-bold mb-0">Time: ${moment.unix(unix).format('DD MMM YYYY HH:mm:ss')}</p>
|
||||
<p class="text-muted mb-0">${Number(obj.latitude).toFixed(5)} - ${Number(obj.longitude).toFixed(6)}</p>
|
||||
<p class="text-muted mb-2">${Helper.shortenText(decodeURIComponent(obj?.fulladdress || 'address'), 255)}</p>
|
||||
<p class="mb-0">Current speed: ${Number(obj.speed)}km/h</p>
|
||||
@ -1348,18 +1465,23 @@
|
||||
eventListMovement: function() {
|
||||
$('#infoMove-plots').on('click', '.plotMove-item', function(e) {
|
||||
let tr = JSON.parse(decodeURIComponent(window.atob($(e.target).closest('.plotMove-item').data('obj'))));
|
||||
// console.log("tr", tr);
|
||||
|
||||
let arrIdx = Helper.getIndexReversedSequence(tr.key_index - 1, Trucks.last_move.length - 1);
|
||||
// console.log("arrIdx", arrIdx);
|
||||
|
||||
PgBar.setCrntVal(arrIdx);
|
||||
Menu.createMarkerDetailPlotMovement(tr);
|
||||
})
|
||||
},
|
||||
createMarkerDetailPlotMovement: function(tr, opt = {}) {
|
||||
Leaflet.clearLayer('eventRemoveDetailPlotMovement');
|
||||
const unix = parseInt(tr?.lst_loc_crt_d) + AppState.TIMEFIX;
|
||||
let marker = Leaflet.addMarkers({
|
||||
lat: tr.latitude,
|
||||
lng: tr.longitude,
|
||||
// label: `<b>${tr.key_index}</b><br>${tr.nopol1} ${tr.nopol2} ${tr.nopol3}<br>${moment.unix(tr?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>Speed: ${(typeof tr.lst_speed != 'undefined') ? tr.lst_speed : '0'}<br>${tr.latitude},${tr.longitude}<br>${decodeURIComponent(tr?.fulladdress || 'address')}`,
|
||||
label: `<b>${tr.nopol1} ${tr.nopol2} ${tr.nopol3}</b><br>${moment.unix(tr?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>${decodeURIComponent(tr?.fulladdress || 'address')}.<br><br>Current speed: ${tr?.speed}km/h`,
|
||||
label: `<b>${tr.nopol1} ${tr.nopol2} ${tr.nopol3}</b><br>${moment.unix(unix).format('DD MMM YYYY HH:mm')}<br>${decodeURIComponent(tr?.fulladdress || 'address')}.<br><br>Current speed: ${tr?.speed}km/h`,
|
||||
//label: `<b>${tr.nopol1} ${tr.nopol2} ${tr.nopol3}</b><br>${moment.unix(tr?.lst_loc_crt_d).utcOffset(9 * 60).format('DD MMM YYYY HH:mm:ss')}<br>${decodeURIComponent(tr?.fulladdress || 'address')}.<br><br>Current speed: ${tr?.speed}km/h`,
|
||||
options: {
|
||||
// icon: Icon.destination()
|
||||
@ -1452,36 +1574,57 @@
|
||||
});
|
||||
},
|
||||
eventFilterHistoryDate: function() {
|
||||
$('#historyStartDate').on('change', function(e) {
|
||||
$('#historySearch').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
// console.log("change history date", this.id, this.value);
|
||||
const value = this.value;
|
||||
const id = this.id;
|
||||
if(State[id] == moment(value, "DD-MM-YYYY HH:mm").unix())
|
||||
return false;
|
||||
|
||||
const date0 = moment($('#historyStartDate').val(), "DD-MM-YYYY HH:mm")
|
||||
const date1 = moment($('#historyEndDate').val(), "DD-MM-YYYY HH:mm")
|
||||
const {
|
||||
isValid,
|
||||
data
|
||||
} = Wrapper.calcPeriodeDate(moment($('#historyStartDate').val()), moment($('#historyEndDate').val()))
|
||||
} = Wrapper.calcPeriodeDate(
|
||||
date0,
|
||||
date1
|
||||
)
|
||||
if (!isValid) return false;
|
||||
State.historyStartDate = data.startDate.unix();
|
||||
State.historyEndDate = data.endDate.unix();
|
||||
// console.log("isValid", isValid, data);
|
||||
|
||||
State.historyStartDate = date0.unix();
|
||||
State.historyEndDate = date1.unix();
|
||||
|
||||
Leaflet.clearLayer('eventRemoveRouteStartEnd');
|
||||
Trucks.bundleShowRouteTruck(false);
|
||||
});
|
||||
$('#historyEndDate').on('change', function(e) {
|
||||
const {
|
||||
isValid,
|
||||
data
|
||||
} = Wrapper.calcPeriodeDate(moment($('#historyStartDate').val()), moment($('#historyEndDate').val()))
|
||||
if (!isValid) return false;
|
||||
State.historyStartDate = data.startDate.unix();
|
||||
State.historyEndDate = data.endDate.unix();
|
||||
// $('#historyEndDate').on('change', function(e) {
|
||||
// const {
|
||||
// isValid,
|
||||
// data
|
||||
// } = Wrapper.calcPeriodeDate(moment($('#historyStartDate').val()), moment($('#historyEndDate').val()))
|
||||
// if (!isValid) return false;
|
||||
// State.historyStartDate = data.startDate.unix();
|
||||
// State.historyEndDate = data.endDate.unix();
|
||||
|
||||
Leaflet.clearLayer('eventRemoveRouteStartEnd');
|
||||
Trucks.bundleShowRouteTruck(false);
|
||||
});
|
||||
// Leaflet.clearLayer('eventRemoveRouteStartEnd');
|
||||
// Trucks.bundleShowRouteTruck(false);
|
||||
// });
|
||||
$('#historyStartDate').on('clearFilterHistoryDate', function(e) {
|
||||
State.historyStartDate = '';
|
||||
State.historyEndDate = '';
|
||||
$('#historyStartDate').val('');
|
||||
$('#historyEndDate').val('');
|
||||
});
|
||||
// default date today
|
||||
State.historyStartDate = moment().startOf('day').unix();
|
||||
State.historyEndDate = moment().endOf('day').unix();
|
||||
$('#historyStartDate').val(moment().startOf('day').format('DD-MM-YYYY HH:mm'));
|
||||
$('#historyEndDate').val(moment().endOf('day').format('DD-MM-YYYY HH:mm'));
|
||||
|
||||
// for testing purpose
|
||||
// State.historyStartDate = '1756054800';
|
||||
// State.historyEndDate = '1756141140';
|
||||
// $('#historyStartDate').val("25-08-2025 00:00");
|
||||
// $('#historyEndDate').val("25-08-2025 23:59");
|
||||
});
|
||||
},
|
||||
handlerFilterPopupVhcMarker: function(markers) {
|
||||
if (State.inShowLastMove) {
|
||||
@ -2033,7 +2176,7 @@
|
||||
},
|
||||
error: (jqXHR, textStatus, error) => {
|
||||
if (jqXHR.status >= 500) {
|
||||
Helper.toast('Error', 'just now', 'Cannot get lists trucks');
|
||||
Helper.toast('Error', 'just now', 'Cannot get lists vehicles');
|
||||
} else {
|
||||
Helper.toast('Error', 'just now', jqXHR.responseJSON.meta
|
||||
.message);
|
||||
@ -2415,7 +2558,7 @@
|
||||
$('#infoVehicles-addr').text(
|
||||
`${Helper.shortenText(decodeURIComponent(truck?.lst_fulladdress || 'address'), 25)}`);
|
||||
$('#infoVehicles-lat_lng').text(Number(truck?.lst_lat).toFixed(5) + ', ' + Number(truck?.lst_lng).toFixed(6));
|
||||
$('#infoVehicles-mileage').text(Number(truck?.vhc_sum_milleage).toFixed(0));
|
||||
$('#infoVehicles-mileage').text(Number(truck?.vhc_sum_milleage_1).toFixed(0));
|
||||
$('#infoVehicles-speedLimit').text(truck?.speed_limit);
|
||||
$('#infoVehicles-currentSpeed').text(truck?.lst_speed);
|
||||
let idlingDur = Wrapper.calcIdlingDur(truck?.lst_idle_at, truck?.lst_speed);
|
||||
@ -2448,7 +2591,7 @@
|
||||
// <p id="" class="mb-0">JNE</p>
|
||||
// </div>
|
||||
// <div class="col-auto">
|
||||
// <small class="text-muted">Destination</small>
|
||||
// <small class="text-muted">Destination</small>
|
||||
// <p id="" class="mb-0">JKT-01</p></div>
|
||||
// </div>
|
||||
// </li>
|
||||
@ -2493,16 +2636,21 @@
|
||||
// last movement
|
||||
// $('#infoVehicles-infoMove').text('Last 24H from ' + moment.unix(truck?.lst_loc_crt).format('DD MMM YYYY HH:mm'));
|
||||
},
|
||||
bundleShowRouteTruck: async function(cache = false) {
|
||||
bundleShowRouteTruck: async function(cache = false, needUpdate = true) {
|
||||
Menu.clearListMovements();
|
||||
if (State.inShowVid != State.loadedLastMoveVid) $('#historyStartDate').trigger('clearFilterHistoryDate');
|
||||
Trucks.last_move = await Trucks.getLastMove(State.inShowVid, cache);
|
||||
if (Trucks.last_move.length < 1) {
|
||||
Helper.toast('Data Not Found', 'just now', 'There are no last data', 'bg-warning');
|
||||
Trucks.last_move = null;
|
||||
return false;
|
||||
}
|
||||
Trucks.showLastMoveToView(Trucks.last_move);
|
||||
if (State.inShowVid != State.loadedLastMoveVid)$('#historyStartDate').trigger('clearFilterHistoryDate');
|
||||
|
||||
if(needUpdate){
|
||||
const getLastMove = await Trucks.getLastMove(State.inShowVid, cache);
|
||||
Trucks.last_move = getLastMove.flat()
|
||||
|
||||
if (Trucks.last_move.length < 1) {
|
||||
Helper.toast('Data Not Found', 'just now', 'There are no last data', 'bg-warning');
|
||||
Trucks.last_move = null;
|
||||
return false;
|
||||
}
|
||||
Trucks.showLastMoveToView(getLastMove);
|
||||
}
|
||||
},
|
||||
getLastMove: async function(vid, cache = false) {
|
||||
State.loadedLastMoveVid = vid;
|
||||
@ -2563,84 +2711,218 @@
|
||||
showLastMoveToView: function(truckRoutes) {
|
||||
// Leaflet.clearLayer('eventAboutTruck');
|
||||
Leaflet.hideLayer('eventHideAllTruck');
|
||||
Trucks.routeStartEnd(truckRoutes);
|
||||
// Trucks.routeStartEnd(truckRoutes);
|
||||
Trucks.routeStartEndGroupTrip(truckRoutes);
|
||||
},
|
||||
routeStartEnd: function(truckRoutes) {
|
||||
let key_length = truckRoutes.length;
|
||||
let polyTruckRoutes = truckRoutes.map((obj, key) => {
|
||||
obj.key_index = key + 1 // key_length - key;
|
||||
// lists per detail info movement
|
||||
Menu.showToListMovement(obj);
|
||||
return {
|
||||
lat: obj.latitude,
|
||||
lng: obj.longitude,
|
||||
options: {
|
||||
// polyline
|
||||
smoothFactor: 1.0,
|
||||
noClip: true,
|
||||
bubblingMouseEvents: false,
|
||||
// circle
|
||||
radius: 2,
|
||||
},
|
||||
// circle
|
||||
// label: `<b>${obj.key_index}</b><br>${obj.nopol1} ${obj.nopol2} ${obj.nopol3}<br>${moment.unix(obj?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>Speed: ${(typeof obj.speed != 'undefined') ? obj.speed : '0'}<br>${Number(obj.latitude).toFixed(5)} - ${Number(obj.longitude).toFixed(6)}<br>${decodeURIComponent(obj?.fulladdress || 'address')}`,
|
||||
// label: `<b>${obj.nopol1} ${obj.nopol2} ${obj.nopol3}</b><br>${moment.unix(obj?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>${decodeURIComponent(obj?.fulladdress || 'address')}`,
|
||||
label: `<b>${obj.nopol1} ${obj.nopol2} ${obj.nopol3}</b><br>${moment.unix(obj?.lst_loc_crt_d).format('DD MMM YYYY HH:mm:ss')}<br>${decodeURIComponent(obj?.fulladdress || 'address')}`,
|
||||
}
|
||||
});
|
||||
// routeStartEnd: function(truckRoutes) {
|
||||
// let key_length = truckRoutes.length;
|
||||
// let polyTruckRoutes = truckRoutes.map((obj, key) => {
|
||||
|
||||
let polyline = Leaflet.addPolylines(polyTruckRoutes);
|
||||
Leaflet.map.fitBounds(polyline.getBounds());
|
||||
// let ctrWaypoint = Leaflet.addWaypoints(polyTruckRoutes.slice(0, 100))
|
||||
// obj.key_index = key + 1 // key_length - key;
|
||||
// // lists per detail info movement
|
||||
// Menu.showToListMovement(obj);
|
||||
// return {
|
||||
// lat: obj.latitude,
|
||||
// lng: obj.longitude,
|
||||
// options: {
|
||||
// // polyline
|
||||
// smoothFactor: 1.0,
|
||||
// noClip: true,
|
||||
// bubblingMouseEvents: false,
|
||||
// // circle
|
||||
// radius: 5,
|
||||
// // markerOpacity: 0
|
||||
// },
|
||||
// // circle
|
||||
// // label: `<b>${obj.key_index}</b><br>${obj.nopol1} ${obj.nopol2} ${obj.nopol3}<br>${moment.unix(obj?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>Speed: ${(typeof obj.speed != 'undefined') ? obj.speed : '0'}<br>${Number(obj.latitude).toFixed(5)} - ${Number(obj.longitude).toFixed(6)}<br>${decodeURIComponent(obj?.fulladdress || 'address')}`,
|
||||
// // label: `<b>${obj.nopol1} ${obj.nopol2} ${obj.nopol3}</b><br>${moment.unix(obj?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>${decodeURIComponent(obj?.fulladdress || 'address')}`,
|
||||
// label: `<b>${obj.nopol1} ${obj.nopol2} ${obj.nopol3}</b><br>${moment.unix(obj?.lst_loc_crt_d).format('DD MMM YYYY HH:mm:ss')}<br>${decodeURIComponent(obj?.fulladdress || 'address')}`,
|
||||
// }
|
||||
// });
|
||||
|
||||
Leaflet.addCircles(polyTruckRoutes, function(circle, i) {
|
||||
window.addEventListener('eventRemoveRouteStartEnd', function handler(e) {
|
||||
circle.remove();
|
||||
});
|
||||
circle.on('click', function() {
|
||||
PgBar.syncToPlotTravelHistory(i);
|
||||
})
|
||||
});
|
||||
// let polyline = Leaflet.addPolylines(polyTruckRoutes);
|
||||
// Leaflet.map.fitBounds(polyline.getBounds());
|
||||
// // let ctrWaypoint = Leaflet.addWaypoints(polyTruckRoutes.slice(0, 100))
|
||||
|
||||
let start = truckRoutes.at(-1);
|
||||
let finish = truckRoutes.at(0);
|
||||
// ${(start?.city_text || start?.state_tex || 'address't)} - ${(start?.postcode || 'postcode')}
|
||||
// ${(finish?.city_text || finish?.state_text || 'address')} - ${(finish?.postcode || 'postcode')}
|
||||
let startMarker = Leaflet.addMarkers({
|
||||
lat: start.latitude,
|
||||
lng: start.longitude,
|
||||
label: `<b>Start Poin</b><br>${start.nopol1} ${start.nopol2} ${start.nopol3}<br>${moment.unix(start?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>Speed: ${(typeof start.lst_speed != 'undefined') ? start.lst_speed : '0'}<br>${Number(start.latitude).toFixed(5)},${Number(start.longitude).toFixed(6)}<br>${decodeURIComponent(start.fulladdress || 'address')}`,
|
||||
// label: `<b>Start Poin</b><br>${start.nopol1} ${start.nopol2} ${start.nopol3}<br>${moment.unix(start?.lst_loc_crt_d).utcOffset(9 * 60).format('DD MMM YYYY HH:mm:ss')}<br>Speed: ${(typeof start.lst_speed != 'undefined') ? start.lst_speed : '0'}<br>${Number(start.latitude).toFixed(5)},${Number(start.longitude).toFixed(6)}<br>${decodeURIComponent(start.fulladdress || 'address')}`,
|
||||
options: {
|
||||
icon: Icon.titikAwal(),
|
||||
// rotationAngle: 290
|
||||
}
|
||||
});
|
||||
let finishMarker = Leaflet.addMarkers({
|
||||
lat: finish.latitude,
|
||||
lng: finish.longitude,
|
||||
label: `<b>End Poin</b><br>${finish.nopol1} ${finish.nopol2} ${finish.nopol3}<br>${moment.unix(finish?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>Speed: ${(typeof finish.lst_speed != 'undefined') ? finish.lst_speed : '0'}<br>${Number(finish.latitude).toFixed(5)},${Number(finish.longitude).toFixed(6)}<br>${decodeURIComponent(finish.fulladdress || 'address')}`,
|
||||
//label: `<b>End Poin</b><br>${finish.nopol1} ${finish.nopol2} ${finish.nopol3}<br>${moment.unix(finish?.lst_loc_crt_d).utcOffset(9 * 60).format('DD MMM YYYY HH:mm:ss')}<br>Speed: ${(typeof finish.lst_speed != 'undefined') ? finish.lst_speed : '0'}<br>${Number(finish.latitude).toFixed(5)},${Number(finish.longitude).toFixed(6)}<br>${decodeURIComponent(finish.fulladdress || 'address')}`,
|
||||
options: {
|
||||
icon: Icon.titikAkhir()
|
||||
}
|
||||
});
|
||||
// Leaflet.addCircles(polyTruckRoutes, function(circle, i) {
|
||||
// window.addEventListener('eventRemoveRouteStartEnd', function handler(e) {
|
||||
// circle.remove();
|
||||
// });
|
||||
// circle.on('click', function() {
|
||||
// PgBar.syncToPlotTravelHistory(i);
|
||||
// })
|
||||
// });
|
||||
|
||||
// let start = truckRoutes.at(-1);
|
||||
// let finish = truckRoutes.at(0);
|
||||
// // ${(start?.city_text || start?.state_tex || 'address't)} - ${(start?.postcode || 'postcode')}
|
||||
// // ${(finish?.city_text || finish?.state_text || 'address')} - ${(finish?.postcode || 'postcode')}
|
||||
// let startMarker = Leaflet.addMarkers({
|
||||
// lat: start.latitude,
|
||||
// lng: start.longitude,
|
||||
// label: `<b>Start Poin</b><br>${start.nopol1} ${start.nopol2} ${start.nopol3}<br>${moment.unix(start?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>Speed: ${(typeof start.lst_speed != 'undefined') ? start.lst_speed : '0'}<br>${Number(start.latitude).toFixed(5)},${Number(start.longitude).toFixed(6)}<br>${decodeURIComponent(start.fulladdress || 'address')}`,
|
||||
// // label: `<b>Start Poin</b><br>${start.nopol1} ${start.nopol2} ${start.nopol3}<br>${moment.unix(start?.lst_loc_crt_d).utcOffset(9 * 60).format('DD MMM YYYY HH:mm:ss')}<br>Speed: ${(typeof start.lst_speed != 'undefined') ? start.lst_speed : '0'}<br>${Number(start.latitude).toFixed(5)},${Number(start.longitude).toFixed(6)}<br>${decodeURIComponent(start.fulladdress || 'address')}`,
|
||||
// options: {
|
||||
// icon: Icon.titikAwal(),
|
||||
// // rotationAngle: 290
|
||||
// }
|
||||
// });
|
||||
// let finishMarker = Leaflet.addMarkers({
|
||||
// lat: finish.latitude,
|
||||
// lng: finish.longitude,
|
||||
// label: `<b>End Poin</b><br>${finish.nopol1} ${finish.nopol2} ${finish.nopol3}<br>${moment.unix(finish?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>Speed: ${(typeof finish.lst_speed != 'undefined') ? finish.lst_speed : '0'}<br>${Number(finish.latitude).toFixed(5)},${Number(finish.longitude).toFixed(6)}<br>${decodeURIComponent(finish.fulladdress || 'address')}`,
|
||||
// //label: `<b>End Poin</b><br>${finish.nopol1} ${finish.nopol2} ${finish.nopol3}<br>${moment.unix(finish?.lst_loc_crt_d).utcOffset(9 * 60).format('DD MMM YYYY HH:mm:ss')}<br>Speed: ${(typeof finish.lst_speed != 'undefined') ? finish.lst_speed : '0'}<br>${Number(finish.latitude).toFixed(5)},${Number(finish.longitude).toFixed(6)}<br>${decodeURIComponent(finish.fulladdress || 'address')}`,
|
||||
// options: {
|
||||
// icon: Icon.titikAkhir()
|
||||
// }
|
||||
// });
|
||||
|
||||
// // remove marker, circle, event listener and all about this marker
|
||||
// State.eventRemoveRouteStartEnd = new CustomEvent('eventRemoveRouteStartEnd', {
|
||||
// startMarker,
|
||||
// finishMarker,
|
||||
// polyline,
|
||||
// polyline,
|
||||
// });
|
||||
// window.addEventListener('eventRemoveRouteStartEnd', function handler(e) {
|
||||
// startMarker.removeEventListener('click');
|
||||
// startMarker.removeEventListener('moveend');
|
||||
// startMarker.remove();
|
||||
// finishMarker.removeEventListener('click');
|
||||
// finishMarker.removeEventListener('moveend');
|
||||
// finishMarker.remove();
|
||||
// polyline.remove();
|
||||
// e.currentTarget.removeEventListener(e.type,
|
||||
// handler); // window.removeEventListener('remove', this.handler, true);
|
||||
// State.eventRemoveRouteStartEnd = null;
|
||||
// State.inShowLastMove = null;
|
||||
|
||||
// PgBar.tglMenuPlayback(false);
|
||||
// PgBar.reset();
|
||||
// });
|
||||
|
||||
// PgBar.setMinMax(0, truckRoutes.length - 1);
|
||||
// },
|
||||
routeStartEndGroupTrip: async function(truckRoutes) {
|
||||
const colors = [
|
||||
"#2980B9", // Dark Blue
|
||||
"#C0392B", // Dark Red
|
||||
"#27AE60", // Dark Green
|
||||
"#D35400", // Dark Orange
|
||||
"#F39C12", // Dark Yellow/Gold
|
||||
]
|
||||
let i = 1
|
||||
let allStartStop = []
|
||||
let polyTruckRoutes = truckRoutes.map((groupTrip, key0) => {
|
||||
return groupTrip.map((obj, key) => {
|
||||
obj.key_index = i++
|
||||
// console.log("obj", obj.key_index);
|
||||
|
||||
Menu.showToListMovement(obj)
|
||||
|
||||
// add start end marker per group trip
|
||||
if(key == 0 || key == groupTrip.length - 1){
|
||||
const marker = Leaflet.addMarkers({
|
||||
lat: obj.latitude,
|
||||
lng: obj.longitude,
|
||||
label: `
|
||||
<b>${(key == 0) ? 'Finish' : 'Start'} Poin</b><br>${obj.nopol1} ${obj.nopol2} ${obj.nopol3}<br>
|
||||
${moment.unix(obj?.lst_loc_crt).format('DD MMM YYYY HH:mm')}<br>
|
||||
Speed: ${(typeof obj.lst_speed != 'undefined') ? obj.lst_speed : '0'}<br>
|
||||
${Number(obj.latitude).toFixed(5)},${Number(obj.longitude).toFixed(6)}<br>
|
||||
${decodeURIComponent(obj.fulladdress || 'address')}
|
||||
`,
|
||||
// label: `<b>Start Poin</b><br>${start.nopol1} ${start.nopol2} ${start.nopol3}<br>${moment.unix(start?.lst_loc_crt_d).utcOffset(9 * 60).format('DD MMM YYYY HH:mm:ss')}<br>Speed: ${(typeof start.lst_speed != 'undefined') ? start.lst_speed : '0'}<br>${Number(start.latitude).toFixed(5)},${Number(start.longitude).toFixed(6)}<br>${decodeURIComponent(start.fulladdress || 'address')}`,
|
||||
options: {
|
||||
icon: (key == 0) ? Icon.titikAkhir() : (key == (groupTrip.length - 1)) ? Icon.titikAwal() : null,
|
||||
// rotationAngle: 290
|
||||
}
|
||||
})
|
||||
allStartStop.push(marker)
|
||||
}
|
||||
|
||||
const unix = parseInt(obj?.lst_loc_crt_d) + AppState.TIMEFIX;
|
||||
|
||||
return {
|
||||
lat: obj.latitude,
|
||||
lng: obj.longitude,
|
||||
options: {
|
||||
// polyline
|
||||
color : colors[key0 % colors.length],
|
||||
smoothFactor : 0,
|
||||
noClip : true,
|
||||
bubblingMouseEvents : false,
|
||||
// circle
|
||||
radius: 5,
|
||||
markerOpacity: 0
|
||||
},
|
||||
label: `<b>${obj.nopol1} ${obj.nopol2} ${obj.nopol3}</b><br>${moment.unix(unix).format('DD MMM YYYY HH:mm:ss')}<br>${decodeURIComponent(obj?.fulladdress || 'address')}`,
|
||||
// startLast : (key == 0) ? 0 : (key == (groupTrip.length - 1)) ? 1 : null,
|
||||
}
|
||||
})
|
||||
})
|
||||
// console.log("truckRoutes update", polyTruckRoutes);
|
||||
|
||||
let circleCounter = 0
|
||||
for (const [idx, poly] of polyTruckRoutes.entries()) {
|
||||
// console.log("poly", poly);
|
||||
function addCirclesAsync(polyCircle) {
|
||||
// console.log("circleCounter", circleCounter);
|
||||
|
||||
// return array of circles start end only
|
||||
return new Promise(resolve => {
|
||||
let circles = [];
|
||||
|
||||
Leaflet.addCircles(polyCircle, function(circle, i) {
|
||||
// console.log("circle", i, circleCounter);
|
||||
|
||||
if (i === 0 || i === (polyCircle.length - 1)) {
|
||||
circles.push(circle);
|
||||
}
|
||||
|
||||
const currentCounter = circleCounter;
|
||||
circle.on('click', function() {
|
||||
PgBar.syncToPlotTravelHistory(currentCounter);
|
||||
});
|
||||
circleCounter++
|
||||
|
||||
// ✅ When last point processed, resolve
|
||||
if (i === polyCircle.length - 1) {
|
||||
resolve(circles);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let polyline = await Leaflet.addRoutes(poly);
|
||||
// console.log("polyline", polyline);
|
||||
allStartStop.push(polyline)
|
||||
|
||||
// wait for all circles
|
||||
const ssmarker = await addCirclesAsync(poly);
|
||||
// console.log("ssmarker", ssmarker);
|
||||
allStartStop.push(...ssmarker)
|
||||
}
|
||||
|
||||
console.log("allStartStop", allStartStop);
|
||||
// console.log("circlesStartStop", circlesStartStop);
|
||||
|
||||
// // remove marker, circle, event listener and all about this marker
|
||||
State.eventRemoveRouteStartEnd = new CustomEvent('eventRemoveRouteStartEnd', {
|
||||
// detail: {
|
||||
allStartStop,
|
||||
// circlesStartStop
|
||||
// }
|
||||
});
|
||||
|
||||
// window.addEventListener('eventRemoveRouteStartEnd', function (e) {
|
||||
// // allStartStop.remove();
|
||||
// allStartStop.forEach(c => c.remove())
|
||||
// // circlesStartStop.forEach(c => c.remove())
|
||||
// });
|
||||
|
||||
// remove marker, circle, event listener and all about this marker
|
||||
State.eventRemoveRouteStartEnd = new CustomEvent('eventRemoveRouteStartEnd', {
|
||||
startMarker,
|
||||
finishMarker,
|
||||
polyline,
|
||||
polyline,
|
||||
});
|
||||
window.addEventListener('eventRemoveRouteStartEnd', function handler(e) {
|
||||
startMarker.removeEventListener('click');
|
||||
startMarker.removeEventListener('moveend');
|
||||
startMarker.remove();
|
||||
finishMarker.removeEventListener('click');
|
||||
finishMarker.removeEventListener('moveend');
|
||||
finishMarker.remove();
|
||||
polyline.remove();
|
||||
allStartStop.forEach(c => c.remove())
|
||||
e.currentTarget.removeEventListener(e.type,
|
||||
handler); // window.removeEventListener('remove', this.handler, true);
|
||||
State.eventRemoveRouteStartEnd = null;
|
||||
@ -2650,7 +2932,7 @@
|
||||
PgBar.reset();
|
||||
});
|
||||
|
||||
PgBar.setMinMax(0, truckRoutes.length - 1);
|
||||
PgBar.setMinMax(0, Trucks.last_move.length - 1);
|
||||
},
|
||||
routePerPoint: function() {
|
||||
Leaflet.addMarkers(truckRoutes.routes.map((obj) => {
|
||||
@ -3210,6 +3492,8 @@
|
||||
}
|
||||
},
|
||||
syncToPlotTravelHistory: function(arrIdx) {
|
||||
console.log("syncToPlotTravelHistory", arrIdx);
|
||||
|
||||
const listPlotTravelHistory = document.querySelectorAll('#infoMove-plots .plotMove-item')[arrIdx];
|
||||
listPlotTravelHistory.scrollIntoView();
|
||||
listPlotTravelHistory.querySelector('li').classList.add('hover');
|
||||
|
||||
347
resources/views/menu_v1/reports/_trip_detail.blade.php
Normal file
347
resources/views/menu_v1/reports/_trip_detail.blade.php
Normal file
@ -0,0 +1,347 @@
|
||||
<style>
|
||||
#map {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
.my-leaflet-map-container img {
|
||||
max-height: none;
|
||||
}
|
||||
.dtl-text{
|
||||
font-size: 11px;
|
||||
}
|
||||
.head-text{
|
||||
font-size: 12px !important;
|
||||
}
|
||||
/* .leaflet-overlay-pane svg {
|
||||
transform: none !important;
|
||||
} */
|
||||
.leaflet-routing-container {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#viewPdf {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 794px;
|
||||
/* height: auto; */
|
||||
max-width: 100%; /* Ensures it is responsive */
|
||||
}
|
||||
/* .modal-dialog{
|
||||
width: 794px;
|
||||
} */
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
<div class="modal-dialog modal-dialog modal-dialog-centered modal-dialog-scrollable modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="mdlDetailTripLabel">{{$nopol1}} Trip Detail</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row head-text" id="viewPdf">
|
||||
<div class="col-12">
|
||||
<h4>{{$nopol1}}</h4>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<p class="text-bold mb-0">Start</p>
|
||||
<p class="mb-0 time">{{ $start['time'] }}</p>
|
||||
<p class="mb-0">Vehicle Mileage: {{number_format($start['mileage'], 2)}} km</p>
|
||||
<p>{{$start['fulladdress']}}</p>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<p class="text-bold mb-0">Finish</p>
|
||||
<p class="mb-0 time">{{ $finish['time'] }}</p>
|
||||
<p class="mb-0">Vehicle Mileage: {{number_format($finish['mileage'], 2)}} km</p>
|
||||
<p>{{$finish['fulladdress']}}</p>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<p class="text-bold mb-0">Distance</p>
|
||||
<p class="mb-0">{{number_format($distance, 2)}} km</p>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<p class="text-bold mb-0">Duration</p>
|
||||
<p class="mb-0">{{$duration}}</p>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div id="leafMap" style="height: 400px;"></div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<!-- <li class="list-group-item p-1 px-2">
|
||||
<p class="text-bold mb-0">Time: 25 Aug 2025 07:31:08</p>
|
||||
<p class="text-muted mb-0 dtl-text">-8.55387 - 125.542409</p>
|
||||
<p class="text-muted mb-0 dtl-text">Avenida Luro Mata, Praia dos Coqueiros, Bebunuk, Dom Aleixo, Dili, Timor-Leste;2066973</p>
|
||||
<p class="mb-0 dtl-text">Current speed: 7km/h</p>
|
||||
</li> -->
|
||||
@foreach ($list as $item)
|
||||
<!-- <li class="list-group-item p-1 px-2">
|
||||
<p class="text-bold mb-0">Time: {{date('d-m-Y H:i:s', $item->crt_d)}}</p>
|
||||
<p class="text-muted mb-0 dtl-text">Vehicle Mileage: {{number_format($item->vhc_milleage, 2)}} km</p>
|
||||
<p class="text-muted mb-0 dtl-text">{{number_format($item->latitude, 6)}} - {{number_format($item->longitude, 6)}}</p>
|
||||
<p class="text-muted mb-0 dtl-text">{{urldecode($item->fulladdress)}}</p>
|
||||
<p class="text-muted mb-0 dtl-text">Current speed: {{number_format($item->speed, 2)}} km/h</p>
|
||||
</li> -->
|
||||
<li class="list-group-item p-1 px-2">
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
<p class="text-bold mb-0 dtl-text">Time: <span class="time">{{ $item->crt_d }}</span></p>
|
||||
<p class="text-muted mb-0 dtl-text">Vehicle Mileage: {{number_format($item->vhc_milleage, 2)}} km</p>
|
||||
<p class="text-muted mb-0 dtl-text">Current speed: {{$item->speed}} km/h</p>
|
||||
</div>
|
||||
<div class="col-8">
|
||||
<p class="text-muted mb-0 dtl-text">{{number_format($item->latitude, 6)}}, {{number_format($item->longitude, 6)}}</p>
|
||||
<p class="text-muted mb-0 dtl-text">{{urldecode($item->fulladdress)}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-sm btn-danger ms-auto" id="btnDownloadReport">Download Report</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$('.time').each(function () {
|
||||
const unix = parseInt($(this).text().trim()) + AppState.TIMEFIX;
|
||||
$(this).text(moment.unix(unix).format('DD MMM YYYY HH:mm:ss'));
|
||||
});
|
||||
|
||||
let coords
|
||||
setTimeout(async() => {
|
||||
map.invalidateSize(); // force Leaflet to recalc
|
||||
map.fitBounds(polyline.getBounds());
|
||||
// map.fitBounds(await coords.map(c => L.latLng(c[0], c[1])));
|
||||
}, 200);
|
||||
|
||||
const linesData = (@json($list));
|
||||
|
||||
// 1) Initialize map
|
||||
const map = L.map("leafMap").setView([-8.90507, 125.9945732], 10)
|
||||
|
||||
// 2) Add tile layer
|
||||
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
||||
maxZoom: 20,
|
||||
crossOrigin: true
|
||||
}).addTo(map);
|
||||
|
||||
// // // 3) Coordinates (Lat, Lng) for polyline
|
||||
const points = linesData
|
||||
.filter(p => p.latitude && p.longitude)
|
||||
.map((point) => [point.latitude, point.longitude])
|
||||
|
||||
// 4) Add polyline
|
||||
const polyline = L.polyline(points,{
|
||||
color: 'red',
|
||||
weight: 3,
|
||||
opacity: 0.7,
|
||||
smoothFactor: 1
|
||||
})
|
||||
// .addTo(map);
|
||||
|
||||
// const lines = L.Routing.control({
|
||||
// waypoints: points,
|
||||
// // router: L.Routing.osrmv1(),
|
||||
// router: L.Routing.osrmv1({
|
||||
// serviceUrl: "https://brilianapps.britimorleste.tl:5001/route/v1",
|
||||
// }),
|
||||
// show: false,
|
||||
// itinerary: null, // 👈 completely removes the panel
|
||||
// addWaypoints: false, // ❌ prevent adding points by clicking
|
||||
// draggableWaypoints: false, // ❌ prevent dragging markers
|
||||
// routeWhileDragging: false, // optional: don’t reroute while dragging
|
||||
// createMarker: () => null,
|
||||
// routingOptions: {
|
||||
// radiuses: [100, 100] // tolerance in meters per waypoint
|
||||
// },
|
||||
// lineOptions:{
|
||||
// styles: [{ color: "#C0392B", weight: 4, opacity: 0.7 }],
|
||||
// },
|
||||
// }).addTo(map)
|
||||
|
||||
function chunkArray(arr, size) {
|
||||
const result = [];
|
||||
for (let i = 0; i < arr.length; i += size) {
|
||||
result.push(arr.slice(i, i + size));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function fetchOsrm(points) {
|
||||
const coords = points;
|
||||
const hints = ";".repeat(points.length - 1);
|
||||
|
||||
const body = {
|
||||
coordinates: coords,
|
||||
overview: "false",
|
||||
alternatives: "false",
|
||||
steps: "true",
|
||||
hints: hints
|
||||
};
|
||||
|
||||
let config = {
|
||||
method: 'post',
|
||||
maxBodyLength: Infinity,
|
||||
url: 'https://brilianapps.britimorleste.tl/osrm-backend/post-route/v1/driving/',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: body
|
||||
};
|
||||
|
||||
return axios.request(config)
|
||||
.then((response) => {
|
||||
return response.data;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error:", error.message);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
function decodeOSRMGeometry(encoded) {
|
||||
const coordinates = [];
|
||||
let index = 0,
|
||||
lat = 0,
|
||||
lng = 0;
|
||||
|
||||
while (index < encoded.length) {
|
||||
let result = 1,
|
||||
shift = 0,
|
||||
b;
|
||||
do {
|
||||
b = encoded.charCodeAt(index++) - 63 - 1;
|
||||
result += b << shift;
|
||||
shift += 5;
|
||||
} while (b >= 0x1f);
|
||||
lat += (result & 1 ? ~(result >> 1) : result >> 1);
|
||||
|
||||
result = 1;
|
||||
shift = 0;
|
||||
do {
|
||||
b = encoded.charCodeAt(index++) - 63 - 1;
|
||||
result += b << shift;
|
||||
shift += 5;
|
||||
} while (b >= 0x1f);
|
||||
lng += (result & 1 ? ~(result >> 1) : result >> 1);
|
||||
|
||||
coordinates.push([lat / 1e5, lng / 1e5]);
|
||||
}
|
||||
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
async function getCoordinates(points) {
|
||||
const chunkSize = 500;
|
||||
const chunks = chunkArray(points, chunkSize); // Split the points array into chunks of 500
|
||||
let allCoords = [];
|
||||
|
||||
for (const chunk of chunks) {
|
||||
const osrm = await fetchOsrm(chunk); // Fetch OSRM data for each chunk
|
||||
|
||||
if (!osrm) {
|
||||
console.log("OSRM failed for chunk");
|
||||
return;
|
||||
}
|
||||
|
||||
const coords = osrm.routes[0].legs.flatMap(leg =>
|
||||
leg.steps.flatMap(step =>
|
||||
decodeOSRMGeometry(step.geometry)
|
||||
)
|
||||
);
|
||||
|
||||
allCoords = allCoords.concat(coords); // Combine the result
|
||||
}
|
||||
|
||||
// Now add the polyline to the map
|
||||
L.polyline(allCoords, {
|
||||
color: "#2980B9",
|
||||
weight: 3,
|
||||
opacity: 0.8
|
||||
}).addTo(map);
|
||||
// map.fitBounds(allCoords.map(c => L.latLng(c[0], c[1])));
|
||||
}
|
||||
|
||||
// Usage: Pass the array of coordinates to the function
|
||||
getCoordinates(points);
|
||||
|
||||
|
||||
// start and finish point
|
||||
const startIcon = L.icon({
|
||||
iconUrl: "{{ asset('images/start.png') }}",
|
||||
iconSize: [30, 30],
|
||||
iconAnchor: [15, 28], // lb, rt, bottom, rb. Positive
|
||||
})
|
||||
L.marker(points[0], {icon: startIcon}).addTo(map)
|
||||
|
||||
const finishIcon = L.icon({
|
||||
iconUrl: "{{ asset('images/finish.png') }}",
|
||||
iconSize: [30, 30],
|
||||
iconAnchor: [15, 28], // lb, rt, bottom, rb. Positive
|
||||
})
|
||||
L.marker(points[points.length - 1], {icon: finishIcon}).addTo(map)
|
||||
|
||||
// // 5) Auto-fit map to polyline bounds
|
||||
// map.fitBounds(polyline.getBounds())
|
||||
|
||||
// download pdf
|
||||
window._downloadReportBound ||= (
|
||||
$(document).on('click', '#btnDownloadReport', function () {
|
||||
$('#viewPdf').printThis({
|
||||
debug: false, // show the iframe for debugging
|
||||
importCSS: true, // copy linked styles
|
||||
importStyle: true, // copy inline styles
|
||||
});
|
||||
|
||||
// const viewPdf = document.getElementById("viewPdf");
|
||||
|
||||
// // find overlay svg (the one holding polylines)
|
||||
// const overlaySvg = document.querySelector('.leaflet-overlay-pane svg');
|
||||
// let originalTransform = '';
|
||||
// if (overlaySvg) {
|
||||
// originalTransform = overlaySvg.style.transform;
|
||||
// overlaySvg.style.transform = 'none';
|
||||
// }
|
||||
|
||||
// html2canvas(viewPdf, {
|
||||
// scale: 2,
|
||||
// useCORS: true,
|
||||
// logging: true
|
||||
// }).then(canvas => {
|
||||
// const imgData = canvas.toDataURL('image/png');
|
||||
// const { jsPDF } = window.jspdf;
|
||||
|
||||
// const pdf = new jsPDF('p', 'mm', 'a4');
|
||||
// const pageWidth = pdf.internal.pageSize.getWidth();
|
||||
// const pageHeight = pdf.internal.pageSize.getHeight();
|
||||
|
||||
// const imgWidth = pageWidth - 20; // margin
|
||||
// const imgHeight = canvas.height * imgWidth / canvas.width;
|
||||
|
||||
// let position = 10;
|
||||
|
||||
// // 👉 Handle multipage content
|
||||
// let heightLeft = imgHeight;
|
||||
// while (heightLeft > 0) {
|
||||
// pdf.addImage(imgData, 'PNG', 10, position, imgWidth, imgHeight);
|
||||
// heightLeft -= pageHeight;
|
||||
// if (heightLeft > 0) {
|
||||
// pdf.addPage();
|
||||
// position = 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
// pdf.save(`{{$nopol1}} Trip Report {{$start['time']}}.pdf`);
|
||||
|
||||
// });
|
||||
}),
|
||||
true
|
||||
);
|
||||
|
||||
});
|
||||
</script>
|
||||
256
resources/views/menu_v1/reports/abnormalities.blade.php
Normal file
256
resources/views/menu_v1/reports/abnormalities.blade.php
Normal file
@ -0,0 +1,256 @@
|
||||
@php
|
||||
$user_role = Auth::user()->role;
|
||||
@endphp
|
||||
|
||||
@extends('app.app')
|
||||
|
||||
@section('title')
|
||||
Vehicles
|
||||
@endsection
|
||||
|
||||
@section('customcss')
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid">
|
||||
<div class="content">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="row d-flex align-items-center">
|
||||
<div class="col-3">
|
||||
<p class="card-title text-bold mb-0">Abnormality Report</p>
|
||||
</div>
|
||||
@if ($user_role == \App\Models\Users::ROLE_VENDOR || $user_role == \App\Models\Users::ROLE_ADMIN)
|
||||
@can('vehicle.create')
|
||||
<!-- <div class="col text-end">
|
||||
<button id="btnMdlNewVhc" class="btn btn-sm btn-danger">Add New Vehicle</button>
|
||||
</div> -->
|
||||
@endcan
|
||||
|
||||
{{-- <div class="col-auto text-end ps-0">
|
||||
<button class="btn btn-sm btn-danger">Upload</button>
|
||||
</div> --}}
|
||||
@endif
|
||||
<div class="col-auto text-end ps-0">
|
||||
<!-- <button class="btn btn-sm btn-danger">Download</button> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- filter -->
|
||||
<div class="row">
|
||||
<div class="col-2">
|
||||
<div class="form-group">
|
||||
<label class="text-muted">From</label>
|
||||
<!-- default today -->
|
||||
<!-- <input class="form-control" id="tgl0" value="20-08-2025 00:00"> -->
|
||||
<input class="form-control" id="tgl0" value="{{ date('d-m-Y 00:00') }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="form-group">
|
||||
<label class="text-muted">To</label>
|
||||
<input class="form-control" id="tgl1" value="{{ date('d-m-Y 23:59') }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="form-group">
|
||||
<label class="text-muted">License Plate</label>
|
||||
<select name="license_plate" class="form-control" id="filterNopol">
|
||||
<option value="">-- All --</option>
|
||||
@foreach ($listNopol as $nopol)
|
||||
<option value="{{ $nopol->id }}">{{ $nopol->nopol1 }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1 d-flex align-items-end">
|
||||
<button class="btn btn-primary" id="submitFilter">Submit</button>
|
||||
</div>
|
||||
<div class="col-5 d-flex align-items-end">
|
||||
<button class="btn btn-sm btn-danger ms-auto" id="btnDownloadReport">Download Report</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive p-3">
|
||||
<table id="tVehicleTrips" class="table table-hover dataTable w-100">
|
||||
<thead>
|
||||
<tr class="">
|
||||
<!-- <th class="">Vehicle ID</th> -->
|
||||
<!-- <th class="text-center">Action</th> -->
|
||||
<!-- <th class="">Vehicle Name</th> -->
|
||||
<th class="">License Plate Number</th>
|
||||
<th class="">Dist. Cat.</th>
|
||||
<th class="">Pool</th>
|
||||
<th class="">Time</th>
|
||||
<th class="">Speed (kph)</th>
|
||||
<th class="">Location</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- modal -->
|
||||
@endsection
|
||||
|
||||
@section('customjs')
|
||||
<script src="{{ asset('assets/js/load-image.all.min.js') }}"></script>
|
||||
<!-- DataTables Buttons + JSZip (for Excel export) -->
|
||||
<script src="https://cdn.datatables.net/buttons/2.4.2/js/dataTables.buttons.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
|
||||
<script src="https://cdn.datatables.net/buttons/2.4.2/js/buttons.html5.min.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const State = {
|
||||
file_jimp_worker: "{{ asset('assets/js/worker/jimp.js') }}",
|
||||
storage_lara: "{{ asset('storage') }}/",
|
||||
dvc_type: {
|
||||
built_in: "{{ \App\Models\Devices::TYPE_BUILT_IN }}",
|
||||
portable: "{{ \App\Models\Devices::TYPE_PORTABLE }}",
|
||||
},
|
||||
};
|
||||
|
||||
const Wrapper = {
|
||||
activate: function() {
|
||||
Wrapper.init();
|
||||
Wrapper.event();
|
||||
// DTable.activate();
|
||||
},
|
||||
init: ()=>{
|
||||
$('#tgl0, #tgl1').datetimepicker({
|
||||
format:'d-m-Y H:i',
|
||||
defaultTime:'00:00',
|
||||
closeOnDateSelect: true,
|
||||
// mask:true
|
||||
});
|
||||
|
||||
},
|
||||
event: function() {
|
||||
$('#submitFilter').on('click', function() {
|
||||
DTable.reload();
|
||||
});
|
||||
// Trigger export on external button click
|
||||
$('#btnDownloadReport').on('click', function() {
|
||||
DTable.table.button('.buttons-excel').trigger();
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const DTable = {
|
||||
table: null,
|
||||
lastAjax: null, // keep track of the last ajax request
|
||||
activate: function() {
|
||||
DTable.reload();
|
||||
},
|
||||
reload: function() {
|
||||
// Abort the last request if it's still running
|
||||
if (DTable.lastAjax) {
|
||||
DTable.lastAjax.abort();
|
||||
}
|
||||
if (DTable.table) {
|
||||
// If table already exists → reload
|
||||
DTable.table.ajax.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
DTable.table = $('#tVehicleTrips').DataTable({
|
||||
searching: false, // 🔹 remove search box
|
||||
ordering: false, // 🔹 disable sorting for all columns
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
bLengthChange: true,
|
||||
deferRender: true,
|
||||
ajax: function(data, callback, settings) {
|
||||
// Abort previous
|
||||
if (DTable.lastAjax) {
|
||||
DTable.lastAjax.abort();
|
||||
}
|
||||
|
||||
// Fire new request
|
||||
DTable.lastAjax = $.ajax({
|
||||
url: `{{ route('api_report_abnormalities_list') }}?
|
||||
cptid=${AppState.current_company}
|
||||
&from_date=${moment($('#tgl0').val(), "DD-MM-YYYY HH:mm").unix()}
|
||||
&to_date=${moment($('#tgl1').val(), "DD-MM-YYYY HH:mm").unix()}
|
||||
&vid=${$('#filterNopol').val() || ''}`,
|
||||
type: 'GET',
|
||||
success: function(json) {
|
||||
callback(json);
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
if (status !== 'abort') {
|
||||
console.error("AJAX error:", error);
|
||||
}
|
||||
},
|
||||
complete: function() {
|
||||
DTable.lastAjax = null;
|
||||
}
|
||||
});
|
||||
},
|
||||
deferRender: true,
|
||||
columns: [
|
||||
// { data: 'id', visible: false }, // vhc_id
|
||||
// {
|
||||
// data: 'name',
|
||||
// className: 'text-start text-nowrap',
|
||||
// },
|
||||
{
|
||||
data: 'nopol1',
|
||||
className: 'text-start',
|
||||
},
|
||||
{
|
||||
data: 'dc_code',
|
||||
className: 'text-start',
|
||||
},
|
||||
{
|
||||
data: 'pool_code',
|
||||
className: 'text-start',
|
||||
},
|
||||
{
|
||||
data: "crt_d",
|
||||
className: 'text-nowrap',
|
||||
render: (data, type, row, meta) => {
|
||||
return moment.unix(data + AppState.TIMEFIX).format('DD MMM YYYY HH:mm:ss');
|
||||
}
|
||||
},
|
||||
{ data: "speed", className: 'text-end'},
|
||||
{
|
||||
data: "fulladdress",
|
||||
render: (data, type, row, meta) => {
|
||||
return Helper.shortenText(decodeURIComponent(data || ''), 255)
|
||||
},
|
||||
},
|
||||
],
|
||||
paging: false,
|
||||
buttons: [
|
||||
{
|
||||
extend: 'excelHtml5',
|
||||
title: () => {
|
||||
return `
|
||||
Abnormality Trip Report -
|
||||
${moment($('#tgl0').val(), "DD-MM-YYYY HH:mm").format('DD MMM YYYY HH:mm')}
|
||||
to
|
||||
${moment($('#tgl1').val(), "DD-MM-YYYY HH:mm").format('DD MMM YYYY HH:mm')}`
|
||||
},
|
||||
className: 'd-none', // hide default button
|
||||
exportOptions: {
|
||||
columns: ':visible:not(:first-child)' // 🔹 exclude first column
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
function safeVal(selector) {
|
||||
const val = $(selector).val();
|
||||
return (val === undefined || val === null || val === '') ? null : val;
|
||||
}
|
||||
|
||||
Wrapper.activate();
|
||||
</script>
|
||||
@endsection
|
||||
507
resources/views/menu_v1/reports/vehicle_trips.blade.php
Normal file
507
resources/views/menu_v1/reports/vehicle_trips.blade.php
Normal file
@ -0,0 +1,507 @@
|
||||
@php
|
||||
$user_role = Auth::user()->role;
|
||||
@endphp
|
||||
|
||||
@extends('app.app')
|
||||
|
||||
@section('title')
|
||||
Vehicles Trip Report
|
||||
@endsection
|
||||
|
||||
@section('customcss')
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
|
||||
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
|
||||
crossorigin=""
|
||||
/>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid">
|
||||
<div class="content">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="row d-flex align-items-center">
|
||||
<div class="col-3">
|
||||
<p class="card-title text-bold mb-0">Vehicle Trip Report</p>
|
||||
</div>
|
||||
@if ($user_role == \App\Models\Users::ROLE_VENDOR || $user_role == \App\Models\Users::ROLE_ADMIN)
|
||||
@can('vehicle.create')
|
||||
<!-- <div class="col text-end">
|
||||
<button id="btnMdlNewVhc" class="btn btn-sm btn-danger">Add New Vehicle</button>
|
||||
</div> -->
|
||||
@endcan
|
||||
|
||||
{{-- <div class="col-auto text-end ps-0">
|
||||
<button class="btn btn-sm btn-danger">Upload</button>
|
||||
</div> --}}
|
||||
@endif
|
||||
<div class="col-auto text-end ps-0">
|
||||
<!-- <button class="btn btn-sm btn-danger">Download</button> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- filter -->
|
||||
<div class="row">
|
||||
<div class="col-2">
|
||||
<div class="form-group">
|
||||
<label class="text-muted">From</label>
|
||||
<!-- default today -->
|
||||
<!-- <input class="form-control" id="tgl0" value="02-09-2025 00:00"> -->
|
||||
<input class="form-control" id="tgl0" value="{{ date('d-m-Y 00:00') }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="form-group">
|
||||
<label class="text-muted">To</label>
|
||||
<!-- <input class="form-control" id="tgl1" value="02-09-2025 23:00"> -->
|
||||
<input class="form-control" id="tgl1" value="{{ date('d-m-Y 23:59') }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="form-group">
|
||||
<label class="text-muted">License Plate</label>
|
||||
<select name="license_plate" class="form-control" id="filterNopol">
|
||||
<option value="">-- All --</option>
|
||||
@foreach ($listNopol as $nopol)
|
||||
<option value="{{ $nopol->id }}">{{ $nopol->nopol1 }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1 d-flex align-items-end">
|
||||
<button class="btn btn-primary" id="submitFilter">Submit</button>
|
||||
</div>
|
||||
<div class="col-5 d-flex align-items-end">
|
||||
<button class="btn btn-sm btn-danger ms-auto" id="btnDownloadReport">Download Report</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive p-3">
|
||||
<table id="tVehicleTrips" class="table table-hover dataTable w-100">
|
||||
<thead>
|
||||
<tr class="">
|
||||
<th class="" hidden>Vehicle ID</th>
|
||||
<th class="">License Plate Number</th>
|
||||
<th class="">Dist. Cat.</th>
|
||||
<th class="">Pool</th>
|
||||
<th class="">Number of Trip</th>
|
||||
<th class="">Total Mileage (km)</th>
|
||||
<th class="">Trip #</th>
|
||||
<th class="">Start</th>
|
||||
<th class="">Finish</th>
|
||||
<th class="">Duration</th>
|
||||
<th class="">Start (km)</th>
|
||||
<th class="">Finish (km)</th>
|
||||
<th class="">Distance (km)</th>
|
||||
<th class="">Detail</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<!-- <tbody>
|
||||
<tr>
|
||||
<td>24-679</td>
|
||||
<td>24-679</td>
|
||||
<td>26</td>
|
||||
<td>442.3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>24-682</td>
|
||||
<td>24-682</td>
|
||||
<td>28</td>
|
||||
<td>312.7</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>24-877</td>
|
||||
<td>24-877</td>
|
||||
<td>15</td>
|
||||
<td>276.4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>A.16-347</td>
|
||||
<td>A.16-347</td>
|
||||
<td>37</td>
|
||||
<td>543.2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AL2025-B21</td>
|
||||
<td>AL2025-B21</td>
|
||||
<td>18</td>
|
||||
<td>295.4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>B.16-542</td>
|
||||
<td>B.16-542</td>
|
||||
<td>32</td>
|
||||
<td>478.2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>B.24-264</td>
|
||||
<td>B.24-264</td>
|
||||
<td>24</td>
|
||||
<td>188.4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>B.24-274</td>
|
||||
<td>B.24-274</td>
|
||||
<td>33</td>
|
||||
<td>440.1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Ford Ranger</td>
|
||||
<td>26-199</td>
|
||||
<td>30</td>
|
||||
<td>631.4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Nissan AD</td>
|
||||
<td>B.10-517</td>
|
||||
<td>27</td>
|
||||
<td>375.9</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Triton</td>
|
||||
<td>A.29-127</td>
|
||||
<td>26</td>
|
||||
<td>508.2</td>
|
||||
</tr>
|
||||
</tbody> -->
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- modal -->
|
||||
<div class="modal fade" data-bs-backdrop="static" data-bs-keyboard="false" id="mdlDetailTrip" aria-labelledby="mdlDetailTripLabel" aria-hidden="true">
|
||||
<!-- <div class="modal-dialog modal-dialog modal-dialog-centered modal-dialog-scrollable modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="mdlDetailTripLabel">-----</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('customjs')
|
||||
<script src="{{ asset('assets/js/load-image.all.min.js') }}"></script>
|
||||
<!-- DataTables Buttons + JSZip (for Excel export) -->
|
||||
<script src="https://cdn.datatables.net/buttons/2.4.2/js/dataTables.buttons.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
|
||||
<script src="https://cdn.datatables.net/buttons/2.4.2/js/buttons.html5.min.js"></script>
|
||||
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js" integrity="sha512-ozq8xQKq6urvuU6jNgkfqAmT7jKN2XumbrX1JiB3TnF7tI48DPI4Gy1GXKD/V3EExgAs1V+pRO7vwtS1LHg0Gw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> -->
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
|
||||
<script src="https://unpkg.com/leaflet-routing-machine@3.2.12/dist/leaflet-routing-machine.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
||||
<script src="{{ asset('assets/vendor/printThis.js') }}"></script>
|
||||
|
||||
<script>
|
||||
'use strict';
|
||||
const State = {
|
||||
file_jimp_worker: "{{ asset('assets/js/worker/jimp.js') }}",
|
||||
storage_lara: "{{ asset('storage') }}/",
|
||||
dvc_type: {
|
||||
built_in: "{{ \App\Models\Devices::TYPE_BUILT_IN }}",
|
||||
portable: "{{ \App\Models\Devices::TYPE_PORTABLE }}",
|
||||
},
|
||||
};
|
||||
|
||||
const Wrapper = {
|
||||
activate: function() {
|
||||
Wrapper.init();
|
||||
Wrapper.event();
|
||||
// DTable.table = $('#tVehicleTrips').DataTable()
|
||||
// DTable.activate();
|
||||
},
|
||||
init: ()=>{
|
||||
$('#tgl0, #tgl1').datetimepicker({
|
||||
format:'d-m-Y H:i',
|
||||
defaultTime:'00:00',
|
||||
closeOnDateSelect: true,
|
||||
// mask:true
|
||||
});
|
||||
|
||||
},
|
||||
event: function() {
|
||||
$('#submitFilter').on('click', function() {
|
||||
DTable.reload();
|
||||
});
|
||||
// Trigger export on external button click
|
||||
$('#btnDownloadReport').on('click', function() {
|
||||
DTable.table.button('.buttons-excel').trigger();
|
||||
});
|
||||
|
||||
// detail trip
|
||||
$('#tVehicleTrips').on('click', '.btnDetailTrip', function(e) {
|
||||
e.preventDefault();
|
||||
const vid = $(this).data('vid');
|
||||
const tgl0 = $(this).data('tgl0');
|
||||
const tgl1 = $(this).data('tgl1');
|
||||
const nopol1 = $(this).data('nopol1');
|
||||
|
||||
// $("#mdlDetailTrip").load("{{ route('view_report_trip_detail') }}");
|
||||
$('#mdlDetailTrip').empty().load("{{ route('view_report_trip_detail') }}", `vid=${vid}&tgl0=${tgl0}&tgl1=${tgl1}&nopol1=${nopol1}`, () => {
|
||||
$('#mdlDetailTrip').modal('show')
|
||||
})
|
||||
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const DTable = {
|
||||
table: null,
|
||||
lastAjax: null, // keep track of the last ajax request
|
||||
activate: function() {
|
||||
DTable.reload();
|
||||
},
|
||||
reload: function() {
|
||||
// Abort the last request if it's still running
|
||||
if (DTable.lastAjax) {
|
||||
DTable.lastAjax.abort();
|
||||
}
|
||||
if (DTable.table) {
|
||||
// If table already exists → reload
|
||||
DTable.table.ajax.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
DTable.table = $('#tVehicleTrips').DataTable({
|
||||
searching: false, // 🔹 remove search box
|
||||
ordering: false, // 🔹 disable sorting for all columns
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
bLengthChange: true,
|
||||
deferRender: true,
|
||||
destroy: true,
|
||||
ajax: function(data, callback, settings) {
|
||||
// Abort previous
|
||||
if (DTable.lastAjax) {
|
||||
DTable.lastAjax.abort();
|
||||
}
|
||||
|
||||
// Fire new request
|
||||
DTable.lastAjax = $.ajax({
|
||||
url: `{{ route('api_report_vehicle_trips_list') }}?
|
||||
cptid=${AppState.current_company}
|
||||
&from_date=${moment($('#tgl0').val(), "DD-MM-YYYY HH:mm").unix()}
|
||||
&to_date=${moment($('#tgl1').val(), "DD-MM-YYYY HH:mm").unix()}
|
||||
&vid=${$('#filterNopol').val() || ''}
|
||||
`,
|
||||
type: 'GET',
|
||||
success: function(json) {
|
||||
callback(json);
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
if (status !== 'abort') {
|
||||
console.error("AJAX error:", error);
|
||||
}
|
||||
},
|
||||
complete: function() {
|
||||
DTable.lastAjax = null;
|
||||
}
|
||||
});
|
||||
},
|
||||
deferRender: true,
|
||||
columns: [
|
||||
{ data: 'id', visible: false }, // vhc_id
|
||||
{
|
||||
data: 'nopol1',
|
||||
className: 'text-start',
|
||||
visible: true,
|
||||
orderable: true,
|
||||
searchable: true,
|
||||
},
|
||||
{ data: "dc_code", className: 'text-start'},
|
||||
{ data: "pool_code", className: 'text-start'},
|
||||
{ data: "total_trip", className: 'text-end'},
|
||||
{ data: "total_mileage", className: 'text-end', render: (data, type, row, meta) => parseFloat(data).toFixed(2)},
|
||||
{ data: "trip_id", className: 'text-end'},
|
||||
{
|
||||
data: 'start',
|
||||
render: (data, type, row, meta) => {
|
||||
// let addr = row
|
||||
return `
|
||||
${moment.unix(data + AppState.TIMEFIX).format('DD MMM YYYY HH:mm:ss')}<br>
|
||||
${Helper.shortenText(decodeURIComponent(row.startLoc || 'address'), 255) || "-"}
|
||||
`;
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 'finish',
|
||||
render: (data, type, row, meta) => {
|
||||
// let addr = row
|
||||
return `
|
||||
${moment.unix(data + AppState.TIMEFIX).format('DD MMM YYYY HH:mm:ss')}<br>
|
||||
${Helper.shortenText(decodeURIComponent(row.finishLoc || 'address'), 255) || "-"}
|
||||
`;
|
||||
}
|
||||
},
|
||||
{
|
||||
className: 'text-start', render: function(data, type, row, meta) {
|
||||
const start = moment.unix(row.start);
|
||||
const finish = moment.unix(row.finish);
|
||||
|
||||
// calculate duration
|
||||
const diff = moment.duration(finish.diff(start));
|
||||
const hours = Math.floor(diff.asHours());
|
||||
const minutes = diff.minutes();
|
||||
|
||||
return `${hours}h ${minutes}m`;
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 'startMileage',
|
||||
className: 'text-end', render: function(data, type, row, meta) {
|
||||
return (data === null) ? '0' : parseFloat(data).toFixed(0);
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 'finishMileage',
|
||||
className: 'text-end', render: function(data, type, row, meta) {
|
||||
return (data === null) ? '0' : parseFloat(data).toFixed(0);
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 'mileage',
|
||||
className: 'text-end', render: function(data, type, row, meta) {
|
||||
const mileage = (row.finishMileage !== null && row.startMileage !== null) ? (row.finishMileage - row.startMileage) : row.mileage;
|
||||
return (parseFloat(mileage).toFixed(2));
|
||||
}
|
||||
},
|
||||
{
|
||||
// visible: false,
|
||||
data: 'vhc_id',
|
||||
className: 'text-center',
|
||||
render: function(data, type, row, meta) {
|
||||
let action = `
|
||||
<a href="#" class="text-decoration-none me-1 btnDetailTrip"
|
||||
data-vid="${data}" data-tgl0="${row.start}" data-tgl1="${row.finish}" data-nopol1="${row.nopol1}">
|
||||
<span class="icon ion-eye fz-16"></span>
|
||||
</a>
|
||||
`;
|
||||
return action;
|
||||
}
|
||||
},
|
||||
],
|
||||
paging: false,
|
||||
drawCallback: function (settings) {
|
||||
const api = this.api();
|
||||
const rows = api.rows({ page: 'current' }).nodes();
|
||||
let last = null;
|
||||
|
||||
api.column(0, { page: 'current' }) // vhc_id col
|
||||
.data()
|
||||
.each(function (group, i) {
|
||||
if (last !== group) {
|
||||
// count how many rows this vhc_id spans
|
||||
const rowspanCount = api
|
||||
.column(0, { page: 'current' })
|
||||
.data()
|
||||
.filter(function (d) {
|
||||
return d === group;
|
||||
}).length;
|
||||
|
||||
// merge vhc_id
|
||||
$(rows).eq(i).find('td:eq(0)').attr('rowspan', rowspanCount);
|
||||
$(rows).eq(i).find('td:eq(1)').attr('rowspan', rowspanCount);
|
||||
$(rows).eq(i).find('td:eq(2)').attr('rowspan', rowspanCount);
|
||||
$(rows).eq(i).find('td:eq(3)').attr('rowspan', rowspanCount);
|
||||
$(rows).eq(i).find('td:eq(4)').attr('rowspan', rowspanCount);
|
||||
|
||||
// $(rows).eq(i).find('td:eq(3)').attr('rowspan', rowspanCount);
|
||||
|
||||
last = group;
|
||||
} else {
|
||||
// remove duplicate cells
|
||||
$(rows).eq(i).find('td:eq(0)').remove();
|
||||
$(rows).eq(i).find('td:eq(0)').remove();
|
||||
$(rows).eq(i).find('td:eq(0)').remove();
|
||||
$(rows).eq(i).find('td:eq(0)').remove();
|
||||
$(rows).eq(i).find('td:eq(0)').remove();
|
||||
// $(rows).eq(i).find('td:eq(0)').remove();
|
||||
}
|
||||
});
|
||||
},
|
||||
buttons: [
|
||||
{
|
||||
extend: 'excelHtml5',
|
||||
title: () => {
|
||||
return `
|
||||
Vehicle Trip Report -
|
||||
${moment($('#tgl0').val(), "DD-MM-YYYY HH:mm").format('DD MMM YYYY HH:mm')}
|
||||
to
|
||||
${moment($('#tgl1').val(), "DD-MM-YYYY HH:mm").format('DD MMM YYYY HH:mm')}`
|
||||
},
|
||||
className: 'd-none', // hide default button
|
||||
exportOptions: {
|
||||
columns: ':visible:not(:last-child)' //
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
function safeVal(selector) {
|
||||
const val = $(selector).val();
|
||||
return (val === undefined || val === null || val === '') ? null : val;
|
||||
}
|
||||
|
||||
async function convertImgHtmlToFile(imgHtml, imgWidth, imgHeight, mimeType, fileName) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
let canvas = document.createElement("canvas")
|
||||
|
||||
// Draw image to canvas.
|
||||
canvas.width = imgWidth
|
||||
canvas.height = imgHeight
|
||||
let ctx = canvas.getContext('2d')
|
||||
ctx.drawImage(imgHtml, 0, 0)
|
||||
|
||||
// Convert canvas to ImageState.
|
||||
let imageData = ctx.getImageData(0, 0, imgWidth, imgHeight)
|
||||
// console.log(imageState.data.byteLength + ' bytes.')
|
||||
|
||||
// Convert canvas to Blob
|
||||
canvas.toBlob((blob) => {
|
||||
let newReader = new FileReader();
|
||||
newReader.addEventListener('loadend', () => {
|
||||
// Convert canvas to ArrayBuffer
|
||||
let arrayBuffer = newReader.result
|
||||
// console.log(arrayBuffer.byteLength + ' bytes.')
|
||||
|
||||
// Convert ArrayBuffer to Blob
|
||||
// let blob = new Blob([arrayBuffer], {type: mimeType})
|
||||
|
||||
// Dispay Blob content in an Image.
|
||||
// console.log(URL.createObjectURL(blob))
|
||||
|
||||
// Generate as file
|
||||
let newFile = new File([arrayBuffer], fileName, {
|
||||
type: mimeType,
|
||||
lastModified: new Date(),
|
||||
size: arrayBuffer.byteLength,
|
||||
})
|
||||
resolve(newFile)
|
||||
});
|
||||
newReader.readAsArrayBuffer(blob);
|
||||
}, mimeType);
|
||||
} catch (e) {
|
||||
reject(e.message)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Wrapper.activate();
|
||||
</script>
|
||||
@endsection
|
||||
@ -77,7 +77,19 @@
|
||||
@foreach ($permission as $module => $perms)
|
||||
<div class="mb-3 row">
|
||||
<label for="add-first_name" class="form-label text-capitalize col-3">
|
||||
{{ $module == 'transaction' ? 'job' : ($module == 'client' ? 'company' : ($module == 'config_truck_type' ? 'Config Vehicle Type' : ($module == 'config_master_device' ? 'Config Master Devices' : ($module == 'config_logs_gps' ? 'Config Logs GPS' : $module)))) }}
|
||||
{{
|
||||
$module == 'transaction' ? 'job' :
|
||||
($module == 'client' ? 'company' :
|
||||
($module == 'config_truck_type' ? 'Config Vehicle Type' :
|
||||
($module == 'config_master_device' ? 'Config Master Devices' :
|
||||
($module == 'config_logs_gps' ? 'Config Logs GPS' :
|
||||
($module == 'config_distribution_category' ? 'Config Distribution Category' :
|
||||
($module == 'config_pool' ? 'Config Pool' :
|
||||
($module == 'report_vehicle_trip' ? 'Report Vehicle Trip' :
|
||||
($module == 'report_abnormality' ? 'Report Abnormality' :
|
||||
($module == 'user_logs' ? 'Config User Activity' : $module
|
||||
)))))))))
|
||||
}}
|
||||
</label>
|
||||
<div class="col-9">
|
||||
<div class="d-flex flex-wrap align-items-center gap-2">
|
||||
@ -125,7 +137,19 @@
|
||||
@foreach ($permission as $module => $perms)
|
||||
<div class="mb-3 row">
|
||||
<label for="add-first_name" class="form-label text-capitalize col-3">
|
||||
{{ $module == 'transaction' ? 'job' : ($module == 'client' ? 'company' : ($module == 'config_truck_type' ? 'Config Vehicle Type' : ($module == 'config_master_device' ? 'Config Master Devices' : ($module == 'config_logs_gps' ? 'Config Logs GPS' : $module)))) }}
|
||||
{{
|
||||
$module == 'transaction' ? 'job' :
|
||||
($module == 'client' ? 'company' :
|
||||
($module == 'config_truck_type' ? 'Config Vehicle Type' :
|
||||
($module == 'config_master_device' ? 'Config Master Devices' :
|
||||
($module == 'config_logs_gps' ? 'Config Logs GPS' :
|
||||
($module == 'config_distribution_category' ? 'Config Distribution Category' :
|
||||
($module == 'config_pool' ? 'Config Pool' :
|
||||
($module == 'report_vehicle_trip' ? 'Report Vehicle Trip' :
|
||||
($module == 'report_abnormality' ? 'Report Abnormality' :
|
||||
($module == 'user_logs' ? 'Config User Activity' : $module
|
||||
)))))))))
|
||||
}}
|
||||
</label>
|
||||
<div class="col-9">
|
||||
<div class="d-flex flex-wrap align-items-center gap-2">
|
||||
|
||||
263
resources/views/menu_v1/userLogs.blade.php
Normal file
263
resources/views/menu_v1/userLogs.blade.php
Normal file
@ -0,0 +1,263 @@
|
||||
@php
|
||||
$user_role = Auth::user()->role;
|
||||
@endphp
|
||||
|
||||
@extends('app.app')
|
||||
|
||||
@section('title')
|
||||
User Activity
|
||||
@endsection
|
||||
|
||||
@section('customcss')
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
|
||||
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
|
||||
crossorigin=""
|
||||
/>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid">
|
||||
<div class="content">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="row d-flex align-items-center">
|
||||
<div class="col-3">
|
||||
<p class="card-title text-bold mb-0">User Activity</p>
|
||||
</div>
|
||||
<div class="col-auto text-end ps-0">
|
||||
<!-- <button class="btn btn-sm btn-danger">Download</button> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- filter -->
|
||||
<div class="row">
|
||||
<div class="col-2">
|
||||
<div class="form-group">
|
||||
<label class="text-muted">From</label>
|
||||
<!-- default today -->
|
||||
<!-- <input class="form-control" id="tgl0" value="02-09-2025 00:00"> -->
|
||||
<input class="form-control" id="tgl0" value="{{ date('d-m-Y 00:00') }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="form-group">
|
||||
<label class="text-muted">To</label>
|
||||
<!-- <input class="form-control" id="tgl1" value="02-09-2025 23:00"> -->
|
||||
<input class="form-control" id="tgl1" value="{{ date('d-m-Y 23:59') }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="form-group">
|
||||
<label class="text-muted">User</label>
|
||||
<select name="user" class="form-control" id="filterUser">
|
||||
<option value="">-- All --</option>
|
||||
@foreach ($users as $user)
|
||||
<option value="{{ $user->id }}">{{ $user->email }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1 d-flex align-items-end">
|
||||
<button class="btn btn-primary" id="submitFilter">Submit</button>
|
||||
</div>
|
||||
<div class="col-5 d-flex align-items-end">
|
||||
<button class="btn btn-sm btn-danger ms-auto" id="btnDownloadReport">Download Report</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive p-3">
|
||||
<table id="tLogs" class="table table-hover dataTable w-100">
|
||||
<thead>
|
||||
<tr class="">
|
||||
<th class="">Time</th>
|
||||
<th class="">User</th>
|
||||
<th class="">Module</th>
|
||||
<th class="">Description</th>
|
||||
<th class="">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@section('customjs')
|
||||
<script src="{{ asset('assets/js/load-image.all.min.js') }}"></script>
|
||||
<!-- DataTables Buttons + JSZip (for Excel export) -->
|
||||
<script src="https://cdn.datatables.net/buttons/2.4.2/js/dataTables.buttons.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
|
||||
<script src="https://cdn.datatables.net/buttons/2.4.2/js/buttons.html5.min.js"></script>
|
||||
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js" integrity="sha512-ozq8xQKq6urvuU6jNgkfqAmT7jKN2XumbrX1JiB3TnF7tI48DPI4Gy1GXKD/V3EExgAs1V+pRO7vwtS1LHg0Gw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> -->
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
|
||||
<script src="https://unpkg.com/leaflet-routing-machine@3.2.12/dist/leaflet-routing-machine.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
||||
<script src="{{ asset('assets/vendor/printThis.js') }}"></script>
|
||||
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
const Wrapper = {
|
||||
activate: function() {
|
||||
Wrapper.init();
|
||||
Wrapper.event();
|
||||
DTable.activate();
|
||||
},
|
||||
init: ()=>{
|
||||
$('.time').each(function () {
|
||||
const unix = parseInt($(this).text().trim()) + AppState.TIMEFIX;
|
||||
$(this).text(moment.unix(unix).format('DD MMM YYYY HH:mm:ss'));
|
||||
});
|
||||
$('#tgl0, #tgl1').datetimepicker({
|
||||
format:'d-m-Y H:i',
|
||||
defaultTime:'00:00',
|
||||
closeOnDateSelect: true,
|
||||
// mask:true
|
||||
});
|
||||
},
|
||||
event: function() {
|
||||
$('#submitFilter').on('click', function() {
|
||||
DTable.reload();
|
||||
});
|
||||
// Trigger export on external button click
|
||||
$('#btnDownloadReport').on('click', function() {
|
||||
DTable.table.button('.buttons-excel').trigger();
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const DTable = {
|
||||
table: null,
|
||||
lastAjax: null, // keep track of the last ajax request
|
||||
activate: function() {
|
||||
DTable.reload();
|
||||
},
|
||||
reload: function() {
|
||||
// Abort the last request if it's still running
|
||||
if (DTable.lastAjax) {
|
||||
DTable.lastAjax.abort();
|
||||
}
|
||||
if (DTable.table) {
|
||||
// If table already exists → reload
|
||||
DTable.table.ajax.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
DTable.table = $('#tLogs').DataTable({
|
||||
searching: false, // 🔹 remove search box
|
||||
ordering: false, // 🔹 disable sorting for all columns
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
bLengthChange: true,
|
||||
deferRender: true,
|
||||
destroy: true,
|
||||
ajax: function(data, callback, settings) {
|
||||
// Abort previous
|
||||
if (DTable.lastAjax) {
|
||||
DTable.lastAjax.abort();
|
||||
}
|
||||
|
||||
// Fire new request
|
||||
DTable.lastAjax = $.ajax({
|
||||
url: `{{ route('api_user_logs') }}?
|
||||
tgl0=${moment($('#tgl0').val(), "DD-MM-YYYY HH:mm").unix()}
|
||||
&tgl1=${moment($('#tgl1').val(), "DD-MM-YYYY HH:mm").unix()}
|
||||
&userId=${$('#filterUser').val() || ''}
|
||||
`,
|
||||
type: 'GET',
|
||||
success: function(json) {
|
||||
callback(json);
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
if (status !== 'abort') {
|
||||
console.error("AJAX error:", error);
|
||||
}
|
||||
},
|
||||
complete: function() {
|
||||
DTable.lastAjax = null;
|
||||
}
|
||||
});
|
||||
},
|
||||
deferRender: true,
|
||||
columns: [
|
||||
{
|
||||
data: 'crt',
|
||||
render: (data, type, row, meta) => {
|
||||
// let addr = row
|
||||
return `
|
||||
${moment.unix(data).format('DD MMM YYYY HH:mm:ss')}<br>
|
||||
`;
|
||||
}
|
||||
|
||||
},
|
||||
{ data: 'email' },
|
||||
{
|
||||
data: 'log',
|
||||
render: (data, type, row, meta) => {
|
||||
let log = JSON.parse(data);
|
||||
let module = log.module || '-';
|
||||
return module;
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 'log',
|
||||
render: (data, type, row, meta) => {
|
||||
let log = JSON.parse(data);
|
||||
let desc = log.desc || '-';
|
||||
return desc;
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 'log',
|
||||
render: (data, type, row, meta) => {
|
||||
let log = JSON.parse(data);
|
||||
let action = log.action || '-';
|
||||
|
||||
// use badge for action
|
||||
// action = `<span class="badge bg-secondary">${action}</span>`;
|
||||
let badge = '';
|
||||
if (action.toLowerCase() === 'create') {
|
||||
badge = `<span class="badge bg-success">${action}</span>`;
|
||||
} else if (action.toLowerCase() === 'update') {
|
||||
badge = `<span class="badge bg-warning">${action}</span>`;
|
||||
} else if (action.toLowerCase() === 'delete') {
|
||||
badge = `<span class="badge bg-danger">${action}</span>`;
|
||||
} else {
|
||||
badge = `<span class="badge bg-secondary">${action}</span>`;
|
||||
}
|
||||
return badge;
|
||||
}
|
||||
},
|
||||
],
|
||||
paging: false,
|
||||
buttons: [
|
||||
{
|
||||
extend: 'excelHtml5',
|
||||
title: () => {
|
||||
return `
|
||||
User Activity Report -
|
||||
${moment($('#tgl0').val(), "DD-MM-YYYY HH:mm").format('DD MMM YYYY HH:mm')}
|
||||
to
|
||||
${moment($('#tgl1').val(), "DD-MM-YYYY HH:mm").format('DD MMM YYYY HH:mm')}`
|
||||
},
|
||||
className: 'd-none', // hide default button
|
||||
// exportOptions: {
|
||||
// columns: ':visible:not(:last-child)' //
|
||||
// }
|
||||
}
|
||||
]
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
Wrapper.activate();
|
||||
</script>
|
||||
@endsection
|
||||
@ -7,8 +7,8 @@
|
||||
@section('customcss')
|
||||
<style>
|
||||
/* .select2-container {
|
||||
z-index: 99999;
|
||||
} */
|
||||
z-index: 99999;
|
||||
} */
|
||||
</style>
|
||||
@endsection
|
||||
|
||||
@ -164,7 +164,7 @@
|
||||
<option value="{{ \App\Models\Users::CHK_TYPE_DROP }}">Drop</option>
|
||||
</select>
|
||||
</div> --}}
|
||||
<div id="add-otherInformationGroup" class="d-none">
|
||||
{{-- <div id="add-otherInformationGroup" class="d-none">
|
||||
<div class="mb-2"> </div>
|
||||
<h6>Informasi Lainnya</h6>
|
||||
<div id="add-bankInformationGroup" class="d-none">
|
||||
@ -189,16 +189,8 @@
|
||||
<label for="add-acc_name" class="form-label">Pemilik Rekening</label>
|
||||
<input type="text" class="form-control form-control-sm" name="add-acc_name" id="add-acc_name">
|
||||
</div>
|
||||
{{-- <div class="mb-3">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" name="add_isVdrBcng" type="checkbox" value="no" id="add_isVdrBcng">
|
||||
<label class="form-check-label text-danger" for="add_isVdrBcng">
|
||||
Vendor Bonceng ?
|
||||
</label>
|
||||
</div>
|
||||
</div> --}}
|
||||
</div>
|
||||
</div>
|
||||
</div> --}}
|
||||
<div class="mb-2"> </div>
|
||||
<h6>Utilities</h6>
|
||||
<div class="mb-3">
|
||||
@ -208,6 +200,13 @@
|
||||
<label class="form-check-label" for="add-status"><span class="text-dark" id="add-txtStatus">Inactive</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="add-status-sms" class="form-label">SMS Notification</label>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="add-status-sms">
|
||||
<label class="form-check-label" for="add-status-sms"><span class="text-dark" id="add-txtStatusSms">Inactive</span></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="add-group_track_vhc" class="row">
|
||||
@ -305,7 +304,7 @@
|
||||
<option value="{{ \App\Models\Users::CHK_TYPE_DROP }}">Drop</option>
|
||||
</select>
|
||||
</div> --}}
|
||||
<div id="updt-otherInformationGroup" class="d-none">
|
||||
{{-- <div id="updt-otherInformationGroup" class="d-none">
|
||||
<div class="mb-2"> </div>
|
||||
<h6>Informasi Lainnya</h6>
|
||||
<div id="updt-bankInformationGroup" class="d-none">
|
||||
@ -330,17 +329,9 @@
|
||||
<label for="updt-acc_name" class="form-label">Pemilik Rekening</label>
|
||||
<input type="text" class="form-control form-control-sm" name="updt-acc_name" id="updt-acc_name">
|
||||
</div>
|
||||
{{-- <div class="mb-3">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" name="updt_isVdrBcng" type="checkbox" value="no" id="updt_isVdrBcng">
|
||||
<label class="form-check-label text-danger" for="updt_isVdrBcng">
|
||||
Vendor Bonceng ?
|
||||
</label>
|
||||
</div>
|
||||
</div> --}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-2"> </div>
|
||||
<div class="mb-2"> </div> --}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@ -398,6 +389,13 @@
|
||||
<label class="form-check-label" for="updt-status"><span class="text-dark" id="updt-txtStatus">Inactive</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="updt-status-sms" class="form-label">SMS Notification</label>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="updt-status-sms">
|
||||
<label class="form-check-label" for="updt-status-sms"><span class="text-dark" id="updt-txtStatusSMS">Inactive</span></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -439,6 +437,11 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" data-bs-backdrop="static" data-bs-keyboard="false" id="mdlUserLogs" aria-labelledby="mdlUserLogsLabel" aria-hidden="true">
|
||||
<!-- ajax -->
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@section('customjs')
|
||||
@ -472,39 +475,41 @@
|
||||
Filter.activate();
|
||||
},
|
||||
event: function() {
|
||||
$('#add-status').bind('change', function() {
|
||||
if ($(this).is(':checked'))
|
||||
$('#add-txtStatus').html('Active')
|
||||
else
|
||||
$('#add-txtStatus').html('Inactive')
|
||||
$('#add-status, #add-status-sms, #updt-status, #updt-status-sms').bind('change', function() {
|
||||
const labelSpan = $(this).closest('.form-check').find('span');
|
||||
labelSpan.html($(this).is(':checked') ? 'Active' : 'Inactive');
|
||||
// if ($(this).is(':checked'))
|
||||
// $('#add-txtStatus').html('Active')
|
||||
// else
|
||||
// $('#add-txtStatus').html('Inactive')
|
||||
});
|
||||
$('#updt-status').bind('change', function() {
|
||||
if ($(this).is(':checked'))
|
||||
$('#updt-txtStatus').html('Active')
|
||||
else
|
||||
$('#updt-txtStatus').html('Inactive')
|
||||
});
|
||||
$('#add-roles').on('change', function() {
|
||||
let role = $('#add-roles').val();
|
||||
if (role == State.user_roles.checker) {
|
||||
$('#add-group-chk_type').removeClass('d-none');
|
||||
$('#add-group_track_vhc').addClass('d-none');
|
||||
// $('#updt-status').bind('change', function() {
|
||||
// if ($(this).is(':checked'))
|
||||
// $('#updt-txtStatus').html('Active')
|
||||
// else
|
||||
// $('#updt-txtStatus').html('Inactive')
|
||||
// });
|
||||
// $('#add-roles').on('change', function() {
|
||||
// let role = $('#add-roles').val();
|
||||
// if (role == State.user_roles.checker) {
|
||||
// $('#add-group-chk_type').removeClass('d-none');
|
||||
// $('#add-group_track_vhc').addClass('d-none');
|
||||
|
||||
$('#add-otherInformationGroup').addClass('d-none');
|
||||
$('#add-bankInformationGroup').addClass('d-none');
|
||||
} else if (role == State.user_roles.vendor) {
|
||||
$('#add-otherInformationGroup').removeClass('d-none');
|
||||
$('#add-bankInformationGroup').removeClass('d-none');
|
||||
// $('#add-otherInformationGroup').addClass('d-none');
|
||||
// $('#add-bankInformationGroup').addClass('d-none');
|
||||
// } else if (role == State.user_roles.vendor) {
|
||||
// $('#add-otherInformationGroup').removeClass('d-none');
|
||||
// $('#add-bankInformationGroup').removeClass('d-none');
|
||||
|
||||
$('#add-group-chk_type').addClass('d-none');
|
||||
$('#add-group_track_vhc').removeClass('d-none');
|
||||
} else {
|
||||
$('#add-group-chk_type').addClass('d-none');
|
||||
$('#add-group_track_vhc').removeClass('d-none');
|
||||
$('#add-otherInformationGroup').addClass('d-none');
|
||||
$('#add-bankInformationGroup').addClass('d-none');
|
||||
}
|
||||
});
|
||||
// $('#add-group-chk_type').addClass('d-none');
|
||||
// $('#add-group_track_vhc').removeClass('d-none');
|
||||
// } else {
|
||||
// $('#add-group-chk_type').addClass('d-none');
|
||||
// $('#add-group_track_vhc').removeClass('d-none');
|
||||
// $('#add-otherInformationGroup').addClass('d-none');
|
||||
// $('#add-bankInformationGroup').addClass('d-none');
|
||||
// }
|
||||
// });
|
||||
$('#updt-roles').on('change', function() {
|
||||
let role = $('#updt-roles').val();
|
||||
if (role == State.user_roles.checker) {
|
||||
@ -635,10 +640,14 @@
|
||||
// <span class="icon ion-eye fz-16"></span>
|
||||
// </a>
|
||||
let action = `
|
||||
<a href="#" class="text-decoration-none me-1 btnEdtUser" data-bs-toggle="tooltip"
|
||||
<a href="#" class="text-decoration-none me-2 btnEdtUser" data-bs-toggle="tooltip"
|
||||
data-bs-placement="bottom" title="Edit">
|
||||
<span class="icon ion-eye fz-16"></span>
|
||||
</a>
|
||||
<a href="#" class="text-decoration-none me-2 btnLogUser" data-bs-toggle="tooltip" data-id="${row.id}"
|
||||
data-bs-placement="bottom" title="Logs">
|
||||
<span class="icon ion-android-laptop fz-16"></span>
|
||||
</a>
|
||||
`;
|
||||
// <a href="#" class="text-decoration-none text-danger btnDelUser"
|
||||
// data-bs-toggle="tooltip" data-bs-placement="bottom" title="Delete">
|
||||
@ -797,6 +806,8 @@
|
||||
data.status = State.user_status.inactive;
|
||||
}
|
||||
|
||||
data.status_sms = ($('#add-status-sms').prop('checked')) ? 1 : 0;
|
||||
|
||||
data.is_tracking = $('#add-is_tracking').val();
|
||||
data.vehicles = $('#add-vehicles').val();
|
||||
return data;
|
||||
@ -875,6 +886,26 @@
|
||||
}
|
||||
UUpdate.passDataToView(resp.data);
|
||||
});
|
||||
$('#tUsers').on('click', '.btnLogUser', async function(e) {
|
||||
// let uid = $(e.target).closest('tr').find('td[data-id]').data('id');
|
||||
// UUpdate.clearInput();
|
||||
// let resp = await UUpdate.reqData({
|
||||
// uid
|
||||
// });
|
||||
// if (resp.type != 'success') {
|
||||
// Helper.toast('User Not Found', 'just now', 'please try again');
|
||||
// return false;
|
||||
// }
|
||||
// UUpdate.passDataToView(resp.data);
|
||||
|
||||
e.preventDefault();
|
||||
const id = $(this).data('id');
|
||||
$('#mdlUserLogs').empty().load("{{ route('view_user_logs1') }}", `id=${id}`, () => {
|
||||
$('#mdlUserLogs').modal('show')
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
$('#updtUserModal').on('shown.bs.modal', function() {
|
||||
// initiate select2 if there
|
||||
});
|
||||
@ -936,6 +967,8 @@
|
||||
});
|
||||
},
|
||||
passDataToView: function(data) {
|
||||
console.log("data", data);
|
||||
|
||||
$('#updt-first_name').val(data.first_name);
|
||||
$('#updt-fulladdress').val(data.fulladdress);
|
||||
$('#updt-phone').val(data.phone);
|
||||
@ -977,6 +1010,8 @@
|
||||
|
||||
$('#updtUserModal').data('id', data.id);
|
||||
$('#updtUserModal').modal('show');
|
||||
|
||||
$('#updt-status-sms').prop('checked', (data.status_sms == 1) ? true : false).trigger('change');
|
||||
},
|
||||
getData: function() {
|
||||
let data = {};
|
||||
@ -1012,6 +1047,8 @@
|
||||
data.is_tracking = $('#updt-is_tracking').val();
|
||||
data.vehicles = $('#updt-vehicles').val();
|
||||
|
||||
data.status_sms = ($('#updt-status-sms').prop('checked')) ? 1 : 0;
|
||||
|
||||
return data;
|
||||
},
|
||||
submitData: async function(data) {
|
||||
|
||||
@ -134,11 +134,45 @@
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-0">
|
||||
<label for="add-speedlimit" class="col-form-label">Speed Limit (kph):</label>
|
||||
<input type="number" id="add-speedlimit" class="form-control">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="mb-0">
|
||||
<label for="add-speedlimit" class="col-form-label">Speed Limit (kph):</label>
|
||||
<input type="number" id="add-speedlimit" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="mb-0">
|
||||
<label for="add-mileage" class="col-form-label">Current Mileage:</label>
|
||||
<input type="number" id="add-mileage" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="mb-0">
|
||||
<label for="add-dc_code" class="col-form-label">Distribution Category:</label>
|
||||
<select id="add-dc_code" class="form-control" style="width:100%;">
|
||||
<option value="">Choose</option>
|
||||
@foreach ($listDistribution as $distribution)
|
||||
<option value="{{ $distribution->dc_code }}">{{ $distribution->dc_code }} - {{ $distribution->dc_name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="mb-0">
|
||||
<label for="add-pool_code" class="col-form-label">Pool:</label>
|
||||
<select id="add-pool_code" class="form-control" style="width:100%;">
|
||||
<option value="">Choose</option>
|
||||
@foreach ($listPool as $pool)
|
||||
<option value="{{ $pool->pool_code }}">{{ $pool->pool_code }} - {{ $pool->pool_name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{-- Job Data --}}
|
||||
@ -339,10 +373,47 @@
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-0">
|
||||
<label for="edt-speedlimit" class="col-form-label">Speed Limit (kph):</label>
|
||||
<input type="number" id="edt-speedlimit" class="form-control">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="mb-0">
|
||||
<label for="edt-speedlimit" class="col-form-label">Speed Limit (kph):</label>
|
||||
<input type="number" id="edt-speedlimit" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6">
|
||||
<div class="mb-0">
|
||||
<label for="edt-mileage" class="col-form-label">Current Mileage:</label>
|
||||
<input type="number" id="edt-mileage" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="mb-0">
|
||||
<label for="edt-dc_code" class="col-form-label">Distribution Category:</label>
|
||||
<select id="edt-dc_code" class="form-control" style="width:100%;">
|
||||
<option value="">Choose</option>
|
||||
@foreach ($listDistribution as $distribution)
|
||||
<option value="{{ $distribution->dc_code }}">{{ $distribution->dc_code }} - {{ $distribution->dc_name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="mb-0">
|
||||
<label for="edt-pool_code" class="col-form-label">Pool:</label>
|
||||
<select id="edt-pool_code" class="form-control" style="width:100%;">
|
||||
<option value="">Choose</option>
|
||||
@foreach ($listPool as $pool)
|
||||
<option value="{{ $pool->pool_code }}">{{ $pool->pool_code }} - {{ $pool->pool_name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -994,6 +1065,7 @@
|
||||
data.append('type_id', safeVal('#add-type'));
|
||||
data.append('model_id', safeVal('#add-model') ?? 0);
|
||||
data.append('speed_limit', safeVal('#add-speedlimit'));
|
||||
data.append('mileage', safeVal('#add-mileage'));
|
||||
data.append('fuel_capacity', safeVal('#add-fuelcapacity') ?? 0);
|
||||
data.append('fuel_drop_treshold', safeVal('#add-fueldroptreshold') ?? 0);
|
||||
data.append('max_pressure', safeVal('#add-maxpressure') ?? 0);
|
||||
@ -1021,6 +1093,9 @@
|
||||
|
||||
data.append('vendor_id', safeVal('#add-vendor_id'));
|
||||
|
||||
data.append('dc_code', safeVal('#add-dc_code'));
|
||||
data.append('pool_code', safeVal('#add-pool_code'));
|
||||
|
||||
// File input (cek ada file atau tidak)
|
||||
const fvhcFile = $('#add-fvhc-file')[0].files[0];
|
||||
if (fvhcFile) data.append('fvhc_file', fvhcFile);
|
||||
@ -1209,6 +1284,7 @@
|
||||
$('#edt-model').val(data?.model_id).trigger('change');
|
||||
|
||||
$('#edt-speedlimit').val(data?.speed_limit);
|
||||
$('#edt-mileage').val(data?.sum_milleage?.toFixed(2));
|
||||
$('#edt-fuelcapacity').val(data?.fuel_capacity);
|
||||
$('#edt-fueldroptreshold').val(data?.fuel_drop_treshold);
|
||||
$('#edt-maxpressure').val(data?.max_pressure);
|
||||
@ -1241,6 +1317,9 @@
|
||||
|
||||
$('#mdlEdtVhc').data('id', data.vid);
|
||||
$('#mdlEdtVhc').modal('show');
|
||||
|
||||
$('#edt-dc_code').val(data?.dc_code).trigger('change');
|
||||
$('#edt-pool_code').val(data?.pool_code).trigger('change');
|
||||
},
|
||||
removeOptionDevice: function(type) {
|
||||
$(`#edt-deviceid option[data-type='${type}']`).remove();
|
||||
@ -1264,6 +1343,7 @@
|
||||
data.model_id = $('#edt-model').val();
|
||||
|
||||
data.speed_limit = $('#edt-speedlimit').val();
|
||||
data.mileage = $('#edt-mileage').val();
|
||||
data.fuel_capacity = $('#edt-fuelcapacity').val();
|
||||
data.fuel_drop_treshold = $('#edt-fueldroptreshold').val();
|
||||
data.max_pressure = $('#edt-maxpressure').val();
|
||||
@ -1289,6 +1369,9 @@
|
||||
// data.kir_exp = $('#edt-kirexp').val().split('-').reverse().join('-');
|
||||
|
||||
data.vendor_id = $('#edt-vendor_id').val();
|
||||
|
||||
data.dc_code = $('#edt-dc_code').val();
|
||||
data.pool_code = $('#edt-pool_code').val();
|
||||
return data;
|
||||
},
|
||||
submitData: async function(data) {
|
||||
|
||||
@ -21,13 +21,6 @@
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
@can('transaction.view')
|
||||
<li class="nav-item {{ Request::path() == 'user/vendor/transactions' || Request::path() == 'transactions/add/special' ? 'active' : '' }}">
|
||||
<a class="nav-link d-flex align-items-center text-capitalize" aria-current="page" href="{{ url('user/vendor/transactions') }}">
|
||||
Transaction
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
@can('zone.view')
|
||||
<li class="nav-item {{ Request::segment(1) == 'zone' ? 'active' : '' }}">
|
||||
<a class="nav-link d-flex align-items-center text-capitalize" aria-current="page" href="{{ route('view_zone') }}">
|
||||
@ -49,14 +42,33 @@
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
@can('zone.view')
|
||||
<li class="nav-item {{ Request::segment(1) == 'zone' ? 'active' : '' }}">
|
||||
<a class="nav-link d-flex align-items-center text-capitalize" aria-current="page" href="{{ route('view_zone') }}">
|
||||
Zone
|
||||
@if (auth()->user()->can('report_vehicle_trip.view') || auth()->user()->can('report_abnormality.view'))
|
||||
<li class="nav-item dropdown {{ Request::segment(1) == 'reports' ? 'active' : '' }}">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="dropdownConfig" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Reports
|
||||
</a>
|
||||
<ul class="dropdown-menu" style="right: 0; left: auto;" aria-labelledby="dropdownConfig">
|
||||
@can('report_vehicle_trip.view')
|
||||
<li>
|
||||
<a class="dropdown-item {{ Request::segment(2) == 'vehicle-trips' ? 'active' : '' }}" href="{{ route('view_report_vehicle_trips') }}" title="">Vehicle Trips</a>
|
||||
</li>
|
||||
@endcan
|
||||
@can('report_abnormality.view')
|
||||
<li>
|
||||
<a class="dropdown-item {{ Request::segment(2) == 'abnormalities' ? 'active' : '' }}" href="{{ route('view_report_abnormalities') }}" title="">Abnormalities</a>
|
||||
</li>
|
||||
@endcan
|
||||
</ul>
|
||||
</li>
|
||||
@endcan
|
||||
@if (auth()->user()->can('config_truck_type.view') || auth()->user()->can('config_master_device.view') || auth()->user()->can('config_logs_gps.view'))
|
||||
@endif
|
||||
@if (
|
||||
auth()->user()->can('config_truck_type.view') ||
|
||||
auth()->user()->can('config_master_device.view') ||
|
||||
auth()->user()->can('config_logs_gps.view') ||
|
||||
auth()->user()->can('config_distribution_category.view') ||
|
||||
auth()->user()->can('config_pool.view') ||
|
||||
auth()->user()->can('user_logs.view')
|
||||
)
|
||||
<li class="nav-item dropdown {{ Request::segment(1) == 'config' ? 'active' : '' }}">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="dropdownConfig" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Configuration
|
||||
@ -73,10 +85,31 @@
|
||||
</li>
|
||||
@endcan
|
||||
@can('config_logs_gps.view')
|
||||
<li>
|
||||
<li>
|
||||
<a class="dropdown-item {{ Request::segment(2) == 'logs_gps' ? 'active' : '' }}" href="{{ route('view_config_logs_gps') }}" title="">Logs Gps</a>
|
||||
</li>
|
||||
@endcan
|
||||
@can('config_distribution_category.view')
|
||||
<li>
|
||||
<a class="dropdown-item {{ Request::segment(2) == 'distribution_category' ? 'active' : '' }}" href="{{ route('view_config_distribution_category') }}" title="">Distribution Category</a>
|
||||
</li>
|
||||
@endcan
|
||||
@can('config_pool.view')
|
||||
<li>
|
||||
<a class="dropdown-item {{ Request::segment(2) == 'pool' ? 'active' : '' }}" href="{{ route('view_config_pool') }}" title="">Pool</a>
|
||||
</li>
|
||||
@endcan
|
||||
@can('user_logs.view')
|
||||
<li>
|
||||
<a class="dropdown-item {{ Request::segment(1) == 'user_logs' ? 'active' : '' }}" href="{{ route('view_user_logs') }}" title="">User Activity</a>
|
||||
</li>
|
||||
|
||||
<!-- <li class="nav-item {{ Request::segment(1) == 'user_logs' ? 'active' : '' }}">
|
||||
<a class="nav-link d-flex align-items-center text-capitalize" aria-current="page" href="{{ route('view_user_logs') }}">
|
||||
User Logs
|
||||
</a>
|
||||
</li> -->
|
||||
@endcan
|
||||
</ul>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
@ -56,7 +56,7 @@ Route::middleware(["auth", "auth.user"])->group(function () {
|
||||
|
||||
Route::get("/transactions/add", "MenuController@view_transactions_add")
|
||||
->name("view_transactions_add")
|
||||
->middleware("permission:transaction.add");
|
||||
->middleware("permission:transaction.create");
|
||||
|
||||
Route::get("/transactions/download_do", "TransactionController@view_transactions_download_do")->name(
|
||||
"view_transactions_download_do"
|
||||
@ -102,7 +102,7 @@ Route::middleware(["auth", "auth.user"])->group(function () {
|
||||
->middleware("permission:zone.view");
|
||||
Route::get("/zone/add", "ZoneController@view_zone_add")
|
||||
->name("view_zone_add")
|
||||
->middleware("permission:zone.add");
|
||||
->middleware("permission:zone.create");
|
||||
Route::get("/zone/edit/{zid}", "ZoneController@view_zone_edit")
|
||||
->name("view_zone_edit")
|
||||
->middleware("permission:zone.edit");
|
||||
@ -120,6 +120,11 @@ Route::middleware(["auth", "auth.user"])->group(function () {
|
||||
Route::get("/users", "UsersController@view_users")
|
||||
->name("view_users")
|
||||
->middleware("permission:user.view");
|
||||
Route::get("/users/logs", "UsersController@view_user_logs1")->name("view_user_logs1");
|
||||
Route::get("/api/users/logs", "UsersController@api_user_logs1")->name("api_user_logs1");
|
||||
|
||||
Route::get("/user-logs", "UserLogsController@view_user_logs")->name("view_user_logs");
|
||||
Route::get("/api/user-logs", "UserLogsController@api_user_logs")->name("api_user_logs");
|
||||
|
||||
Route::get("/roles", "RolesController@view")
|
||||
->name("view_roles")
|
||||
@ -153,6 +158,33 @@ Route::middleware(["auth", "auth.user"])->group(function () {
|
||||
);
|
||||
Route::get("/config/logbook_keys", "LogbookKeysController@view_lgb_keys")->name("view_config_lgb_keys");
|
||||
|
||||
// config distribution category
|
||||
Route::get("/config/distribution_category", "ConfDistributionController@view_distribution_category")
|
||||
->name("view_config_distribution_category")
|
||||
->middleware("permission:config_distribution_category.view");
|
||||
Route::post("/api/conf/distribution_category", "ConfDistributionController@api_add_distribution_category")->name("api_conf_add_distribution_category");
|
||||
Route::get("/api/conf/distribution_category", "ConfDistributionController@api_list_distribution_category")->name("api_conf_list_distribution_category");
|
||||
Route::get("/api/conf/distribution_category/{id}", "ConfDistributionController@api_show_distribution_category")->name("api_conf_show_distribution_category");
|
||||
Route::delete("/api/conf/distribution_category/{id}", "ConfDistributionController@api_del_distribution_category")->name("api_conf_del_distribution_category");
|
||||
|
||||
// config pool
|
||||
Route::get("/config/pool", "ConfPoolController@view_pool")
|
||||
->name("view_config_pool")
|
||||
->middleware("permission:config_pool.view");
|
||||
Route::post("/api/conf/pool", "ConfPoolController@api_add_pool")->name("api_conf_add_pool");
|
||||
Route::get("/api/conf/pool", "ConfPoolController@api_list_pool")->name("api_conf_list_pool");
|
||||
Route::get("/api/conf/pool/{id}", "ConfPoolController@api_show_pool")->name("api_conf_show_pool");
|
||||
Route::delete("/api/conf/pool/{id}", "ConfPoolController@api_del_pool")->name("api_conf_del_pool")->middleware("permission:config_pool.delete");
|
||||
|
||||
|
||||
// reports
|
||||
Route::get("/reports/vehicle-trips", "ReportsController@view_report_vehicle_trips")->name("view_report_vehicle_trips");
|
||||
Route::get("/reports/vehicle-trips-list", "ReportsController@api_report_vehicle_trips_list")->name("api_report_vehicle_trips_list");
|
||||
Route::get("/reports/vehicle-trip-detail", "ReportsController@view_report_trip_detail")->name("view_report_trip_detail");
|
||||
Route::get("/reports/abnormalities", "ReportsController@view_report_abnormalities")->name("view_report_abnormalities");
|
||||
Route::get("/reports/abnormalities-list", "ReportsController@api_report_abnormalities_list")->name("api_report_abnormalities_list");
|
||||
|
||||
|
||||
Route::get("/user/vendor/transactions", "MenuController@view_user_vendor_transaction")->name(
|
||||
"view_user_vendor_transaction"
|
||||
);
|
||||
@ -252,6 +284,9 @@ Route::middleware(["auth", "auth.user"])->group(function () {
|
||||
Route::get("/api/users/{uid}", "UsersController@api_show_user")->name("api_show_user");
|
||||
Route::post("/api/users", "UsersController@api_add_user")->name("api_add_user");
|
||||
Route::put("/api/users/{uid}", "UsersController@api_edit_user")->name("api_edit_user");
|
||||
Route::put("/api/users/profile/{uid}", "UsersController@api_edit_user_profile")->name(
|
||||
"api_edit_user_profile"
|
||||
);
|
||||
Route::delete("/api/users/{uid}", "UsersController@api_del_user")->name("api_del_user");
|
||||
Route::post("/api/users/search/name", "UsersController@api_search_user_name")->name(
|
||||
"api_search_user_name"
|
||||
|
||||
Reference in New Issue
Block a user