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:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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 () {
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user