The followings are the available columns in table:
Inheritance: extends BaseEventTypeElement
 public function testIsPatientUnavailable()
 {
     $unavailables_data = array(array('start_date' => '2014-04-03', 'end_date' => '2014-04-03'), array('start_date' => '2014-04-12', 'end_date' => '2014-05-03'));
     $unavailables = array();
     foreach ($unavailables_data as $data) {
         $u = new OphTrOperationbooking_ScheduleOperation_PatientUnavailable();
         $u->attributes = $data;
         $unavailables[] = $u;
     }
     $test1 = new Element_OphTrOperationbooking_ScheduleOperation();
     $test1->patient_unavailables = array($unavailables[0]);
     $this->assertFalse($test1->isPatientAvailable('2014-04-03'));
     $this->assertTrue($test1->isPatientAvailable('2014-04-04'));
     $test2 = new Element_OphTrOperationbooking_ScheduleOperation();
     $test2->patient_unavailables = array($unavailables[0], $unavailables[1]);
     $this->assertTrue($test2->isPatientAvailable('2014-04-02'));
     $this->assertFalse($test2->isPatientAvailable('2014-04-03'));
     $this->assertTrue($test2->isPatientAvailable('2014-04-09'));
     $this->assertFalse($test2->isPatientAvailable('2014-04-12'));
     $this->assertFalse($test2->isPatientAvailable('2014-04-19'));
     $this->assertFalse($test2->isPatientAvailable('2014-05-03'));
     $this->assertTrue($test2->isPatientAvailable('2014-05-04'));
     // check it works when no unavailable data
     $test3 = new Element_OphTrOperationbooking_ScheduleOperation();
     $this->assertTrue($test3->isPatientAvailable('2041-04-02'));
 }
 /**
  * @param OphTrOperationbooking_Operation_Booking $booking
  * @param $operation_comments
  * @param $session_comments
  * @param $operation_comments_rtt
  * @param bool                                            $reschedule
  * @param null                                            $cancellation_data
  * @param Element_OphTrOperationbooking_ScheduleOperation $schedule_op
  *
  * @throws RaceConditionException
  * @throws Exception
  *
  * @internal param $booking_attributes
  *
  * @return array|bool
  */
 public function schedule($booking, $operation_comments, $session_comments, $operation_comments_rtt, $reschedule = false, $cancellation_data = null, $schedule_op = null)
 {
     if ($schedule_op == null) {
         throw new Exception('schedule_op argument required for scheduling');
     }
     if (Yii::app()->params['ophtroperationbooking_schedulerequiresreferral'] && !$this->referral) {
         return array(array('Referral required to schedule operation'));
     }
     $session = $booking->session;
     if (!$schedule_op->isPatientAvailable($session->date)) {
         return array(array('Cannot book patient into a session they are not available for.'));
     }
     if (!$session->operationBookable($this)) {
         return array(array('Attempted to book operation into incompatible session: ' . $session->unbookableReason($this)));
     }
     $reschedule = in_array($this->status_id, array(2, 3, 4));
     if (preg_match('/(^[0-9]{1,2}).*?([0-9]{2})$/', $booking->admission_time, $m)) {
         $booking->admission_time = $m[1] . ':' . $m[2];
     }
     // parse the cancellation data
     $cancellation_submitted = false;
     $cancellation_reason_id = null;
     $cancellation_comment = null;
     if ($cancellation_data) {
         $cancellation_submitted = $cancellation_data['submitted'];
         $cancellation_reason_id = $cancellation_data['reason_id'];
         $cancellation_comment = $cancellation_data['comment'];
     }
     if ($this->booking && !$reschedule) {
         // race condition, two users attempted to book the same operation at the same time
         throw new RaceConditionException('This operation has already been scheduled by ' . $this->booking->user->fullName);
     }
     if ($reschedule && !$cancellation_submitted && $this->booking) {
         // race condition, two users attempted to book the same operation at the same time
         throw new RaceConditionException('This operation has already been scheduled by ' . $this->booking->user->fullName);
     }
     if ($reschedule && $this->booking) {
         if (!($reason = OphTrOperationbooking_Operation_Cancellation_Reason::model()->findByPk($cancellation_reason_id))) {
             return array(array('Please select a rescheduling reason'));
         }
         $this->booking->cancel($reason, $cancellation_comment, $reschedule);
     }
     foreach (array('date', 'start_time', 'end_time', 'theatre_id') as $field) {
         $booking->{'session_' . $field} = $booking->session->{$field};
     }
     if (!$booking->save()) {
         return $booking->getErrors();
     }
     OELog::log('Booking ' . ($reschedule ? 'rescheduled' : 'made') . " {$booking->id}");
     $booking->audit('booking', $reschedule ? 'reschedule' : 'create');
     $this->latest_booking_id = $booking->id;
     $this->comments = $operation_comments;
     $this->comments_rtt = $operation_comments_rtt;
     $this->site_id = $booking->session->theatre->site_id;
     if ($reschedule) {
         $this->setStatus('Rescheduled', false);
     } else {
         $this->setStatus('Scheduled', false);
         // Lock the RTT for this operation booking
         if ($ref = $this->referral) {
             if ($active = $ref->getActiveRTT()) {
                 if (count($active) == 1) {
                     $this->rtt_id = $active[0]->id;
                 }
             }
         }
     }
     if (!$this->save()) {
         throw new Exception('Unable to update operation data: ' . print_r($this->getErrors(), true));
     }
     $session->comments = $session_comments;
     if (!$session->save()) {
         throw new Exception('Unable to save session comments: ' . print_r($session->getErrors(), true));
     }
     // if the session has no firm, this implies it's an emergency booking so there is no need to calculate EROD
     if ($booking->session->firm && ($erod = $this->calculateEROD($booking->session->firm))) {
         $erod->booking_id = $booking->id;
         if (!$erod->save()) {
             throw new Exception('Unable to save erod: ' . print_r($erod->getErrors(), true));
         }
     }
     $this->event->episode->episode_status_id = 3;
     if (!$this->event->episode->save()) {
         throw new Exception('Unable to change episode status id for episode ' . $this->event->episode->id);
     }
     $this->event->deleteIssues();
     if (Yii::app()->params['urgent_booking_notify_hours'] && Yii::app()->params['urgent_booking_notify_email']) {
         if (strtotime($session->date) <= strtotime(date('Y-m-d')) + Yii::app()->params['urgent_booking_notify_hours'] * 3600) {
             if (!is_array(Yii::app()->params['urgent_booking_notify_email'])) {
                 $targets = array(Yii::app()->params['urgent_booking_notify_email']);
             } else {
                 $targets = Yii::app()->params['urgent_booking_notify_email'];
             }
             if ($reschedule) {
                 $subject = '[OpenEyes] Urgent reschedule made';
                 $body = "A patient booking was rescheduled with a TCI date within the next 24 hours.\n\nDisorder: " . $this->getDisorderText() . "\n\nPlease see: http://" . @$_SERVER['SERVER_NAME'] . "/transport\n\nIf you need any assistance you can reply to this email and one of the OpenEyes support personnel will respond.";
             } else {
                 $subject = '[OpenEyes] Urgent booking made';
                 $body = "A patient booking was made with a TCI date within the next 24 hours.\n\nDisorder: " . $this->getDisorderText() . "\n\nPlease see: http://" . @$_SERVER['SERVER_NAME'] . "/transport\n\nIf you need any assistance you can reply to this email and one of the OpenEyes support personnel will respond.";
             }
             $from = Yii::app()->params['urgent_booking_notify_email_from'];
             foreach ($targets as $email) {
                 if (!Mailer::mail($email, $subject, $body, $from)) {
                     Yii::app()->user->setFlash('warning.email-failure', 'E-mail Failure. Failed to send one or more urgent booking notification E-mails.');
                 }
             }
         }
     }
     return true;
 }