3, "MODIFY_RESERVATION" => 8 ]; protected $ERROR_FIELDS = []; protected $RESERVATION = NULL; protected $RESERVATION_OTHER_DETAILS = NULL; protected $POST_DATA = NULL; const EVENT_RESPONSE = [ "EVENT_CLOSED" => "Reservation is not allowed. Event is currently closed.", "EVENT_FULL_RES_TO_WL" => "Cannot reserve, event is already full.", "EVENT_REG_DISABLED" => "Reservation is not allowed.", "EVENT_FULL" => "Reservation is not allowed event is full.", "EVENT_REG_UNAVAILABLE" => "You have reached the maximum reservation allowed per subscriber in this event.", "EVENT_RES_OK" => "You have successfully registered to an event.", "EVENT_RES_ADDED_SEAT" => "You have successfully added seat to your reservations.", "EVENT_404" => "Event not found.", "EVENT_RESTRICT_MULTIPLE_RES" => "You have reached the maximum reservation allowed per subscriber in this event.", "EVENT_RES_NULL" => "Reserve seats should not be null.", "EVENT_WRONG_FORMAT_PAYLOAD" => "Wrong format of JSON data", // Reservation "EVENT_RESERVATION_ERR" => "Reservation unsuccessfull. Try again later.", "EVENT_NO_RESERVATION" => "No current reservation.", "EVENT_RESERVATION_EMIAL_ERR" => "Unable to queue reservation confirmation email." ]; const PAYLOAD_FIELDS = [ // Optional fields "mage_id" => ["required" => false, "dtype" => "string"], "firstname" => ["required" => false, "dtype" => "string"], "lastname" => ["required" => false, "dtype" => "string"], "event_date_time" => ["required" => false, "dtype" => "date"], "update_date_time" => ["required" => false, "dtype" => "date"], "comment" => ["required" => false, "dtype" => "string"], // Required fields "magento_id" => ["required" => true, "dtype" => "int"], "email" => ["required" => true, "dtype" => "email"], "cart_id" => ["required" => true, "dtype" => "string"], // Required to determine which event_schedule to query from "code_selection" => ["required" => true, "dtype" => "string"], "item_name" => ["required" => true, "dtype" => "string"], "number_of_seat" => ["required" => true, "dtype" => "int"], "unit_price" => ["required" => true, "dtype" => "int"], "amount_cart" => ["required" => true, "dtype" => "int"], "procurement_date_time" => ["required" => true, "dtype" => "date"] ]; /** * Get All Data from this method. * * @return Response */ public function __construct() { parent::__construct(); $this->load->database(); $this->load->model('user_model'); $this->load->model("event_schedule_model"); $this->load->model("event_registration_paid_event_model"); $this->load->model('event_wait_list_model'); $this->load->model('event_registration_model'); $this->load->model("user_subscriber_model"); $this->load->model('event_email_template_model'); $this->load->model('event_email_recipient_model'); $this->load->model('user_activity_log_model'); } /** * Reserve seat * * @return Response */ public function action_post() { // Validate payload and initialize variables $this->validate_payload(); // Get event details $event_sched_details = $this->event_schedule_model->event_schedule_details($this->EVENT_ID, $this->EVENT_SCHEDULE_ID); // Validate registration information $this->validate_reservation($event_sched_details); if ($this->RES_ALLOWED) { $this->RESERVATION = array( "event_id" => $this->EVENT_ID, "seat_feature" => $event_sched_details->seat_feature, "action" => $this->REG_ACTION, "reg_type" => $this->REG_TYPE, "user_id" => $this->USER_ID, "seats_reserved" => $this->NUMBER_OF_SEATS, "event_schedule_id" => $this->EVENT_SCHEDULE_ID, "guest_emails" => "", "user_agent" => $_SERVER['HTTP_USER_AGENT'] ?? null, "is_user_moderated" => 0 ); $this->RESERVATION_OTHER_DETAILS = [ "cart_id" => $this->POST_DATA['cart_id'], "item_code" => $this->POST_DATA['code_selection'], "item_name" => $this->POST_DATA['item_name'], "number_of_seats" => $this->NUMBER_OF_SEATS, "unit_price" => $this->POST_DATA['unit_price'], "amount_cart" => $this->POST_DATA['amount_cart'], "comment" => (isset($this->POST_DATA['comment']) && !empty($this->POST_DATA['comment'])) ? $this->POST_DATA['comment'] : NULL, "procurement_date_time" => $this->POST_DATA['procurement_date_time'] ?? NULL, "update_date_time" => $this->POST_DATA['update_date_time'] ?? NULL ]; if ($this->REG_ACTION == "register") return $this->add_reservation(); else return $this->modify_reservation(); } $this->responseFormatter("EVENT_RESERVATION_ERR"); } private function validate_payload() { $POST_DATA = countVal($this->input->post()) ? $this->input->post() : $this->request->body; if ( !countVal($POST_DATA) ) $this->responseFormatter("EVENT_WRONG_FORMAT_PAYLOAD"); // Checking Unknown fields foreach ($POST_DATA as $key => $value) { // Unknown fields if ( !array_key_exists($key, self::PAYLOAD_FIELDS) ) { array_push($this->ERROR_FIELDS , [ "field" => $key, "description" => "Unkown field" ]); continue; } } foreach (self::PAYLOAD_FIELDS as $key => $value) { // Requied fields if ( self::PAYLOAD_FIELDS[$key]["required"]) { $msg = (!array_key_exists($key, $POST_DATA)) ? "Ce champ est obligatoire." : (isset($POST_DATA[$key]) && empty($POST_DATA[$key]) ) ? "Required field must not be null" : ""; if ($msg) { array_push($this->ERROR_FIELDS , ["field" => $key, "description" => $msg]); continue; } } isset($POST_DATA[$key]) && $this->validate_field($key, $POST_DATA[$key]); } if ( countVal($this->ERROR_FIELDS) ) { $this->responseHandler(["message" => "Field validation error" , "details" => $this->ERROR_FIELDS], REST_Controller::HTTP_BAD_REQUEST); } /** * Required fields are validated so we verify its values */ // Verify code selection $eventInfo = $this->event_registration_paid_event_model->get_event_by_code_selection($POST_DATA['code_selection']); if (!$eventInfo) { $this->responseHandler("Invalid code selection", REST_Controller::HTTP_BAD_REQUEST); } $this->EVENT_ID = $eventInfo->event_id; $this->EVENT_SCHEDULE_ID = $eventInfo->event_schedule_id; // Verify user email, magento_id || mage_id $user = $this->user_model->get_user_by_email_or_magento_id($POST_DATA['email'], $POST_DATA['magento_id'], $POST_DATA['mage_id'] ?? null); if (!$user) { $this->responseHandler([ "message" => "Subscriber with email '".$POST_DATA['email']."' not recognized", "description" => "Make sure 'magento_id' and 'email' are valid." ], REST_Controller::HTTP_BAD_REQUEST); } $this->USER_ID = $user->user_id; $this->NUMBER_OF_SEATS = $POST_DATA['number_of_seat']; $this->POST_DATA = $POST_DATA; } private function validate_reservation($event_sched_details) { // Event exists if ( !countVal($event_sched_details) > 0 ) $this->responseFormatter("EVENT_404", REST_Controller::HTTP_NOT_FOUND); // Check if subscriber is allowed to book for more than 1 date per event if ( !$this->event_registration_paid_event_model->can_register_to_event($this->EVENT_ID, $this->USER_ID, $this->REG_TYPE) ) $this->responseFormatter("EVENT_RESTRICT_MULTIPLE_RES"); // Check if there are seats avaiable or if the limit for seat_per_subscriber have not been reached $event = $this->event_registration_paid_event_model->check_availability($this->EVENT_ID, $this->EVENT_SCHEDULE_ID, $this->NUMBER_OF_SEATS); $prev_reservation = $this->event_registration_model->seats_reserved($this->USER_ID, $this->EVENT_SCHEDULE_ID); if ($prev_reservation) $this->REG_ACTION = "modify"; // Event is Closed if (countVal($event) <= 0 || $event->back_office_status >= 4) $this->responseFormatter("EVENT_CLOSED"); // Event FULL if ($event->back_office_status == 3 || ($event->event_status == 'FULL' && $event->remaining_seat >=0)) $this->responseFormatter("EVENT_FULL"); // Register to regular/normal registration disabled : must register to waiting list if ($event->remaining_seat <= 0 && $event->quota_waiting_list_seat > 0) $this->responseFormatter("EVENT_FULL_RES_TO_WL"); // Event FULL if ($event->remaining_seat <= 0) $this->responseFormatter("EVENT_FULL"); // Event Registration disabled if ($event->seats_per_subscriber <=0) $this->responseFormatter("EVENT_REG_DISABLED"); // Allow Reserver for normal or regular reservation $currentTotalReservation = $prev_reservation + $this->NUMBER_OF_SEATS; if ($event->remaining_seat > 0 && $event->event_status == 'AVAILABLE' && $event->remaining_seat >= $this->NUMBER_OF_SEATS && $currentTotalReservation <= $event->seats_per_subscriber) { return $this->RES_ALLOWED = true; } else { //Event registration disabled $this->responseFormatter("EVENT_REG_UNAVAILABLE"); } } private function validate_field($field, $value, $required = false) { switch(self::PAYLOAD_FIELDS[$field]["dtype"]) { case 'email': if ( !filter_var($value, FILTER_VALIDATE_EMAIL) ) { array_push($this->ERROR_FIELDS , [ "field" => $field, "description" => "Invalid email" ]); } return; case 'date': $dFormat = 'Y-m-d H:i:s'; $d = DateTime::createFromFormat($dFormat , $value); if (!$d || $d->format($dFormat ) != $value) { array_push($this->ERROR_FIELDS , [ "field" => $field, "description" => "Invalid date format" ]); } return; case 'int': if (!is_numeric($value)) { array_push($this->ERROR_FIELDS , [ "field" => $field, "description" => "Invalid number" ]); return; } if (is_numeric($value) && (int) $value <= 0 ) { array_push($this->ERROR_FIELDS , [ "field" => $field, "description" => "Number must be greater than zero" ]); return; } return; } } private function add_reservation() { $registration_id = $this->event_registration_model->register($this->RESERVATION); // Send email when reservation is successfull if (!$registration_id) return $this->responseFormatter("EVENT_RESERVATION_ERR"); // Add entry to paid event table $paidEventId = $this->add_paid_event_entry($registration_id); // Save logs $this->add_log("ADD", $paidEventId); // Queue email $this->queue_confirmation_email($this->RES_EMAIL_TYPE['CONFIRMATION_EMAIL'], $registration_id); return $this->responseFormatter("EVENT_RES_OK", REST_Controller::HTTP_OK); } private function modify_reservation() { $registration_id = $this->event_registration_model->register($this->RESERVATION); // Send email when reservation is successfull if (!$registration_id) return $this->responseFormatter("EVENT_RESERVATION_ERR"); // Add entry to paid event table $paidEventId = $this->add_paid_event_entry($registration_id); // Save logs $this->add_log("EDIT", $paidEventId); $seats_reserved = $this->event_registration_model->seats_reserved($this->USER_ID, $this->EVENT_SCHEDULE_ID); if (!$seats_reserved) return $this->responseFormatter("EVENT_NO_RESERVATION"); // Queue email $this->queue_confirmation_email($this->RES_EMAIL_TYPE['MODIFY_RESERVATION'], $registration_id); return $this->responseFormatter("EVENT_RES_ADDED_SEAT", REST_Controller::HTTP_OK); } private function queue_confirmation_email($email_type_d, $registration_id) { $emailRefId = $this->event_email_recipient_model->queue_reservation_email([ 'event_schedule_id' => $this->EVENT_SCHEDULE_ID, 'reference_id' => $registration_id, 'email_type_id' => $email_type_d, 'email_status' => '0' ]); if (!$emailRefId) return $this->responseFormatter("EVENT_RESERVATION_EMIAL_ERR"); } private function add_log($action, $registration_id) { $this->user_activity_log_model->add_activity_log([ "description" => $action." Paid Event Reservations", "user_id" => $this->USER_ID, "action" => $action, "table_origin" => "event_registration_paid_event", "reference_id" => $registration_id ]); } private function add_paid_event_entry($registration_id) { $this->RESERVATION_OTHER_DETAILS['registration_id'] = $registration_id; return $this->event_registration_paid_event_model->add_paid_event($this->RESERVATION_OTHER_DETAILS); } private function responseFormatter($message, $httpStatus = REST_Controller::HTTP_BAD_REQUEST) { $this->responseHandler(self::EVENT_RESPONSE[$message], $httpStatus); } }