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.
This commit is contained in:
Jepp9350
2025-01-21 21:16:42 +01:00
parent 635ad0fa04
commit b794e95ba9
20 changed files with 744 additions and 102 deletions
+169
View File
@@ -144,4 +144,173 @@ class redis implements redis_i
$this->delete('department_name_' . $department_id);
return $this;
}
/**
* @inheritDoc
*/
public function cache_economic_customer_discount_percentage(int $customer_number, int $discount_percentage): self
{
// Cache the economic customer discount percentage
$this->set('economic_customer_discount_percentage_' . $customer_number, $discount_percentage);
return $this;
}
/**
* @inheritDoc
*/
public function get_economic_customer_discount_percentage(int $customer_number): int|null
{
// Get the economic customer discount percentage
return $this->get('economic_customer_discount_percentage_' . $customer_number);
}
/**
* @inheritDoc
*/
public function clear_economic_customer_discount_percentage(int $customer_number): self
{
// Clear the economic customer discount percentage
$this->delete('economic_customer_discount_percentage_' . $customer_number);
return $this;
}
/**
* @inheritDoc
*/
public function cache_customer_notes(int $customer_id, array $customer_notes): self
{
// Cache the customer notes
$this->set_array('customer_notes_' . $customer_id, $customer_notes);
return $this;
}
/**
* @inheritDoc
*/
public function get_customer_notes(int $customer_id): array|null
{
// Get the customer notes
return $this->get_array('customer_notes_' . $customer_id);
}
/**
* @inheritDoc
*/
public function clear_customer_notes(int $customer_id): self
{
// Clear the customer notes
$this->delete('customer_notes_' . $customer_id);
return $this;
}
/**
* @inheritDoc
*/
public function add_log(string $module, string $department, int $type, int $user_id, string $action, string $message): redis_i
{
// Get the current timestamp
$timestamp = strtotime('now');
// Get unique id for the log
$log_id = uniqid();
// Add the log to the cache
$this->set_array('log_' . $log_id, [
'module' => $module,
'department' => $department,
'type' => $type,
'user_id' => $user_id,
'action' => $action,
'message' => $message,
'timestamp' => $timestamp
]);
return $this;
}
/**
* @inheritDoc
*/
public function get_logs(): array|null
{
// Get all logs from the cache
return $this->get_arrays('log_*');
}
/**
* @inheritDoc
*/
public function clear_logs(): self
{
// Clear all logs from the cache
$keys = $this->get_keys('log_*');
foreach ( $keys as $key ) {
$this->delete($key);
}
return $this;
}
/**
* @inheritDoc
*/
public function get_department(int $department_id): array|null
{
// Get the department
return $this->get_array('department_' . $department_id);
}
/**
* @inheritDoc
*/
public function clear_department(int $department_id): self
{
// Clear the departments
$this->clear_departments();
return $this;
}
/**
* @inheritDoc
*/
public function clear_departments(): self
{
// Clear all departments from the cache
$this->delete('departments');
$keys = $this->get_keys('department_*');
foreach ( $keys as $key ) {
$this->delete($key);
}
return $this;
}
/**
* @inheritDoc
*/
public function get_departments(): array|null
{
// Get all departments from the cache
return $this->get_array('departments');
}
/**
* @inheritDoc
*/
public function cache_departments(array $departments): self
{
// Cache the departments
foreach ( $departments as $department ) {
$this->cache_department($department['id'], $department);
}
redis->set_array('departments', $departments);
return $this;
}
/**
* @inheritDoc
*/
public function cache_department(int $department_id, array $department): self
{
// Cache the department
$this->set_array('department_' . $department_id, $department);
return $this;
}
}
+29 -15
View File
@@ -19,6 +19,7 @@ class response implements response_i
#[NoReturn] public function response(bool $success, mixed $data, int $status = null): void
{
global $DEBUG;
header('Content-Type: application/json');
if ($status) {
http_response_code($status);
@@ -29,6 +30,14 @@ class response implements response_i
if (!is_array($data)) {
$data = ['message' => $data];
}
// If the debug mode is enabled, add the debug data to the response
if ($DEBUG) {
$this->add_include('debug', [
'memory' => memory_get_usage(),
'time' => microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'],
'data' => $this->get_data()
]);
}
echo json_encode([
'success' => $success,
'data' => $data,
@@ -38,6 +47,21 @@ class response implements response_i
exit;
}
public function add_include(string $string, array $dataArray): void
{
$this->add_included($string, $dataArray);
}
public function add_included(string $key, mixed $value): void
{
$this->includes[$key] = $value;
}
public function get_data(): array
{
return $this->data;
}
#[NoReturn] public function not_found(): void
{
$this->error('Not found', 404);
@@ -89,11 +113,6 @@ class response implements response_i
$this->meta[$key] = $value;
}
public function get_data(): array
{
return $this->data;
}
public function is_matching_route_found(): bool
{
return $this->matching_route_found;
@@ -123,16 +142,6 @@ class response implements response_i
return $data[$key] ?? null;
}
public function add_include(string $string, array $dataArray): void
{
$this->add_included($string, $dataArray);
}
public function add_included(string $key, mixed $value): void
{
$this->includes[$key] = $value;
}
public function parseFilters(?string $filters): array|null
{
if ($filters) {
@@ -149,4 +158,9 @@ class response implements response_i
}
return null;
}
public function add_debug_list(string $list_name, int $key, $value): void
{
$this->add_data($list_name, [$key => $value]);
}
}
+24 -1
View File
@@ -90,7 +90,30 @@ class slack implements notification_i
// Get the customer name
$customer_name = (new users_o())->getCustomerName($customer_number);
// Format the message
return "New booking created\n"
return "*New booking created* ( ID: " . $id . " )\n"
. "Customer: $customer_name\n"
. "Customer number: $customer_number\n"
. "Wash type: $wash_type\n"
. "Contact email: $contact_email\n"
. "Reference number: $reference_number\n"
. "RegNr Traekker: $regNrTraekker\n"
. "RegNr Trailer: $regNrTrailer\n"
. "Wash certificate email: $washCertificateEmail\n"
. "Date: $date\n"
. "Department: $department_name\n"
. "Pickup: $pickup_bool\n"
. "Notes: $notes\n"
. "Status: $status";
}
public function format_unfulfilled_booking($id, $customer_number, string $wash_type, string $contact_email, string $reference_number, string $regNrTraekker, string $regNrTrailer, string $washCertificateEmail, string $date, int $department, $pickup_bool, string $notes, string $washCertificateStatus, string $washCertificateUrl, string $status): string
{
// Get the department name
$department_name = (new departments_o())->getDepartmentName($department);
// Get the customer name
$customer_name = (new users_o())->getCustomerName($customer_number);
// Format the message
return "Unfulfilled booking from " . $date . "\n"
. "ID: $id\n"
. "Customer: $customer_name\n"
. "Customer number: $customer_number\n"
+7
View File
@@ -16,6 +16,10 @@ if ($args[1] === 'run') {
echo "Running the redis test script";
require_once 'tests/redis/redisTest.php';
break;
case 'redis-logSync-test':
echo "Running the redis log sync test script";
require_once 'tests/redis/redisLogSyncTest.php';
break;
case 'bookingModule-test':
echo "Running the bookingModule test script";
require_once 'tests/bookingModule/bookingModuleTest.php';
@@ -31,6 +35,9 @@ if ($args[1] === 'run') {
case 'bookingSync':
require_once 'cron/SyncBookings.php';
break;
case 'SyncLogs':
require_once 'cron/SyncLogs.php';
break;
default:
echo "Invalid script name";
break;
+4 -1
View File
@@ -16,4 +16,7 @@ if (!defined('WD')) {
// Sync the bookings
$bookings_o = new bookings_o();
$bookings_o->syncBookings();
$bookings_o->syncBookings();
// Check if any bookings from yesterday haven't been fulfilled
$bookings_o->checkUnfulfilledBookings();
+19
View File
@@ -0,0 +1,19 @@
<?php
/**
* This script is used to sync the logs to the database.
* It is run as a cron job.
*
* index.php run SyncLogs
*/
// prevent direct access
use objects\logs_o;
if (!defined('WD')) {
exit;
}
// Sync the logs to the database
$logs_o = new logs_o();
$logs_o->syncLogsToDatabase();
+110
View File
@@ -91,4 +91,114 @@ interface redis_i
* @return self
*/
public function clear_department_name(int $department_id): self;
/**
* Cache an economic customers discount percentage
* @param int $customer_number
* @param int $discount_percentage
* @return self
*/
public function cache_economic_customer_discount_percentage(int $customer_number, int $discount_percentage): self;
/**
* Get an economic customers discount percentage
* @param int $customer_number
* @return int|null
*/
public function get_economic_customer_discount_percentage(int $customer_number): int|null;
/**
* Clear an economic customers discount percentage
* @param int $customer_number
* @return self
*/
public function clear_economic_customer_discount_percentage(int $customer_number): self;
/**
* Cache a customer notes
* @param int $customer_id
* @param array $customer_notes
* @return self
*/
public function cache_customer_notes(int $customer_id, array $customer_notes): self;
/**
* Get a customer notes
* @param int $customer_id
* @return array|null
*/
public function get_customer_notes(int $customer_id): array|null;
/**
* Clear a customer notes
* @param int $customer_id
* @return self
*/
public function clear_customer_notes(int $customer_id): self;
/**
* Add a log to the logs cache
* @param string $module
* @param string $department
* @param int $type
* @param int $user_id
* @param string $action
* @param string $message
* @return self
*/
public function add_log(string $module, string $department, int $type, int $user_id, string $action, string $message): self;
/**
* Get all logs from the logs cache
* @return array|null
*/
public function get_logs(): array|null;
/**
* Clear all logs from the logs cache
* @return self
*/
public function clear_logs(): self;
/**
* Cache a department
* @param int $department_id
* @param array $department
* @return self
*/
public function cache_department(int $department_id, array $department): self;
/**
* Get a department
* @param int $department_id
* @return array|null
*/
public function get_department(int $department_id): array|null;
/**
* Clear a department
* @param int $department_id
* @return self
*/
public function clear_department(int $department_id): self;
/**
* Get departments from the cache
* @return array|null
*/
public function get_departments(): array|null;
/**
* Cache departments
* @param array $departments
* @return self
*/
public function cache_departments(array $departments): self;
/**
* Clear departments from the cache
* @return self
*/
public function clear_departments(): self;
}
@@ -24,7 +24,7 @@ class economicCustomers extends economic_m
}
// Get the customer name from the economic system
$customer = $this->getCustomerId($customer_number);
if (count($customer) > 0) {
if ($customer) {
$customer = $customer[0];
redis->cache_economic_customer_name($customer_number, $customer->name);
return $customer->name;
@@ -32,12 +32,47 @@ class economicCustomers extends economic_m
return null;
}
public function getCustomerId(int $customerNumber): array|bool
public function getCustomerId(int $customerNumber): object|bool
{
// Check if the customer exists
$url = '/customers?filter=customerNumber$eq:' . $customerNumber;
$url = '/customers/' . $customerNumber;
$response = $this->send_request($url, 'GET', '');
$response = json_decode($response);
return $response->collection;
return isset($response->customerNumber) ? $response : false;
}
public function getCustomerProduct(int $customer_number, int $product_id): object
{
// Get the customer product
$url = '/customers/' . $customer_number . '/templates/invoiceline/' . $product_id;
$response = $this->send_request($url, 'GET', '');
return json_decode($response);
}
public function getCustomerDiscountPercentage(int $customer_number): int
{
// Get the customer products
$products = $this->getCustomerProducts($customer_number, 1)->collection;
$discount = $this->getCustomerProductDiscount($customer_number, $products[0]->product->productNumber);
// Since the discount is global, we only need to get the discount for one product
return $discount->discountPercentage;
}
public function getCustomerProducts(int $customer_number, int $limit = 10, int $page = 1): object
{
// Get the customer products
$url = '/customers/' . $customer_number . '/templates/invoiceline/?pagesize=' . $limit . '&skippages=' . $page - 1;
$response = $this->send_request($url, 'GET', '');
return json_decode($response);
}
public function getCustomerProductDiscount(int $customer_number, int $product_id)
{
// Get the customer global discount
$url = '/customers/' . $customer_number . '/templates/invoiceline/' . $product_id;
$response = $this->send_request($url, 'GET', '');
$response = json_decode($response);
return $response;
}
}
@@ -2,6 +2,8 @@
namespace customers;
use classes\response;
class economic_customer_mo
{
public int $customer_number;
@@ -22,8 +24,8 @@ class economic_customer_mo
$economicCustomers = new economicCustomers();
$customer = $economicCustomers->getCustomerId($customer_number);
// Check if the customer exists
if (count($customer) > 0) {
return $this->parseCustomer($customer[0]);
if ($customer) {
return $this->parseCustomer($customer);
}
return $this;
@@ -31,6 +33,8 @@ class economic_customer_mo
public function parseCustomer($customer): static
{
global /** @var response $response */
$response;
$this->customer_number = $customer->customerNumber;
$this->name = ($customer->name ?? null);
$this->address = ($customer->address ?? null);
@@ -43,6 +47,9 @@ class economic_customer_mo
$this->country = ($customer->country ?? null);
// Cache the customer name
redis->cache_economic_customer_name($this->customer_number, $this->name);
$economicCustomers = new economicCustomers();
// Add the customer to the debug log
$response->add_debug_list('economic_customer', $this->customer_number, $customer);
return $this;
}
+46 -10
View File
@@ -6,6 +6,7 @@ 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;
@@ -28,16 +29,6 @@ class bookings_o extends db
public object_property $washCertificateUrl;
public object_property $status;
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 structure(): void
{
$this->setTable('bookings');
@@ -270,4 +261,49 @@ class bookings_o extends db
$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);
}
}
+39 -9
View File
@@ -9,6 +9,7 @@ use traits\db_object_t;
class customer_notes_o extends db
{
use db_object_t;
public object_property $customer_id;
public object_property $note;
public object_property $cashier_id;
@@ -19,14 +20,6 @@ class customer_notes_o extends db
$this->setTable('customer_notes');
}
public function getObjectProperties(): void
{
$this->customer_id = new object_property($this->table, $this->id, 'customer_id', 'int', true);
$this->note = new object_property($this->table, $this->id, 'note', 'string', true);
$this->cashier_id = new object_property($this->table, $this->id, 'cashier_id', 'int', true);
$this->deleted_at = new object_property($this->table, $this->id, 'deleted_at', 'timestamp', false);
}
public function add(int $customer_id, string $note, int $cashier_id): customer_notes_o
{
global $db, $response;
@@ -42,15 +35,32 @@ class customer_notes_o extends db
// Set the values of the object properties
$this->getObjectProperties();
// Clear the cache
redis->clear_customer_notes($customer_id);
} catch (\Exception $e) {
$response->error($e->getMessage());
}
return $this;
}
public function getObjectProperties(): void
{
$this->customer_id = new object_property($this->table, $this->id, 'customer_id', 'int', true);
$this->note = new object_property($this->table, $this->id, 'note', 'string', true);
$this->cashier_id = new object_property($this->table, $this->id, 'cashier_id', 'int', true);
$this->deleted_at = new object_property($this->table, $this->id, 'deleted_at', 'timestamp', false);
}
public function getCustomerNotesAsArray(int $customer_id): array
{
global $db;
global $response, $db;
// Check if the result is cached
$cached = redis->get_customer_notes($customer_id);
if ($cached) {
$response->add_meta('cached', true);
return $cached;
}
$sql = "SELECT * FROM $this->table WHERE customer_id = $customer_id AND deleted_at IS NULL";
$result = $db->query($sql);
$customer_notes = [];
@@ -59,6 +69,8 @@ class customer_notes_o extends db
$customer_notes[] = $row;
}
}
// Cache the result
redis->cache_customer_notes($customer_id, $customer_notes);
return $customer_notes;
}
@@ -81,6 +93,21 @@ class customer_notes_o extends db
$this->id = $id;
$sql = "UPDATE $this->table SET deleted_at = NOW() WHERE id = $this->id";
$db->query($sql);
// Clear the cache
$customer_id = $this->getCustomerByNoteId($this->id);
redis->clear_customer_notes($customer_id);
}
public function getCustomerByNoteId(int $id): int
{
global $db;
$sql = "SELECT customer_id FROM $this->table WHERE id = $id";
$result = $db->query($sql);
if ($result->num_rows > 0) {
$row = $result->fetch_assoc();
return $row['customer_id'];
}
return 0;
}
public function restore(int $id): void
@@ -89,5 +116,8 @@ class customer_notes_o extends db
$this->id = $id;
$sql = "UPDATE $this->table SET deleted_at = NULL WHERE id = $this->id";
$db->query($sql);
// Clear the cache
$customer_id = $this->getCustomerByNoteId($this->id);
redis->clear_customer_notes($customer_id);
}
}
+34 -10
View File
@@ -35,6 +35,9 @@ class departments_o extends db
// Set the values of the object properties
$this->getObjectProperties();
// Clear the cache
redis->clear_departments();
}
public function getObjectProperties(): void
@@ -62,34 +65,55 @@ class departments_o extends db
// Set the values of the object properties
$this->getObjectProperties();
// Clear the cache
redis->clear_department($id);
}
public function list($superUser = false): array
{
global $db;
$sql = "SELECT * FROM $this->table";
$result = $db->query($sql);
$result = $db->fetch_all($result);
// Check if the departments are cached
$departments = redis->get_departments();
// If the departments are not cached, get them from the database
if ($departments === null) {
$sql = "SELECT * FROM $this->table";
$result = $db->query($sql);
$departments = $db->fetch_all($result);
// Cache the departments (If it is not empty or null)
if (!empty($departments)) {
redis->cache_departments($departments);
}
}
// Only show the name, description and id if the user isn't a super user
if (!$superUser) {
$result = array_map(function ($department) {
$departments = array_map(function ($department) {
return [
'name' => $department['name'],
'description' => $department['description'],
'id' => $department['id']
];
}, $result);
return $result;
}, $departments);
}
return $result;
return $departments;
}
public function getDepartmentById(int $id): array
{
global $db;
$sql = "SELECT * FROM $this->table WHERE id = $id";
$result = $db->query($sql);
return $db->fetch_assoc($result);
// Check if the department is cached
$department = redis->get_department($id);
// If the department is not cached, get it from the database
if ($department === null) {
$sql = "SELECT * FROM $this->table WHERE id = $id";
$result = $db->query($sql);
$department = $db->fetch_assoc($result);
// Cache the department (If it is not empty or null)
if (!empty($department)) {
redis->cache_department($id, $department);
}
}
return $department;
}
/**
+29 -16
View File
@@ -9,6 +9,7 @@ use traits\db_object_t;
class logs_o extends db
{
use db_object_t;
public object_property $module;
public object_property $department;
public object_property $type;
@@ -21,6 +22,12 @@ class logs_o extends db
$this->setTable('logs');
}
public function add(string $module, string $department, int $type, int $user_id, string $action, string $message): void
{
// Add to the cache instead of the database, to make it faster
redis->add_log($module, $department, $type, $user_id, $action, $message);
}
public function getObjectProperties(): void
{
$this->module = new object_property($this->table, $this->id, 'module', 'string', true);
@@ -31,22 +38,28 @@ class logs_o extends db
$this->message = new object_property($this->table, $this->id, 'message', 'string', false);
}
public function add(string $module, string $department, int $type, int $user_id, string $action, string $message): void
public function syncLogsToDatabase(): void
{
global $db;
// Avoid SQL injection
$module = $db->escape_string($module);
$department = $db->escape_string($department);
$action = $db->escape_string($action);
$message = $db->escape_string($message);
// Create a new record in the database
$sql = "INSERT INTO $this->table (module, department, type, user_id, action, message) VALUES ('$module', '$department', $type, $user_id, '$action', '$message')";
$db->query($sql);
// Get the id of the new record
$this->id = $db->insert_id();
// Set the values of the object properties
$this->getObjectProperties();
global /** @var db $db */
$db;
// Get all logs from the cache
$logs = redis->get_logs();
if ($logs) {
foreach ( $logs as $log ) {
// Avoid SQL injection
$module = $db->escape_string($log['module']);
$department = $db->escape_string($log['department']);
$action = $db->escape_string($log['action']);
$message = $db->escape_string($log['message']);
$timestamp = $log['timestamp'];
// Convert the timestamp to a date
$timestamp = date('Y-m-d H:i:s', $timestamp);
// Create a new record in the database
$sql = "INSERT INTO $this->table (module, department, type, user_id, action, message, created_at, updated_at) VALUES ('$module', '$department', {$log['type']}, {$log['user_id']}, '$action', '$message', '$timestamp', '$timestamp')";
$db->query($sql);
}
// Clear all logs from the cache
redis->clear_keys($logs);
}
}
}
-1
View File
@@ -50,7 +50,6 @@ class orders_o extends db
return $this;
} catch (\Exception $e) {
$response->error($e->getMessage());
return $this;
}
}
+22 -1
View File
@@ -106,15 +106,22 @@ class user_price_overrides_o extends db
if (!$is_category) {
$product = (new products_o())->getProductById($product_or_category_id);
if ($product->apply_category_discount->value()) {
// Get the economic user discount
$economic_user_global_discount = (new users_o())->getUserById($this->user_id)->getEconomicCustomerDiscountPercentage();
// Get the category discount
$sql = "SELECT * FROM $this->table WHERE user_id = " . $this->user_id . " AND is_category = 1 AND product_or_category_id = '" . $product->category->value() . "'";
$result = $db->query($sql);
if ($result->num_rows > 0) {
$category_discount = $result->fetch_assoc()['percentage'];
// If the category discount is higher than the product discount, return the category discount
if ((int)$category_discount > (int)$percentage) {
if ((int)$category_discount > (int)$percentage && (int)$category_discount > (int)$economic_user_global_discount) {
return $category_discount;
}
}
// If the economic user discount is higher than the product discount, return the economic user discount
if ((int)$economic_user_global_discount > (int)$percentage) {
return $economic_user_global_discount;
}
}
}
return $percentage;
@@ -127,6 +134,8 @@ class user_price_overrides_o extends db
public function getAllPrices(): array
{
global $db;
// Get the customers global discount
$economic_user_global_discount = (new users_o())->getUserById($this->user_id)->getEconomicCustomerDiscountPercentage();
// Get all the price overrides for the user
$sql = "SELECT * FROM $this->table WHERE user_id = " . $this->user_id;
$result = $db->query($sql);
@@ -136,6 +145,18 @@ class user_price_overrides_o extends db
$prices[] = $row;
}
}
// If the user has a global discount, add it to the list
if ($economic_user_global_discount > 0) {
$prices[] = [
'id' => "999999",
'user_id' => "" . $this->user_id,
'is_category' => "1",
'product_or_category_id' => "global",
'percentage' => "" . $economic_user_global_discount,
'created_at' => "2021-01-01 00:00:00",
'updated_at' => "2021-01-01 00:00:00"
];
}
return $prices;
}
}
+17 -2
View File
@@ -103,9 +103,9 @@ class users_o extends db
$customer_data = $economic->getCustomerId($customer_number);
// DEBUG: Return the customer data
// Check if the customer exists
if (isset($customer_data[0])) {
if ($customer_data) {
// Avoid SQL injection
$customer_number = $db->escape_string($customer_data[0]->customerNumber);
$customer_number = $db->escape_string($customer_data->customerNumber);
// Double check if the customer exists
$sql = "SELECT * FROM $this->table WHERE customer_number = '$customer_number'";
$result = $db->query($sql);
@@ -669,4 +669,19 @@ class users_o extends db
}
return $listObjectsWithPaginationIfSet;
}
public function getEconomicCustomerDiscountPercentage(): int
{
// Check if the discount percentage is cached
$cached_discount_percentage = redis->get_economic_customer_discount_percentage($this->customer_number->value());
if ($cached_discount_percentage !== null) {
return $cached_discount_percentage;
}
// Get the discount percentage from the external source
$economic = new economicCustomers();
$discount_percentage = $economic->getCustomerDiscountPercentage($this->customer_number->value());
// Cache the discount percentage
redis->cache_economic_customer_discount_percentage($this->customer_number->value(), $discount_percentage);
return $discount_percentage;
}
}
+15 -6
View File
@@ -25,16 +25,19 @@ class customerNotes
// Get the query parameters from the URL
$data = $_GET;
// Check if the required fields are set
if (!isset($data['customer_number']) && !isset($data['user_id'])) { $response->error('User ID or Customer Number is required', 400); }
if (!isset($data['customer_number']) && !isset($data['user_id'])) {
$response->error('User ID or Customer Number is required', 400);
}
// Log the incident
(new logs_o())->add('customer_notes', 'global', 1, $user->id, 'LIST_CUSTOMER_NOTES', 'Successfully listed customer notes');
// Check if the user exists
if (!(new users_o())->automaticGetTargetUserFromRequest()->exists()) {
$targetUser = (new users_o())->automaticGetTargetUserFromRequest();
if (!$targetUser->exists()) {
$response->error('Customer not found', 400);
}
// Return the list of customer notes
$response->success(
(new users_o())->automaticGetTargetUserFromRequest()->getNotes()
($targetUser->getNotes())
);
} else {
// Log the incident
@@ -55,8 +58,12 @@ class customerNotes
// Get the post data
$data = json_decode(file_get_contents('php://input'), true);
// Check if the required fields are set
if (!isset($data['user_id']) && !isset($data['customer_number'])) { $response->error('User ID or Customer Number is required', 400); }
if (!isset($data['note'])) { $response->error('Note is required', 400); }
if (!isset($data['user_id']) && !isset($data['customer_number'])) {
$response->error('User ID or Customer Number is required', 400);
}
if (!isset($data['note'])) {
$response->error('Note is required', 400);
}
// Add the note to the customer
$customer = (new users_o())->automaticGetTargetUserFromRequest();
// Check if the customer exists
@@ -87,7 +94,9 @@ class customerNotes
// Get the query parameters from the URL
$data = $_GET;
// Check if the required fields are set
if (!isset($data['id'])) { $response->error('Note ID is required', 400); }
if (!isset($data['id'])) {
$response->error('Note ID is required', 400);
}
// Delete the note from the customer
(new customer_notes_o())->delete((int)$data['id']);
// Log the incident
+5 -3
View File
@@ -55,11 +55,13 @@ class ordersRoute
$response->error('Department not found', 400);
}
// Make sure the customer number set is valid
if (!(new users_o())->getCustomerByIdOrCustomerNumber((int)$data['customer_id'])->exists() || empty($data['customer_id'])) {
$response->error('Customer not found or invalid', 400);
$targetUser = (new users_o())->getCustomerByIdOrCustomerNumber((int)$data['customer_id']);
if (!$targetUser->exists()) {
$response->error('Customer not found', 400);
}
// Check if the user requires a reference
if ((new users_o())->getCustomerByIdOrCustomerNumber((int)$data['customer_id'])->requiresReference() && empty($data['reference'])) {
if ($targetUser->requiresReference() && empty($data['reference'])) {
$response->error('Reference is required by the customer', 400);
}
// Get the registration number
+24
View File
@@ -0,0 +1,24 @@
<?php
// prevent direct access
if (!defined('WD')) {
exit;
}
global $REDIS_CONFIG;
function warn($message): void
{
echo "\n\033[33m$message\033[0m\n";
}
// Check if the MINIO array is set
if (!isset($REDIS_CONFIG)) {
throw new Exception('REDIS array is not set in config.php');
}
// Check if the MINIO array has the required keys
if (!isset($REDIS_CONFIG['host']) || !isset($REDIS_CONFIG['database']) || !isset($REDIS_CONFIG['password'])) {
throw new Exception('REDIS array is missing required keys');
}
// Create a new Redis object
$logs_o = new objects\logs_o();
$logs_o->syncLogsToDatabase();
+103 -21
View File
@@ -56,27 +56,6 @@ trait redis_t
return $this->redis->exists($key);
}
/**
* Set the value in the Redis server
* @param string $key
* @param string $value
* @return redis|redis_t
*/
public function set(string $key, string $value): self
{
$this->redis->set($key, $value);
return $this;
}
/**
* Get all keys from the Redis server
* @return array
*/
public function keys(): array
{
return $this->redis->keys('*');
}
/**
* Get the Redis client
* @return PredisClient
@@ -246,4 +225,107 @@ trait redis_t
{
$this->redis->disconnect();
}
/**
* Set array key in Redis
* @param string $key
* @param array $value
* @return redis|redis_t
*/
public function set_array(string $key, array $value): self
{
$this->set($key, json_encode($value));
return $this;
}
/**
* Set the value in the Redis server
* @param string $key
* @param string $value
* @return redis|redis_t
*/
public function set(string $key, string $value): self
{
$this->redis->set($key, $value);
return $this;
}
/**
* Clear keys from Redis
* @param array $keys
* @return redis|redis_t
*/
public function clear_keys(array $keys): self
{
foreach ( $keys as $key ) {
$this->delete($key);
}
return $this;
}
/**
* Get arrays from Redis
* @param string $key The key to search for (supports wildcards)
* @return array|null
*/
public function get_arrays(string $key): array|null
{
$keys = $this->get_keys($key);
$arrays = [];
foreach ( $keys as $key ) {
$arrays[] = $this->get_array($key);
}
return $arrays;
}
/**
* Get keys from Redis
* @param string $key The key to search for (supports wildcards)
* @return array
*/
public function get_keys(string $key): array
{
// Get all keys from the cache
return $this->redis->keys($key);
}
/**
* Get all keys from the Redis server
* @return array
*/
public function keys(): array
{
return $this->redis->keys('*');
}
/**
* Get array key from Redis
* @param string $key
* @return array|null
*/
public function get_array(string $key): array|null
{
// Get the array from the cache
$value = $this->get($key);
// Check if the value is not null
if ($value === null) {
return null;
}
// Check if the value is not a valid JSON
if (!self::is_json($value)) {
return null;
}
return json_decode($value, true);
}
/**
* Check if the value is a valid JSON
* @param string $value
* @return bool
*/
private function is_json(string $value): bool
{
json_decode($value);
return json_last_error() === JSON_ERROR_NONE;
}
}