fitness-web/common/manager/EventRegistrationManager.php

337 lines
12 KiB
PHP

<?php
namespace common\manager;
use common\models\Card;
use common\models\CardEventRegistrationForm;
use common\models\Customer;
use common\models\Event;
use common\models\EventRegistration;
use common\models\Ticket;
use customerapi\models\available\EventInterval;
use customerapi\models\registrations\EventRegistrationAvailable;
use customerapi\models\details\EventRegistrationView;
use Exception;
use Yii;
use yii\base\BaseObject;
use yii\db\ActiveRecord;
use yii\db\Query;
use yii\web\BadRequestHttpException;
use yii\web\NotFoundHttpException;
use yii\web\ServerErrorHttpException;
/**
* Created by IntelliJ IDEA.
* User: rocho
* Date: 2018.12.17.
* Time: 6:12
*/
class EventRegistrationManager extends BaseObject
{
const CARD_NOT_FOUND = 1;
const CUSTOMER_NOT_FOUND = 2;
const TICKET_NOT_FOUND = 3;
const NO_FREE_SEATS = 4;
const EVENT_TYPE_NOT_FOUND = 5;
const TICKET_INSUFFICIENT = 6;
const UNKNOWN_ERROR = 7;
const MAX_SEAT_COUNT_EXCEEDED = 8;
const EVENT_UNAVAILABLE = 9;
const ALREADY_REGISTERED = 10;
const EVENT_START_DATE_IN_PAST = 11;
const EVENT_NOT_FOUND = 12;
const ALREADY_CANCELLED = 13;
const ALREADY_DELETED = 14;
const CANCEL_TIME_LIMIT_REACHED = 15;
public static $STATES = [
self::CARD_NOT_FOUND => "Kártya nem található",
self::CUSTOMER_NOT_FOUND => "Vendég nem található",
self::TICKET_NOT_FOUND => "Bérlet nem található",
self::NO_FREE_SEATS => "Nincs szabad hely",
self::EVENT_TYPE_NOT_FOUND => "Esemény típus nem található",
self::TICKET_INSUFFICIENT => "Bérlet nem található",
self::UNKNOWN_ERROR => "Ismeretlen hiba",
self::MAX_SEAT_COUNT_EXCEEDED => "Nincs szabad hely",
self::EVENT_UNAVAILABLE => "Esemény nem elérhető",
self::ALREADY_REGISTERED => "Már regisztrálva van",
self::EVENT_START_DATE_IN_PAST => "Az esemény már elkezdődött",
self::EVENT_NOT_FOUND => "Esemény tnem található",
self::ALREADY_CANCELLED => "Ez a regisztráció már lemndásra került",
self::ALREADY_DELETED => "Ez a regisztráció már törlésre került",
self::CANCEL_TIME_LIMIT_REACHED => "Ez a regisztráció már nem mondható le",
];
/**
* @param CardEventRegistrationForm $cardEventForm
* @throws Exception
*/
public function registerCard($cardEventForm)
{
$db = Yii::$app->db;
$tx = $db->beginTransaction();
try {
if ($cardEventForm->validate()) {
$requiresTicket = false;
/** @var Card $card */
$card = Card::readCard($cardEventForm->card_number, false);
if (!isset($card)) {
throw new NotFoundHttpException('Card not found: ' . $cardEventForm->card_number, self::CARD_NOT_FOUND);
}
if ($card->isFree()) {
throw new NotFoundHttpException('Customer not found', self::CUSTOMER_NOT_FOUND);
}
$activeTickets = $card->getActiveTickets();
if (count($activeTickets) === 0) {
throw new BadRequestHttpException('Ticket not found1', self::TICKET_NOT_FOUND);
}
/** @var Event $event */
$event = Event::find()->andWhere(['id' => $cardEventForm->event_id])->one();
if (!isset($event)) {
throw new NotFoundHttpException('Event not found: ' . $cardEventForm->event_id);
}
if (isset($event->deleted_at)) {
throw new BadRequestHttpException('Event deleted', self::EVENT_UNAVAILABLE);
}
$now = strtotime("now utc");
if ($event->start < $now) {
throw new BadRequestHttpException('Event start date in past', self::EVENT_START_DATE_IN_PAST);
}
if (!$event->hasFreeSeats()) {
throw new BadRequestHttpException('No free seats', self::NO_FREE_SEATS);
}
$eventType = $event->eventType;
if (!isset($eventType)) {
throw new ServerErrorHttpException('Event type not found', self::EVENT_TYPE_NOT_FOUND);
}
//detect if customer is already registered to event
/** @var EventRegistration[] $registrations */
$registrations = $event->getActiveEventRegistrations()->all();
foreach ($registrations as $registration) {
if ($registration->id_customer == $card->customer->id_customer) {
throw new BadRequestHttpException("Already registered", self::ALREADY_REGISTERED);
}
}
$selectedTicket = $eventType->findTicketAllowingEventType($activeTickets);
if (!isset($selectedTicket)) {
throw new BadRequestHttpException('Ticket not found2', self::TICKET_INSUFFICIENT);
}
try {
$selectedTicket->consumeReservationCount(1);
} catch (\Exception $e) {
throw new BadRequestHttpException('Max ticket seat count exceeded', self::MAX_SEAT_COUNT_EXCEEDED);
}
$selectedTicket->save(false);
$registration = new EventRegistration();
$registration->id_event = $event->id;
$registration->id_card = $card->id_card;
$registration->id_ticket = $selectedTicket->id_ticket;
$registration->id_customer = $card->customer->id_customer;
try {
$registration->save(false);
} catch (\yii\db\Exception $exception) {
throw new ServerErrorHttpException('Failed to save', self::UNKNOWN_ERROR);
}
$cardEventForm->registration = $registration;
}
$tx->commit();
} catch (Exception $exception) {
$tx->rollBack();
throw $exception;
}
}
public function createFindRegistrationsQuery($idEvent)
{
$query = new Query();
$query->select([
'event_registration.id as event_registration_id',
'event_registration.created_at as event_registration_created_at',
'event_registration.canceled_at as event_registration_canceled_at',
'event_registration.deleted_at as event_registration_deleted_at',
'card.id_card as card_id_card',
'card.number as card_number',
'customer.id_customer as customer_id_customer',
'customer.name as customer_name',
'customer.email as customer_email',
]);
$query->from(EventRegistration::tableName());
$query->innerJoin(Event::tableName(), 'event_registration.id_event = event.id');
$query->innerJoin(Card::tableName(), 'event_registration.id_card = card.id_card');
$query->innerJoin(Customer::tableName(), 'customer.id_customer_card = card.id_card');
$query->andWhere(['event_registration.id_event' => $idEvent]);
return $query;
}
/**
* @param $idRegistration
* @return array|EventRegistration|ActiveRecord|null
* @throws NotFoundHttpException
*/
public function loadRegistration($idRegistration, $idCustomer)
{
$query = EventRegistration::find()
->andWhere(['id' => $idRegistration]);
if (isset($idCustomer)) {
$query->andWhere(['id_customer' => $idCustomer]);
}
$registration = $query->one();
if ($registration === null) {
throw new NotFoundHttpException('The requested registration does not exist.');
}
return $registration;
}
public function cancelRegistrationTX($registration, $idCustomer, $reason)
{
$tx = \Yii::$app->db->beginTransaction();
try {
$this->cancelRegistration($registration, $idCustomer, $reason);
$tx->commit();
} catch (\Exception $e) {
$tx->rollBack();
throw $e;
}
}
/**
* @param EventRegistration $registration
* @throws ServerErrorHttpException
*/
public function cancelRegistration($registration, $idCustomer, $reason)
{
if (isset($idCustomer) && $registration->id_customer != $idCustomer) {
throw new NotFoundHttpException('The requested registration does not exist.');
}
if (isset($registration->canceled_at)) {
throw new BadRequestHttpException('The registration is already canceled', self::ALREADY_CANCELLED);
}
if (isset($registration->deleted_at)) {
throw new BadRequestHttpException('The reservation is already deleted', self::ALREADY_DELETED);
}
$event = Event::findOne($registration->id_event);
if (!isset($event)) {
throw new BadRequestHttpException('The reservation is already deleted', self::EVENT_NOT_FOUND);
}
$now = strtotime("now UTC");
if ($reason != EventRegistration::CANCEL_REASON_CUSTOMER) {
$timeUntilEventStart = $event->start - $now;
if ($timeUntilEventStart < 30 * 60) {
throw new BadRequestHttpException('The reservation is already deleted', self::CANCEL_TIME_LIMIT_REACHED);
}
}
$now = strtotime("now");
// if user cancels then cancel_at will be set
if ( $reason == EventRegistration::CANCEL_REASON_CUSTOMER){
$registration->canceled_at = date('Y-m-d H:i:s', $now);
}else{
// otherwise ( e.g. event is deleted ) the delete_at will be set
$registration->deleted_at = date('Y-m-d H:i:s', $now);
}
$registration->save(false);
$ticket = Ticket::findOne($registration->id_ticket);
if (!isset($ticket)) {
throw new BadRequestHttpException('The ticket is not found');
}
$ticket->restoreReservationCount(1);
$ticket->save(false);
}
public function findAllRegistrations($idEvent, $idCustomer = null)
{
$registrations =
EventRegistration::find()
->andWhere(['id_event' => $idEvent])->all();
if (isset($idCustomer)) {
$registrations = EventRegistration::filterForCustomer($registrations, $idCustomer);
}
return $registrations;
}
public function findActiveRegistrations($idEvent, $idCustomer = null)
{
$registrations = $this->findAllRegistrations($idEvent, $idCustomer);
return EventRegistration::filterActive($registrations);
}
/**
* Delete an event
* @param Event $event
* @throws Exception
* @throws Throwable
*/
public function deleteEvent($event)
{
$db = Yii::$app->db;
$tx = $db->beginTransaction();
try {
$eventRegistrationManager = new EventRegistrationManager();
$allRegistrations = $eventRegistrationManager->findAllRegistrations($event->id);
$activeRegistrations = $eventRegistrationManager->findActiveRegistrations($event->id);
// ////////////////////////////////
// if event has no registrations
// we can simply delete it from db
// ////////////////////////////////
if (count($allRegistrations) === 0) {
$event->delete();
} else {
// /////////////////////////////
// otherwise we mark the event deleted
// and we have to delete the registrations
// /////////////////////////////
$event->deleted_at = date('Y-m-d H:i:s');
$event->save(false);
foreach ($activeRegistrations as $registration) {
if (!isset($registration->deleted_at)) {
/** @var EventRegistration $registration */
$this->cancelRegistration($registration, null, EventRegistration::CANCEL_REASON_EVENT);
}
}
}
$tx->commit();
} catch (Exception $e) {
$tx->rollBack();
throw $e;
}
}
}