updateOrCreate(['config_key' => 'school_year'], ['config_value' => $schoolYear]); Configuration::query()->updateOrCreate(['config_key' => 'semester'], ['config_value' => $semester]); } if (class_exists(SchoolYear::class)) { SchoolYear::query()->updateOrCreate( ['name' => $schoolYear], [ 'start_date' => '2025-09-01', 'end_date' => '2026-06-30', 'status' => SchoolYear::STATUS_ACTIVE, 'is_current' => true, ] ); } } /** * @return array */ protected function seedApiRoles(): array { $roles = [ 'administrator' => ['priority' => 1, 'dashboard_route' => 'administrator/administratordashboard'], 'admin' => ['priority' => 2, 'dashboard_route' => 'administrator/administratordashboard'], 'teacher' => ['priority' => 3, 'dashboard_route' => 'teacher/classes'], 'parent' => ['priority' => 4, 'dashboard_route' => 'parents/profile'], 'student' => ['priority' => 5, 'dashboard_route' => 'student/dashboard'], ]; $created = []; foreach ($roles as $name => $attributes) { $created[$name] = Role::query()->updateOrCreate( ['name' => $name], [ 'slug' => $name, 'description' => ucfirst($name), 'priority' => $attributes['priority'], 'dashboard_route' => $attributes['dashboard_route'], 'is_active' => 1, ] ); } return $created; } protected function createApiUserWithRole(string $roleName = 'administrator', array $overrides = []): User { $roles = $this->seedApiRoles(); $this->seedApiTestConfig(); $this->seedSchoolYearClosurePermissionsForTests($roles); $user = User::factory()->create(array_merge([ 'status' => 'Active', 'is_verified' => 1, 'is_suspended' => 0, 'address_street' => '1 Test Street', 'city' => 'Brooklyn', 'state' => 'NY', 'zip' => '11201', 'email' => $roleName.'-api-test-'.str_replace('.', '', uniqid('', true)).'@example.test', ], $overrides)); $role = $roles[$roleName] ?? Role::query()->where('name', $roleName)->firstOrFail(); $user->roles()->syncWithoutDetaching([$role->id]); return $user->fresh() ?? $user; } protected function actingAsApiAdministrator(): User { $user = $this->createApiUserWithRole('administrator'); $this->actingAs($user, 'api'); Sanctum::actingAs($user); return $user; } protected function actingAsTeacher(array $overrides = []): User { $user = $this->createApiUserWithRole('teacher', $overrides); $this->actingAs($user, 'api'); Sanctum::actingAs($user); return $user; } protected function actingAsStaff(array $overrides = []): User { $user = $this->createApiUserWithRole('admin', $overrides); $this->actingAs($user, 'api'); Sanctum::actingAs($user); return $user; } protected function actingAsParent(array $overrides = []): User { $user = $this->createApiUserWithRole('parent', $overrides); $this->actingAs($user, 'api'); Sanctum::actingAs($user); return $user; } protected function actingAsWithPermission(string $permission, array $overrides = []): User { $user = $this->createApiUserWithRole('administrator', $overrides); if (\Illuminate\Support\Facades\Schema::hasTable('permissions') && \Illuminate\Support\Facades\Schema::hasTable('role_permissions')) { $permissionId = (int) \Illuminate\Support\Facades\DB::table('permissions')->where('name', $permission)->value('id'); if ($permissionId > 0) { $roleIds = $user->roles()->pluck('roles.id')->all(); foreach ($roleIds as $roleId) { \Illuminate\Support\Facades\DB::table('role_permissions')->updateOrInsert( ['role_id' => $roleId, 'permission_id' => $permissionId], [ 'can_create' => true, 'can_read' => true, 'can_update' => true, 'can_delete' => true, 'can_manage' => true, 'created_at' => now(), 'updated_at' => now(), ] ); } } } $this->actingAs($user, 'api'); Sanctum::actingAs($user); return $user; } /** * Keep test fixtures aligned with explicit permission middleware. * Production receives these through the closure permission migration. * * @param array $roles */ protected function seedSchoolYearClosurePermissionsForTests(array $roles): void { if (! Schema::hasTable('permissions') || ! Schema::hasTable('role_permissions')) { return; } $permissions = [ 'school_year.view', 'school_year.view_closed', 'school_year.create', 'school_year.close', 'school_year.reopen', 'school_year.archive', 'school_year.manage', 'school_year.select', 'student_enrollment.view', 'student_enrollment.promote', 'finance.view', 'finance.balance_transfer.view', 'reports.view', ]; foreach ($permissions as $permission) { DB::table('permissions')->updateOrInsert( ['name' => $permission], ['description' => 'Test permission '.$permission, 'created_at' => now(), 'updated_at' => now()] ); } $adminRoleIds = collect([$roles['administrator'] ?? null, $roles['admin'] ?? null])->filter()->map(fn (Role $role) => (int) $role->id)->all(); $teacherRoleId = isset($roles['teacher']) ? (int) $roles['teacher']->id : null; $parentRoleId = isset($roles['parent']) ? (int) $roles['parent']->id : null; $this->grantTestPermissions($adminRoleIds, $permissions); if ($teacherRoleId) { $this->grantTestPermissions([$teacherRoleId], ['school_year.view', 'school_year.view_closed', 'school_year.select', 'student_enrollment.view']); } if ($parentRoleId) { $this->grantTestPermissions([$parentRoleId], ['school_year.view', 'school_year.select', 'finance.view']); } } /** @param list $roleIds */ private function grantTestPermissions(array $roleIds, array $permissions): void { foreach ($roleIds as $roleId) { foreach ($permissions as $permission) { $permissionId = (int) DB::table('permissions')->where('name', $permission)->value('id'); if ($permissionId <= 0) { continue; } DB::table('role_permissions')->updateOrInsert( ['role_id' => $roleId, 'permission_id' => $permissionId], [ 'can_create' => true, 'can_read' => true, 'can_update' => true, 'can_delete' => true, 'can_manage' => true, 'created_at' => now(), 'updated_at' => now(), ] ); } } } /** * @return array */ protected function validUserPayload(int $roleId, array $overrides = []): array { $unique = str_replace('.', '', uniqid('', true)); return array_merge([ 'firstname' => 'Api', 'lastname' => 'Coverage', 'gender' => 'Male', 'cellphone' => '5551234567', 'email' => "api.coverage.$unique@example.test", 'address_street' => '1 Test Street', 'city' => 'Brooklyn', 'state' => 'NY', 'zip' => '11201', 'accept_school_policy' => true, 'role_id' => $roleId, 'password' => 'password', 'semester' => 'Fall', 'school_year' => '2025-2026', 'school_id' => 1, 'user_type' => 'primary', 'status' => 'Active', 'is_verified' => true, 'is_suspended' => false, ], $overrides); } }