diff --git a/app/Exports/TechnicianReportExport.php b/app/Exports/TechnicianReportExport.php index 67fe940..6d0b920 100644 --- a/app/Exports/TechnicianReportExport.php +++ b/app/Exports/TechnicianReportExport.php @@ -83,7 +83,26 @@ class TechnicianReportExport implements FromCollection, WithHeadings, WithStyles $dealerName = $dealer ? $dealer->name : 'Unknown Dealer'; $this->filterInfo[] = "Dealer: {$dealerName}"; } else { - $this->filterInfo[] = "Dealer: Semua Dealer"; + // 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 { + $this->filterInfo[] = "Dealer: Semua Dealer"; + } + } else { + $this->filterInfo[] = "Dealer: Semua Dealer"; + } + } else { + $this->filterInfo[] = "Dealer: Semua Dealer"; + } } // Date range filter @@ -300,7 +319,12 @@ class TechnicianReportExport implements FromCollection, WithHeadings, WithStyles // Auto-size columns foreach (range('A', $lastColumn) as $column) { - $sheet->getColumnDimension($column)->setAutoSize(true); + 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); + } } } catch (\Exception $e) { @@ -311,7 +335,7 @@ class TechnicianReportExport implements FromCollection, WithHeadings, WithStyles public function columnWidths(): array { $widths = [ - 'A' => 8, // No + 'A' => 5, // No - reduced from 8 to 5 'B' => 30, // Nama Pekerjaan 'C' => 15, // Kode Pekerjaan 'D' => 20, // Kategori diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 31e5d7f..5462b68 100755 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use App\Models\Privilege; +use App\Models\User; use App\Providers\RouteServiceProvider; use Illuminate\Http\Request; use Illuminate\Foundation\Auth\AuthenticatesUsers; @@ -50,11 +51,39 @@ class LoginController extends Controller */ 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 (!$roleId) { + // User has no role, redirect to default + return redirect(RouteServiceProvider::HOME); + } - if ($user != null) { - return redirect()->route('dashboard'); - }else{ + // 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); } } diff --git a/app/Http/Controllers/Reports/ReportTechniciansController.php b/app/Http/Controllers/Reports/ReportTechniciansController.php index 6a7d362..0acc44e 100644 --- a/app/Http/Controllers/Reports/ReportTechniciansController.php +++ b/app/Http/Controllers/Reports/ReportTechniciansController.php @@ -5,11 +5,14 @@ namespace App\Http\Controllers\Reports; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use App\Models\Menu; +use App\Models\Role; use App\Services\TechnicianReportService; use App\Exports\TechnicianReportExport; use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Log; use Maatwebsite\Excel\Facades\Excel; +use Illuminate\Support\Facades\DB; // Added DB facade +use App\Models\Dealer; // Added Dealer model class ReportTechniciansController extends Controller { @@ -34,18 +37,66 @@ class ReportTechniciansController extends Controller public function getDealers() { 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(); - // 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([ 'status' => 'success', 'data' => $dealers, - 'default_dealer' => null + 'default_dealer' => $defaultDealer ? $defaultDealer->id : null ]); } catch (\Exception $e) { - Log::error('Error getting dealers: ' . $e->getMessage()); + Log::error('Controller: Error getting dealers: ' . $e->getMessage(), [ + 'trace' => $e->getTraceAsString() + ]); return response()->json([ 'status' => 'error', - 'message' => 'Gagal mengambil data dealer' + 'message' => 'Gagal mengambil data dealer: ' . $e->getMessage() ], 500); } } @@ -60,10 +111,23 @@ class ReportTechniciansController extends Controller $startDate = $request->input('start_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:', [ 'dealer_id' => $dealerId, '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( @@ -116,10 +180,22 @@ class ReportTechniciansController extends Controller $startDate = $request->input('start_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:', [ 'dealer_id' => $dealerId, '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( @@ -153,12 +229,87 @@ class ReportTechniciansController extends Controller $startDate = $request->input('start_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', [ 'dealer_id' => $dealerId, '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'); } catch (\Exception $e) { @@ -175,5 +326,4 @@ class ReportTechniciansController extends Controller } } - } diff --git a/app/Http/Controllers/RolePrivilegeController.php b/app/Http/Controllers/RolePrivilegeController.php index c5b6d5b..5721a29 100755 --- a/app/Http/Controllers/RolePrivilegeController.php +++ b/app/Http/Controllers/RolePrivilegeController.php @@ -6,6 +6,7 @@ use App\Models\Menu; use App\Models\Privilege; use App\Models\Role; use App\Models\User; +use App\Models\Dealer; use Illuminate\Http\Request; use Illuminate\Support\Facades\Gate; @@ -14,10 +15,11 @@ class RolePrivilegeController extends Controller public function index() { $menu = Menu::where('link', 'roleprivileges.index')->first(); abort_if(Gate::denies('view', $menu), 403, 'Unauthorized User'); - $roles = Role::all(); + $roles = Role::with('dealers')->get(); $menus = Menu::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) { @@ -117,4 +119,36 @@ class RolePrivilegeController extends Controller User::where('role_id', $id)->update(['role_id' => 0]); 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 + ]); + } } diff --git a/app/Models/Dealer.php b/app/Models/Dealer.php index 084a9b3..f241c5e 100755 --- a/app/Models/Dealer.php +++ b/app/Models/Dealer.php @@ -82,4 +82,9 @@ class Dealer extends Model { return $this->hasMany(WorkDealerPrice::class)->active(); } + + public function roles() + { + return $this->belongsToMany(Role::class, 'role_dealer'); + } } diff --git a/app/Models/Role.php b/app/Models/Role.php index bfba968..59de317 100755 --- a/app/Models/Role.php +++ b/app/Models/Role.php @@ -4,6 +4,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Facades\Log; class Role extends Model { @@ -11,4 +12,19 @@ class Role extends Model protected $fillable = [ '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(); + } } diff --git a/app/Models/User.php b/app/Models/User.php index 1b9b941..b957ad7 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -192,4 +192,113 @@ class User extends Authenticatable ->where('month', $month) ->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(); + } } diff --git a/app/Services/TechnicianReportService.php b/app/Services/TechnicianReportService.php index 6b9427b..c284f1f 100644 --- a/app/Services/TechnicianReportService.php +++ b/app/Services/TechnicianReportService.php @@ -6,6 +6,7 @@ use App\Models\Work; use App\Models\User; use App\Models\Transaction; use App\Models\Dealer; +use App\Models\Role; use Carbon\Carbon; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; @@ -18,23 +19,60 @@ class TechnicianReportService public function getTechnicianReportData($dealerId = null, $startDate = null, $endDate = null) { try { - // Debug: Check all users and roles - $allUsers = User::with('role')->get(); - Log::info('All users in database:', [ - 'total_users' => $allUsers->count(), - 'users_with_roles' => $allUsers->map(function($user) { - $roleName = 'No role'; - if ($user->role) { - $roleName = is_string($user->role) ? $user->role : $user->role->name; + // Get current authenticated user + $user = auth()->user(); + + if (!$user) { + return [ + '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 [ + 'data' => [], + 'mechanics' => collect(), + 'works' => collect() + ]; + } + } else { + // User has dealer_id but no role, can only access their dealer + return [ + 'data' => [], + 'mechanics' => collect(), + 'works' => collect() + ]; + } } - return [ - 'id' => $user->id, - 'name' => $user->name, - 'role_id' => $user->role_id, - 'role_name' => $roleName, - 'dealer_id' => $user->dealer_id - ]; - }) + } 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 @@ -42,29 +80,10 @@ class TechnicianReportService ->orderBy('name') ->get(); - // Get all mechanics (users with role name = 'mechanic') - $mechanics = User::with('role')->whereHas('role', function($query) { - $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']); + // Get mechanics based on dealer and role access + $mechanics = $this->getMechanicsByDealer($dealerId); - // 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']); - } - - Log::info('Mechanics found:', [ + Log::info('Mechanics found for report:', [ 'count' => $mechanics->count(), 'dealer_id_filter' => $dealerId, 'mechanics' => $mechanics->map(function($mechanic) { @@ -87,7 +106,12 @@ class TechnicianReportService Log::info('Transaction data:', [ '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 = []; @@ -148,6 +172,46 @@ class TechnicianReportService */ 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( 'work_id', 'user_id', @@ -158,6 +222,15 @@ class TechnicianReportService if ($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) { @@ -179,6 +252,10 @@ class TechnicianReportService // Remove index hint that doesn't exist $results = $query->get(); + Log::info('Transaction query results', [ + 'results_count' => $results->count() + ]); + // Organize data by work_id_user_id key $organizedData = []; @@ -281,16 +358,200 @@ class TechnicianReportService */ 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() { - // Dealer pertama saja jika ada - return Dealer::orderBy('name')->first(); + // Get current authenticated user + $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) { + // 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->where('name', 'mechanic'); }); - if ($dealerId) { + // 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) { + $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); + } + + // 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); } - return $query->orderBy('name')->get(['id', 'name', 'dealer_id']); + $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) { 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 $works = Work::with(['category']) ->orderBy('name') ->get(); - // Get all mechanics - $mechanics = User::with('role')->whereHas('role', function($query) { - $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 mechanics based on dealer and role access + $mechanics = $this->getMechanicsByDealer($dealerId); // Get transaction data $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 = []; foreach ($works as $work) { @@ -366,6 +764,12 @@ class TechnicianReportService $data[] = $row; } + Log::info('DataTable response prepared', [ + 'data_count' => count($data), + 'mechanics_count' => $mechanics->count(), + 'works_count' => $works->count() + ]); + // Create DataTable response return response()->json([ 'draw' => request()->input('draw', 1), diff --git a/database/migrations/2025_07_09_120017_create_role_dealer_table.php b/database/migrations/2025_07_09_120017_create_role_dealer_table.php new file mode 100644 index 0000000..29ae609 --- /dev/null +++ b/database/migrations/2025_07_09_120017_create_role_dealer_table.php @@ -0,0 +1,35 @@ +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'); + } +} diff --git a/database/seeders/MenuSeeder.php b/database/seeders/MenuSeeder.php index e502504..275ae87 100755 --- a/database/seeders/MenuSeeder.php +++ b/database/seeders/MenuSeeder.php @@ -59,5 +59,7 @@ class MenuSeeder extends Seeder ] ); } + + Menu::whereIn('link', ['targets.index','product-categories.index'])->delete(); } } diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index 4b8680d..0744150 100755 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -81,7 +81,7 @@