Enhance booking handling with service options and transactions

Added support for including customer name, department name, and parsed services in `asArray()` method. Introduced functionality for creating transactions, linking bookings to orders, and properly handling related services. Improved department daily report handling and removed unnecessary fields.
This commit is contained in:
Jepp9350
2025-04-16 12:37:57 +02:00
parent 69b39fcba2
commit 8c70e6e3bc
6 changed files with 349 additions and 111 deletions
+252 -7
View File
@@ -356,12 +356,23 @@ class bookings_o extends db
}
/**
* Convert the object to an array
* @options include_customer_name Include the customer name
* @options include_department_name Include the department name
* @options include_parsed_services Include the parsed services
* @param array $options [@options] The options to include in the array
* @return array The object as an array
* @throws Exception If the object is not selected
*/
public function asArray(): array
public function asArray(array $options = []): array
{
self::requireSelected();
return [
$options = array_merge([
'include_customer_name' => false,
'include_department_name' => false,
'include_parsed_services' => false,
], $options);
$tmp_array = [
'id' => (int)$this->id,
'customer_number' => (int)$this->customer_number->value(),
'wash_type' => $this->wash_type->value(),
@@ -380,16 +391,39 @@ class bookings_o extends db
'status' => $this->status->value(),
'data' => $this->data->value() ? json_decode($this->data->value(), true) : null,
];
// Include the customer name
if ($options['include_customer_name']) {
$customer = (new users_o())->getUserByCustomerNumber((int)$this->customer_number->value());
$tmp_array['customer_name'] = $customer->getCustomerName($this->customer_number->value());
}
// Include the department name
if ($options['include_department_name']) {
$department = (new departments_o())->select((int)$this->department->value());
if ($department->exists()) {
$tmp_array['department_name'] = $department->name->value();
}
}
// Include the parsed services
if ($options['include_parsed_services']) {
// Format the wash type from the services array as followed:
// 1 => 'Udvendig sættevognstræk ( Trækker / trailer )',
$tmp_array['parsed_services']['string'] = $this->formatWashTypeFromServices(
$this->data->value() ? json_decode($this->data->value(), true) : []
);
$tmp_array['parsed_services']['array'] = $this->data->value() ? json_decode($this->data->value(), true) : [];
}
return $tmp_array;
}
/**
* Format the wash type from the services array
* @param array $services The services array
* @return string The formatted wash type
*/
private function formatWashTypeFromServices(array $services): string
{
// Format the wash type from the services array
$wash_services = [
1 => 'Udvendig sættevognstræk ( Trækker / trailer )',
2 => 'Udvendigt trailer vask',
3 => 'Indvendig trailer vask',
];
$wash_services = self::getWashServicesString(self::getWashServices());
$string = '';
foreach ( $services as $service ) {
if (isset($wash_services[$service])) {
@@ -400,6 +434,89 @@ class bookings_o extends db
return rtrim($string, ', ');
}
private static function getWashServicesString(array $services): array
{
// Format the wash services as a string (product1, product2, product3)
$string = [];
foreach ( $services as $key => $service ) {
if (isset($service['overrides']['name'])) {
$string[$key] = $service['overrides']['name'];
} else {
$string[$key] = $service['name'];
}
}
return $string;
}
/**
* @throws Exception
*/
private function getWashServices(): array
{
// Define the product function
// Get the wash services from the database
return [
// Exterior wash "Sættevognstræk"
1 => self::defineProduct(1, 3, [
'name' => 'Udvendig sættevognstræk ( Trækker / trailer )',
'description' => 'Udvendig vask af sættevognstræk',
]),
// Exterior trailer wash "Udvendig trailer vask"
2 => self::defineProduct(2, 2, [
'name' => 'Udvendig trailer vask',
'description' => 'Udvendig vask af trailer',
]),
3 => self::defineProduct(3, 10, [
'name' => 'Indvendig trailer vask',
'description' => 'Indvendig vask af trailer',
]),
4 => self::defineProduct(41, 41),
];
}
/**
* Define a product for the booking
* @param int $id
* @param int $product_id
* @param array $overrides
* @param array $options
* @param array $addons
* @return array
* @throws Exception
* @see getWashServices()
* @see getWashServicesString()
*/
private function defineProduct(int $id, int $product_id, array $overrides = [], array $options = [], array $addons = []): array
{
// Check if the product exists
if (!empty($product_id)) {
$product_obj = (new products_o())->select((int)$product_id);
if ($product_obj->exists()) {
$default_options = $product_obj->asArray();
}
}
// Return the product
return [
'id' => (int)$id,
'product_id' => (int)$product_id,
'addons' => [...$addons],
...($default_options ?? []),
'overrides' => [
'name' => null,
'quantity' => null,
'description' => null,
'notes' => null,
'reference' => null,
...$overrides,
],
...$options,
];
}
public function checkUnfulfilledBookings(): void
{
$unfulfilled_bookings = [];
@@ -543,6 +660,10 @@ class bookings_o extends db
$pdf_path = $pdf_generator->generate_pdf();
// Set the PDF in the booking
$this->wash_certificate_pdf->set($pdf_path);
// Add the wash certificate to the bookings data (If it does not exist)
if (!self::hasServiceInBookingData(4)) {
self::addServiceToBookingData(4);
}
}
/**
@@ -559,6 +680,37 @@ class bookings_o extends db
return false;
}
/**
* Check if the booking data has a service
* @param int $service_id The service id
* @return bool True if the service exists, false otherwise
* @throws Exception If the object is not selected
*/
public function hasServiceInBookingData(int $service_id): bool
{
self::requireSelected();
// Get the current data
$data = $this->data->value() ? json_decode($this->data->value(), true) : [];
// Check if the service exists
return in_array($service_id, $data);
}
/**
* Add a service to the booking data
* @param int $service_id The service id
* @throws Exception If the object is not selected
*/
public function addServiceToBookingData(int $service_id): void
{
self::requireSelected();
// Get the current data
$data = $this->data->value() ? json_decode($this->data->value(), true) : [];
// Add the service to the data
$data[] = (int)$service_id;
// Set the data
$this->data->set(json_encode($data));
}
/**
* Send the wash certificate to the customer
* @throws Exception If the object is not selected
@@ -584,4 +736,97 @@ class bookings_o extends db
}
/**
* @throws Exception
*/
public function createTransaction(): orders_o
{
global $response;
self::requireSelected();
// Get the services from the booking
$services = $this->data->value() ? json_decode($this->data->value(), true) : [];
// Get the department from the booking
$department = (new departments_o())->select((int)$this->department->value());
if (!$department->exists()) {
throw new Exception('Department not found');
}
// Create a new order
$order = new orders_o();
$order->add(
(int)$this->customer_number->value(),
(int)$this->id,
(string)$this->reference_number->value(),
(string)$this->notes->value(),
(int)$this->department->value(),
(string)$this->regNrTraekker->value(),
(string)$this->regNrTrailer->value(),
);
// Set the orders booking id
$order->booking_id->set((int)$this->id);
// Define the relation order item ids, when applicable.
$relations = [
// This is the order item id for the primary product, the wash certificate applies to.
// This can be left null, if the product does not exist.
4 => null,
];
// Sort the services, so the primary product is first, and the services with relations are last.
$services_sorted = [];
$services_not_relation = [];
$services_relation = [];
foreach ( $services as $service ) {
// Get the service id
$service_id = (int)$service;
// Check if the service has the posibility to have a relation (null values are allowed)
if (in_array($service_id, array_keys($relations))) {
$services_relation[] = $service_id;
} else {
$services_not_relation[] = $service_id;
}
}
// Sort the services, so the primary product is first, and the services with (potential) relations are last.
$services_sorted = [
...$services_not_relation,
...$services_relation,
];
// Add the services to the order
foreach ( $services_sorted as $service_id ) {
$service = self::getWashServiceProduct((int)$service_id);
// Add the service to the order
$tmp_order_item = new order_items_o();
$tmp_order_item->addItemToOrder(
$order->id,
(int)$service->id,
(int)$response->get_user()->id,
(int)1,
$relations[(int)$service_id] ?? null,
);
// Check if the service allows for a wash certificate
if ((int)$service_id === 3) {
// Set the relation id for the wash certificate
$relations[4] = (int)$tmp_order_item->id;
}
}
// Return the order
return $order;
}
/**
* @throws Exception
*/
private function getWashServiceProduct(int $service_id): products_o
{
// Get the product id from the service id
$services = self::getWashServices();
if (!isset($services[$service_id])) {
throw new Exception('Service not found');
}
$product_id = $services[$service_id]['product_id'];
// Get the wash service product from the database
$product = (new products_o())->select($product_id);
if (!$product->exists()) {
throw new Exception('Product not found');
}
return $product;
}
}