create([ 'username' => 'admin_list', 'password_hash' => 'unused', 'name' => '管理员', 'status' => 'active', ])); $competition = Competition::query()->create([ 'slug' => 'xxf', 'name' => '测试赛', 'published' => true, ]); $active = Application::query()->create([ 'user_id' => User::query()->create(['mobile' => '13800138001'])->id, 'competition_id' => $competition->id, 'status' => 'submitted', 'project_name' => '有效项目', ]); $deleted = Application::query()->create([ 'user_id' => User::query()->create(['mobile' => '13800138002'])->id, 'competition_id' => $competition->id, 'status' => 'submitted', 'project_name' => '已删除项目', ]); $deleted->forceFill(['deleted_at' => now()])->save(); $response = $this->getJson("/api/v1/admin/competitions/{$competition->id}/applications?status=submitted") ->assertOk(); $ids = collect($response->json('data'))->pluck('id')->all(); $this->assertContains($active->id, $ids); $this->assertNotContains($deleted->id, $ids); } public function test_admin_application_list_filters_by_review_result(): void { Sanctum::actingAs(AdminUser::query()->create([ 'username' => 'admin_filter', 'password_hash' => 'unused', 'name' => '管理员', 'status' => 'active', ])); $competition = Competition::query()->create([ 'slug' => 'xxf-filter', 'name' => '筛选测试赛', 'published' => true, ]); $passed = Application::query()->create([ 'user_id' => User::query()->create(['mobile' => '13800138011'])->id, 'competition_id' => $competition->id, 'status' => 'submitted', 'project_name' => '已通过项目', 'review_result' => 'passed', ]); Application::query()->create([ 'user_id' => User::query()->create(['mobile' => '13800138012'])->id, 'competition_id' => $competition->id, 'status' => 'submitted', 'project_name' => '待评定项目', 'review_result' => null, ]); $response = $this->getJson("/api/v1/admin/competitions/{$competition->id}/applications?status=submitted&review_result=passed") ->assertOk(); $ids = collect($response->json('data'))->pluck('id')->all(); $this->assertContains($passed->id, $ids); $this->assertCount(1, $ids); } public function test_admin_application_list_survives_schema_without_list_flag(): void { Sanctum::actingAs(AdminUser::query()->create([ 'username' => 'admin_schema_list', 'password_hash' => 'unused', 'name' => '管理员', 'status' => 'active', ])); $competition = Competition::query()->create([ 'slug' => 'xxf-schema-list', 'name' => '缺 list 字段赛', 'published' => true, ]); $schema = FormSchemaDefinition::query()->create([ 'competition_id' => $competition->id, 'purpose' => FormSchemaDefinition::PURPOSE_SIGNUP, 'name' => '报名表', 'version' => 1, 'is_published' => true, 'schema_json' => [ [ 'key' => 'contact_email', 'type' => 'email', 'label' => '邮箱', ], [ 'key' => 'event_location', 'type' => 'select', 'label' => '意向参赛地点', ], ], ]); $competition->forceFill(['form_schema_id' => $schema->id])->save(); Application::query()->create([ 'user_id' => User::query()->create(['mobile' => '13800138021'])->id, 'competition_id' => $competition->id, 'status' => 'submitted', 'project_name' => '缺 list 项目', 'review_eligible' => true, ]); $this->getJson("/api/v1/admin/competitions/{$competition->id}/applications?page=1&per_page=15&status=submitted&review_eligible=true") ->assertOk() ->assertJsonPath('data.0.project_name', '缺 list 项目'); } public function test_admin_application_list_keeps_files_count_when_sorting_by_team_avg(): void { Sanctum::actingAs(AdminUser::query()->create([ 'username' => 'admin_files_count', 'password_hash' => 'unused', 'name' => '管理员', 'status' => 'active', ])); $competition = Competition::query()->create([ 'slug' => 'xxf-files-count', 'name' => '附件计数赛', 'published' => true, ]); $application = Application::query()->create([ 'user_id' => User::query()->create(['mobile' => '13800138031'])->id, 'competition_id' => $competition->id, 'status' => 'submitted', 'project_name' => '有附件项目', ]); ApplicationFile::query()->create([ 'application_id' => $application->id, 'kind' => 'plan', 'disk' => 'public', 'path' => 'applications/plan.pdf', 'original_name' => '商业计划书.pdf', 'size' => 1024, 'mime' => 'application/pdf', ]); ApplicationFile::query()->create([ 'application_id' => $application->id, 'kind' => 'supporting', 'disk' => 'public', 'path' => 'applications/extra.pdf', 'original_name' => '补充材料.pdf', 'size' => 2048, 'mime' => 'application/pdf', ]); $this->getJson("/api/v1/admin/competitions/{$competition->id}/applications?status=submitted&sort_by=team_avg&sort_dir=desc") ->assertOk() ->assertJsonPath('data.0.id', $application->id) ->assertJsonPath('data.0.files_count', 2); } public function test_admin_application_list_rounds_team_avg_to_two_decimals(): void { Sanctum::actingAs(AdminUser::query()->create([ 'username' => 'admin_avg_round', 'password_hash' => 'unused', 'name' => '管理员', 'status' => 'active', ])); $competition = Competition::query()->create([ 'slug' => 'xxf-avg-round', 'name' => '均分取整赛', 'published' => true, ]); $application = Application::query()->create([ 'user_id' => User::query()->create(['mobile' => '13800138032'])->id, 'competition_id' => $competition->id, 'status' => 'submitted', 'project_name' => '小数均分项目', ]); $reviewerA = Reviewer::query()->create([ 'mobile' => '13900139201', 'username' => 'rev_avg_a', 'name' => '评委A', 'status' => 'active', 'password_hash' => 'unused', ]); $reviewerB = Reviewer::query()->create([ 'mobile' => '13900139202', 'username' => 'rev_avg_b', 'name' => '评委B', 'status' => 'active', 'password_hash' => 'unused', ]); ApplicationReviewScore::query()->create([ 'application_id' => $application->id, 'reviewer_id' => $reviewerA->id, 'payload_json' => ['line_total' => 80.33], 'line_total' => 80.33, ]); ApplicationReviewScore::query()->create([ 'application_id' => $application->id, 'reviewer_id' => $reviewerB->id, 'payload_json' => ['line_total' => 80.34], 'line_total' => 80.34, ]); $this->getJson("/api/v1/admin/competitions/{$competition->id}/applications?status=submitted") ->assertOk() ->assertJsonPath('data.0.id', $application->id) ->assertJsonPath('data.0.team_sum', 160.67) ->assertJsonPath('data.0.team_avg', 80.34); } }