Generate and attach wash certificate to orders

- Added `generateWashCertificate` method to `orders_o` for wash certificate PDF generation and attachment.
- Introduced `OTHER_TYPE_WASH_CERTIFICATE` constant in `attachment_content` for new attachment type.
- Added `/order/wash-certificate` route to provide wash certificate generation functionality via API.
This commit is contained in:
Jeppe Bundgaard
2025-12-03 08:45:13 +01:00
parent 3c46ee86ec
commit d3d3657dfd
3 changed files with 141 additions and 0 deletions
@@ -4,6 +4,7 @@ namespace attachments\helpers;
class attachment_content
{
const OTHER_TYPE_WASH_CERTIFICATE = 'WASH_CERTIFICATE';
public ?string $image; // Used to store the attachment object name, in the attachment store.
public ?string $document; // Used to store the attachment object name, in the attachment store.
public ?attachment_relation $relation; // Used to store the attachment relation object.
+83
View File
@@ -2,10 +2,13 @@
namespace objects;
use attachments\helpers\attachment_content;
use classes\db;
use classes\pdf_generator;
use classes\motorapi;
use classes\object_property;
use classes\response;
use DateTime;
use Exception;
use helpers\xlvask_usage_log;
use helpers\xlvask_wash_item;
@@ -1376,6 +1379,86 @@ class orders_o extends db
return false; // No wash certificate product found in the order items
}
/**
* Generate and attach a wash certificate directly on an order (without a booking)
* @param int|null $safety_seal Optional safety seal number
* @param string|null $operator Optional operator/employee name who carried out the wash
* @param string|DateTime|null $date Optional date of the wash (defaults to current date)
* @throws Exception If the order is not selected or required related objects are missing
*/
public function generateWashCertificate(int|null $safety_seal = null, string|null $operator = null, $date = null): void
{
self::requireSelected();
// Avoid generating duplicate certificates
if ($this->hasWashCertificateAttached()) {
return;
}
// Get the department for the order
$department = (new departments_o())->select((int)$this->department_id->value());
if (!$department->exists()) {
throw new Exception('Department not found');
}
// Get branding for the department
$branding = (new branding_o())->select((int)$department->branding->value());
if (!$branding->exists()) {
throw new Exception('Branding not found');
}
// Get the customer for the order
$customer = (new users_o())->getUserByCustomerNumber((int)$this->customer_id->value());
$department_array = $department->asArray();
$department_array['branding'] = $branding->asArray();
$customer_array = $customer->asArray();
$order_array = $this->asArray();
// Format the date as 17:35 02-12-2025
$date = ($date instanceof DateTime ? $date : ($date !== null ? new DateTime($date) : new DateTime()));
$date_formatted = ($date instanceof DateTime ? $date->format('d-m-Y') : date('d-m-Y'));
$time_formatted = ($date instanceof DateTime ? $date->format('H:i') : date('H:i'));
// Generate PDF
$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, // Used as document number on the template
'seal_number' => ($safety_seal ?? null),
'reg_1' => $order_array['reg_1'],
'reg_2' => $order_array['reg_2'],
'date' => $date_formatted,
'time' => $time_formatted,
'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' => 'ORDER_WASH'
])
->getHtml()
);
$pdf_path = $pdf_generator->generate_pdf();
// Attach PDF to the order
$this->addAttachment(new attachment_content((object)[
'document' => $pdf_path,
'other' => attachment_content::OTHER_TYPE_WASH_CERTIFICATE,
]));
}
/**
* @throws Exception
*/
+57
View File
@@ -54,6 +54,63 @@ class orderRoute
]
);
$this->post('/order/wash-certificate', function () {
// Require the user to be logged in and have permission
global /** @var response $response */
$response;
$this->requirePermission('complete_bookings');
// Get the user
$user = (new authentication())->get_user();
if (!$user) {
(new logs_o())->add('orders', 'global', 1, 0, 'GENERATE_ORDER_WASH_CERTIFICATE', 'No user found, or invalid session');
$response->error('Invalid session', 400);
}
// Parse request body
$data = json_decode(file_get_contents('php://input'), true) ?? [];
if (!isset($data['id']) || !(int)$data['id']) {
$response->error('Order id is required', 400);
}
$orders_o = new orders_o();
$orders_o->select((int)$data['id']);
if (!$orders_o->exists()) {
$response->error('Order not found', 400);
}
// Check department access
self::requireDepartmentAccess($orders_o->department_id->value());
// Collect optional params
$safety_seal = null;
if (isset($data['safety_seal']) && $data['safety_seal'] !== '') {
$safety_seal = (int)$data['safety_seal'];
}
$operator = isset($data['operator']) && $data['operator'] !== '' ? (string)$data['operator'] : (string)$user->display_name->value();
// Set the date to the creation date of the order if not provided
if (isset($data['date']) && $data['date'] !== '') {
$date = date('Y-m-d H:i:s', strtotime($data['date']));
} else {
$date = date('Y-m-d H:i:s', strtotime($orders_o->created_at->value()));
}
// Determine if already exists
$already_exists = $orders_o->hasWashCertificateAttached();
// Generate (no-op if already exists)
$orders_o->generateWashCertificate($safety_seal, $operator, $date);
$now_exists = $orders_o->hasWashCertificateAttached();
(new logs_o())->add('orders', $orders_o->department_id->value(), 1, $user->id, 'GENERATE_ORDER_WASH_CERTIFICATE', 'Wash certificate ' . ($already_exists ? 'already existed' : 'generated'));
$response->success([
'order_id' => (int)$orders_o->id,
'created' => !$already_exists && $now_exists,
'already_existed' => $already_exists,
]);
}, [
'complete_bookings' => 'Generate and attach a wash certificate PDF to an order',
'department_access_:id' => 'Access to the department the order is in'
]);
/**
* $this->put('/order', function () {
*