- Added functionality to create and attach wash certificates during booking completion. - Enhanced `completeBooking` to generate and associate wash certificates with orders based on booking items. - Updated safety seal parameter handling in relevant methods. - Integrated wash certificate PDF generation with customer branding and order attachment logic. - Improved file retrieval logic in the `file_server` to handle missing certificates via alternative store lookup.
356 lines
13 KiB
PHP
356 lines
13 KiB
PHP
<?php
|
|
|
|
namespace objects;
|
|
|
|
use attachments\helpers\attachment_content;
|
|
use classes\db;
|
|
use classes\email;
|
|
use classes\gatewayapi;
|
|
use classes\object_property;
|
|
use classes\pdf_generator;
|
|
use classes\slack;
|
|
use Exception;
|
|
use traits\db_object_t;
|
|
|
|
class order_bookings_o extends db
|
|
{
|
|
use db_object_t;
|
|
|
|
public object_property $customer_number;
|
|
public object_property $department;
|
|
public object_property $reg_1;
|
|
public object_property $reg_2;
|
|
public object_property $reg_3;
|
|
public object_property $datetime;
|
|
public object_property $note;
|
|
public object_property $reference;
|
|
public object_property $po;
|
|
public object_property $pickup;
|
|
public object_property $items;
|
|
public object_property $order_id;
|
|
public object_property $created_at;
|
|
public object_property $updated_at;
|
|
public object_property $deleted_at;
|
|
|
|
|
|
public function structure(): void
|
|
{
|
|
$this->setTable('order_bookings');
|
|
}
|
|
|
|
/**
|
|
* Add an object
|
|
* @param array $data The additional data of the object (e.g. ["key" => "value"])
|
|
* @return void
|
|
* @throws Exception If the object was not created successfully
|
|
*/
|
|
public function add(
|
|
array $data,
|
|
): void
|
|
{
|
|
global /** @var db $db */
|
|
$db;
|
|
// Add the object to the database
|
|
$new_id = self::add_object($data);
|
|
self::select($new_id);
|
|
$this->onAfterNewBooking();
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
*/
|
|
public function onAfterNewBooking(): void
|
|
{
|
|
self::requireSelected();
|
|
// TODO: Send department notification (Slack, SMS)
|
|
}
|
|
|
|
/**
|
|
* Notify the department about a new booking
|
|
* @throws Exception If the object is not selected
|
|
* @throws ClientExceptionInterface If the request to the API fails
|
|
*/
|
|
public function notifyNewBooking(): void
|
|
{
|
|
self::requireSelected();
|
|
// Get the department from the booking
|
|
$department = (new departments_o())->select((int)$this->department->value());
|
|
if (!$department->exists()) {
|
|
throw new Exception('Department not found');
|
|
}
|
|
// Get the branding from the department
|
|
$branding = (new branding_o())->select((int)$department->branding->value());
|
|
if (!$branding->exists()) {
|
|
throw new Exception('Branding not found');
|
|
}
|
|
// Get the customer from the booking
|
|
$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_\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());
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public function getObjectProperties(): void
|
|
{
|
|
$this->customer_number = new object_property($this->table, $this->id, 'customer_number', 'int', false);
|
|
$this->department = new object_property($this->table, $this->id, 'department', 'int', false);
|
|
$this->reg_1 = new object_property($this->table, $this->id, 'reg_1', 'string', false);
|
|
$this->reg_2 = new object_property($this->table, $this->id, 'reg_2', 'string', false);
|
|
$this->reg_3 = new object_property($this->table, $this->id, 'reg_3', 'string', false);
|
|
$this->datetime = new object_property($this->table, $this->id, 'datetime', 'timestamp', false);
|
|
$this->note = new object_property($this->table, $this->id, 'note', 'string', false);
|
|
$this->reference = new object_property($this->table, $this->id, 'reference', 'string', false);
|
|
$this->po = new object_property($this->table, $this->id, 'po', 'string', false);
|
|
$this->pickup = new object_property($this->table, $this->id, 'pickup', 'bool', false);
|
|
$this->items = new object_property($this->table, $this->id, 'items', 'json', false);
|
|
$this->order_id = new object_property($this->table, $this->id, 'order_id', 'int', false);
|
|
$this->created_at = new object_property($this->table, $this->id, 'created_at', 'timestamp', false);
|
|
$this->updated_at = new object_property($this->table, $this->id, 'updated_at', 'timestamp', false);
|
|
$this->deleted_at = new object_property($this->table, $this->id, 'deleted_at', 'timestamp', false);
|
|
}
|
|
|
|
public function objectChanged(): void
|
|
{
|
|
//TODO: Add cache invalidation
|
|
}
|
|
|
|
|
|
public function asArray(): array
|
|
{
|
|
$order_id = $this->order_id->value();
|
|
return [
|
|
'id' => (int)$this->id,
|
|
'customer_number' => (int)$this->customer_number->value(),
|
|
'department' => (int)$this->department->value(),
|
|
'reg_1' => $this->reg_1->value(),
|
|
'reg_2' => $this->reg_2->value(),
|
|
'reg_3' => $this->reg_3->value(),
|
|
'datetime' => $this->datetime->value(),
|
|
'note' => $this->note->value(),
|
|
'reference' => $this->reference->value(),
|
|
'po' => $this->po->value(),
|
|
'pickup' => (bool)$this->pickup->value(),
|
|
'items' => $this->items->value(),
|
|
'order_id' => $order_id === null ? null : (int)$order_id,
|
|
'created_at' => $this->created_at->value(),
|
|
'updated_at' => $this->updated_at->value(),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
*/
|
|
public function completeBooking(int $user_id, string $safety_seal = null): void
|
|
{
|
|
self::requireSelected();
|
|
if (!$this->order_id->value()) {
|
|
// Create order, if not already created
|
|
self::createOrderBy($user_id);
|
|
// Add order items, re-calculate the prices to be customer-specific
|
|
self::createOrderItemsBy($user_id);
|
|
}
|
|
// TODO: Create wash certificate
|
|
if (self::containsWashCertificateItem()) self::attachWashCertificate($user_id, $safety_seal);
|
|
// TODO: Send wash certificate
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
*/
|
|
public function createOrderBy(int $user_id): void
|
|
{
|
|
self::requireSelected();
|
|
// Create order
|
|
$orders = new orders_o();
|
|
$orders->createOrderFromBooking($this->id, $user_id);
|
|
// Set the order id in the booking
|
|
$this->order_id->set((int)$orders->id);
|
|
self::objectChanged();
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
*/
|
|
public function createOrderItemsBy(int $user_id): void
|
|
{
|
|
self::requireSelected();
|
|
// Get the order
|
|
$order = self::getOrder();
|
|
$order->requireSelected();
|
|
// Add order items
|
|
foreach ($this->items->value() as $item) {
|
|
if (!isset($item['id']) || !isset($item['quantity'])) {
|
|
continue;
|
|
}
|
|
$orderItems = new order_items_o();
|
|
$orderItems->addItemToOrder(
|
|
(int)$order->id,
|
|
(int)$item['id'],
|
|
(int)$user_id,
|
|
(int)$item['quantity'],
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
*/
|
|
private function containsWashCertificateItem(): bool
|
|
{
|
|
self::requireSelected();
|
|
return self::containsProductId(41);
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
*/
|
|
private function containsProductId(int $productId): bool
|
|
{
|
|
self::requireSelected();
|
|
$items = $this->items->value();
|
|
foreach ($items as $item) {
|
|
if (isset($item['id']) && (int)$item['id'] == $productId) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
*/
|
|
public function getOrder(): orders_o
|
|
{
|
|
self::requireSelected();
|
|
if (!$this->order_id->value()) {
|
|
throw new \Exception('Order not found for this booking');
|
|
}
|
|
$order = new orders_o();
|
|
$order->select((int)$this->order_id->value());
|
|
if (!$order->exists()) {
|
|
throw new \Exception('Order not found for this booking');
|
|
}
|
|
return $order;
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
*/
|
|
private function attachWashCertificate(int $user_id, string $safety_seal = null): void
|
|
{
|
|
self::requireSelected();
|
|
// Check if the order already has a wash certificate attached
|
|
if (self::getOrder()->hasWashCertificateAttached()) {
|
|
return;
|
|
}
|
|
// Get the operator name
|
|
$operator = (new users_o())->select($user_id);
|
|
if (!$operator->exists()) {
|
|
throw new Exception('Operator not found');
|
|
}
|
|
// Generate wash certificate
|
|
self::generateWashCertificate($safety_seal, $operator->display_name->value());
|
|
}
|
|
|
|
/**
|
|
* Generate a wash certificate
|
|
* @param int|null $safety_seal The safety seal number
|
|
* @param string|null $operator The operator name
|
|
* @throws Exception If the object is not selected
|
|
* @throws Exception If the booking already has a wash certificate
|
|
*/
|
|
public function generateWashCertificate(int|null $safety_seal = null, string|null $operator = null): void
|
|
{
|
|
self::requireSelected();
|
|
// Generate the wash certificate
|
|
// Get the department from the booking
|
|
$department = (new departments_o())->select((int)$this->department->value());
|
|
if (!$department->exists()) {
|
|
throw new Exception('Department not found');
|
|
}
|
|
// Get the branding from the department
|
|
$branding = (new branding_o())->select((int)$department->branding->value());
|
|
if (!$branding->exists()) {
|
|
throw new Exception('Branding not found');
|
|
}
|
|
// Get the customer from the booking
|
|
$customer = (new users_o())->getUserByCustomerNumber((int)$this->customer_number->value());
|
|
$department_array = $department->asArray();
|
|
$customer_array = $customer->asArray();
|
|
$booking_array = self::asArray();
|
|
$department_array['branding'] = $branding->asArray();
|
|
//print_r($department_array);
|
|
//print_r($customer_array);
|
|
//print_r($booking_array);
|
|
$pdf_generator = new pdf_generator();
|
|
$pdf_generator->add_html($pdf_generator->templates->getTemplate('wash_certificate')
|
|
->setCompany([
|
|
'name' => 'Truck Wash',
|
|
'address' => 'Letland Allé 2',
|
|
'zip' => 2630,
|
|
'city' => 'Taastrup',
|
|
'phone_prefix' => 45,
|
|
'phone' => 43717886,
|
|
'email' => 'cph@truckwash.dk',
|
|
'website' => 'www.truckwash.dk',
|
|
'images' => [
|
|
'logo' => '/truckwash-banner-png.png',
|
|
'banner' => '/truckwash-banner-png.png',
|
|
'signature' => '/truckwash-underskrift.png',
|
|
],
|
|
])
|
|
->addData([
|
|
'booking_number' => $this->id,
|
|
'seal_number' => ($safety_seal ?? null),
|
|
'reg_1' => $booking_array['reg_1'],
|
|
'reg_2' => $booking_array['reg_2'],
|
|
'date' => date('d-m-Y'),
|
|
'time' => date('H:i'),
|
|
'carried_out_by' => ($operator ?? null),
|
|
'department_id' => $department->id,
|
|
'department_name' => $department_array['branding']['name'] ?: $department_array['name'],
|
|
'department_address' => $department_array['branding']['address'] ?: $department_array['description'],
|
|
'customer_name' => $customer->getCustomerName($customer_array['customer_number']),
|
|
'customer_address' => $customer->getCustomerEcocomicData($customer_array['customer_number'])->economic_customer->address ?: '-',
|
|
'wash_type' => 'BOOK_WASH'
|
|
])
|
|
->getHtml()
|
|
);
|
|
$pdf_path = $pdf_generator->generate_pdf();
|
|
// Set the PDF in the order
|
|
$this->getOrder()->addAttachment(new attachment_content((object)['document' => $pdf_path, 'other' => 'wash_certificate']));
|
|
}
|
|
|
|
} |