Send wash certificate email to customers during order bookings

- Added `sendWashCertificateToCustomer` method in `order_bookings_o` to handle email sending for wash certificates.
- Implemented `sendWashCertificateEmailToCustomer` in `email` to generate and attach wash certificate PDFs.
- Updated attachment permission logic in `ordersRoute` and `db_object_t`.
- Changed `object_attachments_o` property types and handling for improved attachment processing.
This commit is contained in:
Jeppe Bundgaard
2025-11-11 15:32:10 +01:00
parent 65bf42d3e3
commit 5193038bea
6 changed files with 94 additions and 10 deletions
+58
View File
@@ -386,5 +386,63 @@ class email implements email_i
); );
} }
/**
* @throws JsonException
* @throws Exception
*/
public function sendWashCertificateEmailToCustomer(\objects\order_bookings_o $order_booking): void
{
// Validate the booking object
$order_booking->requireSelected();
if (!$order_booking->hasTransaction()) return; // Only send a wash certificate if the order has been created.
// Get the order details
$order = $order_booking->getOrder();
// 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();
// Check if the customer has a booking-specific email provided
if (!empty($customer->wash_certificate_email->value())) {
$recipient_email = (string)$customer->wash_certificate_email->value();
}
// Generate HTML email
$html = self::generateHtmlHeader();
// Add email content
$html .= (new email_template_wash_certificate(
$order_booking->id,
$recipient_name,
))->generate_html();
// Add email footer
$html .= self::generateHtmlFooter();
// Attach the wash certificate
$attachments = $order->listAttachments();
$pdf = null;
foreach ($attachments as $attachment) {
if ($attachment->isWashCertificate()) {
$pdf = (new pdf_store())->download($attachment->content->document);
break;
}
}
if (!$pdf) {
throw new Exception('Wash certificate PDF not found for order booking ID: ' . $order_booking->id);
}
// Send email
$this->sendEmailMailerSend(
$recipient_email,
$recipient_name,
'Truck Wash Booking ( ID: ' . $order_booking->id . ', REF: ' . $order_booking->reference->value() . ' )',
'',
$html,
null,
[
[
$pdf,
'wash_certificate_' . $order_booking->id . '_' . $order_booking->reference->value() . '.pdf'
]
]
);
}
} }
@@ -2,6 +2,7 @@
namespace interfaces; namespace interfaces;
use attachments\helpers\attachment;
use attachments\helpers\attachment_content; use attachments\helpers\attachment_content;
use objects\object_attachments_o; use objects\object_attachments_o;
@@ -12,7 +13,7 @@ interface attachments_i
* @param string $type The type of the entity parent. (E.g. users_o, groups_o, etc.) * @param string $type The type of the entity parent. (E.g. users_o, groups_o, etc.)
* @param int $object_id The ID of the entity. * @param int $object_id The ID of the entity.
* @param array $options Optional parameters for filtering or modifying the retrieval. * @param array $options Optional parameters for filtering or modifying the retrieval.
* @return object_attachments_o[] An array of attachment objects. * @return attachment[] An array of attachment objects.
*/ */
public function list(string $type, int $object_id, array $options = []): array; public function list(string $type, int $object_id, array $options = []): array;
/** /**
@@ -44,7 +44,7 @@ class object_attachments_o extends db
{ {
$this->object_type = new object_property($this->table, $this->id, 'object_type', 'string', false); $this->object_type = new object_property($this->table, $this->id, 'object_type', 'string', false);
$this->object_id = new object_property($this->table, $this->id, 'object_id', 'int', false); $this->object_id = new object_property($this->table, $this->id, 'object_id', 'int', false);
$this->content = new object_property($this->table, $this->id, 'content', 'string', false); $this->content = new object_property($this->table, $this->id, 'content', 'json', false);
$this->created_at = new object_property($this->table, $this->id, 'created_at', 'string', false); $this->created_at = new object_property($this->table, $this->id, 'created_at', 'string', false);
$this->updated_at = new object_property($this->table, $this->id, 'updated_at', 'string', false); $this->updated_at = new object_property($this->table, $this->id, 'updated_at', 'string', false);
$this->deleted_at = new object_property($this->table, $this->id, 'deleted_at', 'string', false); $this->deleted_at = new object_property($this->table, $this->id, 'deleted_at', 'string', false);
@@ -61,7 +61,7 @@ class object_attachments_o extends db
'id' => (int)$this->id, 'id' => (int)$this->id,
'object_type' => (string)$this->object_type->value(), 'object_type' => (string)$this->object_type->value(),
'object_id' => (int)$this->object_id->value(), 'object_id' => (int)$this->object_id->value(),
'content' => json_decode($this->content->value(), true), 'content' => $this->content->value(),
'created_at' => $this->created_at->value(), 'created_at' => $this->created_at->value(),
'updated_at' => $this->updated_at->value(), 'updated_at' => $this->updated_at->value(),
'deleted_at' => $this->deleted_at->value(), 'deleted_at' => $this->deleted_at->value(),
@@ -32,6 +32,33 @@ class order_bookings_o extends db
public object_property $updated_at; public object_property $updated_at;
public object_property $deleted_at; public object_property $deleted_at;
/**
* @throws Exception
*/
public function sendWashCertificateToCustomer(): void
{
self::requireSelected();
// Get the customer from the booking
$customer = (new users_o())->getUserByCustomerNumber((int)$this->customer_number->value());
if (!$customer->exists()) {
return;
}
// Check if the customer wants email notifications
if (!$customer->wantsEmailNotifications()) {
return;
}
// Get the email
$customer_email = !empty($customer->wash_certificate_email->value())
? $customer->wash_certificate_email->value()
: $customer->email->value();
if (empty($customer_email)) {
return;
}
// Send wash certificate email
$email = new email();
$email->sendWashCertificateEmailToCustomer($this);
}
public function structure(): void public function structure(): void
{ {
@@ -235,9 +262,10 @@ class order_bookings_o extends db
// Add order items, re-calculate the prices to be customer-specific // Add order items, re-calculate the prices to be customer-specific
self::createOrderItemsBy($user_id); self::createOrderItemsBy($user_id);
} }
// TODO: Create wash certificate // Create a wash certificate (If applicable)
if (self::containsWashCertificateItem()) self::attachWashCertificate($user_id, $safety_seal); if (self::containsWashCertificateItem()) self::attachWashCertificate($user_id, $safety_seal);
// TODO: Send wash certificate // Send wash certificate
self::sendWashCertificateToCustomer();
} }
/** /**
+1 -4
View File
@@ -475,12 +475,9 @@ class ordersRoute
$hasPermission = true; $hasPermission = true;
self::requirePermission('list_own_order_attachments'); self::requirePermission('list_own_order_attachments');
} }
} else {
$hasPermission = true;
self::requirePermission('list_order_attachments');
} }
if (!$hasPermission) { if (!$hasPermission) {
$response->error('You do not have permission to list attachments for this order', 403); self::requirePermission('list_order_attachments');
} }
// Get the attachments // Get the attachments
$attachments = $order->listAttachments(); $attachments = $order->listAttachments();
+1 -1
View File
@@ -1248,7 +1248,7 @@ trait db_object_t
} }
/** /**
* List attachments of the (current) object * List attachments of the (current) object
* @return object_attachments_o[] The list of attachments of the object * @return attachment[] The list of attachments of the object
* @throws Exception If the object is not selected, it throws an exception * @throws Exception If the object is not selected, it throws an exception
*/ */
public function listAttachments(): array public function listAttachments(): array