'Super Admin', 'guard_name' => 'web']); Role::firstOrCreate(['name' => 'admin', 'guard_name' => 'web']); Role::firstOrCreate(['name' => 'Project Manager', 'guard_name' => 'web']); $this->admin = User::factory()->create(['user_type' => 'admin', 'status' => 'active']); $this->admin->assignRole('Super Admin'); $this->project = Project::factory()->create(['status' => 'in_progress']); $this->material = Material::factory()->create(['unit_cost' => 500.00]); } public function test_admin_can_approve_material_requisition_via_modal_action(): void { $requisition = MaterialRequisition::create([ 'project_id' => $this->project->id, 'document_number' => 'MR-2026-0001', 'requisition_type' => 'project', 'status' => 'draft', 'requested_by' => $this->admin->id, ]); MaterialRequisitionItem::create([ 'material_requisition_id' => $requisition->id, 'material_id' => $this->material->id, 'quantity' => 10, 'unit_cost' => 500.00, ]); // 1. Submit for approval $this->actingAs($this->admin)->patch(route('requisitions.submit', $requisition->ulid)); $requisition->refresh(); $this->assertEquals('submitted', $requisition->status); $chain = ApprovalChain::where('approvable_type', MaterialRequisition::class) ->where('approvable_id', $requisition->id) ->firstOrFail(); // 2. Approve via modal $response = $this->actingAs($this->admin)->patch(route('approvals.approve', $chain->ulid), [ 'notes' => 'Approved for immediate purchasing', ]); $response->assertSessionHas('success'); $requisition->refresh(); $this->assertEquals('approved', $requisition->status); $this->assertEquals($this->admin->id, $requisition->approved_by); $this->assertNotNull($requisition->approved_at); } public function test_admin_can_reject_material_requisition_via_modal_action(): void { $requisition = MaterialRequisition::create([ 'project_id' => $this->project->id, 'document_number' => 'MR-2026-0002', 'requisition_type' => 'project', 'status' => 'draft', 'requested_by' => $this->admin->id, ]); MaterialRequisitionItem::create([ 'material_requisition_id' => $requisition->id, 'material_id' => $this->material->id, 'quantity' => 5, 'unit_cost' => 500.00, ]); // 1. Submit for approval $this->actingAs($this->admin)->patch(route('requisitions.submit', $requisition->ulid)); $requisition->refresh(); $chain = ApprovalChain::where('approvable_type', MaterialRequisition::class) ->where('approvable_id', $requisition->id) ->firstOrFail(); // 2. Reject via modal $response = $this->actingAs($this->admin)->patch(route('approvals.reject', $chain->ulid), [ 'notes' => 'Rejected due to budget constraints', ]); $response->assertSessionHas('success'); $requisition->refresh(); $this->assertEquals('rejected', $requisition->status); } public function test_admin_can_approve_material_requisition_via_direct_fallback_route(): void { $requisition = MaterialRequisition::create([ 'project_id' => $this->project->id, 'document_number' => 'MR-2026-0003', 'requisition_type' => 'project', 'status' => 'submitted', 'requested_by' => $this->admin->id, ]); $response = $this->actingAs($this->admin)->patch(route('requisitions.approve', $requisition->ulid), [ 'notes' => 'Direct approval without chain', ]); $response->assertSessionHas('success'); $requisition->refresh(); $this->assertEquals('approved', $requisition->status); $this->assertEquals($this->admin->id, $requisition->approved_by); } public function test_admin_can_reject_material_requisition_via_direct_fallback_route(): void { $requisition = MaterialRequisition::create([ 'project_id' => $this->project->id, 'document_number' => 'MR-2026-0004', 'requisition_type' => 'project', 'status' => 'submitted', 'requested_by' => $this->admin->id, ]); $response = $this->actingAs($this->admin)->patch(route('requisitions.reject', $requisition->ulid), [ 'notes' => 'Direct rejection reason note', ]); $response->assertSessionHas('success'); $requisition->refresh(); $this->assertEquals('rejected', $requisition->status); } }