326 lines
11 KiB
PHP
326 lines
11 KiB
PHP
<?php namespace models\summit;
|
|
/**
|
|
* Copyright 2019 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 Doctrine\Common\Collections\ArrayCollection;
|
|
use Doctrine\Common\Collections\Criteria;
|
|
use Doctrine\ORM\Mapping AS ORM;
|
|
use models\exceptions\ValidationException;
|
|
/**
|
|
* @ORM\Entity
|
|
* @ORM\Table(name="SummitBookableVenueRoom")
|
|
* Class SummitBookableVenueRoom
|
|
* @package models\summit
|
|
*/
|
|
class SummitBookableVenueRoom extends SummitVenueRoom
|
|
{
|
|
|
|
const ClassName = 'SummitBookableVenueRoom';
|
|
|
|
/**
|
|
* @ORM\Column(name="TimeSlotCost", type="integer")
|
|
* @var int
|
|
*/
|
|
private $time_slot_cost;
|
|
|
|
/**
|
|
* @var string
|
|
* @ORM\Column(name="Currency", type="string")
|
|
*/
|
|
private $currency;
|
|
|
|
/**
|
|
* @ORM\OneToMany(targetEntity="models\summit\SummitRoomReservation", mappedBy="room", cascade={"persist"}, orphanRemoval=true)
|
|
* @var ArrayCollection
|
|
*/
|
|
private $reservations;
|
|
|
|
/**
|
|
* @ORM\ManyToMany(targetEntity="models\summit\SummitBookableVenueRoomAttributeValue")
|
|
* @ORM\JoinTable(name="SummitBookableVenueRoom_Attributes",
|
|
* joinColumns={@ORM\JoinColumn(name="SummitBookableVenueRoomID", referencedColumnName="ID")},
|
|
* inverseJoinColumns={@ORM\JoinColumn(name="SummitBookableVenueRoomAttributeValueID", referencedColumnName="ID", unique=true)}
|
|
* )
|
|
*/
|
|
private $attributes;
|
|
|
|
public function __construct()
|
|
{
|
|
parent::__construct();
|
|
$this->reservations = new ArrayCollection();
|
|
$this->attributes = new ArrayCollection();
|
|
}
|
|
|
|
/**
|
|
* @param SummitRoomReservation $reservation
|
|
* @return $this
|
|
* @throws ValidationException
|
|
*/
|
|
public function addReservation(SummitRoomReservation $reservation){
|
|
|
|
$criteria = Criteria::create();
|
|
|
|
$start_date = $reservation->getStartDatetime();
|
|
$end_date = $reservation->getEndDatetime();
|
|
|
|
$criteria
|
|
->where(Criteria::expr()->eq('start_datetime', $start_date))
|
|
->andWhere(Criteria::expr()->eq('end_datetime',$end_date))
|
|
->andWhere(Criteria::expr()->notIn("status", [SummitRoomReservation::RequestedRefundStatus, SummitRoomReservation::RefundedStatus]));
|
|
|
|
if($this->reservations->matching($criteria)->count() > 0)
|
|
throw new ValidationException(sprintf("reservation overlaps an existent reservation"));
|
|
|
|
$criteria
|
|
->where(Criteria::expr()->lte('start_datetime', $end_date))
|
|
->andWhere(Criteria::expr()->gte('end_datetime', $start_date))
|
|
->andWhere(Criteria::expr()->notIn("status", [SummitRoomReservation::RequestedRefundStatus, SummitRoomReservation::RefundedStatus]));
|
|
|
|
if($this->reservations->matching($criteria)->count() > 0)
|
|
throw new ValidationException(sprintf("reservation overlaps an existent reservation"));
|
|
|
|
$summit = $this->summit;
|
|
|
|
$local_start_date = $summit->convertDateFromUTC2TimeZone($start_date);
|
|
$local_end_date = $summit->convertDateFromUTC2TimeZone($end_date);
|
|
$start_time = $summit->getMeetingRoomBookingStartTime();
|
|
$end_time = $summit->getMeetingRoomBookingEndTime();
|
|
|
|
if(!$summit->isTimeFrameInsideSummitDuration($local_start_date, $local_end_date))
|
|
throw new ValidationException("requested reservation period does not belong to summit period");
|
|
|
|
$local_start_time = new \DateTime("now", $this->summit->getTimeZone());
|
|
$local_start_time->setTime(
|
|
intval($start_time->format("H")),
|
|
intval($start_time->format("i")),
|
|
intval($start_time->format("s"))
|
|
);
|
|
|
|
$local_end_time = new \DateTime("now", $this->summit->getTimeZone());
|
|
$local_end_time->setTime(
|
|
intval($end_time->format("H")),
|
|
intval($end_time->format("i")),
|
|
intval($end_time->format("s"))
|
|
);
|
|
|
|
$local_start_time->setDate
|
|
(
|
|
intval($local_start_date->format("Y")),
|
|
intval($local_start_date->format("m")),
|
|
intval($local_start_date->format("d"))
|
|
);
|
|
|
|
$local_end_time->setDate
|
|
(
|
|
intval($local_start_date->format("Y")),
|
|
intval($local_start_date->format("m")),
|
|
intval($local_start_date->format("d"))
|
|
);
|
|
|
|
if(!($local_start_time <= $local_start_date
|
|
&& $local_end_date <= $local_end_time))
|
|
throw new ValidationException
|
|
(
|
|
sprintf
|
|
(
|
|
"requested booking time slot is not allowed! requested [from %s to %s] allowed [from %s to %s]",
|
|
$local_start_date->format("Y-m-d H:i:s"),
|
|
$local_end_date->format("Y-m-d H:i:s"),
|
|
$local_start_time->format("Y-m-d H:i:s"),
|
|
$local_end_time->format("Y-m-d H:i:s")
|
|
)
|
|
);
|
|
|
|
$interval = $end_date->diff($start_date);
|
|
$minutes = ($interval->d * 24 * 60) + ($interval->h * 60) + $interval->i;
|
|
if($minutes != $summit->getMeetingRoomBookingSlotLength())
|
|
throw new ValidationException
|
|
(
|
|
sprintf
|
|
(
|
|
"requested booking time slot is not allowed! request slot (%s minutes) - summit allowed slot (%s minutes)",
|
|
$minutes,
|
|
$summit->getMeetingRoomBookingSlotLength()
|
|
)
|
|
);
|
|
|
|
$this->reservations->add($reservation);
|
|
$reservation->setRoom($this);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @return int
|
|
*/
|
|
public function getTimeSlotCost(): int
|
|
{
|
|
return $this->time_slot_cost;
|
|
}
|
|
|
|
/**
|
|
* @param int $time_slot_cost
|
|
*/
|
|
public function setTimeSlotCost(int $time_slot_cost): void
|
|
{
|
|
$this->time_slot_cost = $time_slot_cost;
|
|
}
|
|
|
|
/**
|
|
* @return ArrayCollection
|
|
*/
|
|
public function getReservations(): ArrayCollection
|
|
{
|
|
return $this->reservations;
|
|
}
|
|
|
|
/**
|
|
* @param int $id
|
|
* @return SummitRoomReservation|null
|
|
*/
|
|
public function getReservationById(int $id):?SummitRoomReservation{
|
|
$criteria = Criteria::create();
|
|
$criteria->where(Criteria::expr()->eq('id', intval($id)));
|
|
$reservation = $this->reservations->matching($criteria)->first();
|
|
return $reservation === false ? null : $reservation;
|
|
}
|
|
|
|
public function clearReservations(){
|
|
$this->reservations->clear();
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function getClassName()
|
|
{
|
|
return self::ClassName;
|
|
}
|
|
|
|
/**
|
|
* @param \DateTime $day should be on local summit day
|
|
* @return array
|
|
* @throws ValidationException
|
|
*/
|
|
public function getAvailableSlots(\DateTime $day):array{
|
|
$availableSlots = [];
|
|
$summit = $this->summit;
|
|
$day = $day->setTimezone($summit->getTimeZone())->setTime(0, 0,0);
|
|
$booking_start_time = $summit->getMeetingRoomBookingStartTime();
|
|
if(is_null($booking_start_time))
|
|
throw new ValidationException("MeetingRoomBookingStartTime is null!");
|
|
|
|
$booking_end_time = $summit->getMeetingRoomBookingEndTime();
|
|
if(is_null($booking_end_time))
|
|
throw new ValidationException("MeetingRoomBookingEndTime is null!");
|
|
|
|
$booking_slot_len = $summit->getMeetingRoomBookingSlotLength();
|
|
$start_datetime = clone $day;
|
|
$end_datetime = clone $day;
|
|
|
|
$start_datetime->setTime(
|
|
intval($booking_start_time->format("H")),
|
|
intval($booking_start_time->format("i")),
|
|
0);
|
|
$start_datetime->setTimezone($summit->getTimeZone());
|
|
|
|
$end_datetime->setTime(
|
|
intval($booking_end_time->format("H")),
|
|
intval($booking_end_time->format("i")),
|
|
00);
|
|
$end_datetime->setTimezone($summit->getTimeZone());
|
|
$criteria = Criteria::create();
|
|
if(!$summit->isTimeFrameInsideSummitDuration($start_datetime, $end_datetime))
|
|
throw new ValidationException("requested day does not belong to summit period");
|
|
|
|
$criteria
|
|
->where(Criteria::expr()->gte('start_datetime', $summit->convertDateFromTimeZone2UTC($start_datetime)))
|
|
->andWhere(Criteria::expr()->lte('end_datetime', $summit->convertDateFromTimeZone2UTC($end_datetime)))
|
|
->andWhere(Criteria::expr()->notIn("status", [SummitRoomReservation::RequestedRefundStatus, SummitRoomReservation::RefundedStatus]));
|
|
|
|
$reservations = $this->reservations->matching($criteria);
|
|
|
|
while($start_datetime <= $end_datetime) {
|
|
$current_time_slot_end = clone $start_datetime;
|
|
$current_time_slot_end->add(new \DateInterval("PT" . $booking_slot_len . 'M'));
|
|
if($current_time_slot_end<=$end_datetime)
|
|
$availableSlots[$start_datetime->format('Y-m-d H:i:s').'|'.$current_time_slot_end->format('Y-m-d H:i:s')] = true;
|
|
$start_datetime = $current_time_slot_end;
|
|
}
|
|
|
|
foreach ($reservations as $reservation){
|
|
if(!$reservation instanceof SummitRoomReservation) continue;
|
|
$availableSlots[
|
|
$summit->convertDateFromUTC2TimeZone($reservation->getStartDatetime())->format("Y-m-d H:i:s")
|
|
.'|'.
|
|
$summit->convertDateFromUTC2TimeZone($reservation->getEndDatetime())->format("Y-m-d H:i:s")
|
|
] = false;
|
|
}
|
|
|
|
return $availableSlots;
|
|
}
|
|
|
|
/**
|
|
* @param \DateTime $day
|
|
* @return array
|
|
* @throws ValidationException
|
|
*/
|
|
public function getFreeSlots(\DateTime $day):array{
|
|
$slots = $this->getAvailableSlots($day);
|
|
$free_slots = [];
|
|
foreach ($slots as $label => $status){
|
|
if(!$status) continue;
|
|
$free_slots[] = $label;
|
|
}
|
|
return $free_slots;
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function getCurrency(): string
|
|
{
|
|
return $this->currency;
|
|
}
|
|
|
|
/**
|
|
* @param string $currency
|
|
*/
|
|
public function setCurrency(string $currency): void
|
|
{
|
|
$this->currency = $currency;
|
|
}
|
|
|
|
/**
|
|
* @return mixed
|
|
*/
|
|
public function getAttributes()
|
|
{
|
|
return $this->attributes;
|
|
}
|
|
|
|
/**
|
|
* @param SummitBookableVenueRoomAttributeValue $attribute
|
|
*/
|
|
public function addAttribute(SummitBookableVenueRoomAttributeValue $attribute){
|
|
if($this->attributes->contains($attribute)) return;
|
|
$this->attributes->add($attribute);
|
|
}
|
|
|
|
/**
|
|
* @param SummitBookableVenueRoomAttributeValue $attribute
|
|
*/
|
|
public function removeAttribute(SummitBookableVenueRoomAttributeValue $attribute){
|
|
if(!$this->attributes->contains($attribute)) return;
|
|
$this->attributes->removeElement($attribute);
|
|
}
|
|
|
|
} |