Files
api/objects/bookings_o.php
T
Jepp9350 b794e95ba9 Refactor and enhance booking, customer, and caching logic
Improved booking handling with unfulfilled booking checks and Slack notifications. Enhanced customer data retrieval with caching optimizations and discount calculations. Added logging, debug capabilities, and expanded Redis functionalities for better data management.
2025-01-21 21:16:42 +01:00

309 lines
15 KiB
PHP

<?php
namespace objects;
use classes\db;
use classes\object_property;
use classes\response;
use classes\slack;
use classes\wash_certificate_store;
use classes\wordpress_bookings_remote;
use traits\db_object_t;
class bookings_o extends db
{
use db_object_t;
public object_property $customer_number;
public object_property $wash_type;
public object_property $contact_email;
public object_property $reference_number;
public object_property $regNrTraekker;
public object_property $regNrTrailer;
public object_property $washCertificateEmail;
public object_property $date;
public object_property $department;
public object_property $pickup_bool;
public object_property $notes;
public object_property $washCertificateStatus;
public object_property $washCertificateUrl;
public object_property $status;
public function structure(): void
{
$this->setTable('bookings');
}
public function getCustomerBookingsPaginated(int $customer_number, int $page = 1, int $limit = 10, array $order = ['id' => 'DESC'], string $search = null, array $filters = null): array
{
global /** @var response $response */
$db, $response;
// Add the customer number to the filters
$filters['customer_number'] = $customer_number;
// List the objects with pagination
$array = $this->listObjectsWithPagination($page, $limit, $search, $filters, $order);
// Get the total number of objects
$total = $this->getTotalObjects($search, $filters);
$response->paginate($page, $limit, $total);
return $array;
}
public function getDepartmentBookingsUnfulfilledCount(int $department_id): int
{
global /** @var response $response */
$db, $response;
// Check if the count is cached
if (redis->get_department_booking_count($department_id)) {
$response->add_meta('cached', true);
return redis->get_department_booking_count($department_id);
}
$sql = "SELECT COUNT(*) as count FROM $this->table WHERE department = $department_id AND status = 'pending'";
$result = $db->query($sql);
$row = $db->fetch_assoc($result);
// Cache the count
redis->cache_department_booking_count($department_id, $row['count']);
return $row['count'];
}
public function delete(int $id): void
{
$this->id = $id;
$this->getObjectProperties();
// Set the status to cancelled
$this->status->set('cancelled');
// Remove the cache
redis->clear_department_booking_count($this->department->value());
}
public function getObjectProperties(): void
{
$this->customer_number = new object_property($this->table, $this->id, 'customer_number', 'int', true);
$this->wash_type = new object_property($this->table, $this->id, 'wash_type', 'string', true);
$this->contact_email = new object_property($this->table, $this->id, 'contact_email', 'string', true);
$this->reference_number = new object_property($this->table, $this->id, 'reference_number', 'string', true);
$this->regNrTraekker = new object_property($this->table, $this->id, 'regNrTraekker', 'string', true);
$this->regNrTrailer = new object_property($this->table, $this->id, 'regNrTrailer', 'string', true);
$this->washCertificateEmail = new object_property($this->table, $this->id, 'washCertificateEmail', 'string', true);
$this->date = new object_property($this->table, $this->id, 'date', 'string', true);
$this->department = new object_property($this->table, $this->id, 'department', 'string', true);
$this->pickup_bool = new object_property($this->table, $this->id, 'pickup_bool', 'int', true);
$this->notes = new object_property($this->table, $this->id, 'notes', 'string', true);
$this->washCertificateStatus = new object_property($this->table, $this->id, 'washCertificateStatus', 'string', true);
$this->washCertificateUrl = new object_property($this->table, $this->id, 'washCertificateUrl', 'string', true);
$this->status = new object_property($this->table, $this->id, 'status', 'string', true);
}
public function parseBookings(array $listObjectsWithPaginationIfSet): array
{
// Parse the customer numbers
$bookings = $this->parseCustomerNumbers($listObjectsWithPaginationIfSet);
return $bookings;
}
public function parseCustomerNumbers(array $listObjectsWithPaginationIfSet): array
{
// Parse the customer numbers
foreach ( $listObjectsWithPaginationIfSet as $key => $value ) {
$listObjectsWithPaginationIfSet[$key]['customer_name'] = redis->get_economic_customer_name($value['customer_number']) ?? (new users_o())->getCustomerName($value['customer_number']);
}
return $listObjectsWithPaginationIfSet;
}
public function syncBookings(): array
{
global /** @var response $response */
$db, $response;
$wordpress_bookings_remote = new wordpress_bookings_remote();
// Get all the bookings from the remote API
$bookings = $wordpress_bookings_remote->get_all_bookings()['data']['all_wash_bookings'];
// Parse the bookings
$parsed_bookings = $wordpress_bookings_remote->parse_bookings($bookings);
// Remove the cancelled bookings from the $parsed_bookings array
$cancelled_bookings = $this->getAllCancelledBookings();
foreach ( $cancelled_bookings as $cancelled_booking ) {
// Remove the cancelled booking from the parsed bookings
foreach ( $parsed_bookings as $key => $parsed_booking ) {
if ((int)$parsed_booking['id'] === (int)$cancelled_booking['id']) {
unset($parsed_bookings[$key]);
}
}
}
// Sync the bookings
foreach ( $parsed_bookings as $booking ) {
// Add or update the booking
$this->addOrUpdate(
$booking['id'],
$booking['customer_number'],
$booking['wash_type'],
$booking['contact_email'],
$booking['reference_number'],
$booking['regNrTraekker'],
$booking['regNrTrailer'],
$booking['washCertificateEmail'],
$booking['date'],
$booking['department'],
$booking['pickup_bool'] === 'true' ? 1 : 0,
$booking['notes'],
$booking['washCertificateStatus'],
$booking['washCertificateUrl'],
$booking['status']
);
}
return [
"bookings" => count($bookings),
"cancelled" => count($cancelled_bookings),
"parsed" => count($parsed_bookings),
];
}
public function getAllCancelledBookings(): array
{
global $db;
// Get all the cancelled bookings
$sql = "SELECT * FROM $this->table WHERE status = 'cancelled'";
$result = $db->query($sql);
return $db->fetch_all($result);
}
public function addOrUpdate($id, $customer_number, $wash_type, $contact_email, $reference_number, $regNrTraekker, $regNrTrailer, $washCertificateEmail, $date, $department, $pickup_bool, $notes, $washCertificateStatus, $washCertificateUrl, $status): void
{
global $db;
// Avoid SQL injection
$wash_type = $db->escape_string($wash_type);
$contact_email = $db->escape_string($contact_email);
$reference_number = $db->escape_string($reference_number);
$regNrTraekker = $db->escape_string($regNrTraekker);
$regNrTrailer = $db->escape_string($regNrTrailer);
$washCertificateEmail = $db->escape_string($washCertificateEmail);
$date = $db->escape_string($date);
// Parse the department name to id
$department = $this->getDepartmentIdByLegacyName($department);
$notes = $db->escape_string($notes);
$washCertificateStatus = $db->escape_string($washCertificateStatus);
$washCertificateUrl = $db->escape_string($washCertificateUrl);
$status = $db->escape_string($status);
// Check if the entry already exists
$sql = "SELECT * FROM $this->table WHERE id = $id";
$result = $db->query($sql);
if ($db->num_rows($result) === 0) {
// Send a department webhook if the booking is new
$slack = new slack();
try {
$slack->send_department_booking_notification($department, $slack->format_new_booking(
$id,
$customer_number,
$wash_type,
$contact_email,
$reference_number,
$regNrTraekker,
$regNrTrailer,
$washCertificateEmail,
$date,
$department,
$pickup_bool,
$notes,
$washCertificateStatus,
$washCertificateUrl,
$status
));
} catch (\Exception $e) {
// Log the error
$logs = new logs_o();
$logs->add('slack', 0, 3, 0, 'SEND_DEPARTMENT_BOOKING_NOTIFICATION', $e->getMessage());
}
}
// Create a new record in the database ( Replace the code, if an entry already exists )
$sql = "INSERT INTO $this->table (id, customer_number, wash_type, contact_email, reference_number, regNrTraekker, regNrTrailer, washCertificateEmail, date, department, pickup_bool, notes, washCertificateStatus, washCertificateUrl, status) VALUES ($id, $customer_number, '$wash_type', '$contact_email', '$reference_number', '$regNrTraekker', '$regNrTrailer', '$washCertificateEmail', '$date', '$department', $pickup_bool, '$notes', '$washCertificateStatus', '$washCertificateUrl', '$status') ON DUPLICATE KEY UPDATE customer_number = $customer_number, wash_type = '$wash_type', contact_email = '$contact_email', reference_number = '$reference_number', regNrTraekker = '$regNrTraekker', regNrTrailer = '$regNrTrailer', washCertificateEmail = '$washCertificateEmail', date = '$date', department = '$department', pickup_bool = $pickup_bool, notes = '$notes', washCertificateStatus = '$washCertificateStatus', washCertificateUrl = '$washCertificateUrl', status = '$status'";
$db->query($sql);
// Clear the cache
redis->clear_department_booking_count($department);
}
public function getDepartmentIdByLegacyName(string $departmentName): int
{
// Get the department id by the legacy name
$departmentLegacyNames = [
'køge' => 4,
'taastrup' => 2,
'aarhusc' => 5,
'roskilde' => 6,
'hvidovre' => 1,
'glostrup' => 3,
];
return $departmentLegacyNames[strtolower($departmentName)] ?? 0;
}
public function add(int $customer_number, string $wash_type, string $contact_email, string $reference_number, string $regNrTraekker, string $regNrTrailer, string $washCertificateEmail, string $date, string $department, int $pickup_bool, string $notes, string $washCertificateStatus, string $washCertificateUrl, string $status): void
{
global $db;
// Avoid SQL injection
$wash_type = $db->escape_string($wash_type);
$contact_email = $db->escape_string($contact_email);
$reference_number = $db->escape_string($reference_number);
$regNrTraekker = $db->escape_string($regNrTraekker);
$regNrTrailer = $db->escape_string($regNrTrailer);
$washCertificateEmail = $db->escape_string($washCertificateEmail);
$date = $db->escape_string($date);
// Parse the department name to id
$department = $this->getDepartmentIdByLegacyName($department);
$notes = $db->escape_string($notes);
$washCertificateStatus = $db->escape_string($washCertificateStatus);
$washCertificateUrl = $db->escape_string($washCertificateUrl);
$status = $db->escape_string($status);
// Create a new record in the database ( Replace the code, if an entry already exists )
$sql = "INSERT INTO $this->table (customer_number, wash_type, contact_email, reference_number, regNrTraekker, regNrTrailer, washCertificateEmail, date, department, pickup_bool, notes, washCertificateStatus, washCertificateUrl, status) VALUES ($customer_number, '$wash_type', '$contact_email', '$reference_number', '$regNrTraekker', '$regNrTrailer', '$washCertificateEmail', '$date', '$department', $pickup_bool, '$notes', '$washCertificateStatus', '$washCertificateUrl', '$status')";
$db->query($sql);
// Clear the cache
redis->clear_department_booking_count($department);
// Get the id of the new record
$this->id = $db->insert_id();
}
public function checkUnfulfilledBookings(): void
{
global $db;
// Get all the unfulfilled bookings
$bookings = $this->listObjectsWithPagination(1, 100000, null, ['status' => 'pending']);
// Check if the booking has been fulfilled
foreach ( $bookings as $booking ) {
if ($this->isCancelled($booking['id'])) {
echo "Booking with ID $booking[id] has been cancelled\n";
continue;
}
// Check if the booking has been fulfilled
$fulfilled = $this->checkBookingFulfilled($booking['id']);
if (!$fulfilled) {
echo "Booking with ID $booking[id] has not been fulfilled\n";
// Send a department webhook if the booking has not been fulfilled
$slack = new slack();
try {
$slack->send_department_booking_notification($booking['department'], $slack->format_unfulfilled_booking($booking['id'], $booking['customer_number'], $booking['wash_type'], $booking['contact_email'], $booking['reference_number'], $booking['regNrTraekker'], $booking['regNrTrailer'], $booking['washCertificateEmail'], $booking['date'], $booking['department'], $booking['pickup_bool'], $booking['notes'], $booking['washCertificateStatus'], $booking['washCertificateUrl'], $booking['status']));
} catch (\Exception $e) {
// Log the error
$logs = new logs_o();
$logs->add('slack', 0, 3, 0, 'SEND_DEPARTMENT_BOOKING_NOTIFICATION', $e->getMessage());
}
}
}
}
private static function isCancelled(int $id): bool
{
global $db;
// Check if the booking has been cancelled
$sql = "SELECT status FROM bookings WHERE id = $id";
$result = $db->query($sql);
$row = $db->fetch_assoc($result);
return $row['status'] === 'cancelled';
}
public function checkBookingFulfilled(int $booking_id): bool
{
// Check if the booking has a wash certificate
$wash_certificate_store = new wash_certificate_store();
return $wash_certificate_store->washCertificateExists($booking_id);
}
}