Files
WMS/Modules/Helpdesk/Services/TicketReferenceService.php
T
2026-06-23 11:05:48 +01:00

59 lines
1.6 KiB
PHP

<?php
/**
* TicketReferenceService.php
*
* Generates collision-resistant Helpdesk ticket references.
*/
declare(strict_types=1);
namespace Modules\Helpdesk\Services;
use Illuminate\Support\Facades\DB;
use Modules\Helpdesk\Models\Ticket;
final class TicketReferenceService
{
/**
* Build the next human-readable ticket reference for the current year.
*
* The lookup uses the highest numeric suffix, not the latest database id,
* because imported, restored, or manually adjusted tickets may not be in
* reference order. On PostgreSQL an advisory transaction lock is also used
* so two users cannot generate the same reference at the same time.
*/
public function next(): string
{
$year = now()->format('Y');
$prefix = 'HD-'.$year.'-';
$this->lockReferenceSeries($prefix);
$lastReference = Ticket::query()
->where('reference', 'like', $prefix.'%')
->orderByDesc('reference')
->value('reference');
$next = $lastReference === null
? 1
: ((int) substr((string) $lastReference, -5)) + 1;
return $prefix.str_pad((string) $next, 5, '0', STR_PAD_LEFT);
}
/**
* Lock the current ticket reference series for the active transaction.
*/
private function lockReferenceSeries(string $prefix): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
return;
}
DB::select('select pg_advisory_xact_lock(hashtext(?))', [
'helpdesk-ticket-reference:'.$prefix,
]);
}
}