fix login auto detect menu link, and partial update tchnician role dealer

This commit is contained in:
2025-07-09 18:32:49 +07:00
parent e468672bbe
commit e59841fd23
14 changed files with 1362 additions and 103 deletions

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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
}
}
}

View File

@@ -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
]);
}
}

View File

@@ -82,4 +82,9 @@ class Dealer extends Model
{
return $this->hasMany(WorkDealerPrice::class)->active();
}
public function roles()
{
return $this->belongsToMany(Role::class, 'role_dealer');
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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),