Esempio n. 1
0
 /**
  * Get appointments for FullCalendar.
  *
  * @param DateTime $start_date
  * @param DateTime $end_date
  *
  * @return array
  */
 public function getAppointmentsForFC(DateTime $start_date, DateTime $end_date)
 {
     if (!$this->isLoaded()) {
         return array();
     }
     $appointments = AB_Appointment::query('a')->select('a.id, a.start_date, a.end_date,
                 s.title AS service_title, s.color AS service_color,
                 ss.capacity AS max_capacity,
                 SUM(ca.number_of_persons) AS total_number_of_persons, ca.custom_fields,
                 c.name AS customer_name, c.phone AS customer_phone, c.email AS customer_email')->leftJoin('AB_CustomerAppointment', 'ca', 'ca.appointment_id = a.id')->leftJoin('AB_Customer', 'c', 'c.id = ca.customer_id')->leftJoin('AB_Service', 's', 's.id = a.service_id')->leftJoin('AB_Staff', 'st', 'st.id = a.staff_id')->leftJoin('AB_StaffService', 'ss', 'ss.staff_id = a.staff_id AND ss.service_id = a.service_id')->where('st.id', $this->get('id'))->whereBetween('DATE(a.start_date)', $start_date->format('Y-m-d'), $end_date->format('Y-m-d'))->groupBy('a.start_date')->fetchArray();
     foreach ($appointments as $key => $appointment) {
         $desc = array();
         if ($appointment['max_capacity'] == 1) {
             foreach (array('customer_name', 'customer_phone', 'customer_email') as $data_entry) {
                 if ($appointment[$data_entry]) {
                     $desc[] = '<div class="fc-employee">' . esc_html($appointment[$data_entry]) . '</div>';
                 }
             }
             $ca = new AB_CustomerAppointment();
             $ca->set('custom_fields', $appointment['custom_fields']);
             foreach ($ca->getCustomFields() as $custom_field) {
                 $desc[] = sprintf('<div class="fc-notes">%s : %s</div>', wp_strip_all_tags($custom_field['label']), esc_html($custom_field['value']));
             }
         } else {
             $desc[] = sprintf('<div class="fc-notes">%s %s</div>', __('Signed up', 'bookly'), $appointment['total_number_of_persons']);
             $desc[] = sprintf('<div class="fc-notes">%s %s</div>', __('Capacity', 'bookly'), $appointment['max_capacity']);
         }
         $appointments[$key] = array('id' => $appointment['id'], 'start' => $appointment['start_date'], 'end' => $appointment['end_date'], 'title' => $appointment['service_title'] ? esc_html($appointment['service_title']) : __('Untitled', 'bookly'), 'desc' => implode('', $desc), 'color' => $appointment['service_color'], 'staffId' => $this->get('id'));
     }
     return $appointments;
 }
 /**
  * Do AIM payment.
  */
 public function executeAuthorizeNetAIM()
 {
     include_once AB_PATH . '/lib/payment/authorize.net/autoload.php';
     $response = null;
     $userData = new AB_UserBookingData($this->getParameter('form_id'));
     if ($userData->load()) {
         define("AUTHORIZENET_API_LOGIN_ID", get_option('ab_authorizenet_api_login_id'));
         define("AUTHORIZENET_TRANSACTION_KEY", get_option('ab_authorizenet_transaction_key'));
         define("AUTHORIZENET_SANDBOX", (bool) get_option('ab_authorizenet_sandbox'));
         $price = $userData->getFinalServicePrice() * $userData->get('number_of_persons');
         $sale = new AuthorizeNetAIM();
         $sale->amount = $price;
         $sale->card_num = $this->getParameter('ab_card_number');
         $sale->card_code = $this->getParameter('ab_card_code');
         $sale->exp_date = $this->getParameter('ab_card_month') . '/' . $this->getParameter('ab_card_year');
         $sale->first_name = $userData->get('name');
         $sale->email = $userData->get('email');
         $sale->phone = $userData->get('phone');
         $response = $sale->authorizeAndCapture();
         if ($response->approved) {
             /** @var AB_Appointment $appointment */
             $appointment = $userData->save();
             $customer_appointment = new AB_CustomerAppointment();
             $customer_appointment->loadBy(array('appointment_id' => $appointment->get('id'), 'customer_id' => $userData->getCustomerId()));
             $payment = new AB_Payment();
             $payment->set('total', $price);
             $payment->set('type', 'authorizeNet');
             $payment->set('customer_appointment_id', $customer_appointment->get('id'));
             $payment->set('created', current_time('mysql'));
             $payment->save();
             $response = array('state' => 'success');
         } else {
             $response = array('status' => 'error', 'error' => $response->response_reason_text);
         }
     } else {
         $response = array('status' => 'error', 'error' => __('Session error.', 'bookly'));
     }
     wp_send_json($response);
 }
Esempio n. 3
0
 public function executeStripe()
 {
     $response = null;
     $userData = new AB_UserBookingData($this->getParameter('form_id'));
     if ($userData->load()) {
         if ($userData->get('service_id')) {
             Stripe::setApiKey(get_option('ab_stripe_secret_key'));
             Stripe::setApiVersion("2014-10-07");
             $price = $userData->getFinalServicePrice() * $userData->get('number_of_persons');
             $stripe_data = array('number' => $this->getParameter('ab_card_number'), 'exp_month' => $this->getParameter('ab_card_month'), 'exp_year' => $this->getParameter('ab_card_year'), 'cvc' => $this->getParameter('ab_card_code'));
             try {
                 $charge = Stripe_Charge::create(array('card' => $stripe_data, 'amount' => intval($price * 100), 'currency' => get_option('ab_paypal_currency'), 'description' => "Charge for " . $userData->get('email')));
                 if ($charge->paid) {
                     $appointment = $userData->save();
                     $customer_appointment = new AB_CustomerAppointment();
                     $customer_appointment->loadBy(array('appointment_id' => $appointment->get('id'), 'customer_id' => $userData->getCustomerId()));
                     $payment = new AB_Payment();
                     $payment->set('total', $price);
                     $payment->set('type', 'stripe');
                     $payment->set('customer_appointment_id', $customer_appointment->get('id'));
                     $payment->set('created', current_time('mysql'));
                     $payment->save();
                     $response = array('status' => 'success');
                 } else {
                     $response = array('status' => 'error', 'error' => 'unknown error');
                 }
             } catch (Exception $e) {
                 $response = array('status' => 'error', 'error' => $e->getMessage());
             }
         }
     } else {
         $response = array('status' => 'error', 'error' => __('Session error.', 'bookly'));
     }
     // Output JSON response.
     wp_send_json($response);
 }
Esempio n. 4
0
 /**
  * Get array with appointments data for customer profile.
  *
  * @return array
  */
 public function getAppointmentsForProfile()
 {
     $records = array();
     if ($this->get('id')) {
         $result = $this->wpdb->get_results($this->wpdb->prepare('SELECT `c`.`name`               `category`,
                     `sv`.`title`             `service`,
                     `s`.`full_name`          `staff`,
                     `a`.`start_date`         `start_date`,
                     `ss`.`price`             `price`,
                     `ca`.`number_of_persons` `number_of_persons`,
                     `ca`.`coupon_discount`   `coupon_discount`,
                     `ca`.`coupon_deduction`  `coupon_deduction`,
                     `ca`.`time_zone_offset`  `time_zone_offset`,
                     `ca`.`token`             `token`
              FROM `' . AB_Appointment::getTableName() . '` `a`
              LEFT JOIN `' . AB_Staff::getTableName() . '` `s` ON `s`.`id` = `a`.`staff_id`
              LEFT JOIN `' . AB_Service::getTableName() . '` `sv` ON `sv`.`id` = `a`.`service_id`
              LEFT JOIN `' . AB_Category::getTableName() . '` `c` ON `c`.`id` = `sv`.`category_id`
              LEFT JOIN `' . AB_StaffService::getTableName() . '` `ss` ON `ss`.`staff_id` = `a`.`staff_id` AND `ss`.`service_id` = `a`.`service_id`
              INNER JOIN `' . AB_CustomerAppointment::getTableName() . '` `ca` ON `ca`.`appointment_id` = `a`.`id` AND `ca`.`customer_id` = %d', $this->get('id')), ARRAY_A);
         if ($result) {
             foreach ($result as $row) {
                 if ($row['time_zone_offset'] !== null) {
                     $row['start_date'] = AB_DateTimeUtils::applyTimeZoneOffset($row['start_date'], $row['time_zone_offset']);
                 }
                 if ($row['coupon_discount'] or $row['coupon_deduction']) {
                     $coupon = new AB_Coupon();
                     $coupon->set('discount', $row['coupon_discount']);
                     $coupon->set('deduction', $row['coupon_deduction']);
                     $row['price'] = $coupon->apply($row['price']);
                 }
                 $row['price'] *= $row['number_of_persons'];
                 unset($row['time_zone_offset'], $row['coupon_discount'], $row['coupon_deduction'], $row['number_of_persons']);
                 $records[] = $row;
             }
         }
     }
     return $records;
 }
 /**
  * Export Appointment to CSV
  */
 public function executeExportToCSV()
 {
     $start_date = new DateTime($this->getParameter('date_start'));
     $start_date = $start_date->format('Y-m-d H:i:s');
     $end_date = new DateTime($this->getParameter('date_end'));
     $end_date = $end_date->modify('+1 day')->format('Y-m-d H:i:s');
     $delimiter = $this->getParameter('delimiter', ',');
     header('Content-Type: text/csv; charset=utf-8');
     header('Content-Disposition: attachment; filename=Appointments.csv');
     $header = array(__('Booking Time', 'bookly'), __('Staff Member', 'bookly'), __('Service', 'bookly'), __('Duration', 'bookly'), __('Price', 'bookly'), __('Customer', 'bookly'), __('Phone', 'bookly'), __('Email', 'bookly'));
     $custom_fields = array();
     $fields_data = json_decode(get_option('ab_custom_fields'));
     foreach ($fields_data as $field_data) {
         $custom_fields[$field_data->id] = '';
         $header[] = $field_data->label;
     }
     $output = fopen('php://output', 'w');
     fwrite($output, pack("CCC", 0xef, 0xbb, 0xbf));
     fputcsv($output, $header, $delimiter);
     $rows = AB_CustomerAppointment::query()->select('r.id,
            r.number_of_persons,
            r.coupon_discount,
            r.coupon_deduction,
            st.full_name  AS staff_name,
            s.title       AS service_title,
            s.duration    AS service_duration,
            c.name        AS customer_name,
            c.phone       AS customer_phone,
            c.email       AS customer_email,
            ss.price,
            a.start_date')->leftJoin('AB_Appointment', 'a', 'a.id = r.appointment_id')->leftJoin('AB_Service', 's', 's.id = a.service_id')->leftJoin('AB_Staff', 'st', 'st.id = a.staff_id')->leftJoin('AB_Customer', 'c', 'c.id = r.customer_id')->leftJoin('AB_StaffService', 'ss', 'ss.staff_id = st.id AND ss.service_id = s.id')->whereBetween('a.start_date', $start_date, $end_date)->sortBy('a.start_date')->order(AB_Query::ORDER_DESCENDING)->fetchArray();
     foreach ($rows as $row) {
         if ($row['coupon_discount'] or $row['coupon_deduction']) {
             $coupon = new AB_Coupon();
             $coupon->set('discount', $row['coupon_discount']);
             $coupon->set('deduction', $row['coupon_deduction']);
             $row['price'] = $coupon->apply($row['price']);
         }
         $row['price'] *= $row['number_of_persons'];
         $row_data = array($row['start_date'], $row['staff_name'], $row['service_title'], AB_Service::durationToString($row['service_duration']), AB_Utils::formatPrice($row['price']), $row['customer_name'], $row['customer_phone'], $row['customer_email']);
         $customer_appointment = new AB_CustomerAppointment();
         $customer_appointment->load($row['id']);
         foreach ($customer_appointment->getCustomFields() as $custom_field) {
             $custom_fields[$custom_field['id']] = $custom_field['value'];
         }
         fputcsv($output, array_merge($row_data, $custom_fields), $delimiter);
         $custom_fields = array_map(function () {
             return '';
         }, $custom_fields);
     }
     fclose($output);
     exit;
 }
 /**
  * @param AB_Notification $notification
  */
 public function processNotification(AB_Notification $notification)
 {
     /** @var $wpdb wpdb */
     global $wpdb;
     $date = new DateTime();
     switch ($notification->get('type')) {
         case 'staff_agenda':
             if ($date->format('H') >= 18) {
                 $rows = $wpdb->get_results('SELECT
                         `a`.*,
                         `c`.`name`       AS `customer_name`,
                         `s`.`title`      AS `service_title`,
                         `st`.`email`     AS `staff_email`,
                         `st`.`phone`     AS `staff_phone`,
                         `st`.`full_name` AS `staff_name`
                     FROM `' . AB_CustomerAppointment::getTableName() . '` `ca`
                     LEFT JOIN `' . AB_Appointment::getTableName() . '` `a`   ON `a`.`id` = `ca`.`appointment_id`
                     LEFT JOIN `' . AB_Customer::getTableName() . '` `c`      ON `c`.`id` = `ca`.`customer_id`
                     LEFT JOIN `' . AB_Service::getTableName() . '` `s`       ON `s`.`id` = `a`.`service_id`
                     LEFT JOIN `' . AB_Staff::getTableName() . '` `st`        ON `st`.`id` = `a`.`staff_id`
                     LEFT JOIN `' . AB_StaffService::getTableName() . '` `ss` ON `ss`.`staff_id` = `a`.`staff_id` AND `ss`.`service_id` = `a`.`service_id`
                     WHERE DATE(DATE_ADD("' . $this->mysql_now . '", INTERVAL 1 DAY)) = DATE(`a`.`start_date`) AND NOT EXISTS (
                         SELECT * FROM `' . AB_SentNotification::getTableName() . '` `sn` WHERE
                             DATE(`sn`.`created`) = DATE("' . $this->mysql_now . '") AND
                             `sn`.`gateway`       = "' . $notification->get('gateway') . '" AND
                             `sn`.`type`          = "staff_agenda" AND
                             `sn`.`staff_id`      = `a`.`staff_id`
                     )');
                 if ($rows) {
                     $appointments = array();
                     foreach ($rows as $row) {
                         $appointments[$row->staff_id][] = $row;
                     }
                     foreach ($appointments as $staff_id => $collection) {
                         $sent = false;
                         $staff_email = null;
                         $staff_phone = null;
                         $table = $notification->get('gateway') == 'email' ? '<table>%s</table>' : '%s';
                         $tr = $notification->get('gateway') == 'email' ? '<tr><td>%s</td><td>%s</td><td>%s</td></tr>' : "%s %s %s\n";
                         $agenda = '';
                         foreach ($collection as $appointment) {
                             $startDate = new DateTime($appointment->start_date);
                             $endDate = new DateTime($appointment->end_date);
                             $agenda .= sprintf($tr, $startDate->format('H:i') . '-' . $endDate->format('H:i'), $appointment->service_title, $appointment->customer_name);
                             $staff_email = $appointment->staff_email;
                             $staff_phone = $appointment->staff_phone;
                         }
                         $agenda = sprintf($table, $agenda);
                         if ($staff_email || $staff_phone) {
                             $replacement = new AB_NotificationCodes();
                             $replacement->set('next_day_agenda', $agenda);
                             $replacement->set('appointment_datetime', $appointment->start_date);
                             $replacement->set('staff_name', $appointment->staff_name);
                             if ($notification->get('gateway') == 'email' && $staff_email) {
                                 $message = $replacement->replace($notification->get('message'));
                                 $subject = $replacement->replace($notification->get('subject'));
                                 // Send email.
                                 $sent = wp_mail($staff_email, $subject, wpautop($message), AB_Utils::getEmailHeaders());
                             } else {
                                 if ($notification->get('gateway') == 'sms' && $staff_phone) {
                                     $message = $replacement->replace($notification->get('message'), $notification->get('gateway'));
                                     // Send sms.
                                     $sent = $this->sms->sendSms($staff_phone, $message);
                                 }
                             }
                         }
                         if ($sent) {
                             $sent_notification = new AB_SentNotification();
                             $sent_notification->set('staff_id', $staff_id);
                             $sent_notification->set('gateway', $notification->get('gateway'));
                             $sent_notification->set('type', 'staff_agenda');
                             $sent_notification->set('created', $date->format('Y-m-d H:i:s'));
                             $sent_notification->save();
                         }
                     }
                 }
             }
             break;
         case 'client_follow_up':
             if ($date->format('H') >= 21) {
                 $rows = $wpdb->get_results('SELECT
                         `a`.*,
                         `ca`.*
                     FROM `' . AB_CustomerAppointment::getTableName() . '` `ca`
                     LEFT JOIN `' . AB_Appointment::getTableName() . '` `a` ON `a`.`id` = `ca`.`appointment_id`
                     WHERE DATE("' . $this->mysql_now . '") = DATE(`a`.`start_date`) AND NOT EXISTS (
                         SELECT * FROM `' . AB_SentNotification::getTableName() . '` `sn` WHERE
                             DATE(`sn`.`created`)           = DATE("' . $this->mysql_now . '") AND
                             `sn`.`gateway`                 = "' . $notification->get('gateway') . '" AND
                             `sn`.`type`                    = "client_follow_up" AND
                             `sn`.`customer_appointment_id` = `ca`.`id`
                     )', ARRAY_A);
                 if ($rows) {
                     foreach ($rows as $row) {
                         $customer_appointment = new AB_CustomerAppointment();
                         $customer_appointment->load($row['id']);
                         if (AB_NotificationSender::sendFromCron(AB_NotificationSender::CRON_FOLLOW_UP_EMAIL, $notification, $customer_appointment)) {
                             $sent_notification = new AB_SentNotification();
                             $sent_notification->set('customer_appointment_id', $customer_appointment->get('id'));
                             $sent_notification->set('gateway', $notification->get('gateway'));
                             $sent_notification->set('type', 'client_follow_up');
                             $sent_notification->set('created', $date->format('Y-m-d H:i:s'));
                             $sent_notification->save();
                         }
                     }
                 }
             }
             break;
         case 'client_reminder':
             if ($date->format('H') >= 18) {
                 $rows = $wpdb->get_results('SELECT
                         `ca`.`id`
                     FROM `' . AB_CustomerAppointment::getTableName() . '` `ca`
                     LEFT JOIN `' . AB_Appointment::getTableName() . '` `a` ON `a`.`id` = `ca`.`appointment_id`
                     WHERE DATE(DATE_ADD("' . $this->mysql_now . '", INTERVAL 1 DAY)) = DATE(`a`.`start_date`) AND NOT EXISTS (
                         SELECT * FROM `' . AB_SentNotification::getTableName() . '` `sn` WHERE
                             DATE(`sn`.`created`)           = DATE("' . $this->mysql_now . '") AND
                             `sn`.`gateway`                 = "' . $notification->get('gateway') . '" AND
                             `sn`.`type`                    = "client_reminder" AND
                             `sn`.`customer_appointment_id` = `ca`.`id`
                     )', ARRAY_A);
                 if ($rows) {
                     foreach ($rows as $row) {
                         $customer_appointment = new AB_CustomerAppointment();
                         $customer_appointment->load($row['id']);
                         if (AB_NotificationSender::sendFromCron(AB_NotificationSender::CRON_NEXT_DAY_APPOINTMENT, $notification, $customer_appointment)) {
                             $sent_notification = new AB_SentNotification();
                             $sent_notification->set('customer_appointment_id', $customer_appointment->get('id'));
                             $sent_notification->set('gateway', $notification->get('gateway'));
                             $sent_notification->set('type', 'client_reminder');
                             $sent_notification->set('created', $date->format('Y-m-d H:i:s'));
                             $sent_notification->save();
                         }
                     }
                 }
             }
             break;
     }
 }
Esempio n. 7
0
 /**
  * Set array of customers associated with this appointment.
  *
  * @param array $data  Array of customer IDs, custom_fields and number_of_persons
  */
 public function setCustomers(array $data)
 {
     // Prepare array of customers.
     $customers = array();
     foreach ($data as $customer) {
         $customers[$customer['id']] = $customer;
     }
     // Retrieve customer IDs currently associated with this appointment.
     $current_ids = array_map(function ($ca) {
         return $ca->customer->get('id');
     }, $this->getCustomerAppointments());
     // Remove redundant customers.
     $customer_appointment = new AB_CustomerAppointment();
     foreach (array_diff($current_ids, array_keys($customers)) as $id) {
         if ($customer_appointment->loadBy(array('appointment_id' => $this->get('id'), 'customer_id' => $id))) {
             $customer_appointment->delete();
         }
     }
     // Add new customers.
     foreach (array_diff(array_keys($customers), $current_ids) as $id) {
         $customer_appointment = new AB_CustomerAppointment();
         $customer_appointment->set('appointment_id', $this->get('id'));
         $customer_appointment->set('customer_id', $id);
         $customer_appointment->set('custom_fields', json_encode($customers[$id]['custom_fields']));
         $customer_appointment->set('number_of_persons', $customers[$id]['number_of_persons']);
         $customer_appointment->save();
     }
     // Update existing customers.
     foreach (array_intersect($current_ids, array_keys($customers)) as $id) {
         $customer_appointment = new AB_CustomerAppointment();
         $customer_appointment->loadBy(array('appointment_id' => $this->get('id'), 'customer_id' => $id));
         $customer_appointment->set('custom_fields', json_encode($customers[$id]['custom_fields']));
         $customer_appointment->set('number_of_persons', $customers[$id]['number_of_persons']);
         $customer_appointment->save();
     }
 }
Esempio n. 8
0
 /**
  * Save all data and create appointment.
  *
  * @return AB_Appointment
  */
 public function save()
 {
     $user_id = get_current_user_id();
     $customer = new AB_Customer();
     if ($user_id) {
         // Try to find customer by WP user ID.
         $customer->loadBy(array('wp_user_id' => $user_id));
     }
     if (!$customer->isLoaded()) {
         // If customer with such name & e-mail exists, append new booking to him, otherwise - create new customer
         $customer->loadBy(array('name' => $this->get('name'), 'email' => $this->get('email')));
     }
     $customer->set('name', $this->get('name'));
     $customer->set('email', $this->get('email'));
     $customer->set('phone', $this->get('phone'));
     if (get_option('ab_settings_create_account', 0) && !$customer->get('wp_user_id')) {
         // Create WP user and link it to customer.
         $customer->setWPUser($user_id ?: null);
     }
     $customer->save();
     $this->customer_id = $customer->get('id');
     $service = $this->getService();
     /**
      * Get appointment, with same params.
      * If it is -> create connection to this appointment,
      * otherwise create appointment and connect customer to new appointment
      */
     $appointment = new AB_Appointment();
     $appointment->loadBy(array('staff_id' => $this->getStaffId(), 'service_id' => $this->get('service_id'), 'start_date' => $this->get('appointment_datetime')));
     if ($appointment->isLoaded() == false) {
         $appointment->set('staff_id', $this->getStaffId());
         $appointment->set('service_id', $this->get('service_id'));
         $appointment->set('start_date', $this->get('appointment_datetime'));
         $endDate = new DateTime($this->get('appointment_datetime'));
         $di = "+ {$service->get('duration')} sec";
         $endDate->modify($di);
         $appointment->set('end_date', $endDate->format('Y-m-d H:i:s'));
         $appointment->save();
     }
     $customer_appointment = new AB_CustomerAppointment();
     $customer_appointment->loadBy(array('customer_id' => $customer->get('id'), 'appointment_id' => $appointment->get('id')));
     if ($customer_appointment->isLoaded()) {
         // Add number of persons to existing booking.
         $customer_appointment->set('number_of_persons', $customer_appointment->get('number_of_persons') + $this->get('number_of_persons'));
     } else {
         $customer_appointment->set('customer_id', $customer->get('id'));
         $customer_appointment->set('appointment_id', $appointment->get('id'));
         $customer_appointment->set('number_of_persons', $this->get('number_of_persons'));
     }
     $customer_appointment->set('custom_fields', $this->get('custom_fields'));
     $customer_appointment->set('time_zone_offset', $this->get('time_zone_offset'));
     $coupon = $this->getCoupon();
     if ($coupon) {
         $customer_appointment->set('coupon_code', $coupon->get('code'));
         $customer_appointment->set('coupon_discount', $coupon->get('discount'));
         $customer_appointment->set('coupon_deduction', $coupon->get('deduction'));
         $coupon->claim();
         $coupon->save();
     }
     $customer_appointment->save();
     // Create fake payment record for 100% discount coupons.
     if ($coupon && $coupon->get('discount') == '100') {
         $payment = new AB_Payment();
         $payment->set('total', '0.00');
         $payment->set('type', 'coupon');
         $payment->set('created', current_time('mysql'));
         $payment->set('customer_appointment_id', $customer_appointment->get('id'));
         $payment->save();
     }
     // Google Calendar.
     $appointment->handleGoogleCalendar();
     // Send email notifications.
     AB_NotificationSender::send(AB_NotificationSender::INSTANT_NEW_APPOINTMENT, $customer_appointment);
     return $appointment;
 }
Esempio n. 9
0
 /**
  * Cancel Appointment using token.
  */
 public function executeCancelAppointment()
 {
     $customer_appointment = new AB_CustomerAppointment();
     if ($customer_appointment->loadBy(array('token' => $this->getParameter('token')))) {
         // Send email.
         AB_NotificationSender::send(AB_NotificationSender::INSTANT_CANCELLED_APPOINTMENT, $customer_appointment);
         $customer_appointment->delete();
         $appointment = new AB_Appointment();
         $appointment->load($customer_appointment->get('appointment_id'));
         // Delete appointment, if there aren't customers.
         $count = AB_CustomerAppointment::query('ca')->where('ca.appointment_id', $customer_appointment->get('appointment_id'))->count();
         if (!$count) {
             $appointment->delete();
         } else {
             $appointment->handleGoogleCalendar();
         }
         if ($this->url = get_option('ab_settings_cancel_page_url')) {
             wp_redirect($this->url);
             $this->render('cancel_appointment');
             exit(0);
         }
     }
     $this->url = home_url();
     if (isset($_SERVER['HTTP_REFERER'])) {
         if (parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST) == parse_url($this->url, PHP_URL_HOST)) {
             // Redirect back if user came from our site.
             $this->url = $_SERVER['HTTP_REFERER'];
         }
     }
     wp_redirect($this->url);
     $this->render('cancel_appointment');
     exit(0);
 }
Esempio n. 10
0
 /**
  * Prepare data for email.
  *
  * @param AB_CustomerAppointment $ca
  * @return array
  */
 private static function _prepareData(AB_CustomerAppointment $ca)
 {
     $appointment = new AB_Appointment();
     $appointment->load($ca->get('appointment_id'));
     $customer = new AB_Customer();
     $customer->load($ca->get('customer_id'));
     $staff = new AB_Staff();
     $staff->load($appointment->get('staff_id'));
     $service = new AB_Service();
     $service->load($appointment->get('service_id'));
     $staff_service = new AB_StaffService();
     $staff_service->loadBy(array('staff_id' => $staff->get('id'), 'service_id' => $service->get('id')));
     $price = $staff_service->get('price');
     if ($ca->get('coupon_discount') or $ca->get('coupon_deduction')) {
         $coupon = new AB_Coupon();
         $coupon->set('discount', $ca->get('coupon_discount'));
         $coupon->set('deduction', $ca->get('coupon_deduction'));
         $price = $coupon->apply($price);
     }
     $codes = new AB_NotificationCodes();
     $codes->set('appointment_datetime', $appointment->get('start_date'));
     $codes->set('appointment_token', $ca->get('token'));
     $codes->set('category_name', $service->getCategoryName());
     $codes->set('client_name', $customer->get('name'));
     $codes->set('client_phone', $customer->get('phone'));
     $codes->set('client_email', $customer->get('email'));
     $codes->set('custom_fields', $ca->getFormattedCustomFields('text'));
     $codes->set('custom_fields_2c', $ca->getFormattedCustomFields('html'));
     $codes->set('number_of_persons', $ca->get('number_of_persons'));
     $codes->set('service_name', $service->getTitle());
     $codes->set('service_price', $price);
     $codes->set('staff_name', $staff->get('full_name'));
     $codes->set('staff_email', $staff->get('email'));
     $codes->set('staff_phone', $staff->get('phone'));
     $codes->set('staff_photo', $staff->get('avatar_url'));
     return array($codes, $staff, $appointment, $customer);
 }
Esempio n. 11
0
 /**
  * Process the Express Checkout RETURNURL
  */
 public function paypalResponseSuccess()
 {
     $form_id = $_GET['ab_fid'];
     $paypal = new AB_PayPal();
     if (isset($_GET["token"]) && isset($_GET["PayerID"])) {
         $token = $_GET["token"];
         $payer_id = $_GET["PayerID"];
         // send the request to PayPal
         $response = $paypal->sendNvpRequest('GetExpressCheckoutDetails', sprintf('&TOKEN=%s', $token));
         if (strtoupper($response["ACK"]) == "SUCCESS") {
             $data = sprintf('&TOKEN=%s&PAYERID=%s&PAYMENTREQUEST_0_PAYMENTACTION=Sale', $token, $payer_id);
             // response keys containing useful data to send via DoExpressCheckoutPayment operation
             $response_data_keys_pattern = sprintf('/^(%s)/', implode('|', array('PAYMENTREQUEST_0_AMT', 'PAYMENTREQUEST_0_ITEMAMT', 'PAYMENTREQUEST_0_CURRENCYCODE', 'L_PAYMENTREQUEST_0')));
             foreach ($response as $key => $value) {
                 // collect product data from response using defined response keys
                 if (preg_match($response_data_keys_pattern, $key)) {
                     $data .= sprintf('&%s=%s', $key, $value);
                 }
             }
             //We need to execute the "DoExpressCheckoutPayment" at this point to Receive payment from user.
             $response = $paypal->sendNvpRequest('DoExpressCheckoutPayment', $data);
             if ("SUCCESS" == strtoupper($response["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($response["ACK"])) {
                 // get transaction info
                 $response = $paypal->sendNvpRequest('GetTransactionDetails', "&TRANSACTIONID=" . urlencode($response["PAYMENTINFO_0_TRANSACTIONID"]));
                 if ("SUCCESS" == strtoupper($response["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($response["ACK"])) {
                     // need session to get Total and Token
                     $token = $_SESSION['bookly'][$form_id]['paypal_response'][0]['TOKEN'];
                     $userData = new AB_UserBookingData($form_id);
                     $userData->load();
                     if ($userData->get('service_id')) {
                         $appointment = $userData->save();
                         $customer_appointment = new AB_CustomerAppointment();
                         $customer_appointment->loadBy(array('appointment_id' => $appointment->get('id'), 'customer_id' => $userData->getCustomerId()));
                         $payment = new AB_Payment();
                         $payment->set('token', urldecode($token));
                         $payment->set('total', $userData->getFinalServicePrice() * $userData->get('number_of_persons'));
                         $payment->set('customer_appointment_id', $customer_appointment->get('id'));
                         $payment->set('transaction', urlencode($response["TRANSACTIONID"]));
                         $payment->set('created', current_time('mysql'));
                         $payment->save();
                         $userData->setPayPalStatus('success');
                     }
                     @wp_redirect(remove_query_arg(array('action', 'token', 'PayerID', 'ab_fid'), AB_Utils::getCurrentPageURL()));
                     exit(0);
                 } else {
                     header('Location: ' . wp_sanitize_redirect(add_query_arg(array('action' => 'ab-paypal-errorurl', 'ab_fid' => $form_id, 'error_msg' => $response["L_LONGMESSAGE0"]), AB_Utils::getCurrentPageURL())));
                     exit;
                 }
             } else {
                 header('Location: ' . wp_sanitize_redirect(add_query_arg(array('action' => 'ab-paypal-errorurl', 'ab_fid' => $form_id, 'error_msg' => $response["L_LONGMESSAGE0"]), AB_Utils::getCurrentPageURL())));
                 exit;
             }
         } else {
             header('Location: ' . wp_sanitize_redirect(add_query_arg(array('action' => 'ab-paypal-errorurl', 'ab_fid' => $form_id, 'error_msg' => 'Invalid token provided'), AB_Utils::getCurrentPageURL())));
             exit;
         }
     } else {
         throw new Exception('Token parameter not found!');
     }
 }
Esempio n. 12
0
 function update_7_0()
 {
     global $wpdb;
     $wpdb->query('ALTER TABLE `ab_customer_appointment` ADD `coupon_deduction` DECIMAL(10,2) DEFAULT NULL AFTER `coupon_discount`');
     $wpdb->query('ALTER TABLE `ab_coupons` CHANGE COLUMN `used` `used` INT UNSIGNED NOT NULL DEFAULT 0,
                    ADD COLUMN `deduction` DECIMAL(10,2) NOT NULL DEFAULT 0 AFTER `discount`,
                    ADD COLUMN `usage_limit` INT UNSIGNED NOT NULL DEFAULT 1');
     $wpdb->query('ALTER TABLE `ab_notifications` CHANGE `slug` `type` VARCHAR(255) NOT NULL DEFAULT ""');
     // SMS.
     $wpdb->query('ALTER TABLE `ab_notifications` ADD `gateway` ENUM("email","sms") NOT NULL DEFAULT "email"');
     $wpdb->query('UPDATE `ab_notifications` SET `gateway` = "email"');
     $sms_notifies = array(array('type' => 'client_new_appointment', 'message' => __("Dear [[CLIENT_NAME]].\nThis is confirmation that you have booked [[SERVICE_NAME]].\nWe are waiting you at [[COMPANY_ADDRESS]] on [[APPOINTMENT_DATE]] at [[APPOINTMENT_TIME]].\nThank you for choosing our company.\n[[COMPANY_NAME]]\n[[COMPANY_PHONE]]\n[[COMPANY_WEBSITE]]", 'bookly'), 'active' => 1), array('type' => 'staff_new_appointment', 'message' => __("Hello.\nYou have new booking.\nService: [[SERVICE_NAME]]\nDate: [[APPOINTMENT_DATE]]\nTime: [[APPOINTMENT_TIME]]\nClient name: [[CLIENT_NAME]]\nClient phone: [[CLIENT_PHONE]]\nClient email: [[CLIENT_EMAIL]]", 'bookly'), 'active' => 0), array('type' => 'client_reminder', 'message' => __("Dear [[CLIENT_NAME]].\nWe would like to remind you that you have booked [[SERVICE_NAME]] tomorrow on [[APPOINTMENT_TIME]]. We are waiting you at [[COMPANY_ADDRESS]].\nThank you for choosing our company.\n[[COMPANY_NAME]]\n[[COMPANY_PHONE]]\n[[COMPANY_WEBSITE]]", 'bookly'), 'active' => 0), array('type' => 'client_follow_up', 'message' => __("Dear [[CLIENT_NAME]].\nThank you for choosing [[COMPANY_NAME]]. We hope you were satisfied with your [[SERVICE_NAME]].\nThank you and we look forward to seeing you again soon.\n[[COMPANY_NAME]]\n[[COMPANY_PHONE]]\n[[COMPANY_WEBSITE]]", 'bookly'), 'active' => 0), array('type' => 'staff_agenda', 'message' => __("Hello.\nYour agenda for tomorrow is:\n[[NEXT_DAY_AGENDA]]", 'bookly'), 'active' => 0), array('type' => 'staff_cancelled_appointment', 'message' => __("Hello.\nThe following booking has been cancelled.\nService: [[SERVICE_NAME]]\nDate: [[APPOINTMENT_DATE]]\nTime: [[APPOINTMENT_TIME]]\nClient name: [[CLIENT_NAME]]\nClient phone: [[CLIENT_PHONE]]\nClient email: [[CLIENT_EMAIL]]", 'bookly'), 'active' => 0), array('type' => 'client_new_wp_user', 'message' => __("Hello.\nAn account was created for you at [[SITE_ADDRESS]]\nYour user details:\nuser: [[NEW_USERNAME]]\npassword: [[NEW_PASSWORD]]\n\nThanks.", 'bookly'), 'active' => 1));
     // Insert notifications.
     foreach ($sms_notifies as $data) {
         $wpdb->insert('ab_notifications', array('gateway' => 'sms', 'type' => $data['type'], 'subject' => '', 'message' => $data['message'], 'active' => $data['active']));
     }
     // Rename notifications.
     $notifications = array('client_info' => 'client_new_appointment', 'provider_info' => 'staff_new_appointment', 'evening_next_day' => 'client_reminder', 'evening_after' => 'client_follow_up', 'event_next_day' => 'staff_agenda', 'cancel_appointment' => 'staff_cancelled_appointment', 'new_wp_user' => 'client_new_wp_user');
     foreach ($notifications as $from => $to) {
         $wpdb->query("UPDATE `ab_notifications` SET `type` = '{$to}' WHERE `type` = '{$from}'");
     }
     $this->drop('ab_email_notification');
     // Rename tables.
     $ab_tables = array('ab_appointment' => AB_Appointment::getTableName(), 'ab_category' => AB_Category::getTableName(), 'ab_coupons' => AB_Coupon::getTableName(), 'ab_customer' => AB_Customer::getTableName(), 'ab_customer_appointment' => AB_CustomerAppointment::getTableName(), 'ab_holiday' => AB_Holiday::getTableName(), 'ab_notifications' => AB_Notification::getTableName(), 'ab_payment' => AB_Payment::getTableName(), 'ab_schedule_item_break' => AB_ScheduleItemBreak::getTableName(), 'ab_service' => AB_Service::getTableName(), 'ab_staff' => AB_Staff::getTableName(), 'ab_staff_schedule_item' => AB_StaffScheduleItem::getTableName(), 'ab_staff_service' => AB_StaffService::getTableName());
     foreach ($ab_tables as $from => $to) {
         $wpdb->query("ALTER TABLE `{$from}` RENAME TO `{$to}`");
     }
     $wpdb->query("CREATE TABLE IF NOT EXISTS  `" . AB_SentNotification::getTableName() . "` (\n                `id`                      INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,\n                `customer_appointment_id` INT UNSIGNED,\n                `staff_id`                INT UNSIGNED,\n                `gateway`                 ENUM('email','sms') NOT NULL DEFAULT 'email',\n                `type`                    VARCHAR(60) NOT NULL,\n                `created`                 DATETIME NOT NULL,\n                CONSTRAINT fk_" . AB_SentNotification::getTableName() . "_" . AB_CustomerAppointment::getTableName() . "_id\n                    FOREIGN KEY (customer_appointment_id)\n                    REFERENCES  " . AB_CustomerAppointment::getTableName() . "(id)\n                    ON DELETE   CASCADE\n                    ON UPDATE   CASCADE,\n                CONSTRAINT fk_" . AB_SentNotification::getTableName() . "_" . AB_Staff::getTableName() . "_id\n                    FOREIGN KEY (staff_id)\n                    REFERENCES  " . AB_Staff::getTableName() . "(id)\n                    ON DELETE   CASCADE\n                    ON UPDATE   CASCADE\n              ) ENGINE = INNODB\n              DEFAULT CHARACTER SET = utf8\n              COLLATE = utf8_general_ci");
     // Google Calendar.
     add_option('ab_settings_google_event_title', '[[SERVICE_NAME]]');
     // Link assets.
     add_option('ab_settings_link_assets_method', 'enqueue');
     // SMS.
     add_option('ab_sms_default_country_code', '');
 }
Esempio n. 13
0
 private function _drop_tables()
 {
     /** @var wpdb $wpdb */
     global $wpdb;
     $ab_tables = array(AB_Appointment::getTableName(), AB_Category::getTableName(), AB_Coupon::getTableName(), AB_Customer::getTableName(), AB_CustomerAppointment::getTableName(), AB_Holiday::getTableName(), AB_Notification::getTableName(), AB_Payment::getTableName(), AB_ScheduleItemBreak::getTableName(), AB_SentNotification::getTableName(), AB_Service::getTableName(), AB_Staff::getTableName(), AB_StaffScheduleItem::getTableName(), AB_StaffService::getTableName());
     $this->_drop_fk($ab_tables);
     $wpdb->query('DROP TABLE IF EXISTS `' . implode('`, `', $ab_tables) . '` CASCADE;');
 }
Esempio n. 14
0
 /**
  * Check if booking time is still available
  * Return TRUE if time is available
  *
  * @return bool
  */
 public function checkBookingTime()
 {
     /** @var WPDB $wpdb */
     global $wpdb;
     $booked_datetime = $this->userData->get('appointment_datetime');
     $endDate = new DateTime($booked_datetime);
     $endDate->modify("+ {$this->userData->getService()->get('duration')} sec");
     $query = $wpdb->prepare("SELECT `a`.*, `ss`.`capacity`, SUM(`ca`.`number_of_persons`) AS `total_number_of_persons`\n                FROM `" . AB_CustomerAppointment::getTableName() . "` `ca`\n                LEFT JOIN `" . AB_Appointment::getTableName() . "`   `a`  ON `a`.`id` = `ca`.`appointment_id`\n                LEFT JOIN `" . AB_StaffService::getTableName() . "` `ss` ON `ss`.`staff_id` = `a`.`staff_id` AND `ss`.`service_id` = `a`.`service_id`\n                WHERE `a`.`staff_id` = %d\n                GROUP BY `a`.`start_date` , `a`.`staff_id` , `a`.`service_id`\n                HAVING\n                      (`a`.`start_date` = %s AND `service_id` =  %d AND `total_number_of_persons` >= `capacity`) OR\n                      (`a`.`start_date` = %s AND `service_id` <> %d) OR\n                      (`a`.`start_date` > %s AND `a`.`end_date` <= %s) OR\n                      (`a`.`start_date` < %s AND `a`.`end_date` > %s) OR\n                      (`a`.`start_date` < %s AND `a`.`end_date` > %s)\n                LIMIT 1", $this->userData->getStaffId(), $booked_datetime, $this->userData->get('service_id'), $booked_datetime, $this->userData->get('service_id'), $booked_datetime, $endDate->format('Y-m-d H:i:s'), $endDate->format('Y-m-d H:i:s'), $endDate->format('Y-m-d H:i:s'), $booked_datetime, $booked_datetime);
     return !(bool) $wpdb->get_row($query);
 }
Esempio n. 15
0
 /**
  * Get appointment data when editing an appointment.
  */
 public function executeGetDataForAppointment()
 {
     $response = array('success' => false, 'data' => array('customers' => array()));
     $appointment = new AB_Appointment();
     if ($appointment->load($this->getParameter('id'))) {
         $response['success'] = true;
         $info = AB_Appointment::query('a')->select('ss.capacity AS max_capacity, SUM( ca.number_of_persons ) AS total_number_of_persons, a.staff_id, a.service_id, a.start_date, a.end_date')->leftJoin('AB_CustomerAppointment', 'ca', 'ca.appointment_id = a.id')->leftJoin('AB_StaffService', 'ss', 'ss.staff_id = a.staff_id AND ss.service_id = a.service_id')->where('a.id', $appointment->get('id'))->fetchRow();
         $response['data']['total_number_of_persons'] = $info['total_number_of_persons'];
         $response['data']['max_capacity'] = $info['max_capacity'];
         $response['data']['start_date'] = $info['start_date'];
         $response['data']['end_date'] = $info['end_date'];
         $response['data']['staff_id'] = $info['staff_id'];
         $response['data']['service_id'] = $info['service_id'];
         $customer_appointments = AB_CustomerAppointment::query()->where('appointment_id', $appointment->get('id'))->fetchArray();
         foreach ($customer_appointments as $customer_appointment) {
             $response['data']['customers'][] = array('id' => $customer_appointment['customer_id'], 'custom_fields' => $customer_appointment['custom_fields'] ? json_decode($customer_appointment['custom_fields'], true) : array(), 'number_of_persons' => $customer_appointment['number_of_persons']);
         }
     }
     wp_send_json($response);
 }