Added CRON task to process eventbrite redeem promo codes

added task that marks promo codes as redeemed for a latest
summit.

Change-Id: I4e865fd025ebb30829b53d77db730503f3b946dd
This commit is contained in:
Sebastian Marcet 2018-04-12 20:16:45 -03:00
parent 8064d6d05c
commit a7a8877ace
10 changed files with 226 additions and 4 deletions

View File

@ -68,4 +68,5 @@ SSH_PUBLIC_KEY=
SSH_PRIVATE_KEY=
SCP_HOST=
SCP_REMOTE_BASE_PATH=/tmp
GOOGLE_GEO_CODING_API_KEY=

View File

@ -0,0 +1,98 @@
<?php namespace App\Console\Commands;
/**
* Copyright 2018 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use App\Services\Model\IAttendeeService;
use Illuminate\Console\Command;
use models\summit\ISummitRepository;
/**
* Class PromoCodesRedeemProcessor
* @package App\Console\Commands
*/
final class PromoCodesRedeemProcessor extends Command
{
/**
* @var IAttendeeService
*/
private $service;
/**
* @var ISummitRepository
*/
private $repository;
/**
* PromoCodesRedeemProcessor constructor.
* @param IAttendeeService $service
* @param ISummitRepository $repository
*/
public function __construct
(
IAttendeeService $service,
ISummitRepository $repository
)
{
parent::__construct();
$this->repository = $repository;
$this->service = $service;
}
/**
* The console command name.
*
* @var string
*/
protected $name = 'summit:promo-codes-redeem-processor';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'summit:promo-codes-redeem-processor {summit_id?}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Redeems promo codes per summit';
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$summit_id = $this->argument('summit_id');
if(is_null($summit_id))// if we dont provide a summit id, then get current
$summit = $this->repository->getCurrent();
else
$summit = $this->repository->getById(intval($summit_id));
$this->info(sprintf("starting to process promo codes for summit id %s", $summit->getIdentifier()));
$has_more_items = false;
$page = 1;
do{
$this->info(sprintf("processing page %s for summit id %s", $page, $summit->getIdentifier()));
$has_more_items = $this->service->updateRedeemedPromoCodes($summit, $page);
++$page;
} while($has_more_items);
$this->info(sprintf("finished to process promo codes for summit id %s", $summit->getIdentifier()));
}
}

View File

@ -31,6 +31,7 @@ class Kernel extends ConsoleKernel
\App\Console\Commands\AdminActionsCalendarSyncProcessingCommand::class,
\App\Console\Commands\ChatTeamMessagesSender::class,
\App\Console\Commands\SummitListJsonGenerator::class,
\App\Console\Commands\PromoCodesRedeemProcessor::class,
];
/**
@ -72,5 +73,9 @@ class Kernel extends ConsoleKernel
// iCloud
$schedule->command('summit:member-schedule-action-process', [CalendarSyncInfo::ProvideriCloud, 1000])->withoutOverlapping();
// redeem code processor
$schedule->command('summit:promo-codes-redeem-processor', [end($summit_ids)])->daily()->withoutOverlapping();
}
}

View File

@ -23,4 +23,10 @@ interface ISummitRegistrationPromoCodeRepository extends ISummitOwnedEntityRepos
* @return array
*/
public function getMetadata(Summit $summit);
/**
* @param string $code
* @return SummitRegistrationPromoCode|null
*/
public function getByCode($code);
}

View File

@ -43,6 +43,26 @@ class DoctrineSummitRegistrationPromoCodeRepository
return SummitRegistrationPromoCode::class;
}
/**
* @param string $code
* @return SummitRegistrationPromoCode|null
*/
public function getByCode($code){
$query = $this->getEntityManager()
->createQueryBuilder()
->select("pc")
->from(SummitRegistrationPromoCode::class, "pc")
->leftJoin(MemberSummitRegistrationPromoCode::class, 'mpc', 'WITH', 'pc.id = mpc.id')
->leftJoin(SponsorSummitRegistrationPromoCode::class, 'spc', 'WITH', 'mpc.id = spc.id')
->leftJoin(SpeakerSummitRegistrationPromoCode::class, 'spkpc', 'WITH', 'spkpc.id = pc.id')
->where("pc.code = :code");
$query->setParameter("code", $code);
return $query->getQuery()->getOneOrNullResult();
}
protected function getFilterMappings()
{
return [

View File

@ -103,4 +103,16 @@ final class EventbriteAPI implements IEventbriteAPI
$url = sprintf('%s/events/%s', self::BaseUrl, $event_id);
return $this->getEntity($url, ['expand' => 'ticket_classes']);
}
/**
* @param Summit $summit
* @param int $page_nbr
* @param string $expand
* @return mixed
*/
public function getAttendees(Summit $summit, $page_nbr, $expand = 'promotional_code'){
$event_id = $summit->getExternalSummitId();
$url = sprintf('%s/events/%s/attendees', self::BaseUrl, $event_id);
return $this->getEntity($url, ['expand' => $expand, 'page' => $page_nbr]);
}
}

