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() ]; } } } 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 $works = Work::with(['category']) ->orderBy('name') ->get(); // Get mechanics based on dealer and role access $mechanics = $this->getMechanicsByDealer($dealerId); Log::info('Mechanics found for report:', [ 'count' => $mechanics->count(), 'dealer_id_filter' => $dealerId, 'mechanics' => $mechanics->map(function($mechanic) { $roleName = 'Unknown'; if ($mechanic->role) { $roleName = is_string($mechanic->role) ? $mechanic->role : $mechanic->role->name; } return [ 'id' => $mechanic->id, 'name' => $mechanic->name, 'role_id' => $mechanic->role_id, 'role_name' => $roleName, 'dealer_id' => $mechanic->dealer_id ]; }) ]); // Get all transaction data in single optimized query $transactions = $this->getOptimizedTransactionData($dealerId, $startDate, $endDate, $mechanics->pluck('id'), $works->pluck('id')); Log::info('Transaction data:', [ 'transaction_count' => count($transactions), '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 = []; foreach ($works as $work) { $row = [ 'work_id' => $work->id, 'work_name' => $work->name, 'work_code' => $work->shortname, 'category_name' => $work->category ? $work->category->name : '-', 'total_tickets' => 0 ]; // Calculate totals for each mechanic foreach ($mechanics as $mechanic) { $key = $work->id . '_' . $mechanic->id; $mechanicData = $transactions[$key] ?? ['total' => 0, 'completed' => 0, 'pending' => 0]; $row["mechanic_{$mechanic->id}_total"] = $mechanicData['total']; // Add to totals $row['total_tickets'] += $mechanicData['total']; } $data[] = $row; } Log::info('Final data prepared:', [ 'data_count' => count($data), 'sample_data' => array_slice($data, 0, 2) ]); return [ 'data' => $data, 'mechanics' => $mechanics, 'works' => $works ]; } catch (\Exception $e) { Log::error('Error in getTechnicianReportData: ' . $e->getMessage(), [ 'dealer_id' => $dealerId, 'start_date' => $startDate, 'end_date' => $endDate, 'trace' => $e->getTraceAsString() ]); // Return empty data structure but with proper format return [ 'data' => [], 'mechanics' => collect(), 'works' => collect() ]; } } /** * Get optimized transaction data in single query */ 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', 'status', DB::raw('COUNT(*) as count') ) ->groupBy('work_id', 'user_id', 'status'); 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) { $query->where('date', '>=', $startDate); } if ($endDate) { $query->where('date', '<=', $endDate); } if ($mechanicIds && $mechanicIds->count() > 0) { $query->whereIn('user_id', $mechanicIds); } if ($workIds && $workIds->count() > 0) { $query->whereIn('work_id', $workIds); } // 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 = []; foreach ($results as $result) { $key = $result->work_id . '_' . $result->user_id; if (!isset($organizedData[$key])) { $organizedData[$key] = [ 'total' => 0, 'completed' => 0, 'pending' => 0 ]; } $organizedData[$key]['total'] += $result->count; if ($result->status == 1) { $organizedData[$key]['completed'] += $result->count; } else { $organizedData[$key]['pending'] += $result->count; } } return $organizedData; } /** * Get total ticket count for a specific work and mechanic (legacy method for backward compatibility) */ private function getTicketCount($workId, $mechanicId, $dealerId = null, $startDate = null, $endDate = null) { $query = Transaction::where('work_id', $workId) ->where('user_id', $mechanicId); if ($dealerId) { $query->where('dealer_id', $dealerId); } if ($startDate) { $query->where('date', '>=', $startDate); } if ($endDate) { $query->where('date', '<=', $endDate); } return $query->count(); } /** * Get completed ticket count for a specific work and mechanic (legacy method for backward compatibility) */ private function getCompletedTicketCount($workId, $mechanicId, $dealerId = null, $startDate = null, $endDate = null) { $query = Transaction::where('work_id', $workId) ->where('user_id', $mechanicId) ->where('status', 1); // Assuming status 1 is completed if ($dealerId) { $query->where('dealer_id', $dealerId); } if ($startDate) { $query->where('date', '>=', $startDate); } if ($endDate) { $query->where('date', '<=', $endDate); } return $query->count(); } /** * Get pending ticket count for a specific work and mechanic (legacy method for backward compatibility) */ private function getPendingTicketCount($workId, $mechanicId, $dealerId = null, $startDate = null, $endDate = null) { $query = Transaction::where('work_id', $workId) ->where('user_id', $mechanicId) ->where('status', 0); // Assuming status 0 is pending if ($dealerId) { $query->where('dealer_id', $dealerId); } if ($startDate) { $query->where('date', '>=', $startDate); } if ($endDate) { $query->where('date', '<=', $endDate); } return $query->count(); } /** * Get all dealers for filter */ public function getDealers() { // 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; } /** * 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' ]; // 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() { // 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; } /** * Get mechanics for a specific dealer */ 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 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); } $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; } /** * Get technician report data for Yajra DataTable */ 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 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) { $row = [ 'DT_RowIndex' => count($data) + 1, 'work_name' => $work->name, 'work_code' => $work->shortname, 'category_name' => $work->category ? $work->category->name : '-' ]; // Add mechanic columns foreach ($mechanics as $mechanic) { $key = $work->id . '_' . $mechanic->id; $mechanicData = $transactions[$key] ?? ['total' => 0, 'completed' => 0, 'pending' => 0]; $row["mechanic_{$mechanic->id}_total"] = $mechanicData['total']; } $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), 'recordsTotal' => count($data), 'recordsFiltered' => count($data), 'data' => $data, 'mechanics' => $mechanics, 'works' => $works ]); } catch (\Exception $e) { Log::error('Error in getTechnicianReportDataForDataTable: ' . $e->getMessage(), [ 'dealer_id' => $dealerId, 'start_date' => $startDate, 'end_date' => $endDate, 'trace' => $e->getTraceAsString() ]); return response()->json([ 'draw' => request()->input('draw', 1), 'recordsTotal' => 0, 'recordsFiltered' => 0, 'data' => [], 'mechanics' => collect(), 'works' => collect() ]); } } }