/** * Get list of customers. */ public function executeGetCustomers() { $wpdb = $this->getWpdb(); $response = array('status' => 'ok', 'data' => array('customers' => array(), 'total' => 0, 'pages' => 0, 'active_page' => 0)); $page = intval($this->getParameter('page')); $sort = in_array($this->getParameter('sort'), array('name', 'phone', 'email', 'notes', 'last_appointment', 'total_appointments', 'payments')) ? $this->getParameter('sort') : 'name'; $order = in_array($this->getParameter('order'), array('asc', 'desc')) ? $this->getParameter('order') : 'asc'; $filter = $wpdb->_real_escape($this->getParameter('filter')); $items_per_page = 20; $total = $wpdb->get_var('SELECT COUNT(*) FROM `ab_customer`'); $pages = ceil($total / $items_per_page); if ($page < 1 || $page > $pages) { $page = 1; } if ($total) { $query = "SELECT `c`.*, MAX(`a`.`start_date`) AS `last_appointment`, COUNT(`a`.`id`) AS `total_appointments`, COALESCE(SUM(`p`.`total`),0) AS `payments`\n FROM `ab_customer` `c`\n LEFT JOIN `ab_customer_appointment` `ca` ON `ca`.`customer_id` = `c`.`id`\n LEFT JOIN `ab_appointment` `a` ON `a`.`id` = `ca`.`appointment_id`\n LEFT JOIN `ab_payment` `p` ON `p`.`appointment_id` = `a`.`id` and `p`.`customer_id` = `c`.`id`"; // WHERE if ($filter !== '') { $query .= " WHERE `c`.`name` LIKE '%{$filter}%' OR `c`.`phone` LIKE '%{$filter}%' OR `c`.`email` LIKE '%{$filter}%'"; } // GROUP BY $query .= ' GROUP BY `c`.`id`'; // ORDER BY $query .= " ORDER BY {$sort} {$order}"; // LIMIT $start = ($page - 1) * $items_per_page; $query .= " LIMIT {$start}, {$items_per_page}"; $data = $wpdb->get_results($query); array_walk($data, function ($row) { $row->last_appointment = AB_CommonUtils::getFormattedDateTime($row->last_appointment); $row->payments = AB_CommonUtils::formatPrice($row->payments); }); // Populate response. $response['data']['customers'] = $data; $response['data']['total'] = $total; $response['data']['pages'] = $pages; $response['data']['active_page'] = $page; } echo json_encode($response); exit(0); }
/** * Constructor. */ public function __construct() { global $wpdb; // Select all services (with categories and staff members) // which have at least one staff member assigned. $rows = $wpdb->get_results(' SELECT `c`.`id` AS `category_id`, `c`.`name` AS `category_name`, `s`.`id` AS `service_id`, `s`.`title` AS `service_name`, `st`.`id` AS `staff_id`, `st`.`full_name` AS `staff_name`, `ss`.`price` AS `price` FROM `ab_service` `s` INNER JOIN `ab_staff_service` `ss` ON `s`.`id` = `ss`.`service_id` LEFT JOIN `ab_category` `c` ON `s`.`category_id` = `c`.`id` LEFT JOIN `ab_staff` `st` ON `ss`.`staff_id` = `st`.`id` ORDER BY `service_name` ', ARRAY_A); foreach ($rows as $row) { if (!isset($this->services[$row['service_id']])) { $this->services[$row['service_id']] = array('id' => $row['service_id'], 'name' => $row['service_name'], 'category_id' => $row['category_id'], 'staff' => array()); } if (!isset($this->staff[$row['staff_id']])) { $this->staff[$row['staff_id']] = array('id' => $row['staff_id'], 'name' => $row['staff_name'], 'category_id' => $row['category_id'], 'service_id' => $row['service_id']); } if ($row['category_id'] && !isset($this->categories[$row['category_id']])) { $this->categories[$row['category_id']] = array('id' => $row['category_id'], 'name' => $row['category_name'], 'services' => array()); } else { if (!$row['category_id'] && !isset($this->categories[0])) { $this->categories[0] = array('id' => 0, 'name' => __('Uncategorized', 'ab'), 'services' => array()); } } if (!isset($this->services[$row['service_id']]['staff'][$row['staff_id']])) { $staff_member = $this->staff[$row['staff_id']]; $staff_member['categories'] = array(); $staff_member['services'] = array(); if (self::isPaymentDisabled() == false) { $staff_member['name'] .= ' (' . AB_CommonUtils::formatPrice($row['price']) . ')'; } $this->services[$row['service_id']]['staff'][$row['staff_id']] = $staff_member; } if (!isset($this->staff[$row['staff_id']]['services'][$row['service_id']])) { $service = $this->services[$row['service_id']]; $service['staff'] = array(); $this->staff[$row['staff_id']]['services'][$row['service_id']] = $service; } if (!isset($this->staff[$row['staff_id']]['categories'][$row['category_id']])) { $category = $this->categories[$row['category_id']]; $category['services'] = array(); $category['staff'] = array(); $this->staff[$row['staff_id']]['categories'][$row['category_id']] = $category; } if (!isset($this->categories[intval($row['category_id'])]['staff'][$row['staff_id']])) { $staff_member = $this->staff[$row['staff_id']]; $staff_member['categories'] = array(); $staff_member['services'] = array(); $this->categories[intval($row['category_id'])]['staff'][$row['staff_id']] = $staff_member; } if (!isset($this->categories[intval($row['category_id'])]['services'][$row['service_id']])) { $service = $this->services[$row['service_id']]; $service['staff'] = array(); $this->categories[intval($row['category_id'])]['services'][$row['service_id']] = $service; } } }
/** * Render info text into a variable. * * @param int $booking_step * @param AB_UserBookingData $userData * @param int $preset_price * * @return string */ private function _prepareInfoText($booking_step, $userData, $preset_price = null) { if ($userData->hasData()) { $service_name = $userData->getServiceName(); $category_name = $userData->getCategoryName(); $staff_name = $userData->getStaffName(); $price = $preset_price === null ? $userData->getServicePrice() : $preset_price; // Convenient Time if ($booking_step === 2) { $replacement = array('[[STAFF_NAME]]' => '<b>' . $staff_name . '</b>', '[[SERVICE_NAME]]' => '<b>' . $service_name . '</b>', '[[CATEGORY_NAME]]' => '<b>' . $category_name . '</b>'); return str_replace(array_keys($replacement), array_values($replacement), nl2br(esc_html(get_option('ab_appearance_text_info_second_step')))); } // Your Details if ($booking_step === 3) { if (get_option('ab_settings_use_client_time_zone') && $this->getParameter('client_time_zone_offset')) { $service_time = date_i18n(get_option('time_format'), strtotime($userData->getBookedDatetime()) - ($this->getParameter('client_time_zone_offset') + get_option('gmt_offset') * 60) * 60); } else { $service_time = date_i18n(get_option('time_format'), strtotime($userData->getBookedDatetime())); } $service_date = date_i18n(get_option('date_format'), strtotime($userData->getBookedDatetime())); $replacement = array('[[STAFF_NAME]]' => '<b>' . $staff_name . '</b>', '[[SERVICE_NAME]]' => '<b>' . $service_name . '</b>', '[[CATEGORY_NAME]]' => '<b>' . $category_name . '</b>', '[[SERVICE_TIME]]' => '<b>' . $service_time . '</b>', '[[SERVICE_DATE]]' => '<b>' . $service_date . '</b>', '[[SERVICE_PRICE]]' => '<b>' . AB_CommonUtils::formatPrice($price) . '</b>'); return str_replace(array_keys($replacement), array_values($replacement), nl2br(esc_html(get_option('ab_appearance_text_info_third_step')))); } // Coupon Text if ($booking_step === 4) { $replacement = array('[[SERVICE_PRICE]]' => '<b>' . AB_CommonUtils::formatPrice($price) . '</b>'); return str_replace(array_keys($replacement), array_values($replacement), nl2br(esc_html(get_option('ab_appearance_text_info_coupon')))); } } return ''; }
/** * Save appointment form (for both create and edit). */ public function executeSaveAppointmentForm() { /** * @var WPDB $wpdb */ global $wpdb; $response = array('status' => 'error'); $start_date = date('Y-m-d H:i:s', strtotime($this->getParameter('start_date'))); $end_date = date('Y-m-d H:i:s', strtotime($this->getParameter('end_date'))); $staff_id = $this->getParameter('staff_id'); $service_id = $this->getParameter('service_id', null); $appointment_id = $this->getParameter('id', 0); $customers = json_decode($this->getParameter('customers', '[]')); $notes = $this->getParameter('notes', ''); $staff_service = new AB_StaffService(); $staff_service->loadByStaffAndService($staff_id, $service_id); // Check for errors. if (!$this->dateIntervalIsAvailableForAppointment($start_date, $end_date, $staff_id, $appointment_id)) { $response['errors'] = array('date_interval_not_available' => true); } if (count($customers) > $staff_service->get('capacity')) { $response['errors']['overflow_capacity'] = true; $response['errors']['overflow_capacity_message'] = __('Number of customers should be not more than ', 'ab') . $staff_service->get('capacity'); } // If no errors then try to save the appointment. if (!isset($response['errors'])) { $appointment = new AB_Appointment(); if ($appointment_id) { // edit $appointment->load($appointment_id); } $appointment->set('start_date', $start_date); $appointment->set('end_date', $end_date); $appointment->set('staff_id', $staff_id); $appointment->set('service_id', $service_id); if ($appointment->save() !== false) { // save customers $current_customers = $appointment->getCustomers(); foreach (array_diff(array_keys($current_customers), $customers) as $el) { $wpdb->delete('ab_customer_appointment', array('appointment_id' => $appointment->get('id'), 'customer_id' => $el)); } foreach (array_diff($customers, array_keys($current_customers)) as $el) { $customer_appointment = new AB_Customer_Appointment(); $customer_appointment->set('appointment_id', $appointment->get('id')); $customer_appointment->set('customer_id', $el); while (true) { $token = md5(uniqid(time(), true)); $result = $wpdb->get_row($wpdb->prepare('SELECT * FROM `ab_customer_appointment` WHERE token = %s', $token)); if (!$result) { break; } } $customer_appointment->set('token', $token); $customer_appointment->save(); } $startDate = new DateTime($appointment->get('start_date')); $endDate = new DateTime($appointment->get('end_date')); $staff = new AB_Staff(); $staff->load($staff_id); $service = new AB_Service(); $service->load($service_id); $response['status'] = 'ok'; $desc = array(); $appointment_additional_info = $wpdb->get_row($wpdb->prepare('SELECT ss.capacity AS max_capacity, COUNT( ca.id ) AS current_capacity, ca.customer_id, ca.notes, ca.id AS ca_id FROM ab_appointment a LEFT JOIN ab_customer_appointment ca ON ca.appointment_id = a.id LEFT JOIN ab_staff_service ss ON ss.staff_id = a.staff_id AND ss.service_id = a.service_id WHERE a.id = %d', $appointment->get('id'))); if ($appointment_additional_info->max_capacity == 1) { // save notes $customer_appointment = new AB_Customer_Appointment(); $customer_appointment->load($appointment_additional_info->ca_id); $customer_appointment->set('notes', $notes); $customer_appointment->save(); $customer = new AB_Customer(); $customer->load($appointment_additional_info->customer_id); foreach (array('name', 'phone', 'email') as $data_entry) { $entry_value = $customer->get($data_entry); if ($entry_value) { $desc[] = '<div class="wc-employee">' . esc_html($entry_value) . '</div>'; } } $desc[] = '<div class="wc-notes">' . nl2br(esc_html($notes ?: $appointment_additional_info->notes)) . '</div>'; } else { // save notes $customer_appointment = new AB_Customer_Appointment(); $customer_appointment->load($appointment_additional_info->ca_id); $customer_appointment->set('notes', null); $customer_appointment->save(); $desc[] = '<div class="wc-notes">Signed up ' . $appointment_additional_info->current_capacity . '</div>'; $desc[] = '<div class="wc-notes">Capacity ' . $appointment_additional_info->max_capacity . '</div>'; } $response['data'] = array('id' => (int) $appointment->get('id'), 'start' => $startDate->format('m/d/Y H:i'), 'end' => $endDate->format('m/d/Y H:i'), 'desc' => implode('', $desc), 'title' => $service->get('title') ? $service->get('title') : __('Untitled', 'ab'), 'color' => $service->get('color'), 'userId' => (int) $appointment->get('staff_id')); // refresh data $current_customers = $appointment->getCustomers(); if ($this->getParameter('email_notification') === 'true') { // Send email notification to client with appointment info $client_notification = $wpdb->get_row('SELECT * FROM ab_notifications WHERE slug = "client_info" AND active = 1'); // Send email notification to service provider with appointment info $staff_notification = $wpdb->get_row('SELECT * FROM ab_notifications WHERE slug = "provider_info" AND active = 1'); foreach ($current_customers as $customer) { if ($client_notification) { $replacement = new AB_NotificationReplacement(); $replacement->setClientName($customer->name); $replacement->setClientPhone($customer->phone); $replacement->setClientEmail($customer->email); // $replacement->setClientNotes( nl2br( esc_html( $notes ) ) ); $replacement->setAppointmentTime($appointment->get('start_date')); $replacement->setServiceName($service->get('title') ? $service->get('title') : __('Untitled', 'ab')); $replacement->setServicePrice($staff_service->get('price')); $replacement->setAppointmentToken($customer->token); $replacement->setStaffName($staff->get('full_name')); $message = wpautop($replacement->replace($client_notification->message)); $subject = $replacement->replaceSubject($client_notification->subject); wp_mail($customer->email, $subject, $message, AB_CommonUtils::getEmailHeaderFrom()); } if ($staff_notification) { $replacement = new AB_NotificationReplacement(); $replacement->setClientName($customer->name); $replacement->setClientPhone($customer->phone); $replacement->setClientEmail($customer->email); // $replacement->setClientNotes( nl2br( esc_html( $notes ) ) ); $replacement->setAppointmentTime($appointment->get('start_date')); $replacement->setServiceName($service->get('title') ? $service->get('title') : __('Untitled', 'ab')); $replacement->setServicePrice($staff_service->get('price')); $replacement->setAppointmentToken($customer->token); $replacement->setStaffName($staff->get('full_name')); $message = wpautop($replacement->replace($staff_notification->message)); $subject = $replacement->replaceSubject($staff_notification->subject); // Send copy to administrators if ($staff_notification->copy) { $admin_emails = AB_CommonUtils::getAdminEmails(); if (!empty($admin_emails)) { wp_mail($admin_emails, $subject, $message, AB_CommonUtils::getEmailHeaderFrom()); } } wp_mail($staff->get('email'), $subject, $message, AB_CommonUtils::getEmailHeaderFrom()); } } } } else { $response['errors'] = array('unknown' => true); } } exit(json_encode($response)); }