View File

@ -35,4 +35,12 @@ interface IEventbriteAPI
* @return mixed
*/
public function getTicketTypes(Summit $summit);
/**
* @param Summit $summit
* @param int $page_nbr
* @param string $expand
* @return mixed
*/
public function getAttendees(Summit $summit, $page_nbr, $expand = 'promotional_code');
}

View File

@ -20,6 +20,7 @@ use models\summit\factories\SummitAttendeeFactory;
use models\summit\factories\SummitAttendeeTicketFactory;
use models\summit\ISummitAttendeeRepository;
use models\summit\ISummitAttendeeTicketRepository;
use models\summit\ISummitRegistrationPromoCodeRepository;
use models\summit\ISummitTicketTypeRepository;
use models\summit\Summit;
use models\summit\SummitAttendee;
@ -29,9 +30,7 @@ use services\apis\IEventbriteAPI;
* Class AttendeeService
* @package App\Services\Model
*/
final class AttendeeService
extends AbstractService
implements IAttendeeService
final class AttendeeService extends AbstractService implements IAttendeeService
{
/**
@ -59,6 +58,11 @@ final class AttendeeService
*/
private $eventbrite_api;
/**
* @var ISummitRegistrationPromoCodeRepository
*/
private $promo_code_repository;
public function __construct
(
@ -66,6 +70,7 @@ final class AttendeeService
IMemberRepository $member_repository,
ISummitAttendeeTicketRepository $ticket_repository,
ISummitTicketTypeRepository $ticket_type_repository,
ISummitRegistrationPromoCodeRepository $promo_code_repository,
IEventbriteAPI $eventbrite_api,
ITransactionService $tx_service
)
@ -75,6 +80,7 @@ final class AttendeeService
$this->ticket_repository = $ticket_repository;
$this->member_repository = $member_repository;
$this->ticket_type_repository = $ticket_type_repository;
$this->promo_code_repository = $promo_code_repository;
$this->eventbrite_api = $eventbrite_api;
}
@ -212,7 +218,7 @@ final class AttendeeService
$summit_external_id = $external_order['event_id'];
if (intval($attendee->getSummit()->getSummitExternalId()) !== intval($summit_external_id))
throw new ValidationException('order %s does not belongs to current summit!', $external_order_id);
throw new ValidationException('order %s does not belongs to current summit!', $summit_external_id);
foreach ($external_order['attendees'] as $external_attendee){
if($data['external_attendee_id'] == $external_attendee['id']){
@ -256,4 +262,35 @@ final class AttendeeService
$attendee->removeTicket($ticket);
});
}
/**
* @param Summit $summit
* @param int $page_nbr
* @return mixed
*/
public function updateRedeemedPromoCodes(Summit $summit, $page_nbr = 1)
{
return $this->tx_service->transaction(function() use($summit, $page_nbr){
$response = $this->eventbrite_api->getAttendees($summit, $page_nbr);
if(!isset($response['pagination'])) return false;
if(!isset($response['attendees'])) return false;
$pagination = $response['pagination'];
$attendees = $response['attendees'];
$has_more_items = boolval($pagination['has_more_items']);
foreach($attendees as $attendee){
if(!isset($attendee['promotional_code'])) continue;
$promotional_code = $attendee['promotional_code'];
if(!isset($promotional_code['code'])) continue;
$code = $promotional_code['code'];
$promo_code = $this->promo_code_repository->getByCode($code);
if(is_null($promo_code)) continue;
$promo_code->setRedeemed(true);
}
return $has_more_items;
});
}
}

View File

@ -67,4 +67,11 @@ interface IAttendeeService
* @return SummitAttendeeTicket
*/
public function deleteAttendeeTicket(SummitAttendee $attendee, $ticket_id);
/**
* @param Summit $summit
* @param int $page_nbr
* @return mixed
*/
public function updateRedeemedPromoCodes(Summit $summit, $page_nbr = 1);
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Copyright 2018 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use App\Services\Model\IAttendeeService;
/**
* Class AttendeeServiceTest
*/
final class AttendeeServiceTest extends TestCase
{
public function testRedeemPromoCodes(){
$service = App::make(IAttendeeService::class);
$repo = EntityManager::getRepository(\models\summit\Summit::class);
$summit = $repo->getById(24);
$service->updateRedeemedPromoCodes($summit);
}
}