Add support for customer booking notifications and phone number updates
- Introduced phone number update functionality in `userSecurityRoute`. - Enhanced `order_bookings_o` to send booking confirmations to customers via SMS and email. - Added `sendOrderBookingConfirmationEmail` method in `email` for HTML-based email notifications. - Updated `notifyNewBooking` to include customer confirmation logic with SMS and email. - Adjusted `users_o` to make phone and email properties public and added `setPhoneNumber` method. - Optimized notification logic in `order_bookings_o` with department and customer-specific notifications.
This commit is contained in:
@@ -335,5 +335,52 @@ class email implements email_i
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws JsonException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function sendOrderBookingConfirmationEmail(\objects\order_bookings_o $order_booking): void
|
||||
{
|
||||
// Validate the booking object
|
||||
$order_booking->requireSelected();
|
||||
// Get customer details
|
||||
$customer = (new users_o())->getUserByCustomerNumber((int)$order_booking->customer_number->value());
|
||||
$customer->requireSelected();
|
||||
$recipient_name = $customer->getCustomerName((int)$customer->customer_number->value());
|
||||
$recipient_email = $customer->email->value();
|
||||
// Get the department details
|
||||
$department = (new departments_o())->select((int)$order_booking->department->value());
|
||||
$department->requireSelected();
|
||||
// Generate HTML email
|
||||
$html = self::generateHtmlHeader();
|
||||
// Add email content
|
||||
$html .= (new email_template_booking_confirmation(
|
||||
$order_booking->id,
|
||||
$recipient_name,
|
||||
$customer->customer_number->value(),
|
||||
$customer->email->value(),
|
||||
$order_booking->reference->value(),
|
||||
$order_booking->reg_1->value(),
|
||||
$order_booking->reg_2->value(),
|
||||
($order_booking->containsWashCertificateItem() ? 'Ja' : 'Nej'),
|
||||
$customer->email->value(), // Wash certificate email is the customer's email
|
||||
$order_booking->datetime->value(),
|
||||
(string)$department->getDepartmentName((int)$department->id),
|
||||
(string)$department->getBranding()->address->value(),
|
||||
!!$order_booking->pickup->value() ? 'Ja' : 'Nej',
|
||||
$order_booking->note->value()
|
||||
))->generate_html();
|
||||
// Add email footer
|
||||
$html .= self::generateHtmlFooter();
|
||||
// Send email
|
||||
$this->sendEmailMailerSend(
|
||||
$recipient_email,
|
||||
$department->getDepartmentName((int)$department->id),
|
||||
'Truck Wash Booking ( ID: ' . $order_booking->id . ', REF: ' . $order_booking->reference->value() . ' )',
|
||||
'',
|
||||
$html
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -73,8 +73,10 @@ class order_bookings_o extends db
|
||||
public function notifyNewBooking(): void
|
||||
{
|
||||
self::requireSelected();
|
||||
$department_notification = false;
|
||||
$customer_notification = true;
|
||||
/**
|
||||
* Department booking notification
|
||||
* Get the department, branding and customer
|
||||
*/
|
||||
// Get the department from the booking
|
||||
$department = (new departments_o())->select((int)$this->department->value());
|
||||
@@ -90,36 +92,84 @@ class order_bookings_o extends db
|
||||
$customer = (new users_o())->getUserByCustomerNumber((int)$this->customer_number->value());
|
||||
$department_array = $department->asArray();
|
||||
$customer_array = $customer->asArray();
|
||||
// Define delivery methods
|
||||
$deliverSlack = (boolean)!empty($department->slack_webhook->value());
|
||||
$deliverSMS = true;
|
||||
// Check if the department has a slack webhook
|
||||
if ($deliverSlack) {
|
||||
// Construct email
|
||||
$message = "*" . $branding->name->value() . "*\n";
|
||||
$message .= "_New Booking Created (TEST)_\n\n";
|
||||
$message .= "*Customer:* " . $customer->getCustomerName($customer_array['customer_number']) . " (`" . $customer_array['customer_number'] . "`)\n";
|
||||
// Send a notification to the department
|
||||
$slack = new slack();
|
||||
$slack->send_department_booking_notification($department->id, $message);
|
||||
}
|
||||
|
||||
if ($deliverSMS) {
|
||||
// Send an SMS notification to the department
|
||||
$gatewayapi = new gatewayapi();
|
||||
try {
|
||||
$gatewayapi->send(
|
||||
[
|
||||
// Add all the phone numbers from the department
|
||||
...$department->notificationSmsPhoneNumbers()
|
||||
],
|
||||
'New booking from ' . $customer->getCustomerName($customer_array['customer_number']) . ' (' . $this->id . ')',
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
// Log the error
|
||||
$logs = new logs_o();
|
||||
$logs->add('gatewayapi', 0, 3, 0, 'SEND_DEPARTMENT_BOOKING_NOTIFICATION', $e->getMessage());
|
||||
/**
|
||||
* Department booking notification
|
||||
*/
|
||||
if ($department_notification) {
|
||||
// Define delivery methods
|
||||
$deliverSlack = (boolean)!empty($department->slack_webhook->value());
|
||||
$deliverSMS = true;
|
||||
// Check if the department has a slack webhook
|
||||
if ($deliverSlack) {
|
||||
// Construct email
|
||||
$message = "*" . $branding->name->value() . "*\n";
|
||||
$message .= "_New Booking Created (TEST)_\n\n";
|
||||
$message .= "*Customer:* " . $customer->getCustomerName($customer_array['customer_number']) . " (`" . $customer_array['customer_number'] . "`)\n";
|
||||
// Send a notification to the department
|
||||
$slack = new slack();
|
||||
$slack->send_department_booking_notification($department->id, $message);
|
||||
}
|
||||
|
||||
if ($deliverSMS) {
|
||||
// Send an SMS notification to the department
|
||||
$gatewayapi = new gatewayapi();
|
||||
try {
|
||||
$gatewayapi->send(
|
||||
[
|
||||
// Add all the phone numbers from the department
|
||||
...$department->notificationSmsPhoneNumbers()
|
||||
],
|
||||
'New booking from ' . $customer->getCustomerName($customer_array['customer_number']) . ' (' . $this->id . ')',
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
// Log the error
|
||||
$logs = new logs_o();
|
||||
$logs->add('gatewayapi', 0, 3, 0, 'SEND_DEPARTMENT_BOOKING_NOTIFICATION', $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Customer booking confirmation
|
||||
*/
|
||||
if ($customer_notification) {
|
||||
// Check if the customer has a phone number
|
||||
$country_code = $customer->phone_country_code->value();
|
||||
$customer_phone = $customer->phone->value();
|
||||
$customer_email = $customer->email->value();
|
||||
if (empty($customer_phone) && empty($customer_email)) {
|
||||
return;
|
||||
}
|
||||
if (!empty($customer_phone)) {
|
||||
// Send an SMS confirmation to the customer
|
||||
$gatewayapi = new gatewayapi();
|
||||
$message = "Tak for din booking hos " . $branding->name->value() . ". Dit bookingnummer er " . $this->id . ". "
|
||||
. "\nDato: " . date('d-m-Y', strtotime($this->datetime->value())) . "."
|
||||
. "\nKøretøj: " . $this->reg_1->value() . (!empty($this->reg_2->value()) ? ", " . $this->reg_2->value() : "") . (
|
||||
!empty($this->reg_3->value()) ? ", " . $this->reg_3->value() : ""
|
||||
) .". "
|
||||
. "\nAdresse: " . $branding->address->value() . ". "
|
||||
. "\nVi glæder os til at se dig!";
|
||||
try {
|
||||
$gatewayapi->send(
|
||||
[
|
||||
(string)$country_code . (string)$customer_phone,
|
||||
],
|
||||
$message,
|
||||
true
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
// Log the error
|
||||
$logs = new logs_o();
|
||||
$logs->add('gatewayapi', 0, 3, 0, 'SEND_CUSTOMER_BOOKING_CONFIRMATION', $e->getMessage());
|
||||
}
|
||||
}
|
||||
// Check if the customer has an email
|
||||
if (!empty($customer_email)) {
|
||||
// Send an email confirmation to the customer
|
||||
$email = new email();
|
||||
$email->sendOrderBookingConfirmationEmail($this);
|
||||
}
|
||||
// TODO: Send booking confirmation to customer
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,7 +280,7 @@ class order_bookings_o extends db
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
private function containsWashCertificateItem(): bool
|
||||
public function containsWashCertificateItem(): bool
|
||||
{
|
||||
self::requireSelected();
|
||||
return self::containsProductId(41);
|
||||
|
||||
@@ -34,9 +34,9 @@ class users_o extends db
|
||||
public language_pack_en_us $language_pack;
|
||||
public object_property $xlvask_customer_id;
|
||||
protected object_property $password;
|
||||
protected object_property $phone_country_code;
|
||||
protected object_property $phone;
|
||||
protected object_property $email;
|
||||
public object_property $phone_country_code;
|
||||
public object_property $phone;
|
||||
public object_property $email;
|
||||
protected array $wash_subscription_transactions;
|
||||
|
||||
public function structure(): void
|
||||
@@ -1333,4 +1333,16 @@ class users_o extends db
|
||||
return $customer_numbers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setPhoneNumber(int $phone_number, int $country_code = 45): void
|
||||
{
|
||||
self::requireSelected();
|
||||
// Set the phone number
|
||||
$this->phone->set((int)$phone_number);
|
||||
$this->phone_country_code->set((int)$country_code);
|
||||
$this->objectChanged();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,7 +34,7 @@ class userSecurityRoute
|
||||
}
|
||||
// Validate the password
|
||||
$password = (string)self::getParameter('password');
|
||||
self::requireMinLength('password', 5);
|
||||
self::requireMinLength('password', 4);
|
||||
self::requireMaxLength('password', 255);
|
||||
self::requireType($password, self::type_string());
|
||||
if (!$user->passwordMatches($password)) {
|
||||
@@ -65,7 +65,7 @@ class userSecurityRoute
|
||||
self::requireParameters(['password']);
|
||||
// Validate the password
|
||||
$password = (string)self::getParameter('password');
|
||||
self::requireMinLength('password', 5);
|
||||
self::requireMinLength('password', 4);
|
||||
self::requireMaxLength('password', 255);
|
||||
self::requireType($password, self::type_string());
|
||||
if (!$user->passwordMatches($password)) {
|
||||
@@ -120,5 +120,35 @@ class userSecurityRoute
|
||||
'user_security_change_password' => 'Change the password of the user',
|
||||
]
|
||||
);
|
||||
|
||||
$this->post('/account/security/change-phone-number', function () {
|
||||
// Require the user to be logged in
|
||||
global $response;
|
||||
self::requirePermission('user_security_change_phone_number');
|
||||
$user = (new authentication())->get_user();
|
||||
if (!$user) {
|
||||
(new logs_o())->add('user_security', 'global', 0, 0, 'USER_SECURITY_CHANGE_PHONE_NUMBER', 'User not logged in');
|
||||
$response->error('Invalid session', 400);
|
||||
}
|
||||
// Require the phone_number parameter
|
||||
self::requireParameters(['phone_number', 'country_code']);
|
||||
// Validate the phone number
|
||||
$phone_number = (int)self::getParameter('phone_number');
|
||||
self::requireMinLength('phone_number', 4);
|
||||
self::requireMaxLength('phone_number', 20);
|
||||
self::requireType($phone_number, self::type_int());
|
||||
$country_code = (int)self::getParameter('country_code');
|
||||
self::requireMinLength('country_code', 1);
|
||||
self::requireMaxLength('country_code', 5);
|
||||
self::requireType($country_code, self::type_int());
|
||||
// Change the phone number
|
||||
$user->setPhoneNumber($phone_number, $country_code);
|
||||
(new logs_o())->add('user_security', 'global', 0, $user->id, 'USER_SECURITY_CHANGE_PHONE_NUMBER', 'Phone number changed');
|
||||
$response->success(['message' => 'Phone number changed']);
|
||||
},
|
||||
[
|
||||
'user_security_change_phone_number' => 'Change the phone number of the user',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user