'manage-branches']); Permission::firstOrCreate(['name' => 'manage-any-branches']); Permission::firstOrCreate(['name' => 'manage-departments']); Permission::firstOrCreate(['name' => 'manage-any-departments']); Permission::firstOrCreate(['name' => 'manage-employees']); Permission::firstOrCreate(['name' => 'manage-any-employees']); Permission::firstOrCreate(['name' => 'manage-payslips']); Permission::firstOrCreate(['name' => 'manage-any-payslips']); Permission::firstOrCreate(['name' => 'manage-payroll-runs']); Permission::firstOrCreate(['name' => 'manage-biometric-attendance']); Permission::firstOrCreate(['name' => 'manage-leave-applications']); Permission::firstOrCreate(['name' => 'manage-any-leave-applications']); Permission::firstOrCreate(['name' => 'manage-own-leave-applications']); Permission::firstOrCreate(['name' => 'manage-leave-balances']); Permission::firstOrCreate(['name' => 'manage-any-leave-balances']); Permission::firstOrCreate(['name' => 'manage-own-leave-balances']); Permission::firstOrCreate(['name' => 'view-leave-balances']); Permission::firstOrCreate(['name' => 'view-leave-applications']); Permission::firstOrCreate(['name' => 'manage-employee-salaries']); Permission::firstOrCreate(['name' => 'manage-any-employee-salaries']); Permission::firstOrCreate(['name' => 'view-payroll-runs']); Permission::firstOrCreate(['name' => 'download-payslips']); } public function test_auth_branch_id_helper_resolution() { $company = User::create([ 'name' => 'Company Admin', 'email' => 'company_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'company', ]); $superadmin = User::create([ 'name' => 'Super Admin', 'email' => 'admin_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'superadmin', ]); $branch = Branch::create([ 'name' => 'Branch Alpha', 'created_by' => $company->id, ]); $userDirectBranch = User::create([ 'name' => 'Branch User', 'email' => 'hr_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'hr', 'branch_id' => $branch->id, 'created_by' => $company->id, ]); $this->actingAs($company); $this->assertNull(authBranchId()); $this->actingAs($superadmin); $this->assertNull(authBranchId()); $this->actingAs($userDirectBranch); $this->assertEquals($branch->id, authBranchId()); } public function test_branch_scoped_user_only_sees_assigned_branch() { $company = User::create([ 'name' => 'Company Admin', 'email' => 'company_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'company', ]); $company->givePermissionTo('manage-branches'); $company->givePermissionTo('manage-any-branches'); $branchA = Branch::create([ 'name' => 'Branch Alpha', 'created_by' => $company->id, ]); $branchB = Branch::create([ 'name' => 'Branch Beta', 'created_by' => $company->id, ]); $hrUser = User::create([ 'name' => 'HR User Branch A', 'email' => 'hr_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'hr', 'branch_id' => $branchA->id, 'created_by' => $company->id, ]); $hrUser->givePermissionTo('manage-branches'); $hrUser->givePermissionTo('manage-any-branches'); // Test HR accessing branches index $response = $this->actingAs($hrUser)->get(route('hr.branches.index')); $response->assertStatus(200); $response->assertSee('Branch Alpha'); $response->assertDontSee('Branch Beta'); // Test Company Admin accessing branches index $companyResponse = $this->actingAs($company)->get(route('hr.branches.index')); $companyResponse->assertStatus(200); $companyResponse->assertSee('Branch Alpha'); $companyResponse->assertSee('Branch Beta'); } public function test_branch_scoped_user_only_sees_assigned_branch_departments_and_employees() { $company = User::create([ 'name' => 'Company Admin', 'email' => 'company_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'company', ]); $branchA = Branch::create([ 'name' => 'Branch Alpha', 'created_by' => $company->id, ]); $branchB = Branch::create([ 'name' => 'Branch Beta', 'created_by' => $company->id, ]); $deptA = Department::create([ 'name' => 'Dept Alpha Finance', 'branch_id' => $branchA->id, 'created_by' => $company->id, ]); $deptB = Department::create([ 'name' => 'Dept Beta Logistics', 'branch_id' => $branchB->id, 'created_by' => $company->id, ]); // Employee in Branch A $userA = User::create([ 'name' => 'Employee Alpha User', 'email' => 'alpha_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'employee', 'created_by' => $company->id, ]); Employee::create([ 'user_id' => $userA->id, 'employee_id' => 'EMP-A-' . rand(100, 999), 'branch_id' => $branchA->id, 'department_id' => $deptA->id, 'created_by' => $company->id, ]); // Employee in Branch B $userB = User::create([ 'name' => 'Employee Beta User', 'email' => 'beta_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'employee', 'created_by' => $company->id, ]); Employee::create([ 'user_id' => $userB->id, 'employee_id' => 'EMP-B-' . rand(100, 999), 'branch_id' => $branchB->id, 'department_id' => $deptB->id, 'created_by' => $company->id, ]); $hrUser = User::create([ 'name' => 'HR Branch A User', 'email' => 'hr_a_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'hr', 'branch_id' => $branchA->id, 'created_by' => $company->id, ]); $hrUser->givePermissionTo('manage-departments'); $hrUser->givePermissionTo('manage-any-departments'); $hrUser->givePermissionTo('manage-employees'); $hrUser->givePermissionTo('manage-any-employees'); // Department index check $deptResponse = $this->actingAs($hrUser)->get(route('hr.departments.index')); $deptResponse->assertStatus(200); $deptResponse->assertSee('Dept Alpha Finance'); $deptResponse->assertDontSee('Dept Beta Logistics'); // Employee index check $empResponse = $this->actingAs($hrUser)->get(route('hr.employees.index')); $empResponse->assertStatus(200); $empResponse->assertSee('Employee Alpha User'); $empResponse->assertDontSee('Employee Beta User'); } public function test_branch_scoped_user_only_sees_assigned_branch_payslips() { $company = User::create([ 'name' => 'Company Admin', 'email' => 'company_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'company', ]); $branchA = Branch::create([ 'name' => 'Branch Alpha', 'created_by' => $company->id, ]); $branchB = Branch::create([ 'name' => 'Branch Beta', 'created_by' => $company->id, ]); // Employee A $userA = User::create([ 'name' => 'Employee Alpha User', 'email' => 'alpha_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'employee', 'created_by' => $company->id, ]); Employee::create([ 'user_id' => $userA->id, 'employee_id' => 'EMP-A-' . rand(100, 999), 'branch_id' => $branchA->id, 'created_by' => $company->id, ]); // Employee B $userB = User::create([ 'name' => 'Employee Beta User', 'email' => 'beta_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'employee', 'created_by' => $company->id, ]); Employee::create([ 'user_id' => $userB->id, 'employee_id' => 'EMP-B-' . rand(100, 999), 'branch_id' => $branchB->id, 'created_by' => $company->id, ]); $payrollRun = PayrollRun::create([ 'title' => 'May 1-15 2026', 'payroll_frequency' => 'monthly', 'pay_period_start' => '2026-05-01', 'pay_period_end' => '2026-05-15', 'pay_date' => '2026-05-15', 'status' => 'completed', 'created_by' => $company->id, ]); $entryA = PayrollEntry::create([ 'payroll_run_id' => $payrollRun->id, 'employee_id' => $userA->id, 'basic_salary' => 10000, 'created_by' => $company->id, ]); $entryB = PayrollEntry::create([ 'payroll_run_id' => $payrollRun->id, 'employee_id' => $userB->id, 'basic_salary' => 10000, 'created_by' => $company->id, ]); // Payslips $payslipA = Payslip::create([ 'payroll_entry_id' => $entryA->id, 'employee_id' => $userA->id, 'payslip_number' => 'PAY-ALPHA-001', 'pay_period_start' => '2026-05-01', 'pay_period_end' => '2026-05-15', 'pay_date' => '2026-05-15', 'status' => 'generated', 'created_by' => $company->id, ]); $payslipB = Payslip::create([ 'payroll_entry_id' => $entryB->id, 'employee_id' => $userB->id, 'payslip_number' => 'PAY-BETA-002', 'pay_period_start' => '2026-05-01', 'pay_period_end' => '2026-05-15', 'pay_date' => '2026-05-15', 'status' => 'generated', 'created_by' => $company->id, ]); $hrUser = User::create([ 'name' => 'HR Branch A User', 'email' => 'hr_a_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'hr', 'branch_id' => $branchA->id, 'created_by' => $company->id, ]); $hrUser->givePermissionTo('manage-payslips'); $hrUser->givePermissionTo('manage-any-payslips'); $response = $this->actingAs($hrUser)->get(route('hr.payslips.index')); $response->assertStatus(200); $response->assertSee('PAY-ALPHA-001'); $response->assertDontSee('PAY-BETA-002'); } public function test_branch_scoped_user_only_sees_assigned_branch_overtime_requests() { $company = User::create([ 'name' => 'Company Admin', 'email' => 'company_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'company', ]); $branchA = Branch::create([ 'name' => 'Branch Alpha', 'created_by' => $company->id, ]); $branchB = Branch::create([ 'name' => 'Branch Beta', 'created_by' => $company->id, ]); // Employee in Branch A $userA = User::create([ 'name' => 'Employee Alpha User', 'email' => 'alpha_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'employee', 'created_by' => $company->id, ]); Employee::create([ 'user_id' => $userA->id, 'employee_id' => 'EMP-A-' . rand(100, 999), 'branch_id' => $branchA->id, 'created_by' => $company->id, ]); // Employee in Branch B $userB = User::create([ 'name' => 'Employee Beta User', 'email' => 'beta_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'employee', 'created_by' => $company->id, ]); Employee::create([ 'user_id' => $userB->id, 'employee_id' => 'EMP-B-' . rand(100, 999), 'branch_id' => $branchB->id, 'created_by' => $company->id, ]); // Overtime requests OvertimeApplication::create([ 'user_id' => $userA->id, 'date' => '2026-05-10', 'requested_hours' => 2.5, 'reason' => 'Alpha Overtime Work', 'status' => 'pending', ]); OvertimeApplication::create([ 'user_id' => $userB->id, 'date' => '2026-05-10', 'requested_hours' => 3.0, 'reason' => 'Beta Overtime Work', 'status' => 'pending', ]); $hrUser = User::create([ 'name' => 'HR Branch A User', 'email' => 'hr_a_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'hr', 'branch_id' => $branchA->id, 'created_by' => $company->id, ]); $response = $this->actingAs($hrUser)->get(route('hr.overtime.index')); $response->assertStatus(200); $response->assertSee('Alpha Overtime Work'); $response->assertDontSee('Beta Overtime Work'); } public function test_branch_scoped_user_only_sees_assigned_branch_thirteenth_month() { $company = User::create([ 'name' => 'Company Admin', 'email' => 'company_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'company', ]); $branchA = Branch::create([ 'name' => 'Branch Alpha', 'created_by' => $company->id, ]); $branchB = Branch::create([ 'name' => 'Branch Beta', 'created_by' => $company->id, ]); // Employee in Branch A $userA = User::create([ 'name' => 'Employee Alpha User', 'email' => 'alpha_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'employee', 'created_by' => $company->id, ]); Employee::create([ 'user_id' => $userA->id, 'employee_id' => 'EMP-A-' . rand(100, 999), 'branch_id' => $branchA->id, 'created_by' => $company->id, ]); // Employee in Branch B $userB = User::create([ 'name' => 'Employee Beta User', 'email' => 'beta_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'employee', 'created_by' => $company->id, ]); Employee::create([ 'user_id' => $userB->id, 'employee_id' => 'EMP-B-' . rand(100, 999), 'branch_id' => $branchB->id, 'created_by' => $company->id, ]); $hrUser = User::create([ 'name' => 'HR Branch A User', 'email' => 'hr_a_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'hr', 'branch_id' => $branchA->id, 'created_by' => $company->id, ]); $hrUser->givePermissionTo('manage-payroll-runs'); $response = $this->actingAs($hrUser)->get(route('hr.thirteenth-month.index')); $response->assertStatus(200); $response->assertSee('Employee Alpha User'); $response->assertDontSee('Employee Beta User'); } public function test_branch_scoped_user_only_sees_assigned_branch_biometric_attendance() { $company = User::create([ 'name' => 'Company Admin', 'email' => 'company_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'company', ]); $branchA = Branch::create([ 'name' => 'Branch Alpha', 'created_by' => $company->id, ]); $branchB = Branch::create([ 'name' => 'Branch Beta', 'created_by' => $company->id, ]); // Employee in Branch A $userA = User::create([ 'name' => 'Employee Alpha User', 'email' => 'alpha_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'employee', 'created_by' => $company->id, ]); $empA = Employee::create([ 'user_id' => $userA->id, 'employee_id' => 'EMP-A-' . rand(100, 999), 'biometric_emp_id' => 'BIO-101', 'branch_id' => $branchA->id, 'created_by' => $company->id, ]); // Employee in Branch B $userB = User::create([ 'name' => 'Employee Beta User', 'email' => 'beta_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'employee', 'created_by' => $company->id, ]); $empB = Employee::create([ 'user_id' => $userB->id, 'employee_id' => 'EMP-B-' . rand(100, 999), 'biometric_emp_id' => 'BIO-102', 'branch_id' => $branchB->id, 'created_by' => $company->id, ]); // Biometric punches BiometricAttendance::create([ 'biometric_emp_id' => 'BIO-101', 'punch_time' => '2026-05-10 09:00:00', 'punch_state' => 0, 'branch_id' => $branchA->id, 'sync_status' => 'pending', ]); BiometricAttendance::create([ 'biometric_emp_id' => 'BIO-102', 'punch_time' => '2026-05-10 09:00:00', 'punch_state' => 0, 'branch_id' => $branchB->id, 'sync_status' => 'pending', ]); $hrUser = User::create([ 'name' => 'HR Branch A User', 'email' => 'hr_a_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'hr', 'branch_id' => $branchA->id, 'created_by' => $company->id, ]); $hrUser->givePermissionTo('manage-biometric-attendance'); $response = $this->actingAs($hrUser)->get(route('hr.biometric-attendance.index')); $response->assertStatus(200); $response->assertSee('BIO-101'); $response->assertDontSee('BIO-102'); // Test show route for foreign branch punch $foreignShowResponse = $this->actingAs($hrUser)->get(route('hr.biometric-attendance.show', [ 'employeeCode' => 'BIO-102', 'date' => '2026-05-10', ])); $foreignShowResponse->assertStatus(403); } public function test_payroll_runs_and_payslips_are_branch_scoped() { $company = User::create([ 'name' => 'Company Admin', 'email' => 'company_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'company', ]); $branchA = Branch::create(['name' => 'Branch Alpha', 'created_by' => $company->id]); $branchB = Branch::create(['name' => 'Branch Beta', 'created_by' => $company->id]); $userA = User::create([ 'name' => 'Employee Alpha User', 'email' => 'alpha_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'employee', 'created_by' => $company->id, ]); $empA = Employee::create([ 'user_id' => $userA->id, 'employee_id' => 'EMP-A-' . rand(100, 999), 'branch_id' => $branchA->id, 'created_by' => $company->id, ]); $userB = User::create([ 'name' => 'Employee Beta User', 'email' => 'beta_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'employee', 'created_by' => $company->id, ]); $empB = Employee::create([ 'user_id' => $userB->id, 'employee_id' => 'EMP-B-' . rand(100, 999), 'branch_id' => $branchB->id, 'created_by' => $company->id, ]); $run = PayrollRun::create([ 'title' => 'May 2026 Payroll', 'pay_period_start' => '2026-05-01', 'pay_period_end' => '2026-05-15', 'pay_date' => '2026-05-16', 'status' => 'draft', 'employee_count' => 2, 'total_gross_pay' => 30000, 'total_net_pay' => 28000, 'created_by' => $company->id, ]); $entryA = PayrollEntry::create([ 'payroll_run_id' => $run->id, 'employee_id' => $userA->id, 'basic_salary' => 15000, 'gross_pay' => 15000, 'net_pay' => 14000, 'status' => 'draft', 'created_by' => $company->id, ]); $entryB = PayrollEntry::create([ 'payroll_run_id' => $run->id, 'employee_id' => $userB->id, 'basic_salary' => 15000, 'gross_pay' => 15000, 'net_pay' => 14000, 'status' => 'draft', 'created_by' => $company->id, ]); $payslipA = Payslip::create([ 'payroll_entry_id' => $entryA->id, 'employee_id' => $userA->id, 'payslip_number' => 'PS-A-101', 'pay_period_start' => '2026-05-01', 'pay_period_end' => '2026-05-15', 'pay_date' => '2026-05-16', 'status' => 'generated', 'created_by' => $company->id, ]); $payslipB = Payslip::create([ 'payroll_entry_id' => $entryB->id, 'employee_id' => $userB->id, 'payslip_number' => 'PS-B-102', 'pay_period_start' => '2026-05-01', 'pay_period_end' => '2026-05-15', 'pay_date' => '2026-05-16', 'status' => 'generated', 'created_by' => $company->id, ]); $hrUser = User::create([ 'name' => 'HR Branch A User', 'email' => 'hr_a_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'hr', 'branch_id' => $branchA->id, 'created_by' => $company->id, ]); $hrUser->givePermissionTo('manage-payroll-runs'); $hrUser->givePermissionTo('view-payroll-runs'); $hrUser->givePermissionTo('manage-payslips'); // HR views Payroll Run show $runShowResponse = $this->actingAs($hrUser)->get(route('hr.payroll-runs.show', $run->id)); $runShowResponse->assertStatus(200); $runShowResponse->assertSee('Employee Alpha User'); $runShowResponse->assertDontSee('Employee Beta User'); // HR views Payslips index $payslipIndexResponse = $this->actingAs($hrUser)->get(route('hr.payslips.index')); $payslipIndexResponse->assertStatus(200); $payslipIndexResponse->assertSee('PS-A-101'); $payslipIndexResponse->assertDontSee('PS-B-102'); } public function test_employee_role_sees_own_leave_data_only() { $company = User::create([ 'name' => 'Company Admin', 'email' => 'company_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'company', ]); $branch = Branch::create(['name' => 'Main Branch', 'created_by' => $company->id]); $userA = User::create([ 'name' => 'Employee Alice', 'email' => 'alice_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'employee', 'created_by' => $company->id, ]); $empA = Employee::create([ 'user_id' => $userA->id, 'employee_id' => 'EMP-ALICE', 'branch_id' => $branch->id, 'created_by' => $company->id, ]); $userB = User::create([ 'name' => 'Employee Bob', 'email' => 'bob_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'employee', 'created_by' => $company->id, ]); $empB = Employee::create([ 'user_id' => $userB->id, 'employee_id' => 'EMP-BOB', 'branch_id' => $branch->id, 'created_by' => $company->id, ]); $leaveType = LeaveType::create([ 'name' => 'Vacation Leave', 'color' => '#3b82f6', 'is_paid' => true, 'status' => 'active', 'created_by' => $company->id, ]); $leavePolicy = LeavePolicy::create([ 'name' => 'Standard Vacation Policy', 'leave_type_id' => $leaveType->id, 'max_days_per_year' => 15, 'requires_approval' => true, 'status' => 'active', 'created_by' => $company->id, ]); $leaveAppA = LeaveApplication::create([ 'employee_id' => $userA->id, 'leave_type_id' => $leaveType->id, 'leave_policy_id' => $leavePolicy->id, 'start_date' => '2026-06-01', 'end_date' => '2026-06-03', 'total_days' => 3, 'reason' => 'Alice Summer Vacation', 'status' => 'pending', 'created_by' => $userA->id, ]); $leaveAppB = LeaveApplication::create([ 'employee_id' => $userB->id, 'leave_type_id' => $leaveType->id, 'leave_policy_id' => $leavePolicy->id, 'start_date' => '2026-06-05', 'end_date' => '2026-06-07', 'total_days' => 3, 'reason' => 'Bob Secret Leave', 'status' => 'pending', 'created_by' => $userB->id, ]); $balanceA = LeaveBalance::create([ 'employee_id' => $userA->id, 'leave_type_id' => $leaveType->id, 'leave_policy_id' => $leavePolicy->id, 'year' => 2026, 'allocated_days' => 15, 'used_days' => 0, 'remaining_days' => 15, 'created_by' => $company->id, ]); $balanceB = LeaveBalance::create([ 'employee_id' => $userB->id, 'leave_type_id' => $leaveType->id, 'leave_policy_id' => $leavePolicy->id, 'year' => 2026, 'allocated_days' => 20, 'used_days' => 5, 'remaining_days' => 15, 'created_by' => $company->id, ]); // Alice visits hr/leave-applications $aliceLeavesResponse = $this->actingAs($userA)->get(route('hr.leave-applications.index')); $aliceLeavesResponse->assertStatus(200); $aliceLeavesResponse->assertSee('Alice Summer Vacation'); $aliceLeavesResponse->assertDontSee('Bob Secret Leave'); // Alice visits hr/leave-balances $aliceBalancesResponse = $this->actingAs($userA)->get(route('hr.leave-balances.index')); $aliceBalancesResponse->assertStatus(200); $aliceBalancesResponse->assertSee('Employee Alice'); $aliceBalancesResponse->assertDontSee('Employee Bob'); } public function test_payslip_template_renders_scx_software_header() { $company = User::create([ 'name' => 'Company Admin', 'email' => 'company_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'company', ]); $user = User::create([ 'name' => 'John Doe', 'email' => 'john_' . uniqid() . '@test.com', 'password' => bcrypt('password'), 'type' => 'employee', 'created_by' => $company->id, ]); $emp = Employee::create([ 'user_id' => $user->id, 'employee_id' => 'EMP-JD-001', 'created_by' => $company->id, ]); $run = PayrollRun::create([ 'title' => 'May 2026 Payroll', 'pay_period_start' => '2026-05-01', 'pay_period_end' => '2026-05-15', 'pay_date' => '2026-05-16', 'status' => 'draft', 'employee_count' => 1, 'total_gross_pay' => 15000, 'total_net_pay' => 14000, 'created_by' => $company->id, ]); $entry = PayrollEntry::create([ 'payroll_run_id' => $run->id, 'employee_id' => $user->id, 'basic_salary' => 15000, 'gross_pay' => 15000, 'net_pay' => 14000, 'status' => 'draft', 'created_by' => $company->id, ]); $payslip = Payslip::create([ 'payroll_entry_id' => $entry->id, 'employee_id' => $user->id, 'payslip_number' => 'PS-JD-001', 'pay_period_start' => '2026-05-01', 'pay_period_end' => '2026-05-15', 'pay_date' => '2026-05-16', 'status' => 'generated', 'created_by' => $company->id, ]); $user->givePermissionTo('download-payslips'); $response = $this->actingAs($user)->get(route('hr.payslips.download', $payslip->id)); $response->assertStatus(200); $response->assertSee('Statlab'); } }