fix(permissions): resolve manager role permissions for leave applications and biometric attendance
This commit is contained in:
@@ -18,142 +18,120 @@ class LeaveApplicationController extends Controller
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
// Employee self-service: always allow employees to see their own leaves
|
||||
if ($user->type === 'employee') {
|
||||
$query = LeaveApplication::with(['employee', 'leaveType', 'leavePolicy', 'approver', 'creator'])
|
||||
->where(function ($q) use ($user) {
|
||||
$q->where('employee_id', $user->id)
|
||||
->orWhere('created_by', $user->id);
|
||||
});
|
||||
$canManageAny = $user->can('manage-any-leave-applications');
|
||||
$canManageBranch = $user->can('manage-leave-applications');
|
||||
$isSelfServiceOnly = !$canManageAny && !$canManageBranch;
|
||||
$isMyLeavesView = $request->boolean('my_leaves') || $isSelfServiceOnly;
|
||||
|
||||
if ($request->has('search') && !empty($request->search)) {
|
||||
$query->where(function ($q) use ($request) {
|
||||
$q->where('reason', 'like', '%'.$request->search.'%')
|
||||
->orWhereHas('leaveType', fn($s) => $s->where('name', 'like', '%'.$request->search.'%'));
|
||||
$query = LeaveApplication::with(['employee.employee', 'leaveType', 'leavePolicy', 'approver', 'creator']);
|
||||
|
||||
if ($isMyLeavesView) {
|
||||
$query->where(function ($q) use ($user) {
|
||||
$q->where('employee_id', $user->id)
|
||||
->orWhere('created_by', $user->id);
|
||||
});
|
||||
} elseif ($canManageAny) {
|
||||
$query->whereIn('created_by', getCompanyAndUsersId());
|
||||
} elseif ($canManageBranch) {
|
||||
$branchId = $user->branch_id ?? $user->employee?->branch_id ?? null;
|
||||
if ($branchId) {
|
||||
$query->whereHas('employee.employee', function ($eq) use ($branchId) {
|
||||
$eq->where('branch_id', $branchId);
|
||||
});
|
||||
} else {
|
||||
$query->where(function ($q) use ($user) {
|
||||
$q->where('created_by', $user->id)
|
||||
->orWhere('employee_id', $user->id)
|
||||
->orWhere('approved_by', $user->id);
|
||||
});
|
||||
}
|
||||
if ($request->has('status') && !empty($request->status) && $request->status !== 'all') {
|
||||
$query->where('status', $request->status);
|
||||
}
|
||||
$query->orderBy('id', 'desc');
|
||||
|
||||
$leaveApplications = $query->paginate($request->per_page ?? 10);
|
||||
|
||||
$leaveTypes = LeaveType::whereIn('created_by', getCompanyAndUsersId())
|
||||
->where('status', 'active')
|
||||
->get(['id', 'name', 'color']);
|
||||
|
||||
return Inertia::render('hr/leave-applications/index', [
|
||||
'leaveApplications' => $leaveApplications,
|
||||
'employees' => [],
|
||||
'leaveTypes' => $leaveTypes,
|
||||
'filters' => $request->all(['search', 'status', 'sort_field', 'sort_direction', 'per_page']),
|
||||
]);
|
||||
} else {
|
||||
$query->whereRaw('1 = 0');
|
||||
}
|
||||
|
||||
if (Auth::user()->can('manage-leave-applications')) {
|
||||
$query = LeaveApplication::with(['employee', 'leaveType', 'leavePolicy', 'approver', 'creator'])
|
||||
->where(function ($q) {
|
||||
if (Auth::user()->can('manage-any-leave-applications')) {
|
||||
$q->whereIn('created_by', getCompanyAndUsersId());
|
||||
} elseif (Auth::user()->can('manage-leave-applications')) {
|
||||
$branchId = Auth::user()->branch_id ?? Auth::user()->employee->branch_id ?? null;
|
||||
if ($branchId) {
|
||||
$q->whereHas('employee.employee', function ($eq) use ($branchId) {
|
||||
$eq->where('branch_id', $branchId);
|
||||
});
|
||||
} else {
|
||||
$q->where('created_by', Auth::id())->orWhere('employee_id', Auth::id())->orWhere('approved_by', Auth::id());
|
||||
}
|
||||
} else {
|
||||
$q->whereRaw('1 = 0');
|
||||
}
|
||||
});
|
||||
// Handle search
|
||||
if ($request->has('search') && ! empty($request->search)) {
|
||||
$query->where(function ($q) use ($request) {
|
||||
$q->where('reason', 'like', '%'.$request->search.'%')
|
||||
->orWhereHas('employee', function ($subQ) use ($request) {
|
||||
$subQ->where('name', 'like', '%'.$request->search.'%');
|
||||
})
|
||||
->orWhereHas('leaveType', function ($subQ) use ($request) {
|
||||
$subQ->where('name', 'like', '%'.$request->search.'%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Handle search
|
||||
if ($request->has('search') && ! empty($request->search)) {
|
||||
$query->where(function ($q) use ($request) {
|
||||
$q->where('reason', 'like', '%'.$request->search.'%')
|
||||
->orWhereHas('employee', function ($subQ) use ($request) {
|
||||
$subQ->where('name', 'like', '%'.$request->search.'%');
|
||||
})
|
||||
->orWhereHas('leaveType', function ($subQ) use ($request) {
|
||||
$subQ->where('name', 'like', '%'.$request->search.'%');
|
||||
});
|
||||
});
|
||||
}
|
||||
// Handle employee filter
|
||||
if ($request->has('employee_id') && ! empty($request->employee_id) && $request->employee_id !== 'all') {
|
||||
$query->where('employee_id', $request->employee_id);
|
||||
}
|
||||
|
||||
// Handle employee filter
|
||||
if ($request->has('employee_id') && ! empty($request->employee_id) && $request->employee_id !== 'all') {
|
||||
$query->where('employee_id', $request->employee_id);
|
||||
}
|
||||
// Handle leave type filter
|
||||
if ($request->has('leave_type_id') && ! empty($request->leave_type_id) && $request->leave_type_id !== 'all') {
|
||||
$query->where('leave_type_id', $request->leave_type_id);
|
||||
}
|
||||
|
||||
// Handle leave type filter
|
||||
if ($request->has('leave_type_id') && ! empty($request->leave_type_id) && $request->leave_type_id !== 'all') {
|
||||
$query->where('leave_type_id', $request->leave_type_id);
|
||||
}
|
||||
// Handle status filter
|
||||
if ($request->has('status') && ! empty($request->status) && $request->status !== 'all') {
|
||||
$query->where('status', $request->status);
|
||||
}
|
||||
|
||||
// Handle status filter
|
||||
if ($request->has('status') && ! empty($request->status) && $request->status !== 'all') {
|
||||
$query->where('status', $request->status);
|
||||
}
|
||||
// Handle sorting
|
||||
if ($request->has('sort_field') && ! empty($request->sort_field)) {
|
||||
$sortField = $request->sort_field;
|
||||
$sortDirection = $request->sort_direction ?? 'asc';
|
||||
|
||||
// Handle sorting
|
||||
if ($request->has('sort_field') && ! empty($request->sort_field)) {
|
||||
$sortField = $request->sort_field;
|
||||
$sortDirection = $request->sort_direction ?? 'asc';
|
||||
|
||||
if (in_array($sortField, ['start_date', 'end_date', 'created_at'])) {
|
||||
$query->orderBy($sortField, $sortDirection);
|
||||
} else {
|
||||
$query->orderBy('id', 'desc');
|
||||
}
|
||||
if (in_array($sortField, ['start_date', 'end_date', 'created_at'])) {
|
||||
$query->orderBy($sortField, $sortDirection);
|
||||
} else {
|
||||
$query->orderBy('id', 'desc');
|
||||
}
|
||||
|
||||
$leaveApplications = $query->paginate($request->per_page ?? 10);
|
||||
|
||||
$leaveApplications->getCollection()->transform(function ($application) {
|
||||
if ($application->employee) {
|
||||
$rawAvatar = $application->employee->getRawOriginal('avatar');
|
||||
$application->employee->avatar = check_file($rawAvatar)
|
||||
? get_file($rawAvatar)
|
||||
: get_file('avatars/avatar.png');
|
||||
}
|
||||
return $application;
|
||||
});
|
||||
|
||||
// Get employees for filter dropdown
|
||||
$employees = User::where('type', 'employee')
|
||||
->whereIn('created_by', getCompanyAndUsersId())
|
||||
->get(['id', 'name']);
|
||||
|
||||
// Get leave types for filter dropdown
|
||||
$leaveTypes = LeaveType::whereIn('created_by', getCompanyAndUsersId())
|
||||
->where('status', 'active')
|
||||
->get(['id', 'name', 'color']);
|
||||
|
||||
return Inertia::render('hr/leave-applications/index', [
|
||||
'leaveApplications' => $leaveApplications,
|
||||
'employees' => $this->getFilteredEmployees(),
|
||||
'leaveTypes' => $leaveTypes,
|
||||
'filters' => $request->all(['search', 'employee_id', 'leave_type_id', 'status', 'sort_field', 'sort_direction', 'per_page']),
|
||||
]);
|
||||
} else {
|
||||
return redirect()->back()->with('error', __('Permission Denied.'));
|
||||
$query->orderBy('id', 'desc');
|
||||
}
|
||||
|
||||
$leaveApplications = $query->paginate($request->per_page ?? 10);
|
||||
|
||||
$leaveApplications->getCollection()->transform(function ($application) {
|
||||
if ($application->employee) {
|
||||
$rawAvatar = $application->employee->getRawOriginal('avatar');
|
||||
$application->employee->avatar = check_file($rawAvatar)
|
||||
? get_file($rawAvatar)
|
||||
: get_file('avatars/avatar.png');
|
||||
}
|
||||
return $application;
|
||||
});
|
||||
|
||||
// Get leave types for filter dropdown
|
||||
$leaveTypes = LeaveType::whereIn('created_by', getCompanyAndUsersId())
|
||||
->where('status', 'active')
|
||||
->get(['id', 'name', 'color']);
|
||||
|
||||
return Inertia::render('hr/leave-applications/index', [
|
||||
'leaveApplications' => $leaveApplications,
|
||||
'employees' => $isMyLeavesView ? [] : $this->getFilteredEmployees(),
|
||||
'leaveTypes' => $leaveTypes,
|
||||
'filters' => $request->all(['search', 'status', 'employee_id', 'leave_type_id', 'sort_field', 'sort_direction', 'per_page']),
|
||||
]);
|
||||
}
|
||||
|
||||
private function getFilteredEmployees()
|
||||
{
|
||||
// Get employees for filter dropdown (compatible with getFilteredEmployees logic)
|
||||
$user = Auth::user();
|
||||
$employeeQuery = Employee::whereIn('created_by', getCompanyAndUsersId());
|
||||
|
||||
if (Auth::user()->can('manage-own-leave-applications') && ! Auth::user()->can('manage-any-leave-applications')) {
|
||||
$employeeQuery->where(function ($q) {
|
||||
$q->where('created_by', Auth::id())->orWhere('user_id', Auth::id());
|
||||
});
|
||||
if (!$user->can('manage-any-leave-applications')) {
|
||||
if ($user->can('manage-leave-applications')) {
|
||||
$branchId = $user->branch_id ?? $user->employee?->branch_id ?? null;
|
||||
if ($branchId) {
|
||||
$employeeQuery->where('branch_id', $branchId);
|
||||
} else {
|
||||
$employeeQuery->where('user_id', $user->id);
|
||||
}
|
||||
} else {
|
||||
$employeeQuery->where('user_id', $user->id);
|
||||
}
|
||||
}
|
||||
|
||||
$employees = User::emp()
|
||||
@@ -163,11 +141,11 @@ class LeaveApplicationController extends Controller
|
||||
->whereIn('id', $employeeQuery->pluck('user_id'))
|
||||
->select('id', 'name')
|
||||
->get()
|
||||
->map(function ($user) {
|
||||
->map(function ($u) {
|
||||
return [
|
||||
'id' => $user->id,
|
||||
'name' => $user->name,
|
||||
'employee_id' => $user->employee->employee_id ?? '',
|
||||
'id' => $u->id,
|
||||
'name' => $u->name,
|
||||
'employee_id' => $u->employee->employee_id ?? '',
|
||||
];
|
||||
});
|
||||
|
||||
@@ -377,6 +355,21 @@ class LeaveApplicationController extends Controller
|
||||
->first();
|
||||
|
||||
if ($leaveApplication) {
|
||||
// If the leave belongs to the currently logged in user, require manage-own-leave-applications permission
|
||||
if ($leaveApplication->employee_id == Auth::id()) {
|
||||
if (!Auth::user()->can('manage-own-leave-applications')) {
|
||||
return redirect()->back()->with(
|
||||
'error',
|
||||
__('You are not authorized to approve or reject your own leave application.')
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$requiredPerm = $validated['status'] === 'approved' ? 'approve-leave-applications' : 'reject-leave-applications';
|
||||
if (!Auth::user()->can($requiredPerm) && !Auth::user()->can('manage-leave-applications') && !Auth::user()->can('manage-any-leave-applications')) {
|
||||
return redirect()->back()->with('error', __('Permission Denied.'));
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$leaveApplication->update([
|
||||
'status' => $validated['status'],
|
||||
@@ -423,10 +416,19 @@ class LeaveApplicationController extends Controller
|
||||
{
|
||||
if (Auth::user()->can('export-leave-applications')) {
|
||||
try {
|
||||
$leaveApplications = LeaveApplication::with(['employee', 'leaveType', 'approver'])
|
||||
$leaveApplications = LeaveApplication::with(['employee.employee', 'leaveType', 'approver'])
|
||||
->where(function ($q) {
|
||||
if (Auth::user()->can('manage-any-leave-applications')) {
|
||||
$q->whereIn('created_by', getCompanyAndUsersId());
|
||||
} elseif (Auth::user()->can('manage-leave-applications')) {
|
||||
$branchId = Auth::user()->branch_id ?? Auth::user()->employee?->branch_id ?? null;
|
||||
if ($branchId) {
|
||||
$q->whereHas('employee.employee', function ($eq) use ($branchId) {
|
||||
$eq->where('branch_id', $branchId);
|
||||
});
|
||||
} else {
|
||||
$q->where('created_by', Auth::id())->orWhere('employee_id', Auth::id())->orWhere('approved_by', Auth::id());
|
||||
}
|
||||
} elseif (Auth::user()->can('manage-own-leave-applications')) {
|
||||
$q->where('created_by', Auth::id())->orWhere('employee_id', Auth::id())->orWhere('approved_by', Auth::id());
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user