feat(auth): enforce strict branch scoping for overtime requests, attendance regularizations, and 13th month pay

- Restrict overtime applications query, submission, approval, and attendance details to assigned branch
- Restrict attendance regularization listing, statistics, and dropdowns to assigned branch
- Restrict 13th month pay batch generation, historical runs, entry updates, approvals, and CSV exports to assigned branch
- Add feature tests in BranchScopedAccessTest for overtime and 13th month isolation
This commit is contained in:
2026-09-10 11:22:15 +08:00
parent 7f467600e9
commit 33f776c6b2
4 changed files with 251 additions and 20 deletions

View File

@@ -15,8 +15,14 @@ class AttendanceRegularizationController extends Controller
public function index(Request $request)
{
if (Auth::user()->can('manage-attendance-regularizations')) {
$query = AttendanceRegularization::with(['employee', 'attendanceRecord', 'approver', 'creator'])->where(function ($q) {
if (Auth::user()->can('manage-any-attendance-regularizations')) {
$scopedBranchId = authBranchId();
$query = AttendanceRegularization::with(['employee', 'attendanceRecord', 'approver', 'creator'])->where(function ($q) use ($scopedBranchId) {
if ($scopedBranchId) {
$q->whereIn('created_by', getCompanyAndUsersId())
->whereHas('employee.employee', function ($eq) use ($scopedBranchId) {
$eq->where('branch_id', $scopedBranchId);
});
} elseif (Auth::user()->can('manage-any-attendance-regularizations')) {
$q->whereIn('created_by', getCompanyAndUsersId());
} elseif (Auth::user()->can('manage-own-attendance-regularizations')) {
$q->where('created_by', Auth::id())->orWhere('employee_id', Auth::id())->orWhere('approved_by', Auth::id());
@@ -80,21 +86,29 @@ class AttendanceRegularizationController extends Controller
return $record;
});
$employees = User::where('type', 'employee')
->whereIn('created_by', getCompanyAndUsersId())
->get(['id', 'name']);
// Get attendance records for form dropdown
$attendanceRecords = AttendanceRecord::whereIn('created_by', getCompanyAndUsersId())
$attQuery = AttendanceRecord::whereIn('created_by', getCompanyAndUsersId())
->with('employee')
->orderBy('date', 'desc')
->take(50)
->get();
->orderBy('date', 'desc');
if ($scopedBranchId) {
$attQuery->where(function($aq) use ($scopedBranchId) {
$aq->where('branch_id', $scopedBranchId)
->orWhereHas('employee', function($eq) use ($scopedBranchId) {
$eq->where('branch_id', $scopedBranchId);
});
});
}
$attendanceRecords = $attQuery->take(50)->get();
$companyUserIds = getCompanyAndUsersId();
$statsQuery = AttendanceRegularization::where(function ($q) {
if (Auth::user()->can('manage-any-attendance-regularizations')) {
$statsQuery = AttendanceRegularization::where(function ($q) use ($scopedBranchId) {
if ($scopedBranchId) {
$q->whereIn('created_by', getCompanyAndUsersId())
->whereHas('employee.employee', function ($eq) use ($scopedBranchId) {
$eq->where('branch_id', $scopedBranchId);
});
} elseif (Auth::user()->can('manage-any-attendance-regularizations')) {
$q->whereIn('created_by', getCompanyAndUsersId());
} elseif (Auth::user()->can('manage-own-attendance-regularizations')) {
$q->where('created_by', Auth::id())->orWhere('employee_id', Auth::id())->orWhere('approved_by', Auth::id());
@@ -125,6 +139,10 @@ class AttendanceRegularizationController extends Controller
{
// Get employees for filter dropdown (compatible with getFilteredEmployees logic)
$employeeQuery = Employee::whereIn('created_by', getCompanyAndUsersId());
$scopedBranchId = authBranchId();
if ($scopedBranchId) {
$employeeQuery->where('branch_id', $scopedBranchId);
}
if (Auth::user()->can('manage-own-attendance-regularizations') && !Auth::user()->can('manage-any-attendance-regularizations')) {
$employeeQuery->where(function ($q) {