major helpdesk updates

This commit is contained in:
Mark Gregory
2026-06-15 13:47:58 +01:00
parent 330d6922a4
commit b668116b11
47 changed files with 2350 additions and 23 deletions
@@ -7,9 +7,12 @@ namespace Modules\Helpdesk\Services;
use App\Models\User;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\URL;
use Modules\Helpdesk\Models\Ticket;
use Modules\Helpdesk\Models\WorkflowLog;
use Modules\Helpdesk\Models\WorkflowTemplate;
use Illuminate\Support\Str;
use Throwable;
final class WorkflowNotificationService
@@ -19,7 +22,7 @@ final class WorkflowNotificationService
*/
public function dispatch(Ticket $ticket, string $event, ?User $actor = null): void
{
$ticket->loadMissing(['owner', 'agent', 'status', 'priority', 'category', 'project', 'team']);
$ticket->loadMissing(['owner', 'agent', 'status', 'priority', 'category', 'project', 'team', 'product']);
WorkflowTemplate::query()
->where('event', $event)
@@ -34,8 +37,9 @@ final class WorkflowNotificationService
return;
}
$trackingToken = Str::random(48);
$subject = $this->renderText($template->subject, $ticket, $actor);
$html = $this->wrapHtml($this->renderText($template->html_body, $ticket, $actor), $ticket);
$html = $this->wrapHtml($this->renderText($template->html_body, $ticket, $actor), $ticket, $trackingToken);
$text = $this->renderText($template->text_body ?: strip_tags($template->html_body), $ticket, $actor);
try {
@@ -51,7 +55,7 @@ final class WorkflowNotificationService
}
});
$this->log($template, $ticket, $event, (string) $recipient->email, 'sent', null, $subject);
$this->log($template, $ticket, $event, (string) $recipient->email, 'sent', null, $subject, $trackingToken);
} catch (Throwable $exception) {
Log::warning('Helpdesk workflow email failed.', ['event' => $event, 'ticket_id' => $ticket->id, 'error' => $exception->getMessage()]);
$this->log($template, $ticket, $event, (string) $recipient->email, 'failed', $exception->getMessage(), $subject);
@@ -87,7 +91,7 @@ final class WorkflowNotificationService
return strtr($template, $tokens);
}
private function wrapHtml(string $body, Ticket $ticket): string
private function wrapHtml(string $body, Ticket $ticket, ?string $trackingToken = null): string
{
return '<div style="font-family:Inter,Arial,sans-serif;background:#f6f8fb;padding:24px">'
.'<div style="max-width:720px;margin:0 auto;background:#ffffff;border:1px solid #d8dee8;border-radius:18px;overflow:hidden">'
@@ -98,10 +102,24 @@ final class WorkflowNotificationService
.'</div><div style="padding:28px;color:#1f2937;line-height:1.65">'
.$body
.'<p style="margin-top:28px"><a href="'.e(route('helpdesk.tickets.show', ['ticket' => $ticket->getKey()])).'" style="display:inline-block;background:#2563eb;color:#ffffff;text-decoration:none;padding:11px 16px;border-radius:10px">Open ticket</a></p>'
.$this->trackingPixel($trackingToken)
.'</div></div></div>';
}
private function log(WorkflowTemplate $template, Ticket $ticket, string $event, ?string $recipient, string $status, ?string $error = null, ?string $subject = null): void
private function trackingPixel(?string $trackingToken): string
{
if ($trackingToken === null) {
return '';
}
$url = Route::has('helpdesk.workflow.open')
? route('helpdesk.workflow.open', ['token' => $trackingToken])
: URL::to('/'.trim((string) config('helpdesk.route_prefix', 'helpdesk'), '/').'/workflow/open/'.$trackingToken);
return '<img src="'.e($url).'" width="1" height="1" alt="" style="display:none" />';
}
private function log(WorkflowTemplate $template, Ticket $ticket, string $event, ?string $recipient, string $status, ?string $error = null, ?string $subject = null, ?string $trackingToken = null): void
{
WorkflowLog::query()->create([
'template_id' => $template->id,
@@ -110,6 +128,7 @@ final class WorkflowNotificationService
'recipient' => $recipient,
'subject' => $subject,
'status' => $status,
'tracking_token' => $trackingToken,
'error' => $error,
]);
}