From f9905a528be4060f6a4ee7e9a1619292413abd80 Mon Sep 17 00:00:00 2001 From: smarcet Date: Thu, 20 Feb 2020 15:26:44 -0300 Subject: [PATCH] Added new cron task to calculate feedback avg rate for ongoing summits Change-Id: I49d989a90cd267bc599e3c95b2689d44759e58d4 Signed-off-by: smarcet --- .../SummitEventSetAvgRateProcessor.php | 83 ++++++++++++++ app/Console/Kernel.php | 6 + .../Summit/Repositories/ISummitRepository.php | 7 +- app/Models/Foundation/Summit/Summit.php | 19 ++++ .../Summit/DoctrineSummitRepository.php | 16 +++ app/Services/Model/ISummitService.php | 3 + app/Services/Model/SummitService.php | 103 +++++++++++++----- 7 files changed, 207 insertions(+), 30 deletions(-) create mode 100644 app/Console/Commands/SummitEventSetAvgRateProcessor.php diff --git a/app/Console/Commands/SummitEventSetAvgRateProcessor.php b/app/Console/Commands/SummitEventSetAvgRateProcessor.php new file mode 100644 index 00000000..f112290e --- /dev/null +++ b/app/Console/Commands/SummitEventSetAvgRateProcessor.php @@ -0,0 +1,83 @@ +summit_service = $summit_service; + } + + /** + * Execute the console command. + * + * @return mixed + */ + public function handle() + { + try { + + $this->info("processing SummitEventSetAvgRateProcessor"); + $start = time(); + $this->summit_service->calculateFeedbackAverageForOngoingSummits(); + $end = time(); + $delta = $end - $start; + $this->info(sprintf("execution call %s seconds", $delta)); + } + catch (Exception $ex) { + Log::error($ex); + } + } + +} \ No newline at end of file diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 23025219..bf2dab50 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -11,6 +11,8 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ + +use App\Console\Commands\SummitEventSetAvgRateProcessor; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; use models\summit\CalendarSync\CalendarSyncInfo; @@ -34,6 +36,7 @@ class Kernel extends ConsoleKernel \App\Console\Commands\PromoCodesRedeemProcessor::class, \App\Console\Commands\SummitRoomReservationRevocationCommand::class, \App\Console\Commands\ExternalScheduleFeedIngestionCommand::class, + \App\Console\Commands\SummitEventSetAvgRateProcessor::class, ]; /** @@ -88,5 +91,8 @@ class Kernel extends ConsoleKernel // external schedule ingestion task $schedule->command("summit:external-schedule-feed-ingestion-process")->everyFifteenMinutes()->withoutOverlapping(); + + // AVG schedule feedback rate + $schedule->command("summit:feedback-avg-rate-processor")->everyFifteenMinutes()->withoutOverlapping(); } } diff --git a/app/Models/Foundation/Summit/Repositories/ISummitRepository.php b/app/Models/Foundation/Summit/Repositories/ISummitRepository.php index d86c27d1..73b65765 100644 --- a/app/Models/Foundation/Summit/Repositories/ISummitRepository.php +++ b/app/Models/Foundation/Summit/Repositories/ISummitRepository.php @@ -12,8 +12,6 @@ * limitations under the License. **/ use models\utils\IBaseRepository; -use phpDocumentor\Reflection\Types\Array_; - /** * Interface ISummitRepository * @package models\summit @@ -66,4 +64,9 @@ interface ISummitRepository extends IBaseRepository * @return Summit[] */ public function getWithExternalFeed():array; + + /** + * @return Summit[] + */ + public function getOnGoing(): array; } \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Summit.php b/app/Models/Foundation/Summit/Summit.php index 8eee09a5..37b726de 100644 --- a/app/Models/Foundation/Summit/Summit.php +++ b/app/Models/Foundation/Summit/Summit.php @@ -2022,6 +2022,25 @@ SQL; self::recalculateOrderForCollection($filtered_locations, $location, $new_order); } + /** + * @return int[] + */ + public function getScheduleEventsIds():array{ + $query = <<getEM()->createQuery($query); + + $native_query->setParameter("summit", $this); + + return $native_query->getResult(); + } + /** * @param SummitAbstractLocation $location * @return int[] diff --git a/app/Repositories/Summit/DoctrineSummitRepository.php b/app/Repositories/Summit/DoctrineSummitRepository.php index c8695c00..38ee4d31 100644 --- a/app/Repositories/Summit/DoctrineSummitRepository.php +++ b/app/Repositories/Summit/DoctrineSummitRepository.php @@ -181,4 +181,20 @@ final class DoctrineSummitRepository ->getQuery() ->getResult(); } + + /** + * @return array + */ + public function getOnGoing(): array + { + return $this->getEntityManager()->createQueryBuilder() + ->select("e") + ->from($this->getBaseEntity(), "e") + ->where("e.begin_date <= :now") + ->andWhere("e.end_date >= :now") + ->orderBy('e.id', 'DESC') + ->setParameter("now", new \DateTime('now', new \DateTimeZone('UTC'))) + ->getQuery() + ->getResult(); + } } \ No newline at end of file diff --git a/app/Services/Model/ISummitService.php b/app/Services/Model/ISummitService.php index 63358a91..cac339ae 100644 --- a/app/Services/Model/ISummitService.php +++ b/app/Services/Model/ISummitService.php @@ -441,4 +441,7 @@ interface ISummitService * @return void` */ public function shareEventByEmail(Summit $summit, int $event_id, array $data):void; + + + public function calculateFeedbackAverageForOngoingSummits():void; } \ No newline at end of file diff --git a/app/Services/Model/SummitService.php b/app/Services/Model/SummitService.php index 18bf8b0c..d2795657 100644 --- a/app/Services/Model/SummitService.php +++ b/app/Services/Model/SummitService.php @@ -388,12 +388,12 @@ final class SummitService extends AbstractService implements ISummitService * @return SummitEventFeedback * @throws Exception */ - public function addMyEventFeedback(Member $member, Summit $summit, int $event_id, array $payload):SummitEventFeedback + public function addMyEventFeedback(Member $member, Summit $summit, int $event_id, array $payload): SummitEventFeedback { return $this->tx_service->transaction(function () use ($member, $summit, $event_id, $payload) { $event = $summit->getScheduleEvent($event_id); - if(is_null($event)) + if (is_null($event)) throw new EntityNotFoundException("Event not found."); if (!Summit::allowToSee($event, $member)) @@ -423,13 +423,13 @@ final class SummitService extends AbstractService implements ISummitService * @return SummitEventFeedback * @throws Exception */ - public function updateMyEventFeedback(Member $member, Summit $summit, int $event_id, array $payload):SummitEventFeedback + public function updateMyEventFeedback(Member $member, Summit $summit, int $event_id, array $payload): SummitEventFeedback { return $this->tx_service->transaction(function () use ($member, $summit, $event_id, $payload) { $event = $summit->getScheduleEvent($event_id); - if(is_null($event)) + if (is_null($event)) throw new EntityNotFoundException("Event not found."); if (!Summit::allowToSee($event, $member)) @@ -455,13 +455,13 @@ final class SummitService extends AbstractService implements ISummitService * @return SummitEventFeedback * @throws Exception */ - public function getMyEventFeedback(Member $member, Summit $summit, int $event_id):SummitEventFeedback + public function getMyEventFeedback(Member $member, Summit $summit, int $event_id): SummitEventFeedback { return $this->tx_service->transaction(function () use ($member, $summit, $event_id) { $event = $summit->getScheduleEvent($event_id); - if(is_null($event)) + if (is_null($event)) throw new EntityNotFoundException("Event not found."); if (!Summit::allowToSee($event, $member)) @@ -486,12 +486,12 @@ final class SummitService extends AbstractService implements ISummitService * @param int $event_id * @throws Exception */ - public function deleteMyEventFeedback(Member $member, Summit $summit, int $event_id):void + public function deleteMyEventFeedback(Member $member, Summit $summit, int $event_id): void { $this->tx_service->transaction(function () use ($member, $summit, $event_id) { $event = $summit->getScheduleEvent($event_id); - if(is_null($event)) + if (is_null($event)) throw new EntityNotFoundException("Event not found."); if (!Summit::allowToSee($event, $member)) @@ -2287,7 +2287,7 @@ final class SummitService extends AbstractService implements ISummitService * @return PersonalCalendarShareInfo|null * @throws Exception */ - public function createScheduleShareableLink(Summit $summit, Member $member):?PersonalCalendarShareInfo + public function createScheduleShareableLink(Summit $summit, Member $member): ?PersonalCalendarShareInfo { return $this->tx_service->transaction(function () use ($summit, $member) { return $member->createScheduleShareableLink($summit); @@ -2300,11 +2300,11 @@ final class SummitService extends AbstractService implements ISummitService * @return PersonalCalendarShareInfo|null * @throws Exception */ - public function revokeScheduleShareableLink(Summit $summit, Member $member):?PersonalCalendarShareInfo + public function revokeScheduleShareableLink(Summit $summit, Member $member): ?PersonalCalendarShareInfo { return $this->tx_service->transaction(function () use ($summit, $member) { $link = $member->getScheduleShareableLinkBy($summit); - if(is_null($link)){ + if (is_null($link)) { throw new EntityNotFoundException("Schedule shareable link not found for member."); } $link->revoke(); @@ -2323,18 +2323,18 @@ final class SummitService extends AbstractService implements ISummitService return $this->tx_service->transaction(function () use ($summit, $cid) { $link = $summit->getScheduleShareableLinkById($cid); - if(is_null($link)){ + if (is_null($link)) { throw new EntityNotFoundException("Schedule shareable link not found for member."); } - $owner = $link->getOwner(); + $owner = $link->getOwner(); $timeZone = $summit->getTimeZone(); $vCalendar = ICalTimeZoneBuilder::build($timeZone, $summit->getName(), true); - foreach($owner->getScheduleBySummit($summit) as $scheduled){ + foreach ($owner->getScheduleBySummit($summit) as $scheduled) { $summitEvent = $scheduled->getEvent(); $local_start_time = new DateTime($summitEvent->getStartDateNice(), $timeZone); - $local_end_time = new DateTime($summitEvent->getEndDateNice(), $timeZone); - $vEvent = new \Eluceo\iCal\Component\Event($summitEvent->getId()); + $local_end_time = new DateTime($summitEvent->getEndDateNice(), $timeZone); + $vEvent = new \Eluceo\iCal\Component\Event($summitEvent->getId()); $vEvent ->setCreated(new DateTime()) @@ -2345,19 +2345,18 @@ final class SummitService extends AbstractService implements ISummitService ->setDescription(strip_tags($summitEvent->getAbstract())) ->setDescriptionHTML($summitEvent->getAbstract()); - if($timeZone->getName() == 'UTC'){ + if ($timeZone->getName() == 'UTC') { $vEvent->setUseUtc(true) ->setUseTimezone(false); - } - else{ + } else { $vEvent->setUseUtc(false) ->setUseTimezone(true); } - if($summitEvent->hasLocation()){ + if ($summitEvent->hasLocation()) { $location = $summitEvent; $geo = null; - if($location instanceof SummitGeoLocatedLocation) { + if ($location instanceof SummitGeoLocatedLocation) { $geo = sprintf("%s;%s", $location->getLat(), $location->getLng()); } $vEvent->setLocation($location->getTitle(), $location->getTitle(), $geo); @@ -2375,31 +2374,32 @@ final class SummitService extends AbstractService implements ISummitService * @param Summit $summit * @param int $event_id * @param array $data - * @throws ValidationException - * @throws EntityNotFoundException * @return void` + * @throws EntityNotFoundException + * @throws ValidationException */ - public function shareEventByEmail(Summit $summit, int $event_id, array $data):void{ + public function shareEventByEmail(Summit $summit, int $event_id, array $data): void + { $this->tx_service->transaction(function () use ($summit, $event_id, $data) { $event = $summit->getScheduleEvent($event_id); - if(is_null($event)){ + if (is_null($event)) { throw new EntityNotFoundException(sprintf("Event %s not found.", $event_id)); } $event_uri = $data['event_uri'] ?? null; - if(empty($event_uri)){ + if (empty($event_uri)) { Log::debug("event_uri not set on payload. trying to get from default one (summit)"); $default_event_uri = $summit->getScheduleDefaultEventDetailUrl(); - if(!empty($default_event_uri)){ + if (!empty($default_event_uri)) { Log::debug("default_event_uri set at summit level using it."); $event_uri = str_replace(":event_id", $event_id, $default_event_uri); } } - if(empty($event_uri)){ + if (empty($event_uri)) { throw new ValidationException(sprintf("Property event_url is empty.")); } @@ -2411,4 +2411,51 @@ final class SummitService extends AbstractService implements ISummitService )); }); } + + + public function calculateFeedbackAverageForOngoingSummits(): void + { + $ongoing_summits = $this->tx_service->transaction(function () { + return $this->summit_repository->getOnGoing(); + }); + + foreach ($ongoing_summits as $summit) { + + Log::debug(sprintf("SummitService::calculateFeedbackAverageForOngoingSummits processing summit %s", $summit->getId())); + + $event_ids = $this->tx_service->transaction(function () use ($summit) { + return $summit->getScheduleEventsIds(); + }); + + foreach ($event_ids as $event_id) { + $event_id = $event_id['id']; + $this->tx_service->transaction(function () use ($event_id) { + try { + Log::debug(sprintf("SummitService::calculateFeedbackAverageForOngoingSummits processing event %s", $event_id)); + $event = $this->event_repository->getById($event_id); + if (is_null($event) || !$event instanceof SummitEvent){ + Log::debug(sprintf("SummitService::calculateFeedbackAverageForOngoingSummits event %s not found", $event_id)); + return; + } + + $rate_sum = 0; + $rate_count = 0; + foreach ($event->getFeedback() as $feedback) { + $rate_count++; + $rate_sum = $rate_sum + $feedback->getRate(); + } + + $avg_rate = ($rate_count > 0) ? ($rate_sum / $rate_count) : 0; + $avg_rate = round($avg_rate, 2); + $old_avg_rate = $event->getAvgFeedbackRate(); + Log::debug(sprintf("SummitService::calculateFeedbackAverageForOngoingSummits new avg rate %s - old avg rate %s - for event id %s", $avg_rate, $old_avg_rate, $event->getId())); + $event->setAvgFeedbackRate($avg_rate); + } + catch (Exception $ex){ + Log::error($ex); + } + }); + } + } + } } \ No newline at end of file