pases 4 ticket updates

This commit is contained in:
Mark Gregory
2026-06-23 11:05:48 +01:00
parent a6148f9bfd
commit 2266298b6c
5 changed files with 142 additions and 57 deletions
@@ -1,27 +1,58 @@
<?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.
* 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.'-';
$last = Ticket::query()
$this->lockReferenceSeries($prefix);
$lastReference = Ticket::query()
->where('reference', 'like', $prefix.'%')
->latest('id')
->orderByDesc('reference')
->value('reference');
$next = $last ? ((int) substr((string) $last, -5)) + 1 : 1;
$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,
]);
}
}