From 1dc2b14954a92180673d0040df2849c0ad167703 Mon Sep 17 00:00:00 2001 From: romanetar Date: Mon, 22 Jun 2026 15:09:12 +0200 Subject: [PATCH] feat(speakers): add has_pending_presentations filter for speakers and submitters Signed-off-by: romanetar --- .../OAuth2SummitSpeakersApiController.php | 16 ++- .../OAuth2SummitSubmittersApiController.php | 10 +- .../ProcessSpeakersEmailRequestJob.php | 1 + .../ProcessSubmittersEmailRequestJob.php | 1 + .../Summit/DoctrineMemberRepository.php | 55 +++++++++ .../Summit/DoctrineSpeakerRepository.php | 101 ++++++++++++++++ app/Services/Model/Imp/SpeakerService.php | 1 + app/Services/Model/Imp/SubmitterService.php | 3 +- tests/oauth2/OAuth2SummitSpeakersApiTest.php | 108 ++++++++++++++++++ .../oauth2/OAuth2SummitSubmittersApiTest.php | 52 +++++++++ 10 files changed, 342 insertions(+), 6 deletions(-) diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSpeakersApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSpeakersApiController.php index 1ef9c6e4f..089627fdc 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSpeakersApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSpeakersApiController.php @@ -251,7 +251,7 @@ public function __construct ), new OA\Parameter( name: 'filter', - description: 'Filter by id, not_id, first_name, last_name, email, full_name, member_id, member_user_external_id, has_accepted_presentations, has_alternate_presentations, has_rejected_presentations, presentations_track_id, presentations_track_group_id, presentations_selection_plan_id, presentations_type_id, presentations_title, presentations_abstract, presentations_submitter_full_name, presentations_submitter_email, has_media_upload_with_type, has_not_media_upload_with_type. Operands supported: == (equal), @@ (contains), =@ (starts with).', + description: 'Filter by id, not_id, first_name, last_name, email, full_name, member_id, member_user_external_id, has_pending_presentations, has_accepted_presentations, has_alternate_presentations, has_rejected_presentations, presentations_track_id, presentations_track_group_id, presentations_selection_plan_id, presentations_type_id, presentations_title, presentations_abstract, presentations_submitter_full_name, presentations_submitter_email, has_media_upload_with_type, has_not_media_upload_with_type. Operands supported: == (equal), @@ (contains), =@ (starts with).', in: 'query', required: false, schema: new OA\Schema(type: 'string') @@ -311,6 +311,7 @@ function () { 'full_name' => ['=@', '@@', '=='], 'member_id' => ['=='], 'member_user_external_id' => ['=='], + 'has_pending_presentations' => ['=='], 'has_accepted_presentations' => ['=='], 'has_alternate_presentations' => ['=='], 'has_rejected_presentations' => ['=='], @@ -336,6 +337,7 @@ function () { 'full_name' => 'sometimes|string', 'member_id' => 'sometimes|integer', 'member_user_external_id' => 'sometimes|integer', + 'has_pending_presentations' => 'sometimes|string|in:true,false', 'has_accepted_presentations' => 'sometimes|string|in:true,false', 'has_alternate_presentations' => 'sometimes|string|in:true,false', 'has_rejected_presentations' => 'sometimes|string|in:true,false', @@ -411,7 +413,7 @@ function ($page, $per_page, $filter, $order, $applyExtraFilters) use ($summit) { ), new OA\Parameter( name: 'filter', - description: 'Filter query (supports multiple operators). Filterable fields: id, not_id, first_name, last_name, email, full_name, member_id, member_user_external_id, has_accepted_presentations, has_alternate_presentations, has_rejected_presentations, presentations_track_id, presentations_track_group_id, presentations_selection_plan_id, presentations_type_id, presentations_title, presentations_abstract, presentations_submitter_full_name, presentations_submitter_email, has_media_upload_with_type, has_not_media_upload_with_type.', + description: 'Filter query (supports multiple operators). Filterable fields: id, not_id, first_name, last_name, email, full_name, member_id, member_user_external_id, has_pending_presentations, has_accepted_presentations, has_alternate_presentations, has_rejected_presentations, presentations_track_id, presentations_track_group_id, presentations_selection_plan_id, presentations_type_id, presentations_title, presentations_abstract, presentations_submitter_full_name, presentations_submitter_email, has_media_upload_with_type, has_not_media_upload_with_type.', in: 'query', required: false, schema: new OA\Schema(type: 'string') @@ -451,6 +453,7 @@ public function getSpeakersActivitiesCount($summit_id) 'full_name' => ['=@', '@@', '=='], 'member_id' => ['=='], 'member_user_external_id' => ['=='], + 'has_pending_presentations' => ['=='], 'has_accepted_presentations' => ['=='], 'has_alternate_presentations' => ['=='], 'has_rejected_presentations' => ['=='], @@ -477,6 +480,7 @@ public function getSpeakersActivitiesCount($summit_id) 'full_name' => 'sometimes|string', 'member_id' => 'sometimes|integer', 'member_user_external_id' => 'sometimes|integer', + 'has_pending_presentations' => 'sometimes|string|in:true,false', 'has_accepted_presentations' => 'sometimes|string|in:true,false', 'has_alternate_presentations' => 'sometimes|string|in:true,false', 'has_rejected_presentations' => 'sometimes|string|in:true,false', @@ -529,7 +533,7 @@ public function getSpeakersActivitiesCount($summit_id) ), new OA\Parameter( name: 'filter', - description: 'Filter by id, not_id, first_name, last_name, email, full_name, member_id, member_user_external_id, has_accepted_presentations, has_alternate_presentations, has_rejected_presentations, presentations_track_id, presentations_track_group_id, presentations_selection_plan_id, presentations_type_id, presentations_title, presentations_abstract, presentations_submitter_full_name, presentations_submitter_email, has_media_upload_with_type, has_not_media_upload_with_type. Operands supported: == (equal), @@ (contains), =@ (starts with).', + description: 'Filter by id, not_id, first_name, last_name, email, full_name, member_id, member_user_external_id, has_pending_presentations, has_accepted_presentations, has_alternate_presentations, has_rejected_presentations, presentations_track_id, presentations_track_group_id, presentations_selection_plan_id, presentations_type_id, presentations_title, presentations_abstract, presentations_submitter_full_name, presentations_submitter_email, has_media_upload_with_type, has_not_media_upload_with_type. Operands supported: == (equal), @@ (contains), =@ (starts with).', in: 'query', required: false, schema: new OA\Schema(type: 'string') @@ -592,6 +596,7 @@ function () { 'full_name' => ['=@', '@@', '=='], 'member_id' => ['=='], 'member_user_external_id' => ['=='], + 'has_pending_presentations' => ['=='], 'has_accepted_presentations' => ['=='], 'has_alternate_presentations' => ['=='], 'has_rejected_presentations' => ['=='], @@ -617,6 +622,7 @@ function () { 'full_name' => 'sometimes|string', 'member_id' => 'sometimes|integer', 'member_user_external_id' => 'sometimes|integer', + 'has_pending_presentations' => 'sometimes|string|in:true,false', 'has_accepted_presentations' => 'sometimes|string|in:true,false', 'has_alternate_presentations' => 'sometimes|string|in:true,false', 'has_rejected_presentations' => 'sometimes|string|in:true,false', @@ -3189,7 +3195,7 @@ public function deleteSpeakerBigPhoto($speaker_id) ), new OA\Parameter( name: 'filter', - description: 'Filter speakers by id, first_name, last_name, email, full_name, has_accepted_presentations, has_alternate_presentations, has_rejected_presentations, presentations_track_id, presentations_track_group_id, presentations_selection_plan_id, presentations_type_id, presentations_title, presentations_abstract, presentations_submitter_full_name, presentations_submitter_email, has_media_upload_with_type, has_not_media_upload_with_type', + description: 'Filter speakers by id, first_name, last_name, email, full_name, has_pending_presentations, has_accepted_presentations, has_alternate_presentations, has_rejected_presentations, presentations_track_id, presentations_track_group_id, presentations_selection_plan_id, presentations_type_id, presentations_title, presentations_abstract, presentations_submitter_full_name, presentations_submitter_email, has_media_upload_with_type, has_not_media_upload_with_type', in: 'query', required: false, schema: new OA\Schema(type: 'string') @@ -3252,6 +3258,7 @@ public function send($summit_id) 'last_name' => ['=@', '@@', '=='], 'email' => ['=@', '@@', '=='], 'full_name' => ['=@', '@@', '=='], + 'has_pending_presentations' => ['=='], 'has_accepted_presentations' => ['=='], 'has_alternate_presentations' => ['=='], 'has_rejected_presentations' => ['=='], @@ -3278,6 +3285,7 @@ public function send($summit_id) 'last_name' => 'sometimes|string', 'email' => 'sometimes|string', 'full_name' => 'sometimes|string', + 'has_pending_presentations' => 'sometimes|string|in:true,false', 'has_accepted_presentations' => 'sometimes|string|in:true,false', 'has_alternate_presentations' => 'sometimes|string|in:true,false', 'has_rejected_presentations' => 'sometimes|string|in:true,false', diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSubmittersApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSubmittersApiController.php index 86653a432..eea24d4c0 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSubmittersApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSubmittersApiController.php @@ -152,6 +152,7 @@ function () { 'full_name' => ['=@', '@@', '=='], 'member_id' => ['=='], 'member_user_external_id' => ['=='], + 'has_pending_presentations' => ['=='], 'has_accepted_presentations' => ['=='], 'has_alternate_presentations' => ['=='], 'has_rejected_presentations' => ['=='], @@ -177,6 +178,7 @@ function () { 'full_name' => 'sometimes|string', 'member_id' => 'sometimes|integer', 'member_user_external_id' => 'sometimes|integer', + 'has_pending_presentations' => 'sometimes|string|in:true,false', 'has_accepted_presentations' => 'sometimes|string|in:true,false', 'has_alternate_presentations' => 'sometimes|string|in:true,false', 'has_rejected_presentations' => 'sometimes|string|in:true,false', @@ -296,6 +298,7 @@ function () { 'full_name' => ['=@', '@@', '=='], 'member_id' => ['=='], 'member_user_external_id' => ['=='], + 'has_pending_presentations' => ['=='], 'has_accepted_presentations' => ['=='], 'has_alternate_presentations' => ['=='], 'has_rejected_presentations' => ['=='], @@ -321,6 +324,7 @@ function () { 'full_name' => 'sometimes|string', 'member_id' => 'sometimes|integer', 'member_user_external_id' => 'sometimes|integer', + 'has_pending_presentations' => 'sometimes|string|in:true,false', 'has_accepted_presentations' => 'sometimes|string|in:true,false', 'has_alternate_presentations' => 'sometimes|string|in:true,false', 'has_rejected_presentations' => 'sometimes|string|in:true,false', @@ -447,6 +451,7 @@ public function send($summit_id) 'full_name' => ['=@', '@@', '=='], 'member_id' => ['=='], 'member_user_external_id' => ['=='], + 'has_pending_presentations' => ['=='], 'has_accepted_presentations' => ['=='], 'has_alternate_presentations' => ['=='], 'has_rejected_presentations' => ['=='], @@ -475,6 +480,7 @@ public function send($summit_id) 'full_name' => 'sometimes|string', 'member_id' => 'sometimes|integer', 'member_user_external_id' => 'sometimes|integer', + 'has_pending_presentations' => 'sometimes|string|in:true,false', 'has_accepted_presentations' => 'sometimes|string|in:true,false', 'has_alternate_presentations' => 'sometimes|string|in:true,false', 'has_rejected_presentations' => 'sometimes|string|in:true,false', @@ -517,7 +523,7 @@ public function send($summit_id) name: "filter", in: "query", required: false, - description: "Filter query (supports multiple operators). Filterable fields: id, not_id, first_name, last_name, email, full_name, member_id, member_user_external_id, has_accepted_presentations, has_alternate_presentations, has_rejected_presentations, presentations_track_id, presentations_selection_plan_id, presentations_type_id, presentations_title, presentations_abstract, presentations_submitter_full_name, presentations_submitter_email, is_speaker, has_media_upload_with_type, has_not_media_upload_with_type.", + description: "Filter query (supports multiple operators). Filterable fields: id, not_id, first_name, last_name, email, full_name, member_id, member_user_external_id, has_pending_presentations, has_accepted_presentations, has_alternate_presentations, has_rejected_presentations, presentations_track_id, presentations_selection_plan_id, presentations_type_id, presentations_title, presentations_abstract, presentations_submitter_full_name, presentations_submitter_email, is_speaker, has_media_upload_with_type, has_not_media_upload_with_type.", schema: new OA\Schema(type: "string", example: "has_accepted_presentations==true") ), ], @@ -555,6 +561,7 @@ public function getSubmittersActivitiesCount($summit_id) 'full_name' => ['=@', '@@', '=='], 'member_id' => ['=='], 'member_user_external_id' => ['=='], + 'has_pending_presentations' => ['=='], 'has_accepted_presentations' => ['=='], 'has_alternate_presentations' => ['=='], 'has_rejected_presentations' => ['=='], @@ -581,6 +588,7 @@ public function getSubmittersActivitiesCount($summit_id) 'full_name' => 'sometimes|string', 'member_id' => 'sometimes|integer', 'member_user_external_id' => 'sometimes|integer', + 'has_pending_presentations' => 'sometimes|string|in:true,false', 'has_accepted_presentations' => 'sometimes|string|in:true,false', 'has_alternate_presentations' => 'sometimes|string|in:true,false', 'has_rejected_presentations' => 'sometimes|string|in:true,false', diff --git a/app/Jobs/Emails/PresentationSubmissions/ProcessSpeakersEmailRequestJob.php b/app/Jobs/Emails/PresentationSubmissions/ProcessSpeakersEmailRequestJob.php index 9df2b20aa..0d78388d3 100644 --- a/app/Jobs/Emails/PresentationSubmissions/ProcessSpeakersEmailRequestJob.php +++ b/app/Jobs/Emails/PresentationSubmissions/ProcessSpeakersEmailRequestJob.php @@ -86,6 +86,7 @@ public function handle 'last_name' => ['=@', '@@', '=='], 'email' => ['=@', '@@', '=='], 'full_name' => ['=@', '@@', '=='], + 'has_pending_presentations' => ['=='], 'has_accepted_presentations' => ['=='], 'has_alternate_presentations' => ['=='], 'has_rejected_presentations' => ['=='], diff --git a/app/Jobs/Emails/PresentationSubmissions/ProcessSubmittersEmailRequestJob.php b/app/Jobs/Emails/PresentationSubmissions/ProcessSubmittersEmailRequestJob.php index f143b12ad..8fdaa94cc 100644 --- a/app/Jobs/Emails/PresentationSubmissions/ProcessSubmittersEmailRequestJob.php +++ b/app/Jobs/Emails/PresentationSubmissions/ProcessSubmittersEmailRequestJob.php @@ -89,6 +89,7 @@ public function handle 'full_name' => ['=@', '@@', '=='], 'member_id' => ['=='], 'member_user_external_id' => ['=='], + 'has_pending_presentations' => ['=='], 'has_accepted_presentations' => ['=='], 'has_alternate_presentations' => ['=='], 'has_rejected_presentations' => ['=='], diff --git a/app/Repositories/Summit/DoctrineMemberRepository.php b/app/Repositories/Summit/DoctrineMemberRepository.php index 9ab2ce596..50dca019e 100644 --- a/app/Repositories/Summit/DoctrineMemberRepository.php +++ b/app/Repositories/Summit/DoctrineMemberRepository.php @@ -219,6 +219,61 @@ protected function getFilterMappings() __p10_1.summit = :summit AND LOWER(__c10.email) :operator LOWER(:value) )" ), + 'has_pending_presentations' => + new DoctrineSwitchFilterMapping([ + 'true' => new DoctrineCaseFilterMapping( + 'true', + sprintf('EXISTS ( + SELECT __p41.id FROM models\summit\Presentation __p41 + JOIN __p41.created_by __c41 WITH __c41 = e.id + JOIN __p41.category __cat41 + JOIN __p41.type __t41 + LEFT JOIN __p41.selection_plan __sel_plan41 + LEFT JOIN models\summit\PresentationMediaUpload __pm41 WITH __pm41.presentation = __p41 + LEFT JOIN __pm41.media_upload_type __mut41 + WHERE + __p41.summit = :summit + AND __p41.published = 0 '. + (!empty($extraSelectionStatusFilter)? sprintf($extraSelectionStatusFilter, '41'): ' '). + ' AND NOT EXISTS ( + SELECT ___sp41.id + FROM models\summit\SummitSelectedPresentation ___sp41 + JOIN ___sp41.presentation ___p41 + JOIN ___sp41.list ___spl41 WITH ___spl41.list_type = \'%1$s\' AND ___spl41.list_class = \'%2$s\' + WHERE ___p41.id = __p41.id + ))', + SummitSelectedPresentationList::Group, + SummitSelectedPresentationList::Session + ) + ), + 'false' => new DoctrineCaseFilterMapping( + 'false', + sprintf(' + NOT EXISTS ( + SELECT __p41.id FROM models\summit\Presentation __p41 + JOIN __p41.created_by __c41 WITH __c41 = e.id + JOIN __p41.category __cat41 + JOIN __p41.type __t41 + LEFT JOIN __p41.selection_plan __sel_plan41 + LEFT JOIN models\summit\PresentationMediaUpload __pm41 WITH __pm41.presentation = __p41 + LEFT JOIN __pm41.media_upload_type __mut41 + WHERE + __p41.summit = :summit + AND __p41.published = 0 '. + (!empty($extraSelectionStatusFilter)? sprintf($extraSelectionStatusFilter, '41'): ' '). + ' AND NOT EXISTS ( + SELECT ___sp41.id + FROM models\summit\SummitSelectedPresentation ___sp41 + JOIN ___sp41.presentation ___p41 + JOIN ___sp41.list ___spl41 WITH ___spl41.list_type = \'%1$s\' AND ___spl41.list_class = \'%2$s\' + WHERE ___p41.id = __p41.id + ))', + SummitSelectedPresentationList::Group, + SummitSelectedPresentationList::Session + ) + ), + ] + ), 'has_accepted_presentations' => new DoctrineSwitchFilterMapping([ 'true' => new DoctrineCaseFilterMapping( diff --git a/app/Repositories/Summit/DoctrineSpeakerRepository.php b/app/Repositories/Summit/DoctrineSpeakerRepository.php index 237042028..496acec22 100644 --- a/app/Repositories/Summit/DoctrineSpeakerRepository.php +++ b/app/Repositories/Summit/DoctrineSpeakerRepository.php @@ -252,6 +252,107 @@ protected function getFilterMappings() WHERE __p10_2.summit = :summit AND LOWER(__cb10_2.email) :operator LOWER(:value) )"), + 'has_pending_presentations' => + new DoctrineSwitchFilterMapping([ + 'true' => new DoctrineCaseFilterMapping( + 'true', + sprintf('EXISTS ( + SELECT __p41.id FROM models\summit\Presentation __p41 + JOIN __p41.speakers __spk41 WITH __spk41.speaker = e.id + JOIN __p41.category __cat41 + JOIN __p41.type __t41 + LEFT JOIN __p41.selection_plan __sel_plan41 + LEFT JOIN models\summit\PresentationMediaUpload __pm41 WITH __pm41.presentation = __p41 + LEFT JOIN __pm41.media_upload_type __mut41 + WHERE + __p41.summit = :summit + AND __p41.published = 0'. + (!empty($extraSelectionStatusFilter)? sprintf($extraSelectionStatusFilter, '41'): ' '). + 'AND NOT EXISTS ( + SELECT ___sp41.id + FROM models\summit\SummitSelectedPresentation ___sp41 + JOIN ___sp41.presentation ___p41 + JOIN ___sp41.list ___spl41 WITH ___spl41.list_type = \'%1$s\' AND ___spl41.list_class = \'%2$s\' + WHERE ___p41.id = __p41.id + ))', + SummitSelectedPresentationList::Group, + SummitSelectedPresentationList::Session + ). + ' OR '. + sprintf('EXISTS ( + SELECT __p42.id FROM models\summit\Presentation __p42 + JOIN __p42.moderator __md42 WITH __md42.id = e.id + JOIN __p42.category __cat42 + JOIN __p42.type __t42 + LEFT JOIN __p42.selection_plan __sel_plan42 + LEFT JOIN models\summit\PresentationMediaUpload __pm42 WITH __pm42.presentation = __p42 + LEFT JOIN __pm42.media_upload_type __mut42 + WHERE + __p42.summit = :summit + AND __p42.published = 0'. + (!empty($extraSelectionStatusFilter)? sprintf($extraSelectionStatusFilter, '42'): ' '). + 'AND NOT EXISTS ( + SELECT ___sp42.id + FROM models\summit\SummitSelectedPresentation ___sp42 + JOIN ___sp42.presentation ___p42 + JOIN ___sp42.list ___spl42 WITH ___spl42.list_type = \'%1$s\' AND ___spl42.list_class = \'%2$s\' + WHERE ___p42.id = __p42.id + ))', + SummitSelectedPresentationList::Group, + SummitSelectedPresentationList::Session + ) + ), + 'false' => new DoctrineCaseFilterMapping( + 'false', + sprintf(' + NOT EXISTS ( + SELECT __p41.id FROM models\summit\Presentation __p41 + JOIN __p41.speakers __spk41 WITH __spk41.speaker = e.id + JOIN __p41.category __cat41 + JOIN __p41.type __t41 + LEFT JOIN __p41.selection_plan __sel_plan41 + LEFT JOIN models\summit\PresentationMediaUpload __pm41 WITH __pm41.presentation = __p41 + LEFT JOIN __pm41.media_upload_type __mut41 + WHERE + __p41.summit = :summit + AND __p41.published = 0'. + (!empty($extraSelectionStatusFilter)? sprintf($extraSelectionStatusFilter, '41'): ' '). + 'AND NOT EXISTS ( + SELECT ___sp41.id + FROM models\summit\SummitSelectedPresentation ___sp41 + JOIN ___sp41.presentation ___p41 + JOIN ___sp41.list ___spl41 WITH ___spl41.list_type = \'%1$s\' AND ___spl41.list_class = \'%2$s\' + WHERE ___p41.id = __p41.id + ))', + SummitSelectedPresentationList::Group, + SummitSelectedPresentationList::Session + ). + ' AND '. + sprintf('NOT EXISTS ( + SELECT __p42.id FROM models\summit\Presentation __p42 + JOIN __p42.moderator __md42 WITH __md42.id = e.id + JOIN __p42.category __cat42 + JOIN __p42.type __t42 + LEFT JOIN __p42.selection_plan __sel_plan42 + LEFT JOIN models\summit\PresentationMediaUpload __pm42 WITH __pm42.presentation = __p42 + LEFT JOIN __pm42.media_upload_type __mut42 + WHERE + __p42.summit = :summit + AND __p42.published = 0'. + (!empty($extraSelectionStatusFilter)? sprintf($extraSelectionStatusFilter, '42'): ' '). + 'AND NOT EXISTS ( + SELECT ___sp42.id + FROM models\summit\SummitSelectedPresentation ___sp42 + JOIN ___sp42.presentation ___p42 + JOIN ___sp42.list ___spl42 WITH ___spl42.list_type = \'%1$s\' AND ___spl42.list_class = \'%2$s\' + WHERE ___p42.id = __p42.id + ))', + SummitSelectedPresentationList::Group, + SummitSelectedPresentationList::Session + ) + ), + ] + ), 'has_accepted_presentations' => new DoctrineSwitchFilterMapping([ 'true' => new DoctrineCaseFilterMapping( diff --git a/app/Services/Model/Imp/SpeakerService.php b/app/Services/Model/Imp/SpeakerService.php index b1e16ae5e..af528a7fb 100644 --- a/app/Services/Model/Imp/SpeakerService.php +++ b/app/Services/Model/Imp/SpeakerService.php @@ -1316,6 +1316,7 @@ function 'last_name' => ['=@', '@@', '=='], 'email' => ['=@', '@@', '=='], 'full_name' => ['=@', '@@', '=='], + 'has_pending_presentations' => ['=='], 'has_accepted_presentations' => ['=='], 'has_alternate_presentations' => ['=='], 'has_rejected_presentations' => ['=='], diff --git a/app/Services/Model/Imp/SubmitterService.php b/app/Services/Model/Imp/SubmitterService.php index 4e30925ad..8b2f9d0f8 100644 --- a/app/Services/Model/Imp/SubmitterService.php +++ b/app/Services/Model/Imp/SubmitterService.php @@ -143,6 +143,7 @@ function 'full_name' => ['=@', '@@', '=='], 'member_id' => ['=='], 'member_user_external_id' => ['=='], + 'has_pending_presentations' => ['=='], 'has_accepted_presentations' => ['=='], 'has_alternate_presentations' => ['=='], 'has_rejected_presentations' => ['=='], @@ -183,4 +184,4 @@ function ($summit, $outcome_email_recipient, $report) { }, $filter); } -} \ No newline at end of file +} diff --git a/tests/oauth2/OAuth2SummitSpeakersApiTest.php b/tests/oauth2/OAuth2SummitSpeakersApiTest.php index 689373bf6..85b907d7a 100644 --- a/tests/oauth2/OAuth2SummitSpeakersApiTest.php +++ b/tests/oauth2/OAuth2SummitSpeakersApiTest.php @@ -614,6 +614,62 @@ public function testGetCurrentSummitSpeakersWithRejectedPresentations() $this->assertTrue(!is_null($speakers)); } + public function testGetCurrentSummitSpeakersWithPendingPresentations() + { + $speaker = new PresentationSpeaker(); + $speaker->setFirstName("Pending"); + $speaker->setLastName("Speaker"); + self::$em->persist($speaker); + + $start = new \DateTime('now', new \DateTimeZone('UTC')); + $end = (clone $start)->add(new \DateInterval('PT2H')); + + $pres = new Presentation(); + self::$summit->addEvent($pres); + $pres->setTitle("Pending Test Presentation"); + $pres->setAbstract("Abstract"); + $pres->setCategory(self::$defaultTrack); + $pres->setType(self::$defaultPresentationType); + $pres->setProgress(Presentation::PHASE_COMPLETE); + $pres->setStatus(Presentation::STATUS_RECEIVED); + $pres->setStartDate($start); + $pres->setEndDate($end); + $pres->addSpeaker($speaker); + // Deliberately NOT published and NOT added to any SummitSelectedPresentation group list + self::$em->flush(); + + $params = [ + 'id' => self::$summit->getId(), + 'page' => 1, + 'per_page' => 10, + 'filter' => [ + 'has_pending_presentations==true', + ], + 'order' => '+id' + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "GET", + "OAuth2SummitSpeakersApiController@getSpeakers", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $speakers = json_decode($content); + $this->assertTrue(!is_null($speakers)); + $this->assertTrue(count($speakers->data) > 0); + } + public function testGetCurrentSummitSpeakersFilteredByMemberExternalUserID() { $params = [ @@ -2016,4 +2072,56 @@ public function testGetCurrentSummitSpeakersActivitiesCountWithAcceptedPresentat $this->assertEquals($baseline + 1, $data->count); } + public function testGetCurrentSummitSpeakersActivitiesCountWithPendingPresentations() + { + $baseline = EntityManager::getRepository(PresentationSpeaker::class) + ->getUniqueActivitiesCountBySummit( + self::$summit, + FilterParser::parse( + ['filter' => 'has_pending_presentations==true'], + ['has_pending_presentations' => ['==']] + ) + ); + + $speaker = new PresentationSpeaker(); + $speaker->setFirstName("Pending"); + $speaker->setLastName("Test"); + self::$em->persist($speaker); + + $start = new \DateTime('now', new \DateTimeZone('UTC')); + $end = (clone $start)->add(new \DateInterval('PT2H')); + + $pres = new Presentation(); + self::$summit->addEvent($pres); + $pres->setTitle("Pending Test Presentation"); + $pres->setAbstract("Abstract"); + $pres->setCategory(self::$defaultTrack); + $pres->setType(self::$defaultPresentationType); + $pres->setProgress(Presentation::PHASE_COMPLETE); + $pres->setStatus(Presentation::STATUS_RECEIVED); + $pres->setStartDate($start); + $pres->setEndDate($end); + $pres->addSpeaker($speaker); + // Deliberately NOT published and NOT added to any SummitSelectedPresentation group list + self::$em->flush(); + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "GET", + "OAuth2SummitSpeakersApiController@getSpeakersActivitiesCount", + ['id' => self::$summit->getId(), 'filter' => ['has_pending_presentations==true']], + [], [], [], $headers + ); + + $this->assertResponseStatus(200); + $data = json_decode($response->getContent()); + $this->assertNotNull($data); + $this->assertTrue(isset($data->count)); + $this->assertEquals($baseline + 1, $data->count); + } + } \ No newline at end of file diff --git a/tests/oauth2/OAuth2SummitSubmittersApiTest.php b/tests/oauth2/OAuth2SummitSubmittersApiTest.php index eb9c8a5eb..b2aa670f9 100644 --- a/tests/oauth2/OAuth2SummitSubmittersApiTest.php +++ b/tests/oauth2/OAuth2SummitSubmittersApiTest.php @@ -1,5 +1,6 @@ assertTrue(!is_null($submitters)); } + public function testGetCurrentSummitSubmittersWithPendingPresentations() + { + $start = new \DateTime('now', new \DateTimeZone('UTC')); + $end = (clone $start)->add(new \DateInterval('PT2H')); + + $pres = new Presentation(); + self::$summit->addEvent($pres); + $pres->setTitle("Pending Test Presentation"); + $pres->setAbstract("Abstract"); + $pres->setCategory(self::$defaultTrack); + $pres->setType(self::$defaultPresentationType); + $pres->setProgress(Presentation::PHASE_COMPLETE); + $pres->setStatus(Presentation::STATUS_RECEIVED); + $pres->setStartDate($start); + $pres->setEndDate($end); + $pres->setCreatedBy(self::$defaultMember); + // Deliberately NOT published and NOT added to any SummitSelectedPresentation group list + self::$em->flush(); + + $params = [ + 'id' => self::$summit->getId(), + 'page' => 1, + 'per_page' => 10, + 'filter' => [ + 'has_pending_presentations==true', + ], + 'order' => '+id' + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "GET", + "OAuth2SummitSubmittersApiController@getAllBySummit", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $submitters = json_decode($content); + $this->assertTrue(!is_null($submitters)); + $this->assertTrue(count($submitters->data) > 0); + } + public function testExportCurrentSummitSubmittersWhoAreSpeakers() { $params = [