From 6a01b46a72da3e019d75b31a0dc5ba1323327909 Mon Sep 17 00:00:00 2001 From: Sebastian Marcet Date: Mon, 10 Sep 2018 15:10:33 -0300 Subject: [PATCH] added new endpoint to reassign attendee ticket to another member PUT /api/v1/summits/{id}/attendees/{attendee_id}/tickets/{ticket_id}/reassign/{other_member_id} Change-Id: Ice8a25dc0e85479bdbfdf8328ac2c2712c6a4e1a --- .../OAuth2SummitAttendeesApiController.php | 47 +++++++++++++++++++ app/Http/routes.php | 6 ++- .../Summit/Attendees/SummitAttendee.php | 7 +++ app/Services/Model/AttendeeService.php | 34 ++++++++++++++ app/Services/Model/IAttendeeService.php | 12 +++++ database/seeds/ApiEndpointsSeeder.php | 18 ++++++- 6 files changed, 121 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitAttendeesApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitAttendeesApiController.php index d08e5c4e..78f91748 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitAttendeesApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitAttendeesApiController.php @@ -17,6 +17,7 @@ use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Request; use models\exceptions\EntityNotFoundException; use models\exceptions\ValidationException; +use models\main\IMemberRepository; use models\oauth2\IResourceServerContext; use models\summit\IEventFeedbackRepository; use models\summit\ISpeakerRepository; @@ -67,6 +68,11 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController */ private $attendee_repository; + /** + * @var IMemberRepository + */ + private $member_repository; + /** * OAuth2SummitAttendeesApiController constructor. * @param ISummitAttendeeRepository $attendee_repository @@ -74,6 +80,7 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController * @param ISummitEventRepository $event_repository * @param ISpeakerRepository $speaker_repository * @param IEventFeedbackRepository $event_feedback_repository + * @param IMemberRepository $member_repository * @param ISummitService $summit_service * @param IAttendeeService $attendee_service * @param IResourceServerContext $resource_server_context @@ -85,6 +92,7 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController ISummitEventRepository $event_repository, ISpeakerRepository $speaker_repository, IEventFeedbackRepository $event_feedback_repository, + IMemberRepository $member_repository, ISummitService $summit_service, IAttendeeService $attendee_service, IResourceServerContext $resource_server_context @@ -95,6 +103,7 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController $this->speaker_repository = $speaker_repository; $this->event_repository = $event_repository; $this->event_feedback_repository = $event_feedback_repository; + $this->member_repository = $member_repository; $this->summit_service = $summit_service; $this->attendee_service = $attendee_service; } @@ -654,4 +663,42 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController return $this->error500($ex); } } + + /** + * @param $summit_id + * @param $attendee_id + * @param $ticket_id + * @param $other_member_id + * @return mixed + */ + public function reassignAttendeeTicket($summit_id, $attendee_id, $ticket_id, $other_member_id){ + try { + + $summit = SummitFinderStrategyFactory::build($this->repository, $this->resource_server_context)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $attendee = $this->attendee_repository->getById($attendee_id); + if(is_null($attendee)) return $this->error404(); + + $other_member = $this->member_repository->getById($other_member_id); + if(is_null($other_member)) return $this->error404(); + + $ticket = $this->attendee_service->reassignAttendeeTicket($summit, $attendee, $other_member_id, $ticket_id); + + return $this->updated(SerializerRegistry::getInstance()->getSerializer($ticket)->serialize()); + } + catch (ValidationException $ex1) { + Log::warning($ex1); + return $this->error412(array($ex1->getMessage())); + } + catch(EntityNotFoundException $ex2) + { + Log::warning($ex2); + return $this->error404(array('message'=> $ex2->getMessage())); + } + catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } } \ No newline at end of file diff --git a/app/Http/routes.php b/app/Http/routes.php index 6e9d2bc6..f398da20 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -197,7 +197,11 @@ Route::group([ Route::group(array('prefix' => 'tickets'), function () { Route::post('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitAttendeesApiController@addAttendeeTicket']); - Route::delete('{ticket_id}', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitAttendeesApiController@deleteAttendeeTicket']); + Route::group(array('prefix' => '{ticket_id}'), function (){ + Route::delete('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitAttendeesApiController@deleteAttendeeTicket']); + Route::put('reassign/{other_member_id}', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitAttendeesApiController@reassignAttendeeTicket']); + }); + }); }); }); diff --git a/app/Models/Foundation/Summit/Attendees/SummitAttendee.php b/app/Models/Foundation/Summit/Attendees/SummitAttendee.php index 4a857f68..c68bada0 100644 --- a/app/Models/Foundation/Summit/Attendees/SummitAttendee.php +++ b/app/Models/Foundation/Summit/Attendees/SummitAttendee.php @@ -258,4 +258,11 @@ class SummitAttendee extends SilverstripeBaseModel return $this; } + /** + * @return bool + */ + public function hasTickets(){ + return $this->tickets->count() > 0; + } + } \ No newline at end of file diff --git a/app/Services/Model/AttendeeService.php b/app/Services/Model/AttendeeService.php index a208b62b..8f8d784f 100644 --- a/app/Services/Model/AttendeeService.php +++ b/app/Services/Model/AttendeeService.php @@ -16,6 +16,7 @@ use libs\utils\ITransactionService; use models\exceptions\EntityNotFoundException; use models\exceptions\ValidationException; use models\main\IMemberRepository; +use models\main\Member; use models\summit\factories\SummitAttendeeFactory; use models\summit\factories\SummitAttendeeTicketFactory; use models\summit\ISummitAttendeeRepository; @@ -293,4 +294,37 @@ final class AttendeeService extends AbstractService implements IAttendeeService return $has_more_items; }); } + + /** + * @param Summit $summit + * @param SummitAttendee $attendee + * @param Member $other_member + * @param int $ticket_id + * @return SummitAttendeeTicket + * @throws ValidationException + * @throws EntityNotFoundException + */ + public function reassignAttendeeTicket(Summit $summit, SummitAttendee $attendee, Member $other_member, $ticket_id) + { + return $this->tx_service->transaction(function() use($summit, $attendee, $other_member, $ticket_id){ + $ticket = $this->ticket_repository->getById($ticket_id); + if(is_null($ticket)){ + throw new EntityNotFoundException("ticket not found"); + } + $new_owner = $this->attendee_repository->getBySummitAndMember($summit, $other_member); + if(is_null($new_owner)){ + $new_owner = SummitAttendeeFactory::build($summit, $other_member, []); + $this->attendee_repository->add($new_owner); + } + if($new_owner->hasTickets()){ + throw new ValidationException('This member is already assigned to another ticket'); + } + $attendee->removeTicket($ticket); + if(!$attendee->hasTickets()){ + $this->attendee_repository->delete($attendee); + } + $new_owner->addTicket($ticket); + return $ticket; + }); + } } \ No newline at end of file diff --git a/app/Services/Model/IAttendeeService.php b/app/Services/Model/IAttendeeService.php index 73269f40..b580fb5f 100644 --- a/app/Services/Model/IAttendeeService.php +++ b/app/Services/Model/IAttendeeService.php @@ -13,6 +13,7 @@ **/ use models\exceptions\EntityNotFoundException; use models\exceptions\ValidationException; +use models\main\Member; use models\summit\Summit; use models\summit\SummitAttendee; use models\summit\SummitAttendeeTicket; @@ -74,4 +75,15 @@ interface IAttendeeService * @return mixed */ public function updateRedeemedPromoCodes(Summit $summit, $page_nbr = 1); + + /** + * @param Summit $summit + * @param SummitAttendee $attendee + * @param Member $other_member + * @param int $ticket_id + * @return SummitAttendeeTicket + * @throws ValidationException + * @throws EntityNotFoundException + */ + public function reassignAttendeeTicket(Summit $summit,SummitAttendee $attendee, Member $other_member, $ticket_id); } \ No newline at end of file diff --git a/database/seeds/ApiEndpointsSeeder.php b/database/seeds/ApiEndpointsSeeder.php index 791c65fa..e5c89905 100644 --- a/database/seeds/ApiEndpointsSeeder.php +++ b/database/seeds/ApiEndpointsSeeder.php @@ -175,6 +175,7 @@ class ApiEndpointsSeeder extends Seeder 'route' => '/api/v1/summits/{id}/attendees/{attendee_id}', 'http_method' => 'DELETE', 'scopes' => [ + sprintf(SummitScopes::WriteSummitData, $current_realm), sprintf(SummitScopes::WriteAttendeesData, $current_realm), ], ], @@ -183,6 +184,7 @@ class ApiEndpointsSeeder extends Seeder 'route' => '/api/v1/summits/{id}/attendees/{attendee_id}', 'http_method' => 'PUT', 'scopes' => [ + sprintf(SummitScopes::WriteSummitData, $current_realm), sprintf(SummitScopes::WriteAttendeesData, $current_realm), ], ], @@ -218,6 +220,7 @@ class ApiEndpointsSeeder extends Seeder 'route' => '/api/v1/summits/{id}/attendees', 'http_method' => 'POST', 'scopes' => [ + sprintf(SummitScopes::WriteSummitData, $current_realm), sprintf(SummitScopes::WriteAttendeesData, $current_realm), ], ), @@ -226,17 +229,28 @@ class ApiEndpointsSeeder extends Seeder 'route' => '/api/v1/summits/{id}/attendees/{attendee_id}/tickets', 'http_method' => 'POST', 'scopes' => [ + sprintf(SummitScopes::WriteSummitData, $current_realm), sprintf(SummitScopes::WriteAttendeesData, $current_realm), ], ), - array( + [ 'name' => 'delete-attendee-ticket', 'route' => '/api/v1/summits/{id}/attendees/{attendee_id}/tickets/{ticket_id}', 'http_method' => 'DELETE', 'scopes' => [ + sprintf(SummitScopes::WriteSummitData, $current_realm), sprintf(SummitScopes::WriteAttendeesData, $current_realm), ], - ), + ], + [ + 'name' => 'reassign-attendee-ticket', + 'route' => '/api/v1/summits/{id}/attendees/{attendee_id}/tickets/{ticket_id}/reassign/{other_member_id}', + 'http_method' => 'PUT', + 'scopes' => [ + sprintf(SummitScopes::WriteSummitData, $current_realm), + sprintf(SummitScopes::WriteAttendeesData, $current_realm), + ], + ], // speakers array( 'name' => 'get-speakers',