fix login auto detect menu link, and partial update tchnician role dealer
This commit is contained in:
@@ -82,9 +82,28 @@ class TechnicianReportExport implements FromCollection, WithHeadings, WithStyles
|
|||||||
$dealer = \App\Models\Dealer::find($this->dealerId);
|
$dealer = \App\Models\Dealer::find($this->dealerId);
|
||||||
$dealerName = $dealer ? $dealer->name : 'Unknown Dealer';
|
$dealerName = $dealer ? $dealer->name : 'Unknown Dealer';
|
||||||
$this->filterInfo[] = "Dealer: {$dealerName}";
|
$this->filterInfo[] = "Dealer: {$dealerName}";
|
||||||
|
} else {
|
||||||
|
// Check user access for "Semua Dealer"
|
||||||
|
$user = auth()->user();
|
||||||
|
if ($user && $user->role_id) {
|
||||||
|
$role = \App\Models\Role::with('dealers')->find($user->role_id);
|
||||||
|
if ($role) {
|
||||||
|
$technicianReportService = new \App\Services\TechnicianReportService();
|
||||||
|
if ($technicianReportService->isAdminRole($role)) {
|
||||||
|
$this->filterInfo[] = "Dealer: Semua Dealer (Admin)";
|
||||||
|
} else if ($role->dealers->count() > 0) {
|
||||||
|
$dealerNames = $role->dealers->pluck('name')->implode(', ');
|
||||||
|
$this->filterInfo[] = "Dealer: Semua Dealer (Pivot: {$dealerNames})";
|
||||||
} else {
|
} else {
|
||||||
$this->filterInfo[] = "Dealer: Semua Dealer";
|
$this->filterInfo[] = "Dealer: Semua Dealer";
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$this->filterInfo[] = "Dealer: Semua Dealer";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->filterInfo[] = "Dealer: Semua Dealer";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Date range filter
|
// Date range filter
|
||||||
if ($this->startDate && $this->endDate) {
|
if ($this->startDate && $this->endDate) {
|
||||||
@@ -300,8 +319,13 @@ class TechnicianReportExport implements FromCollection, WithHeadings, WithStyles
|
|||||||
|
|
||||||
// Auto-size columns
|
// Auto-size columns
|
||||||
foreach (range('A', $lastColumn) as $column) {
|
foreach (range('A', $lastColumn) as $column) {
|
||||||
|
if ($column === 'A') {
|
||||||
|
// Set specific width for column A (No) - don't auto-size
|
||||||
|
$sheet->getColumnDimension($column)->setWidth(5);
|
||||||
|
} else {
|
||||||
$sheet->getColumnDimension($column)->setAutoSize(true);
|
$sheet->getColumnDimension($column)->setAutoSize(true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
Log::error('Error applying styles: ' . $e->getMessage());
|
Log::error('Error applying styles: ' . $e->getMessage());
|
||||||
@@ -311,7 +335,7 @@ class TechnicianReportExport implements FromCollection, WithHeadings, WithStyles
|
|||||||
public function columnWidths(): array
|
public function columnWidths(): array
|
||||||
{
|
{
|
||||||
$widths = [
|
$widths = [
|
||||||
'A' => 8, // No
|
'A' => 5, // No - reduced from 8 to 5
|
||||||
'B' => 30, // Nama Pekerjaan
|
'B' => 30, // Nama Pekerjaan
|
||||||
'C' => 15, // Kode Pekerjaan
|
'C' => 15, // Kode Pekerjaan
|
||||||
'D' => 20, // Kategori
|
'D' => 20, // Kategori
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Auth;
|
|||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Privilege;
|
use App\Models\Privilege;
|
||||||
|
use App\Models\User;
|
||||||
use App\Providers\RouteServiceProvider;
|
use App\Providers\RouteServiceProvider;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||||
@@ -50,11 +51,39 @@ class LoginController extends Controller
|
|||||||
*/
|
*/
|
||||||
protected function authenticated(Request $request, $user)
|
protected function authenticated(Request $request, $user)
|
||||||
{
|
{
|
||||||
$user = Privilege::where('menu_id', 10)->where('role_id', Auth::user()->role_id)->where('view', 1)->first();
|
// Get user's role_id
|
||||||
|
$roleId = Auth::user()->role_id;
|
||||||
|
|
||||||
if ($user != null) {
|
if (!$roleId) {
|
||||||
return redirect()->route('dashboard');
|
// User has no role, redirect to default
|
||||||
}else{
|
return redirect(RouteServiceProvider::HOME);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if user has access to adminarea menu
|
||||||
|
if (!User::roleCanAccessMenu($roleId, 'adminarea')) {
|
||||||
|
// User doesn't have admin area access, redirect to default home
|
||||||
|
return redirect(RouteServiceProvider::HOME);
|
||||||
|
}
|
||||||
|
|
||||||
|
// User has admin area access, get first accessible menu (excluding adminarea and mechanicarea)
|
||||||
|
$firstMenu = Privilege::join('menus', 'privileges.menu_id', '=', 'menus.id')
|
||||||
|
->where('privileges.role_id', $roleId)
|
||||||
|
->where('privileges.view', 1)
|
||||||
|
->whereNotIn('menus.link', ['adminarea', 'mechanicarea'])
|
||||||
|
->select('menus.*', 'privileges.view', 'privileges.create', 'privileges.update', 'privileges.delete')
|
||||||
|
->orderBy('menus.id')
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$firstMenu) {
|
||||||
|
// User has no accessible menus (excluding adminarea/mechanicarea), redirect to default
|
||||||
|
return redirect(RouteServiceProvider::HOME);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Try to redirect to the first accessible menu
|
||||||
|
return redirect()->route($firstMenu->link);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Route doesn't exist, fallback to default home
|
||||||
return redirect(RouteServiceProvider::HOME);
|
return redirect(RouteServiceProvider::HOME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,14 @@ namespace App\Http\Controllers\Reports;
|
|||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Models\Menu;
|
use App\Models\Menu;
|
||||||
|
use App\Models\Role;
|
||||||
use App\Services\TechnicianReportService;
|
use App\Services\TechnicianReportService;
|
||||||
use App\Exports\TechnicianReportExport;
|
use App\Exports\TechnicianReportExport;
|
||||||
use Illuminate\Support\Facades\Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
|
use Illuminate\Support\Facades\DB; // Added DB facade
|
||||||
|
use App\Models\Dealer; // Added Dealer model
|
||||||
|
|
||||||
class ReportTechniciansController extends Controller
|
class ReportTechniciansController extends Controller
|
||||||
{
|
{
|
||||||
@@ -34,18 +37,66 @@ class ReportTechniciansController extends Controller
|
|||||||
public function getDealers()
|
public function getDealers()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
// Get current authenticated user
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
Log::info('Controller: No authenticated user found');
|
||||||
|
return response()->json([
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'User tidak terautentikasi'
|
||||||
|
], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info('Controller: Getting dealers for user:', [
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'user_name' => $user->name,
|
||||||
|
'user_role_id' => $user->role_id,
|
||||||
|
'user_dealer_id' => $user->dealer_id
|
||||||
|
]);
|
||||||
|
|
||||||
$dealers = $this->technicianReportService->getDealers();
|
$dealers = $this->technicianReportService->getDealers();
|
||||||
// Default ke "Semua Dealer" (tidak ada dealer yang terselect)
|
$defaultDealer = $this->technicianReportService->getDefaultDealer();
|
||||||
|
|
||||||
|
Log::info('Controller: Service returned dealers:', [
|
||||||
|
'dealers_count' => $dealers->count(),
|
||||||
|
'dealers' => $dealers->toArray(),
|
||||||
|
'default_dealer' => $defaultDealer ? $defaultDealer->toArray() : null,
|
||||||
|
'default_dealer_id' => $defaultDealer ? $defaultDealer->id : null
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Check if default dealer exists in dealers list
|
||||||
|
if ($defaultDealer && $dealers->count() > 0) {
|
||||||
|
$defaultDealerExists = $dealers->contains('id', $defaultDealer->id);
|
||||||
|
Log::info('Controller: Default dealer validation:', [
|
||||||
|
'default_dealer_id' => $defaultDealer->id,
|
||||||
|
'default_dealer_exists_in_list' => $defaultDealerExists,
|
||||||
|
'available_dealer_ids' => $dealers->pluck('id')->toArray()
|
||||||
|
]);
|
||||||
|
|
||||||
|
// If default dealer doesn't exist in list, use first dealer from list
|
||||||
|
if (!$defaultDealerExists) {
|
||||||
|
Log::info('Controller: Default dealer not in list, using first dealer from list');
|
||||||
|
$defaultDealer = $dealers->first();
|
||||||
|
Log::info('Controller: New default dealer:', $defaultDealer ? $defaultDealer->toArray() : null);
|
||||||
|
}
|
||||||
|
} else if ($defaultDealer === null && $dealers->count() > 0) {
|
||||||
|
// Admin without default dealer - no need to set default
|
||||||
|
Log::info('Controller: Admin without default dealer, no default will be set');
|
||||||
|
}
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'status' => 'success',
|
'status' => 'success',
|
||||||
'data' => $dealers,
|
'data' => $dealers,
|
||||||
'default_dealer' => null
|
'default_dealer' => $defaultDealer ? $defaultDealer->id : null
|
||||||
]);
|
]);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
Log::error('Error getting dealers: ' . $e->getMessage());
|
Log::error('Controller: Error getting dealers: ' . $e->getMessage(), [
|
||||||
|
'trace' => $e->getTraceAsString()
|
||||||
|
]);
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'status' => 'error',
|
'status' => 'error',
|
||||||
'message' => 'Gagal mengambil data dealer'
|
'message' => 'Gagal mengambil data dealer: ' . $e->getMessage()
|
||||||
], 500);
|
], 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,10 +111,23 @@ class ReportTechniciansController extends Controller
|
|||||||
$startDate = $request->input('start_date');
|
$startDate = $request->input('start_date');
|
||||||
$endDate = $request->input('end_date');
|
$endDate = $request->input('end_date');
|
||||||
|
|
||||||
|
// Get current authenticated user
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return response()->json([
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'User tidak terautentikasi'
|
||||||
|
], 401);
|
||||||
|
}
|
||||||
|
|
||||||
Log::info('Requesting technician report data:', [
|
Log::info('Requesting technician report data:', [
|
||||||
'dealer_id' => $dealerId,
|
'dealer_id' => $dealerId,
|
||||||
'start_date' => $startDate,
|
'start_date' => $startDate,
|
||||||
'end_date' => $endDate
|
'end_date' => $endDate,
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'user_role_id' => $user->role_id,
|
||||||
|
'user_dealer_id' => $user->dealer_id
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$reportData = $this->technicianReportService->getTechnicianReportData(
|
$reportData = $this->technicianReportService->getTechnicianReportData(
|
||||||
@@ -116,10 +180,22 @@ class ReportTechniciansController extends Controller
|
|||||||
$startDate = $request->input('start_date');
|
$startDate = $request->input('start_date');
|
||||||
$endDate = $request->input('end_date');
|
$endDate = $request->input('end_date');
|
||||||
|
|
||||||
|
// Get current authenticated user
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'User tidak terautentikasi'
|
||||||
|
], 401);
|
||||||
|
}
|
||||||
|
|
||||||
Log::info('Requesting technician report data for DataTable:', [
|
Log::info('Requesting technician report data for DataTable:', [
|
||||||
'dealer_id' => $dealerId,
|
'dealer_id' => $dealerId,
|
||||||
'start_date' => $startDate,
|
'start_date' => $startDate,
|
||||||
'end_date' => $endDate
|
'end_date' => $endDate,
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'user_role_id' => $user->role_id,
|
||||||
|
'user_dealer_id' => $user->dealer_id
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$reportData = $this->technicianReportService->getTechnicianReportDataForDataTable(
|
$reportData = $this->technicianReportService->getTechnicianReportDataForDataTable(
|
||||||
@@ -153,12 +229,87 @@ class ReportTechniciansController extends Controller
|
|||||||
$startDate = $request->input('start_date');
|
$startDate = $request->input('start_date');
|
||||||
$endDate = $request->input('end_date');
|
$endDate = $request->input('end_date');
|
||||||
|
|
||||||
|
// Get current authenticated user
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return response()->json([
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'User tidak terautentikasi'
|
||||||
|
], 401);
|
||||||
|
}
|
||||||
|
|
||||||
Log::info('Exporting technician report', [
|
Log::info('Exporting technician report', [
|
||||||
'dealer_id' => $dealerId,
|
'dealer_id' => $dealerId,
|
||||||
'start_date' => $startDate,
|
'start_date' => $startDate,
|
||||||
'end_date' => $endDate
|
'end_date' => $endDate,
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'user_role_id' => $user->role_id,
|
||||||
|
'user_dealer_id' => $user->dealer_id
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Validate dealer access for export
|
||||||
|
if ($dealerId) {
|
||||||
|
// User is trying to export specific dealer
|
||||||
|
if ($user->dealer_id) {
|
||||||
|
// User has specific dealer_id, check if they can access the requested dealer
|
||||||
|
if ($user->dealer_id != $dealerId) {
|
||||||
|
if ($user->role_id) {
|
||||||
|
$role = \App\Models\Role::with('dealers')->find($user->role_id);
|
||||||
|
if (!$role || !$role->hasDealer($dealerId)) {
|
||||||
|
return response()->json([
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'Anda tidak memiliki akses untuk export data dealer ini'
|
||||||
|
], 403);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return response()->json([
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'Anda tidak memiliki akses untuk export data dealer ini'
|
||||||
|
], 403);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ($user->role_id) {
|
||||||
|
// User has role, check if they can access the requested dealer
|
||||||
|
$role = \App\Models\Role::with('dealers')->find($user->role_id);
|
||||||
|
if (!$role || !$role->hasDealer($dealerId)) {
|
||||||
|
return response()->json([
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'Anda tidak memiliki akses untuk export data dealer ini'
|
||||||
|
], 403);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// User is trying to export "Semua Dealer" - check if they have permission
|
||||||
|
if ($user->role_id) {
|
||||||
|
$role = \App\Models\Role::with('dealers')->find($user->role_id);
|
||||||
|
if ($role) {
|
||||||
|
// Check if role is admin type
|
||||||
|
$technicianReportService = new \App\Services\TechnicianReportService();
|
||||||
|
if ($technicianReportService->isAdminRole($role)) {
|
||||||
|
// Admin can export all dealers
|
||||||
|
Log::info('Admin user exporting all dealers');
|
||||||
|
} else {
|
||||||
|
// Non-admin with pivot dealers - can only export pivot dealers
|
||||||
|
if ($role->dealers->count() > 0) {
|
||||||
|
Log::info('User with pivot dealers exporting pivot dealers only');
|
||||||
|
} else {
|
||||||
|
return response()->json([
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'Anda tidak memiliki akses untuk export data semua dealer'
|
||||||
|
], 403);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ($user->dealer_id) {
|
||||||
|
// User with specific dealer_id cannot export all dealers
|
||||||
|
return response()->json([
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'Anda hanya dapat export data dealer Anda sendiri'
|
||||||
|
], 403);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Excel::download(new TechnicianReportExport($dealerId, $startDate, $endDate), 'laporan_teknisi_' . date('Y-m-d') . '.xlsx');
|
return Excel::download(new TechnicianReportExport($dealerId, $startDate, $endDate), 'laporan_teknisi_' . date('Y-m-d') . '.xlsx');
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
@@ -175,5 +326,4 @@ class ReportTechniciansController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use App\Models\Menu;
|
|||||||
use App\Models\Privilege;
|
use App\Models\Privilege;
|
||||||
use App\Models\Role;
|
use App\Models\Role;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Models\Dealer;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
|
||||||
@@ -14,10 +15,11 @@ class RolePrivilegeController extends Controller
|
|||||||
public function index() {
|
public function index() {
|
||||||
$menu = Menu::where('link', 'roleprivileges.index')->first();
|
$menu = Menu::where('link', 'roleprivileges.index')->first();
|
||||||
abort_if(Gate::denies('view', $menu), 403, 'Unauthorized User');
|
abort_if(Gate::denies('view', $menu), 403, 'Unauthorized User');
|
||||||
$roles = Role::all();
|
$roles = Role::with('dealers')->get();
|
||||||
$menus = Menu::all();
|
$menus = Menu::all();
|
||||||
$users = User::all();
|
$users = User::all();
|
||||||
return view('back.roleprivileges', compact('roles', 'users', 'menus'));
|
$dealers = Dealer::all();
|
||||||
|
return view('back.roleprivileges', compact('roles', 'users', 'menus', 'dealers'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function store(Request $request) {
|
public function store(Request $request) {
|
||||||
@@ -117,4 +119,36 @@ class RolePrivilegeController extends Controller
|
|||||||
User::where('role_id', $id)->update(['role_id' => 0]);
|
User::where('role_id', $id)->update(['role_id' => 0]);
|
||||||
return redirect()->back()->with('success', 'Berhasil Hapus Role');
|
return redirect()->back()->with('success', 'Berhasil Hapus Role');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function assignDealer(Request $request, $id) {
|
||||||
|
$menu = Menu::where('link', 'roleprivileges.index')->first();
|
||||||
|
abort_if(Gate::denies('create', $menu), 403, 'Unauthorized User');
|
||||||
|
|
||||||
|
$request->validate([
|
||||||
|
'dealers' => 'required|array',
|
||||||
|
'dealers.*' => 'exists:dealers,id'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$role = Role::findOrFail($id);
|
||||||
|
|
||||||
|
// Sync dealers (this will replace existing assignments)
|
||||||
|
$role->dealers()->sync($request->dealers);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Berhasil assign dealer ke role'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAssignedDealers($id) {
|
||||||
|
$menu = Menu::where('link', 'roleprivileges.index')->first();
|
||||||
|
abort_if(Gate::denies('view', $menu), 403, 'Unauthorized User');
|
||||||
|
|
||||||
|
$role = Role::findOrFail($id);
|
||||||
|
$assignedDealers = $role->dealers()->pluck('dealers.id')->toArray();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'assignedDealers' => $assignedDealers
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,4 +82,9 @@ class Dealer extends Model
|
|||||||
{
|
{
|
||||||
return $this->hasMany(WorkDealerPrice::class)->active();
|
return $this->hasMany(WorkDealerPrice::class)->active();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function roles()
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(Role::class, 'role_dealer');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace App\Models;
|
|||||||
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class Role extends Model
|
class Role extends Model
|
||||||
{
|
{
|
||||||
@@ -11,4 +12,19 @@ class Role extends Model
|
|||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name'
|
'name'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public function dealers()
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(Dealer::class, 'role_dealer');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function users()
|
||||||
|
{
|
||||||
|
return $this->hasMany(User::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasDealer($dealerId)
|
||||||
|
{
|
||||||
|
return $this->dealers()->where('dealers.id', $dealerId)->whereNull('dealers.deleted_at')->exists();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,4 +192,113 @@ class User extends Authenticatable
|
|||||||
->where('month', $month)
|
->where('month', $month)
|
||||||
->first();
|
->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function accessibleDealers()
|
||||||
|
{
|
||||||
|
if (!$this->role_id) {
|
||||||
|
return collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load role with dealers
|
||||||
|
if (!$this->relationLoaded('role')) {
|
||||||
|
$this->load('role.dealers');
|
||||||
|
}
|
||||||
|
|
||||||
|
// If user has specific dealer_id, check if role allows access
|
||||||
|
if ($this->dealer_id) {
|
||||||
|
if ($this->role && $this->role->hasDealer($this->dealer_id)) {
|
||||||
|
return Dealer::where('id', $this->dealer_id)->get();
|
||||||
|
}
|
||||||
|
return collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no specific dealer_id, return all dealers accessible by role
|
||||||
|
return $this->role ? $this->role->dealers : collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function canAccessDealer($dealerId)
|
||||||
|
{
|
||||||
|
if (!$this->role_id) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load role with dealers
|
||||||
|
if (!$this->relationLoaded('role')) {
|
||||||
|
$this->load('role.dealers');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->role && $this->role->hasDealer($dealerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPrimaryDealer()
|
||||||
|
{
|
||||||
|
if ($this->dealer_id && $this->canAccessDealer($this->dealer_id)) {
|
||||||
|
return $this->dealer;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all accessible menus for a specific role
|
||||||
|
*
|
||||||
|
* @param int $roleId
|
||||||
|
* @return \Illuminate\Database\Eloquent\Collection
|
||||||
|
*/
|
||||||
|
public static function getAccessibleMenus($roleId)
|
||||||
|
{
|
||||||
|
return \App\Models\Privilege::join('menus', 'privileges.menu_id', '=', 'menus.id')
|
||||||
|
->where('privileges.role_id', $roleId)
|
||||||
|
->where('privileges.view', 1)
|
||||||
|
->select('menus.*', 'privileges.view', 'privileges.create', 'privileges.update', 'privileges.delete')
|
||||||
|
->orderBy('menus.id')
|
||||||
|
->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get accessible menus for current user
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Database\Eloquent\Collection
|
||||||
|
*/
|
||||||
|
public function getMyAccessibleMenus()
|
||||||
|
{
|
||||||
|
if (!$this->role_id) {
|
||||||
|
return collect();
|
||||||
|
}
|
||||||
|
return self::getAccessibleMenus($this->role_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if user can access specific menu
|
||||||
|
*
|
||||||
|
* @param string $menuLink
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function canAccessMenu($menuLink)
|
||||||
|
{
|
||||||
|
if (!$this->role_id) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return \App\Models\Privilege::join('menus', 'privileges.menu_id', '=', 'menus.id')
|
||||||
|
->where('privileges.role_id', $this->role_id)
|
||||||
|
->where('menus.link', $menuLink)
|
||||||
|
->where('privileges.view', 1)
|
||||||
|
->exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if role can access specific menu (static method)
|
||||||
|
*
|
||||||
|
* @param int $roleId
|
||||||
|
* @param string $menuLink
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function roleCanAccessMenu($roleId, $menuLink)
|
||||||
|
{
|
||||||
|
return \App\Models\Privilege::join('menus', 'privileges.menu_id', '=', 'menus.id')
|
||||||
|
->where('privileges.role_id', $roleId)
|
||||||
|
->where('menus.link', $menuLink)
|
||||||
|
->where('privileges.view', 1)
|
||||||
|
->exists();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use App\Models\Work;
|
|||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\Transaction;
|
use App\Models\Transaction;
|
||||||
use App\Models\Dealer;
|
use App\Models\Dealer;
|
||||||
|
use App\Models\Role;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
@@ -18,23 +19,60 @@ class TechnicianReportService
|
|||||||
public function getTechnicianReportData($dealerId = null, $startDate = null, $endDate = null)
|
public function getTechnicianReportData($dealerId = null, $startDate = null, $endDate = null)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// Debug: Check all users and roles
|
// Get current authenticated user
|
||||||
$allUsers = User::with('role')->get();
|
$user = auth()->user();
|
||||||
Log::info('All users in database:', [
|
|
||||||
'total_users' => $allUsers->count(),
|
if (!$user) {
|
||||||
'users_with_roles' => $allUsers->map(function($user) {
|
|
||||||
$roleName = 'No role';
|
|
||||||
if ($user->role) {
|
|
||||||
$roleName = is_string($user->role) ? $user->role : $user->role->name;
|
|
||||||
}
|
|
||||||
return [
|
return [
|
||||||
'id' => $user->id,
|
'data' => [],
|
||||||
'name' => $user->name,
|
'mechanics' => collect(),
|
||||||
'role_id' => $user->role_id,
|
'works' => collect()
|
||||||
'role_name' => $roleName,
|
|
||||||
'dealer_id' => $user->dealer_id
|
|
||||||
];
|
];
|
||||||
})
|
}
|
||||||
|
|
||||||
|
// Validate dealer access
|
||||||
|
if ($dealerId) {
|
||||||
|
if ($user->dealer_id) {
|
||||||
|
// User has specific dealer_id, check if they can access the requested dealer
|
||||||
|
if ($user->dealer_id != $dealerId) {
|
||||||
|
if ($user->role_id) {
|
||||||
|
$role = Role::with('dealers')->find($user->role_id);
|
||||||
|
if (!$role || !$role->hasDealer($dealerId)) {
|
||||||
|
// User doesn't have access to this dealer
|
||||||
|
return [
|
||||||
|
'data' => [],
|
||||||
|
'mechanics' => collect(),
|
||||||
|
'works' => collect()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// User has dealer_id but no role, can only access their dealer
|
||||||
|
return [
|
||||||
|
'data' => [],
|
||||||
|
'mechanics' => collect(),
|
||||||
|
'works' => collect()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ($user->role_id) {
|
||||||
|
// User has role, check if they can access the requested dealer
|
||||||
|
$role = Role::with('dealers')->find($user->role_id);
|
||||||
|
if (!$role || !$role->hasDealer($dealerId)) {
|
||||||
|
// User doesn't have access to this dealer
|
||||||
|
return [
|
||||||
|
'data' => [],
|
||||||
|
'mechanics' => collect(),
|
||||||
|
'works' => collect()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info('Getting technician report data', [
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'dealer_id' => $dealerId,
|
||||||
|
'start_date' => $startDate,
|
||||||
|
'end_date' => $endDate
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Get all works with category in single query
|
// Get all works with category in single query
|
||||||
@@ -42,29 +80,10 @@ class TechnicianReportService
|
|||||||
->orderBy('name')
|
->orderBy('name')
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
// Get all mechanics (users with role name = 'mechanic')
|
// Get mechanics based on dealer and role access
|
||||||
$mechanics = User::with('role')->whereHas('role', function($query) {
|
$mechanics = $this->getMechanicsByDealer($dealerId);
|
||||||
$query->where('name', 'mechanic');
|
|
||||||
})
|
|
||||||
->when($dealerId, function($query) use ($dealerId) {
|
|
||||||
return $query->where('dealer_id', $dealerId);
|
|
||||||
})
|
|
||||||
->orderBy('name')
|
|
||||||
->get(['id', 'name', 'role_id', 'dealer_id']);
|
|
||||||
|
|
||||||
// Fallback: If no mechanics found, get all users with dealer_id
|
Log::info('Mechanics found for report:', [
|
||||||
if ($mechanics->isEmpty()) {
|
|
||||||
Log::info('No users with role "mechanic" found, using fallback: all users with dealer_id');
|
|
||||||
$mechanics = User::with('role')->whereNotNull('dealer_id')
|
|
||||||
->whereNotNull('role_id')
|
|
||||||
->when($dealerId, function($query) use ($dealerId) {
|
|
||||||
return $query->where('dealer_id', $dealerId);
|
|
||||||
})
|
|
||||||
->orderBy('name')
|
|
||||||
->get(['id', 'name', 'role_id', 'dealer_id']);
|
|
||||||
}
|
|
||||||
|
|
||||||
Log::info('Mechanics found:', [
|
|
||||||
'count' => $mechanics->count(),
|
'count' => $mechanics->count(),
|
||||||
'dealer_id_filter' => $dealerId,
|
'dealer_id_filter' => $dealerId,
|
||||||
'mechanics' => $mechanics->map(function($mechanic) {
|
'mechanics' => $mechanics->map(function($mechanic) {
|
||||||
@@ -87,7 +106,12 @@ class TechnicianReportService
|
|||||||
|
|
||||||
Log::info('Transaction data:', [
|
Log::info('Transaction data:', [
|
||||||
'transaction_count' => count($transactions),
|
'transaction_count' => count($transactions),
|
||||||
'sample_transactions' => array_slice($transactions, 0, 5, true)
|
'sample_transactions' => array_slice($transactions, 0, 5, true),
|
||||||
|
'dealer_id_filter' => $dealerId,
|
||||||
|
'is_admin_with_pivot' => $user->role_id ? (function() use ($user) {
|
||||||
|
$role = Role::with('dealers')->find($user->role_id);
|
||||||
|
return $role && $this->isAdminRole($role) && $role->dealers->count() > 0;
|
||||||
|
})() : false
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$data = [];
|
$data = [];
|
||||||
@@ -148,6 +172,46 @@ class TechnicianReportService
|
|||||||
*/
|
*/
|
||||||
private function getOptimizedTransactionData($dealerId = null, $startDate = null, $endDate = null, $mechanicIds = null, $workIds = null)
|
private function getOptimizedTransactionData($dealerId = null, $startDate = null, $endDate = null, $mechanicIds = null, $workIds = null)
|
||||||
{
|
{
|
||||||
|
// Get current authenticated user
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate dealer access
|
||||||
|
if ($dealerId) {
|
||||||
|
if ($user->dealer_id) {
|
||||||
|
// User has specific dealer_id, check if they can access the requested dealer
|
||||||
|
if ($user->dealer_id != $dealerId) {
|
||||||
|
if ($user->role_id) {
|
||||||
|
$role = Role::with('dealers')->find($user->role_id);
|
||||||
|
if (!$role || !$role->hasDealer($dealerId)) {
|
||||||
|
// User doesn't have access to this dealer
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// User has dealer_id but no role, can only access their dealer
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ($user->role_id) {
|
||||||
|
// User has role, check if they can access the requested dealer
|
||||||
|
$role = Role::with('dealers')->find($user->role_id);
|
||||||
|
if (!$role || !$role->hasDealer($dealerId)) {
|
||||||
|
// User doesn't have access to this dealer
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info('Getting optimized transaction data', [
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'dealer_id' => $dealerId,
|
||||||
|
'start_date' => $startDate,
|
||||||
|
'end_date' => $endDate
|
||||||
|
]);
|
||||||
|
|
||||||
$query = Transaction::select(
|
$query = Transaction::select(
|
||||||
'work_id',
|
'work_id',
|
||||||
'user_id',
|
'user_id',
|
||||||
@@ -158,6 +222,15 @@ class TechnicianReportService
|
|||||||
|
|
||||||
if ($dealerId) {
|
if ($dealerId) {
|
||||||
$query->where('dealer_id', $dealerId);
|
$query->where('dealer_id', $dealerId);
|
||||||
|
} else if ($user->role_id) {
|
||||||
|
// Check if admin with pivot dealers and "Semua Dealer" selected
|
||||||
|
$role = Role::with('dealers')->find($user->role_id);
|
||||||
|
if ($role && $this->isAdminRole($role) && $role->dealers->count() > 0) {
|
||||||
|
// Admin with pivot dealers and "Semua Dealer" selected - filter by pivot dealers
|
||||||
|
$accessibleDealerIds = $role->dealers->pluck('id');
|
||||||
|
$query->whereIn('dealer_id', $accessibleDealerIds);
|
||||||
|
Log::info('Admin with pivot dealers, filtering transactions by pivot dealer IDs:', $accessibleDealerIds->toArray());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($startDate) {
|
if ($startDate) {
|
||||||
@@ -179,6 +252,10 @@ class TechnicianReportService
|
|||||||
// Remove index hint that doesn't exist
|
// Remove index hint that doesn't exist
|
||||||
$results = $query->get();
|
$results = $query->get();
|
||||||
|
|
||||||
|
Log::info('Transaction query results', [
|
||||||
|
'results_count' => $results->count()
|
||||||
|
]);
|
||||||
|
|
||||||
// Organize data by work_id_user_id key
|
// Organize data by work_id_user_id key
|
||||||
$organizedData = [];
|
$organizedData = [];
|
||||||
|
|
||||||
@@ -281,16 +358,200 @@ class TechnicianReportService
|
|||||||
*/
|
*/
|
||||||
public function getDealers()
|
public function getDealers()
|
||||||
{
|
{
|
||||||
return Dealer::orderBy('name')->get(['id', 'name', 'dealer_code']);
|
// Get current authenticated user
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
Log::info('No authenticated user found');
|
||||||
|
return collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info('Getting dealers for user:', [
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'user_name' => $user->name,
|
||||||
|
'user_role_id' => $user->role_id,
|
||||||
|
'user_dealer_id' => $user->dealer_id
|
||||||
|
]);
|
||||||
|
|
||||||
|
// If user has role, check role type and dealer access
|
||||||
|
if ($user->role_id) {
|
||||||
|
$role = Role::with(['dealers' => function($query) {
|
||||||
|
$query->whereNull('dealers.deleted_at'); // Only active dealers
|
||||||
|
}])->find($user->role_id);
|
||||||
|
|
||||||
|
Log::info('Role details:', [
|
||||||
|
'role_id' => $role ? $role->id : null,
|
||||||
|
'role_name' => $role ? $role->name : null,
|
||||||
|
'role_dealers_count' => $role ? $role->dealers->count() : 0,
|
||||||
|
'role_dealers' => $role ? $role->dealers->pluck('id', 'name')->toArray() : []
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($role) {
|
||||||
|
// Check if role is admin type
|
||||||
|
if ($this->isAdminRole($role)) {
|
||||||
|
// Admin role - check if has pivot dealers
|
||||||
|
if ($role->dealers->count() > 0) {
|
||||||
|
// Admin with pivot dealers - return pivot dealers (for "Semua Dealer" option)
|
||||||
|
Log::info('Admin role with pivot dealers, returning pivot dealers');
|
||||||
|
$dealers = $role->dealers()->whereNull('dealers.deleted_at')->orderBy('name')->get(['dealers.id', 'dealers.name', 'dealers.dealer_code']);
|
||||||
|
Log::info('Returning pivot dealers for admin:', $dealers->toArray());
|
||||||
|
return $dealers;
|
||||||
|
} else {
|
||||||
|
// Admin without pivot dealers - return all dealers
|
||||||
|
Log::info('Admin role without pivot dealers, returning all dealers');
|
||||||
|
$allDealers = Dealer::whereNull('deleted_at')->orderBy('name')->get(['id', 'name', 'dealer_code']);
|
||||||
|
Log::info('Returning all dealers for admin:', $allDealers->toArray());
|
||||||
|
return $allDealers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Role has dealer relationship (tampilkan dealer berdasarkan pivot)
|
||||||
|
if ($role->dealers->count() > 0) {
|
||||||
|
Log::info('Role has dealers relationship, returning role dealers');
|
||||||
|
$dealers = $role->dealers()->whereNull('dealers.deleted_at')->orderBy('name')->get(['dealers.id', 'dealers.name', 'dealers.dealer_code']);
|
||||||
|
Log::info('Returning dealers from role:', $dealers->toArray());
|
||||||
|
return $dealers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If user has specific dealer_id but no role dealers, check if they can access their dealer_id
|
||||||
|
if ($user->dealer_id) {
|
||||||
|
Log::info('User has specific dealer_id:', ['dealer_id' => $user->dealer_id]);
|
||||||
|
if ($user->role_id) {
|
||||||
|
$role = Role::with(['dealers' => function($query) {
|
||||||
|
$query->whereNull('dealers.deleted_at'); // Only active dealers
|
||||||
|
}])->find($user->role_id);
|
||||||
|
|
||||||
|
if ($role && $role->hasDealer($user->dealer_id)) {
|
||||||
|
Log::info('User can access their dealer_id, returning single dealer');
|
||||||
|
$dealer = Dealer::where('id', $user->dealer_id)->whereNull('deleted_at')->orderBy('name')->get(['id', 'name', 'dealer_code']);
|
||||||
|
Log::info('Returning dealer:', $dealer->toArray());
|
||||||
|
return $dealer;
|
||||||
|
} else {
|
||||||
|
Log::info('User cannot access their dealer_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log::info('User has dealer_id but no role or no access, returning empty');
|
||||||
|
return collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: return all dealers if no restrictions
|
||||||
|
Log::info('No restrictions found, returning all dealers');
|
||||||
|
$allDealers = Dealer::whereNull('deleted_at')->orderBy('name')->get(['id', 'name', 'dealer_code']);
|
||||||
|
Log::info('Returning all dealers:', $allDealers->toArray());
|
||||||
|
return $allDealers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get default dealer for filter (tidak perlu berbasis user)
|
* Check if role is admin type (should show all dealers)
|
||||||
|
*/
|
||||||
|
public function isAdminRole($role)
|
||||||
|
{
|
||||||
|
// Define admin role names that should have access to all dealers
|
||||||
|
$adminRoleNames = [
|
||||||
|
'admin',
|
||||||
|
'super admin',
|
||||||
|
'administrator',
|
||||||
|
'sa',
|
||||||
|
'superadmin'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Check if role name contains admin keywords (but not "area")
|
||||||
|
$roleName = strtolower(trim($role->name));
|
||||||
|
foreach ($adminRoleNames as $adminName) {
|
||||||
|
if (strpos($roleName, $adminName) !== false && strpos($roleName, 'area') === false) {
|
||||||
|
Log::info('Role identified as admin type:', ['role_name' => $role->name]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if role has no dealer restrictions (no pivot relationships)
|
||||||
|
// This means role can access all dealers
|
||||||
|
if ($role->dealers->count() === 0) {
|
||||||
|
Log::info('Role has no dealer restrictions, treating as admin type:', ['role_name' => $role->name]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Role with "area" in name should use pivot dealers, not all dealers
|
||||||
|
if (strpos($roleName, 'area') !== false) {
|
||||||
|
Log::info('Role contains "area", treating as area role (use pivot dealers):', ['role_name' => $role->name]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info('Role is not admin type:', ['role_name' => $role->name]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get default dealer for filter (berbasis user role)
|
||||||
*/
|
*/
|
||||||
public function getDefaultDealer()
|
public function getDefaultDealer()
|
||||||
{
|
{
|
||||||
// Dealer pertama saja jika ada
|
// Get current authenticated user
|
||||||
return Dealer::orderBy('name')->first();
|
$user = auth()->user();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info('Getting default dealer for user:', [
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'user_role_id' => $user->role_id,
|
||||||
|
'user_dealer_id' => $user->dealer_id
|
||||||
|
]);
|
||||||
|
|
||||||
|
// If user has role, check role type and dealer access
|
||||||
|
if ($user->role_id) {
|
||||||
|
$role = Role::with(['dealers' => function($query) {
|
||||||
|
$query->whereNull('dealers.deleted_at'); // Only active dealers
|
||||||
|
}])->find($user->role_id);
|
||||||
|
|
||||||
|
if ($role) {
|
||||||
|
// Check if role is admin type
|
||||||
|
if ($this->isAdminRole($role)) {
|
||||||
|
// Admin role - check if has pivot dealers
|
||||||
|
if ($role->dealers->count() > 0) {
|
||||||
|
// Admin with pivot dealers - return first dealer from pivot
|
||||||
|
Log::info('Admin role with pivot dealers, returning first dealer from pivot');
|
||||||
|
$defaultDealer = $role->dealers()->whereNull('dealers.deleted_at')->orderBy('name')->first();
|
||||||
|
Log::info('Default dealer for admin with pivot:', $defaultDealer ? $defaultDealer->toArray() : null);
|
||||||
|
return $defaultDealer;
|
||||||
|
} else {
|
||||||
|
// Admin without pivot dealers - no default dealer (show all dealers without selection)
|
||||||
|
Log::info('Admin role without pivot dealers, no default dealer');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Role has dealer relationship (return first dealer from role dealers)
|
||||||
|
if ($role->dealers->count() > 0) {
|
||||||
|
Log::info('Role has dealers relationship, returning first dealer from role dealers');
|
||||||
|
$defaultDealer = $role->dealers()->whereNull('dealers.deleted_at')->orderBy('name')->first();
|
||||||
|
Log::info('Default dealer from role dealers:', $defaultDealer ? $defaultDealer->toArray() : null);
|
||||||
|
return $defaultDealer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If user has specific dealer_id, check if they can access it
|
||||||
|
if ($user->dealer_id) {
|
||||||
|
if ($user->role_id) {
|
||||||
|
$role = Role::with(['dealers' => function($query) {
|
||||||
|
$query->whereNull('dealers.deleted_at'); // Only active dealers
|
||||||
|
}])->find($user->role_id);
|
||||||
|
if ($role && $role->hasDealer($user->dealer_id)) {
|
||||||
|
$defaultDealer = Dealer::where('id', $user->dealer_id)->whereNull('deleted_at')->first();
|
||||||
|
Log::info('User dealer found:', $defaultDealer ? $defaultDealer->toArray() : null);
|
||||||
|
return $defaultDealer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: no default dealer
|
||||||
|
Log::info('No default dealer found');
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -298,15 +559,94 @@ class TechnicianReportService
|
|||||||
*/
|
*/
|
||||||
public function getMechanicsByDealer($dealerId = null)
|
public function getMechanicsByDealer($dealerId = null)
|
||||||
{
|
{
|
||||||
|
// Get current authenticated user
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info('Getting mechanics by dealer:', [
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'user_role_id' => $user->role_id,
|
||||||
|
'user_dealer_id' => $user->dealer_id,
|
||||||
|
'requested_dealer_id' => $dealerId
|
||||||
|
]);
|
||||||
|
|
||||||
$query = User::with('role')->whereHas('role', function($query) {
|
$query = User::with('role')->whereHas('role', function($query) {
|
||||||
$query->where('name', 'mechanic');
|
$query->where('name', 'mechanic');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// If user has role, check role type and dealer access
|
||||||
|
if ($user->role_id) {
|
||||||
|
$role = Role::with(['dealers' => function($query) {
|
||||||
|
$query->whereNull('dealers.deleted_at'); // Only active dealers
|
||||||
|
}])->find($user->role_id);
|
||||||
|
|
||||||
|
if ($role) {
|
||||||
|
// Check if role is admin type
|
||||||
|
if ($this->isAdminRole($role)) {
|
||||||
|
// Admin role - check if has pivot dealers
|
||||||
|
if ($role->dealers->count() > 0) {
|
||||||
|
// Admin with pivot dealers
|
||||||
|
if ($dealerId) {
|
||||||
|
// Specific dealer selected - get mechanics from that dealer
|
||||||
|
Log::info('Admin with pivot dealers, specific dealer selected:', ['dealer_id' => $dealerId]);
|
||||||
|
$query->where('dealer_id', $dealerId);
|
||||||
|
} else {
|
||||||
|
// "Semua Dealer" selected - get mechanics from all pivot dealers
|
||||||
|
Log::info('Admin with pivot dealers, "Semua Dealer" selected, getting mechanics from all pivot dealers');
|
||||||
|
$accessibleDealerIds = $role->dealers->pluck('id');
|
||||||
|
$query->whereIn('dealer_id', $accessibleDealerIds);
|
||||||
|
Log::info('Accessible dealer IDs for admin:', $accessibleDealerIds->toArray());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Admin without pivot dealers - can access all dealers
|
||||||
|
Log::info('Admin without pivot dealers, can access mechanics from all dealers');
|
||||||
if ($dealerId) {
|
if ($dealerId) {
|
||||||
$query->where('dealer_id', $dealerId);
|
$query->where('dealer_id', $dealerId);
|
||||||
}
|
}
|
||||||
|
// If no dealer_id, show all mechanics (no additional filtering)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Role has dealer relationship (filter by accessible dealers)
|
||||||
|
if ($role->dealers->count() > 0) {
|
||||||
|
Log::info('Role has dealers relationship, filtering mechanics by accessible dealers');
|
||||||
|
$accessibleDealerIds = $role->dealers->pluck('id');
|
||||||
|
$query->whereIn('dealer_id', $accessibleDealerIds);
|
||||||
|
Log::info('Accessible dealer IDs:', $accessibleDealerIds->toArray());
|
||||||
|
} else {
|
||||||
|
Log::info('Role has no dealers, returning empty');
|
||||||
|
return collect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ($user->dealer_id) {
|
||||||
|
// User has specific dealer_id but no role, can only access their dealer
|
||||||
|
Log::info('User has dealer_id but no role, can only access their dealer');
|
||||||
|
$query->where('dealer_id', $user->dealer_id);
|
||||||
|
}
|
||||||
|
|
||||||
return $query->orderBy('name')->get(['id', 'name', 'dealer_id']);
|
// Apply dealer filter if provided (for non-admin roles)
|
||||||
|
if ($dealerId && !$this->isAdminRole($role ?? null)) {
|
||||||
|
Log::info('Applying dealer filter for non-admin role:', ['dealer_id' => $dealerId]);
|
||||||
|
$query->where('dealer_id', $dealerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
$mechanics = $query->orderBy('name')->get(['id', 'name', 'dealer_id']);
|
||||||
|
|
||||||
|
Log::info('Mechanics found:', [
|
||||||
|
'count' => $mechanics->count(),
|
||||||
|
'mechanics' => $mechanics->map(function($mechanic) {
|
||||||
|
return [
|
||||||
|
'id' => $mechanic->id,
|
||||||
|
'name' => $mechanic->name,
|
||||||
|
'dealer_id' => $mechanic->dealer_id
|
||||||
|
];
|
||||||
|
})->toArray()
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $mechanics;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -315,36 +655,94 @@ class TechnicianReportService
|
|||||||
public function getTechnicianReportDataForDataTable($dealerId = null, $startDate = null, $endDate = null)
|
public function getTechnicianReportDataForDataTable($dealerId = null, $startDate = null, $endDate = null)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
// Get current authenticated user
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return response()->json([
|
||||||
|
'draw' => request()->input('draw', 1),
|
||||||
|
'recordsTotal' => 0,
|
||||||
|
'recordsFiltered' => 0,
|
||||||
|
'data' => [],
|
||||||
|
'mechanics' => collect(),
|
||||||
|
'works' => collect()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate dealer access
|
||||||
|
if ($dealerId) {
|
||||||
|
if ($user->dealer_id) {
|
||||||
|
// User has specific dealer_id, check if they can access the requested dealer
|
||||||
|
if ($user->dealer_id != $dealerId) {
|
||||||
|
if ($user->role_id) {
|
||||||
|
$role = Role::with('dealers')->find($user->role_id);
|
||||||
|
if (!$role || !$role->hasDealer($dealerId)) {
|
||||||
|
// User doesn't have access to this dealer
|
||||||
|
return response()->json([
|
||||||
|
'draw' => request()->input('draw', 1),
|
||||||
|
'recordsTotal' => 0,
|
||||||
|
'recordsFiltered' => 0,
|
||||||
|
'data' => [],
|
||||||
|
'mechanics' => collect(),
|
||||||
|
'works' => collect()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// User has dealer_id but no role, can only access their dealer
|
||||||
|
return response()->json([
|
||||||
|
'draw' => request()->input('draw', 1),
|
||||||
|
'recordsTotal' => 0,
|
||||||
|
'recordsFiltered' => 0,
|
||||||
|
'data' => [],
|
||||||
|
'mechanics' => collect(),
|
||||||
|
'works' => collect()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ($user->role_id) {
|
||||||
|
// User has role, check if they can access the requested dealer
|
||||||
|
$role = Role::with('dealers')->find($user->role_id);
|
||||||
|
if (!$role || !$role->hasDealer($dealerId)) {
|
||||||
|
// User doesn't have access to this dealer
|
||||||
|
return response()->json([
|
||||||
|
'draw' => request()->input('draw', 1),
|
||||||
|
'recordsTotal' => 0,
|
||||||
|
'recordsFiltered' => 0,
|
||||||
|
'data' => [],
|
||||||
|
'mechanics' => collect(),
|
||||||
|
'works' => collect()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info('Getting technician report data for DataTable', [
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'dealer_id' => $dealerId,
|
||||||
|
'start_date' => $startDate,
|
||||||
|
'end_date' => $endDate
|
||||||
|
]);
|
||||||
|
|
||||||
// Get all works with category
|
// Get all works with category
|
||||||
$works = Work::with(['category'])
|
$works = Work::with(['category'])
|
||||||
->orderBy('name')
|
->orderBy('name')
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
// Get all mechanics
|
// Get mechanics based on dealer and role access
|
||||||
$mechanics = User::with('role')->whereHas('role', function($query) {
|
$mechanics = $this->getMechanicsByDealer($dealerId);
|
||||||
$query->where('name', 'mechanic');
|
|
||||||
})
|
|
||||||
->when($dealerId, function($query) use ($dealerId) {
|
|
||||||
return $query->where('dealer_id', $dealerId);
|
|
||||||
})
|
|
||||||
->orderBy('name')
|
|
||||||
->get(['id', 'name', 'role_id', 'dealer_id']);
|
|
||||||
|
|
||||||
// Fallback: If no mechanics found, get all users with dealer_id
|
|
||||||
if ($mechanics->isEmpty()) {
|
|
||||||
Log::info('No users with role "mechanic" found, using fallback: all users with dealer_id');
|
|
||||||
$mechanics = User::with('role')->whereNotNull('dealer_id')
|
|
||||||
->whereNotNull('role_id')
|
|
||||||
->when($dealerId, function($query) use ($dealerId) {
|
|
||||||
return $query->where('dealer_id', $dealerId);
|
|
||||||
})
|
|
||||||
->orderBy('name')
|
|
||||||
->get(['id', 'name', 'role_id', 'dealer_id']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get transaction data
|
// Get transaction data
|
||||||
$transactions = $this->getOptimizedTransactionData($dealerId, $startDate, $endDate, $mechanics->pluck('id'), $works->pluck('id'));
|
$transactions = $this->getOptimizedTransactionData($dealerId, $startDate, $endDate, $mechanics->pluck('id'), $works->pluck('id'));
|
||||||
|
|
||||||
|
Log::info('Transaction data for DataTable:', [
|
||||||
|
'transaction_count' => count($transactions),
|
||||||
|
'dealer_id_filter' => $dealerId,
|
||||||
|
'is_admin_with_pivot' => $user->role_id ? (function() use ($user) {
|
||||||
|
$role = Role::with('dealers')->find($user->role_id);
|
||||||
|
return $role && $this->isAdminRole($role) && $role->dealers->count() > 0;
|
||||||
|
})() : false
|
||||||
|
]);
|
||||||
|
|
||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
foreach ($works as $work) {
|
foreach ($works as $work) {
|
||||||
@@ -366,6 +764,12 @@ class TechnicianReportService
|
|||||||
$data[] = $row;
|
$data[] = $row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log::info('DataTable response prepared', [
|
||||||
|
'data_count' => count($data),
|
||||||
|
'mechanics_count' => $mechanics->count(),
|
||||||
|
'works_count' => $works->count()
|
||||||
|
]);
|
||||||
|
|
||||||
// Create DataTable response
|
// Create DataTable response
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'draw' => request()->input('draw', 1),
|
'draw' => request()->input('draw', 1),
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class CreateRoleDealerTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('role_dealer', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('role_id')->constrained()->onDelete('cascade');
|
||||||
|
$table->foreignId('dealer_id')->constrained()->onDelete('cascade');
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->unique(['role_id', 'dealer_id']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('role_dealer');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -59,5 +59,7 @@ class MenuSeeder extends Seeder
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Menu::whereIn('link', ['targets.index','product-categories.index'])->delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@
|
|||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|
||||||
<title>POS | Login</title>
|
<title>POS | Login</title>
|
||||||
<meta name="description" content="Login page example">
|
<meta name="description" content="CKB POS Login Page">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<meta name="base-url" content="{{ url('/') }}">
|
<meta name="base-url" content="{{ url('/') }}">
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>No</th>
|
<th>No</th>
|
||||||
<th>Nama Role</th>
|
<th>Nama Role</th>
|
||||||
|
<th>Dealer Tambahan</th>
|
||||||
<th>Aksi</th>
|
<th>Aksi</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -47,13 +48,30 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td>{{ $loop->iteration }}</td>
|
<td>{{ $loop->iteration }}</td>
|
||||||
<td>{{ $role->name }}</td>
|
<td>{{ $role->name }}</td>
|
||||||
|
<td>
|
||||||
|
@if($role->dealers->count() > 0)
|
||||||
|
<div class="dealer-list">
|
||||||
|
@foreach($role->dealers->take(3) as $dealer)
|
||||||
|
<span class="badge badge-info mr-1 mb-1">{{ $dealer->name }}</span>
|
||||||
|
@endforeach
|
||||||
|
@if($role->dealers->count() > 3)
|
||||||
|
<span class="badge badge-secondary">+{{ $role->dealers->count() - 3 }} more</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<span class="text-muted">Tidak ada dealer tambahan untuk role ini</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
@can('update', $menus['roleprivileges.index'])
|
@can('update', $menus['roleprivileges.index'])
|
||||||
<button class="btn btn-sm btn-bold btn-warning mr-2" onclick="editRole({{$role->id}})"> Edit</button>
|
<button class="btn btn-sm btn-bold btn-warning mr-2" onclick="editRole({{$role->id}})"> Edit</button>
|
||||||
@endcan
|
@endcan
|
||||||
@can('delete', $menus['roleprivileges.index'])
|
@can('delete', $menus['roleprivileges.index'])
|
||||||
<button class="btn btn-sm btn-bold btn-danger" onclick="deleteRole({{$role->id}}, '{{$role->name}}')">Hapus</button>
|
<button class="btn btn-sm btn-bold btn-danger mr-2" onclick="deleteRole({{$role->id}}, '{{$role->name}}')">Hapus</button>
|
||||||
|
@endcan
|
||||||
|
@can('create', $menus['roleprivileges.index'])
|
||||||
|
<button class="btn btn-sm btn-bold btn-success" onclick="assignDealer({{$role->id}})"> Tambah Dealer</button>
|
||||||
@endcan
|
@endcan
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@@ -183,6 +201,141 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="modal fade" id="assignDealerModal" tabindex="-1" role="dialog" aria-labelledby="assignDealerModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
|
<form id="assignDealerForm" method="POST">
|
||||||
|
@csrf
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="assignDealerModalLabel">
|
||||||
|
Assign Dealer ke Role
|
||||||
|
</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="alert alert-light border">
|
||||||
|
<strong>Petunjuk:</strong> Pilih dealer yang akan di-assign ke role ini. Dealer yang sudah di-assign akan otomatis tercentang.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="font-weight-bold">
|
||||||
|
Daftar Dealer
|
||||||
|
</label>
|
||||||
|
<div class="dealer-checkboxes border rounded p-3" style="max-height: 350px; overflow-y: auto;">
|
||||||
|
<div class="row">
|
||||||
|
@foreach ($dealers as $dealer)
|
||||||
|
<div class="col-md-6 mb-2">
|
||||||
|
<div class="form-check custom-checkbox">
|
||||||
|
<input class="form-check-input dealer-checkbox" type="checkbox"
|
||||||
|
name="dealers[]" value="{{ $dealer->id }}"
|
||||||
|
id="dealer_{{ $dealer->id }}">
|
||||||
|
<label class="form-check-label d-flex align-items-center" for="dealer_{{ $dealer->id }}">
|
||||||
|
<div class="dealer-info">
|
||||||
|
<div class="dealer-name font-weight-semibold">{{ $dealer->name }}</div>
|
||||||
|
<div class="dealer-code text-muted small">
|
||||||
|
<i class="fas fa-tag mr-1"></i>
|
||||||
|
{{ $dealer->dealer_code }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group mb-0">
|
||||||
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
|
<div>
|
||||||
|
<button type="button" class="btn btn-outline-primary btn-sm mr-2" onclick="selectAllDealers()">
|
||||||
|
Pilih Semua
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="deselectAllDealers()">
|
||||||
|
Hapus Semua
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="text-muted small">
|
||||||
|
<span id="selectedCount">0</span> dealer dipilih
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||||
|
Batal
|
||||||
|
</button>
|
||||||
|
<button type="submit" class="btn btn-primary" id="submitBtn">
|
||||||
|
Simpan Perubahan
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('styles')
|
||||||
|
<style>
|
||||||
|
.custom-checkbox .form-check-label {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0.5rem;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
transition: background-color 0.2s ease;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-checkbox .form-check-label:hover {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-checkbox .form-check-input:checked + .form-check-label {
|
||||||
|
background-color: #e8f5e8;
|
||||||
|
border-left: 3px solid #28a745;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dealer-info {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dealer-name {
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 0.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dealer-code {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: #6c757d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dealer-checkboxes::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dealer-checkboxes::-webkit-scrollbar-track {
|
||||||
|
background: #f1f1f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dealer-checkboxes::-webkit-scrollbar-thumb {
|
||||||
|
background: #c1c1c1;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dealer-checkboxes::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #a8a8a8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive improvements */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.dealer-checkboxes .col-md-6 {
|
||||||
|
flex: 0 0 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('javascripts')
|
@section('javascripts')
|
||||||
@@ -296,17 +449,145 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function assignDealer(roleId) {
|
||||||
|
// Set form action
|
||||||
|
let url = '{{ route("roleprivileges.assignDealer", ":id") }}'.replace(':id', roleId);
|
||||||
|
$("#assignDealerForm").attr("action", url);
|
||||||
|
|
||||||
|
// Reset checkboxes and counter
|
||||||
|
$('.dealer-checkbox').prop('checked', false);
|
||||||
|
updateSelectedCount();
|
||||||
|
|
||||||
|
// Load existing assigned dealers
|
||||||
|
$.ajax({
|
||||||
|
url: '{{ route("roleprivileges.getAssignedDealers", ":id") }}'.replace(':id', roleId),
|
||||||
|
type: 'GET',
|
||||||
|
success: function(response) {
|
||||||
|
if (response.assignedDealers) {
|
||||||
|
response.assignedDealers.forEach(function(dealerId) {
|
||||||
|
$(`#dealer_${dealerId}`).prop('checked', true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
updateSelectedCount();
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
console.log('Error loading assigned dealers');
|
||||||
|
updateSelectedCount();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#assignDealerModal").modal("show");
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectAllDealers() {
|
||||||
|
$('.dealer-checkbox').prop('checked', true);
|
||||||
|
updateSelectedCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
function deselectAllDealers() {
|
||||||
|
$('.dealer-checkbox').prop('checked', false);
|
||||||
|
updateSelectedCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSelectedCount() {
|
||||||
|
const selectedCount = $('.dealer-checkbox:checked').length;
|
||||||
|
$('#selectedCount').text(selectedCount);
|
||||||
|
|
||||||
|
// Update submit button state
|
||||||
|
if (selectedCount > 0) {
|
||||||
|
$('#submitBtn').prop('disabled', false).removeClass('btn-secondary').addClass('btn-primary');
|
||||||
|
} else {
|
||||||
|
$('#submitBtn').prop('disabled', true).removeClass('btn-primary').addClass('btn-secondary');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
// Add event handlers for modal close buttons
|
// Add event handlers for modal close buttons
|
||||||
$('.close, [data-dismiss="modal"]').on("click", function () {
|
$('.close, [data-dismiss="modal"]').on("click", function () {
|
||||||
$("#roleModal").modal("hide");
|
$("#roleModal").modal("hide");
|
||||||
$("#roleEditModal").modal("hide");
|
$("#roleEditModal").modal("hide");
|
||||||
|
$("#assignDealerModal").modal("hide");
|
||||||
});
|
});
|
||||||
|
|
||||||
// Also handle the "Close" button
|
// Also handle the "Close" button
|
||||||
$('.btn-secondary[data-dismiss="modal"]').on("click", function () {
|
$('.btn-secondary[data-dismiss="modal"]').on("click", function () {
|
||||||
$("#roleModal").modal("hide");
|
$("#roleModal").modal("hide");
|
||||||
$("#roleEditModal").modal("hide");
|
$("#roleEditModal").modal("hide");
|
||||||
|
$("#assignDealerModal").modal("hide");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Event listener for dealer checkboxes
|
||||||
|
$(document).on('change', '.dealer-checkbox', function() {
|
||||||
|
updateSelectedCount();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle form submission for assign dealer
|
||||||
|
$("#assignDealerForm").on("submit", function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
// Validate if at least one dealer is selected
|
||||||
|
const selectedDealers = $('.dealer-checkbox:checked').length;
|
||||||
|
if (selectedDealers === 0) {
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Peringatan!',
|
||||||
|
text: 'Silakan pilih minimal satu dealer',
|
||||||
|
icon: 'warning',
|
||||||
|
confirmButtonText: 'OK'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable submit button and show loading
|
||||||
|
const submitBtn = $('#submitBtn');
|
||||||
|
const originalText = submitBtn.html();
|
||||||
|
submitBtn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin mr-1"></i>Menyimpan...');
|
||||||
|
|
||||||
|
let formData = new FormData(this);
|
||||||
|
let url = $(this).attr("action");
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: url,
|
||||||
|
type: 'POST',
|
||||||
|
data: formData,
|
||||||
|
processData: false,
|
||||||
|
contentType: false,
|
||||||
|
success: function(response) {
|
||||||
|
if (response.success) {
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Berhasil!',
|
||||||
|
text: response.message,
|
||||||
|
icon: 'success',
|
||||||
|
confirmButtonText: 'OK'
|
||||||
|
}).then(() => {
|
||||||
|
location.reload();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Error!',
|
||||||
|
text: response.message || 'Terjadi kesalahan',
|
||||||
|
icon: 'error',
|
||||||
|
confirmButtonText: 'OK'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(xhr) {
|
||||||
|
let message = 'Terjadi kesalahan';
|
||||||
|
if (xhr.responseJSON && xhr.responseJSON.message) {
|
||||||
|
message = xhr.responseJSON.message;
|
||||||
|
}
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Error!',
|
||||||
|
text: message,
|
||||||
|
icon: 'error',
|
||||||
|
confirmButtonText: 'OK'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
complete: function() {
|
||||||
|
// Re-enable submit button
|
||||||
|
submitBtn.prop('disabled', false).html(originalText);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -153,7 +153,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<small class="form-text text-muted" id="default-dealer-info">Pilih dealer untuk memfilter data atau biarkan "Semua Dealer" untuk melihat data lengkap.</small>
|
<small class="form-text text-muted" id="default-dealer-info">Filter diset ke "Semua Dealer" untuk melihat data lengkap. Pilih dealer untuk memfilter data.</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -283,15 +283,46 @@ $(document).ready(function() {
|
|||||||
// Initialize Select2 after populating options
|
// Initialize Select2 after populating options
|
||||||
initializeSelect2();
|
initializeSelect2();
|
||||||
|
|
||||||
// Default ke "Semua Dealer" (tidak ada dealer yang terselect)
|
// Set default dealer if provided
|
||||||
console.log('Default set to "Semua Dealer"');
|
if (response.default_dealer && response.data.length > 0) {
|
||||||
$('#default-dealer-info').text('Pilih dealer untuk memfilter data atau biarkan "Semua Dealer" untuk melihat data lengkap.');
|
// Don't set default dealer - always show "Semua Dealer" on initial load
|
||||||
|
$('#default-dealer-info').text('Filter diset ke "Semua Dealer" untuk melihat data lengkap. Pilih dealer untuk memfilter data.');
|
||||||
|
|
||||||
// Load initial mechanics and then initialize DataTable
|
// Load initial data without dealer filter (show all dealers)
|
||||||
if (!isInitialized) {
|
if (!isInitialized) {
|
||||||
console.log('Dealers loaded, loading initial mechanics...');
|
console.log('Default dealer available but loading with "Semua Dealer" filter');
|
||||||
loadInitialMechanics();
|
loadInitialMechanics();
|
||||||
}
|
}
|
||||||
|
} else if (response.default_dealer === null && response.data.length > 0) {
|
||||||
|
// Admin without default dealer - show all dealers without selection
|
||||||
|
$('#default-dealer-info').text('Filter diset ke "Semua Dealer" untuk melihat data lengkap. Pilih dealer untuk memfilter data.');
|
||||||
|
|
||||||
|
// Load initial data without dealer filter
|
||||||
|
if (!isInitialized) {
|
||||||
|
console.log('Admin without default dealer, loading initial data');
|
||||||
|
loadInitialMechanics();
|
||||||
|
}
|
||||||
|
} else if (response.data.length > 0) {
|
||||||
|
$('#default-dealer-info').text('Filter diset ke "Semua Dealer" untuk melihat data lengkap. Pilih dealer untuk memfilter data.');
|
||||||
|
|
||||||
|
// Load initial data without dealer filter
|
||||||
|
if (!isInitialized) {
|
||||||
|
console.log('No default dealer, loading initial data');
|
||||||
|
loadInitialMechanics();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No dealers available
|
||||||
|
$('#default-dealer-info').text('Tidak ada dealer yang tersedia untuk Anda.');
|
||||||
|
hideLoadingOverlay();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if user has access to any dealers
|
||||||
|
if (response.data.length === 0) {
|
||||||
|
toastr.warning('Anda tidak memiliki akses ke dealer manapun. Silakan hubungi administrator.');
|
||||||
|
$('#default-dealer-info').text('Anda tidak memiliki akses ke dealer manapun.');
|
||||||
|
hideLoadingOverlay();
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
toastr.error('Gagal memuat data dealer');
|
toastr.error('Gagal memuat data dealer');
|
||||||
hideLoadingOverlay();
|
hideLoadingOverlay();
|
||||||
@@ -304,14 +335,14 @@ $(document).ready(function() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadInitialMechanics() {
|
function loadDataWithDealer(dealerId) {
|
||||||
// Get initial filter values (empty dealer, default dates)
|
// Show loading overlay
|
||||||
let dealerId = '';
|
showLoadingOverlay("Memuat data laporan teknisi...");
|
||||||
|
|
||||||
const startDate = $('#filter-start-date').val();
|
const startDate = $('#filter-start-date').val();
|
||||||
const endDate = $('#filter-end-date').val();
|
const endDate = $('#filter-end-date').val();
|
||||||
|
|
||||||
// Show loading overlay
|
console.log('Loading data with dealer:', dealerId, 'date range:', { startDate, endDate });
|
||||||
showLoadingOverlay("Memuat data laporan teknisi...");
|
|
||||||
|
|
||||||
// Get mechanics first, then initialize DataTable
|
// Get mechanics first, then initialize DataTable
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@@ -319,9 +350,21 @@ $(document).ready(function() {
|
|||||||
type: 'GET',
|
type: 'GET',
|
||||||
data: { dealer_id: dealerId, start_date: startDate, end_date: endDate },
|
data: { dealer_id: dealerId, start_date: startDate, end_date: endDate },
|
||||||
success: function(response) {
|
success: function(response) {
|
||||||
|
console.log('Data response:', response);
|
||||||
|
|
||||||
if (response.status === 'success' && Array.isArray(response.mechanics)) {
|
if (response.status === 'success' && Array.isArray(response.mechanics)) {
|
||||||
mechanics = response.mechanics;
|
mechanics = response.mechanics;
|
||||||
console.log('Initial mechanics loaded:', mechanics.length);
|
console.log('Data loaded with dealer:', dealerId, 'mechanics:', mechanics.length);
|
||||||
|
|
||||||
|
// Check if user has access to any data
|
||||||
|
if (response.data.length === 0 && response.mechanics.length === 0) {
|
||||||
|
console.log('No data available for dealer:', dealerId);
|
||||||
|
toastr.info('Tidak ada data yang tersedia untuk dealer yang dipilih. Silakan pilih dealer lain.');
|
||||||
|
$('#default-dealer-info').text('Tidak ada data yang tersedia untuk dealer yang dipilih.');
|
||||||
|
hideLoadingOverlay();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Now initialize DataTable with mechanics ready
|
// Now initialize DataTable with mechanics ready
|
||||||
updateTableStructureWithMechanics();
|
updateTableStructureWithMechanics();
|
||||||
isInitialized = true;
|
isInitialized = true;
|
||||||
@@ -332,7 +375,70 @@ $(document).ready(function() {
|
|||||||
isInitialized = true;
|
isInitialized = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: function() {
|
error: function(xhr, status, error) {
|
||||||
|
console.error('Error loading data with dealer:', error);
|
||||||
|
console.error('Response:', xhr.responseText);
|
||||||
|
|
||||||
|
toastr.error('Gagal memuat data untuk dealer yang dipilih. Silakan coba lagi.');
|
||||||
|
hideLoadingOverlay();
|
||||||
|
|
||||||
|
// Don't try fallback to avoid multiple notifications
|
||||||
|
mechanics = [];
|
||||||
|
updateTableStructureWithMechanics();
|
||||||
|
isInitialized = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadInitialMechanics() {
|
||||||
|
// Get initial filter values (empty dealer, default dates)
|
||||||
|
let dealerId = '';
|
||||||
|
const startDate = $('#filter-start-date').val();
|
||||||
|
const endDate = $('#filter-end-date').val();
|
||||||
|
|
||||||
|
console.log('Loading initial mechanics without dealer filter, date range:', { startDate, endDate });
|
||||||
|
|
||||||
|
// Show loading overlay
|
||||||
|
showLoadingOverlay("Memuat data laporan teknisi...");
|
||||||
|
|
||||||
|
// Get mechanics first, then initialize DataTable
|
||||||
|
$.ajax({
|
||||||
|
url: '{{ route("reports.technician.data") }}',
|
||||||
|
type: 'GET',
|
||||||
|
data: { dealer_id: dealerId, start_date: startDate, end_date: endDate },
|
||||||
|
success: function(response) {
|
||||||
|
console.log('Initial data response:', response);
|
||||||
|
|
||||||
|
if (response.status === 'success' && Array.isArray(response.mechanics)) {
|
||||||
|
mechanics = response.mechanics;
|
||||||
|
console.log('Initial mechanics loaded:', mechanics.length);
|
||||||
|
|
||||||
|
// Check if user has access to any data
|
||||||
|
if (response.data.length === 0 && response.mechanics.length === 0) {
|
||||||
|
console.log('No data available without dealer filter');
|
||||||
|
// Don't show notification for initial load without dealer filter
|
||||||
|
$('#default-dealer-info').text('Tidak ada data yang tersedia. Silakan pilih dealer untuk memfilter data.');
|
||||||
|
hideLoadingOverlay();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now initialize DataTable with mechanics ready
|
||||||
|
updateTableStructureWithMechanics();
|
||||||
|
isInitialized = true;
|
||||||
|
} else {
|
||||||
|
console.warn('Invalid mechanics data, using fallback');
|
||||||
|
mechanics = [];
|
||||||
|
updateTableStructureWithMechanics();
|
||||||
|
isInitialized = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
console.error('Error loading initial mechanics:', error);
|
||||||
|
console.error('Response:', xhr.responseText);
|
||||||
|
|
||||||
|
toastr.error('Gagal memuat data laporan teknisi. Silakan coba lagi.');
|
||||||
|
hideLoadingOverlay();
|
||||||
|
|
||||||
console.warn('Error loading initial mechanics, using fallback');
|
console.warn('Error loading initial mechanics, using fallback');
|
||||||
mechanics = [];
|
mechanics = [];
|
||||||
updateTableStructureWithMechanics();
|
updateTableStructureWithMechanics();
|
||||||
@@ -382,6 +488,12 @@ $(document).ready(function() {
|
|||||||
mechanics = [];
|
mechanics = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if user has access to any data
|
||||||
|
if (response.data.length === 0 && response.mechanics.length === 0) {
|
||||||
|
toastr.info('Tidak ada data yang tersedia untuk filter yang dipilih atau Anda tidak memiliki akses ke data tersebut.');
|
||||||
|
$('#default-dealer-info').text('Tidak ada data yang tersedia untuk filter yang dipilih.');
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
console.error('Server returned error status:', response);
|
console.error('Server returned error status:', response);
|
||||||
toastr.error('Gagal memuat data laporan teknisi');
|
toastr.error('Gagal memuat data laporan teknisi');
|
||||||
@@ -401,7 +513,7 @@ $(document).ready(function() {
|
|||||||
} else if (xhr.status === 404) {
|
} else if (xhr.status === 404) {
|
||||||
errorMessage = 'Endpoint tidak ditemukan';
|
errorMessage = 'Endpoint tidak ditemukan';
|
||||||
} else if (xhr.status === 403) {
|
} else if (xhr.status === 403) {
|
||||||
errorMessage = 'Akses ditolak';
|
errorMessage = 'Akses ditolak - Anda tidak memiliki izin untuk mengakses data ini';
|
||||||
}
|
}
|
||||||
|
|
||||||
toastr.error(errorMessage);
|
toastr.error(errorMessage);
|
||||||
@@ -500,6 +612,13 @@ $(document).ready(function() {
|
|||||||
dataSrc: function(json) {
|
dataSrc: function(json) {
|
||||||
console.log('DataTable response:', json);
|
console.log('DataTable response:', json);
|
||||||
|
|
||||||
|
// Check for error response
|
||||||
|
if (json.error) {
|
||||||
|
console.error('DataTable error:', json.error);
|
||||||
|
toastr.error('Error loading data: ' + json.error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
// Update mechanics from response
|
// Update mechanics from response
|
||||||
if (json.mechanics && Array.isArray(json.mechanics)) {
|
if (json.mechanics && Array.isArray(json.mechanics)) {
|
||||||
mechanics = json.mechanics;
|
mechanics = json.mechanics;
|
||||||
@@ -512,6 +631,27 @@ $(document).ready(function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return json.data || [];
|
return json.data || [];
|
||||||
|
},
|
||||||
|
error: function(xhr, error, thrown) {
|
||||||
|
console.error('DataTable AJAX error:', {
|
||||||
|
xhr: xhr,
|
||||||
|
error: error,
|
||||||
|
thrown: thrown
|
||||||
|
});
|
||||||
|
|
||||||
|
let errorMessage = 'Gagal memuat data';
|
||||||
|
if (xhr.responseJSON && xhr.responseJSON.error) {
|
||||||
|
errorMessage = xhr.responseJSON.error;
|
||||||
|
} else if (xhr.status === 500) {
|
||||||
|
errorMessage = 'Server error: ' + (xhr.responseText || 'Unknown error');
|
||||||
|
} else if (xhr.status === 404) {
|
||||||
|
errorMessage = 'Endpoint tidak ditemukan';
|
||||||
|
} else if (xhr.status === 403) {
|
||||||
|
errorMessage = 'Akses ditolak';
|
||||||
|
}
|
||||||
|
|
||||||
|
toastr.error(errorMessage);
|
||||||
|
hideLoadingOverlay();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
columns: [
|
columns: [
|
||||||
@@ -754,12 +894,40 @@ $(document).ready(function() {
|
|||||||
dataSrc: function(json) {
|
dataSrc: function(json) {
|
||||||
console.log('DataTable response:', json);
|
console.log('DataTable response:', json);
|
||||||
|
|
||||||
|
// Check for error response
|
||||||
|
if (json.error) {
|
||||||
|
console.error('DataTable error:', json.error);
|
||||||
|
toastr.error('Error loading data: ' + json.error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
// Don't update mechanics from datatable response - use existing mechanics
|
// Don't update mechanics from datatable response - use existing mechanics
|
||||||
// if (json.mechanics && Array.isArray(json.mechanics)) {
|
// if (json.mechanics && Array.isArray(json.mechanics)) {
|
||||||
// mechanics = json.mechanics;
|
// mechanics = json.mechanics;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return json.data || [];
|
return json.data || [];
|
||||||
|
},
|
||||||
|
error: function(xhr, error, thrown) {
|
||||||
|
console.error('DataTable AJAX error:', {
|
||||||
|
xhr: xhr,
|
||||||
|
error: error,
|
||||||
|
thrown: thrown
|
||||||
|
});
|
||||||
|
|
||||||
|
let errorMessage = 'Gagal memuat data';
|
||||||
|
if (xhr.responseJSON && xhr.responseJSON.error) {
|
||||||
|
errorMessage = xhr.responseJSON.error;
|
||||||
|
} else if (xhr.status === 500) {
|
||||||
|
errorMessage = 'Server error: ' + (xhr.responseText || 'Unknown error');
|
||||||
|
} else if (xhr.status === 404) {
|
||||||
|
errorMessage = 'Endpoint tidak ditemukan';
|
||||||
|
} else if (xhr.status === 403) {
|
||||||
|
errorMessage = 'Akses ditolak';
|
||||||
|
}
|
||||||
|
|
||||||
|
toastr.error(errorMessage);
|
||||||
|
hideLoadingOverlay();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
columns: columns,
|
columns: columns,
|
||||||
@@ -1105,7 +1273,7 @@ $(document).ready(function() {
|
|||||||
$('#btn-reset').on('click', function() {
|
$('#btn-reset').on('click', function() {
|
||||||
console.log('Reset button clicked');
|
console.log('Reset button clicked');
|
||||||
|
|
||||||
// Reset dealer selection
|
// Reset dealer selection to "Semua Dealer"
|
||||||
if (typeof $.fn.select2 !== 'undefined' && $('#filter-dealer').data('select2')) {
|
if (typeof $.fn.select2 !== 'undefined' && $('#filter-dealer').data('select2')) {
|
||||||
$('#filter-dealer').val('').trigger('change');
|
$('#filter-dealer').val('').trigger('change');
|
||||||
} else {
|
} else {
|
||||||
@@ -1116,7 +1284,7 @@ $(document).ready(function() {
|
|||||||
$('#filter-start-date').val('{{ date('Y-m-d', strtotime('-30 days')) }}');
|
$('#filter-start-date').val('{{ date('Y-m-d', strtotime('-30 days')) }}');
|
||||||
$('#filter-end-date').val('{{ date('Y-m-d') }}');
|
$('#filter-end-date').val('{{ date('Y-m-d') }}');
|
||||||
|
|
||||||
console.log('Filters reset, reloading DataTable...');
|
console.log('Filters reset to "Semua Dealer", reloading DataTable...');
|
||||||
|
|
||||||
// Reset initialization flag
|
// Reset initialization flag
|
||||||
isInitialized = false;
|
isInitialized = false;
|
||||||
|
|||||||
@@ -230,6 +230,8 @@ Route::group(['middleware' => 'auth'], function() {
|
|||||||
Route::get('/roleprivileges/{id}/edit', [RolePrivilegeController::class, 'edit'])->name('roleprivileges.edit');
|
Route::get('/roleprivileges/{id}/edit', [RolePrivilegeController::class, 'edit'])->name('roleprivileges.edit');
|
||||||
Route::put('/roleprivileges/{id}/update', [RolePrivilegeController::class, 'update'])->name('roleprivileges.update');
|
Route::put('/roleprivileges/{id}/update', [RolePrivilegeController::class, 'update'])->name('roleprivileges.update');
|
||||||
Route::delete('/roleprivileges/{id}/delete', [RolePrivilegeController::class, 'delete'])->name('roleprivileges.delete');
|
Route::delete('/roleprivileges/{id}/delete', [RolePrivilegeController::class, 'delete'])->name('roleprivileges.delete');
|
||||||
|
Route::post('/roleprivileges/{id}/assign-dealer', [RolePrivilegeController::class, 'assignDealer'])->name('roleprivileges.assignDealer');
|
||||||
|
Route::get('/roleprivileges/{id}/assigned-dealers', [RolePrivilegeController::class, 'getAssignedDealers'])->name('roleprivileges.getAssignedDealers');
|
||||||
|
|
||||||
Route::get('/report/transaction', [ReportController::class, 'transaction'])->name('report.transaction');
|
Route::get('/report/transaction', [ReportController::class, 'transaction'])->name('report.transaction');
|
||||||
Route::post('/report/transaction/data', [ReportController::class, 'transaction_data'])->name('report.transaction_data');
|
Route::post('/report/transaction/data', [ReportController::class, 'transaction_data'])->name('report.transaction_data');
|
||||||
|
|||||||
Reference in New Issue
Block a user