From 95b69e94961159959ccd801780c3c92716295586 Mon Sep 17 00:00:00 2001 From: Corentin Huet Date: Wed, 11 Feb 2026 13:21:29 +0100 Subject: [PATCH] feat: :sparkles: add new status + sync of g-wip label with in development --- app/Console/Commands/UpdateGitlabDatas.php | 54 ++++++++++++++++++++-- app/Console/Kernel.php | 2 +- app/Enums/Tickets/TicketStatusEnum.php | 5 +- app/Models/Ticket.php | 43 +++++++++-------- 4 files changed, 76 insertions(+), 28 deletions(-) diff --git a/app/Console/Commands/UpdateGitlabDatas.php b/app/Console/Commands/UpdateGitlabDatas.php index e85a6c1..629eb62 100644 --- a/app/Console/Commands/UpdateGitlabDatas.php +++ b/app/Console/Commands/UpdateGitlabDatas.php @@ -2,14 +2,16 @@ namespace App\Console\Commands; +use Carbon\Carbon; +use App\Models\Ticket; use App\Models\GitlabIssues; use App\Models\GitlabLabels; -use App\Models\GitlabMilestones; use App\Models\GitlabProjects; -use Carbon\Carbon; -use GrahamCampbell\GitLab\Facades\GitLab; use Illuminate\Console\Command; +use App\Models\GitlabMilestones; use Illuminate\Support\Facades\Cache; +use App\Enums\Tickets\TicketStatusEnum; +use GrahamCampbell\GitLab\Facades\GitLab; class UpdateGitlabDatas extends Command { @@ -48,6 +50,8 @@ class UpdateGitlabDatas extends Command $this->updateMilestonesByProject($project); $this->updateIssuesByProject($project, $isCron); } + + $this->syncTicketStatus(); } /** @@ -191,6 +195,7 @@ class UpdateGitlabDatas extends Command ); $issueModel = GitlabIssues::where('gitlab_id', $issue['id'])->firstOrFail(); + $labelIds = []; foreach ($issue['labels'] as $labelName) { $label = Cache::remember("gitlab_label_{$labelName}", 300, function () use ($labelName) { @@ -198,9 +203,11 @@ class UpdateGitlabDatas extends Command }); if ($label) { - $issueModel->gitlabLabels()->syncWithoutDetaching($label); + $labelIds[] = $label; } } + + $issueModel->gitlabLabels()->sync($labelIds); }//end foreach $this->info("Gitlab issues upsert complete."); @@ -257,4 +264,43 @@ class UpdateGitlabDatas extends Command $this->info("Gitlab milestones upsert complete."); } + + /** + * Synchronizes ticket statuses based on GitLab issue labels. + * + * @return void + */ + private function syncTicketStatus(): void + { + $tickets = Ticket::whereNotNull('gitlab_issue')->whereNot('status', TicketStatusEnum::archived)->get(); + + foreach ($tickets as $ticket) { + $gitlabIssue = GitlabIssues::where('url', $ticket->gitlab_issue)->with('gitlabLabels')->first(); + + $gitlabIssueLabels = $gitlabIssue ? $gitlabIssue->gitlabLabels->pluck('name') : []; + + if ($gitlabIssueLabels) { + match (true) { + $gitlabIssueLabels->contains('g-wip') => $this->updateTicketStatus($ticket, TicketStatusEnum::inDev), + default => null, + }; + } + } + } + + /** + * Updates the ticket status only if it has changed. + * + * @param Ticket $ticket The ticket to update. + * @param TicketStatusEnum $status The new status to apply. + * + * @return void + */ + private function updateTicketStatus(Ticket $ticket, TicketStatusEnum $status): void + { + if ($ticket->status !== $status && $ticket->status !== TicketStatusEnum::waiting) { + $ticket->status = $status; + $ticket->saveOrFail(); + } + } } diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index f226000..6fca931 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -28,7 +28,7 @@ class Kernel extends ConsoleKernel $schedule->job(ExportTicketsState::class)->weekly()->mondays()->at('07:00'); $schedule->job(AutoCloseOldTickets::class)->dailyAt('08:00'); $schedule->job(WarnBeforeAutoCloseTicket::class)->dailyAt('08:05'); - $schedule->command('app:update-gitlab-datas --is-cron')->twiceDaily(1, 13); + $schedule->command('app:update-gitlab-datas --is-cron')->hourly()->between('7:00', '19:00'); } /** diff --git a/app/Enums/Tickets/TicketStatusEnum.php b/app/Enums/Tickets/TicketStatusEnum.php index 744be98..b14de01 100644 --- a/app/Enums/Tickets/TicketStatusEnum.php +++ b/app/Enums/Tickets/TicketStatusEnum.php @@ -17,6 +17,7 @@ enum TicketStatusEnum: int case recetteValidated = 7; case production = 8; case archived = 9; + case inDev = 10; /** * Optionnal labels definition @@ -24,13 +25,14 @@ enum TicketStatusEnum: int private const LABELS = [ self::new->name => "Nouveau", self::estimateTodo->name => "Étude chef(s) de projet", - self::takenInAccount->name => "Pris en compte", + self::takenInAccount->name => "À planifier", self::waiting->name => "En attente de réponse", self::waitingValidation->name => "En attente de validation", self::recette->name => "En recettage", self::recetteValidated->name => "Recettage validé", self::production->name => "En production", self::archived->name => "Archivé", + self::inDev->name => "En cours de développement", ]; /** @@ -46,6 +48,7 @@ enum TicketStatusEnum: int self::recetteValidated->name => 'text-success', self::production->name => 'text-success', self::archived->name => 'text-secondary', + self::inDev->name => 'text-discovery', ]; /** diff --git a/app/Models/Ticket.php b/app/Models/Ticket.php index b96617b..11fb8b6 100644 --- a/app/Models/Ticket.php +++ b/app/Models/Ticket.php @@ -2,23 +2,25 @@ namespace App\Models; -use App\Enums\Users\RoleEnum; -use App\Enums\Tickets\TicketStatusEnum; -use App\Enums\Tickets\TicketTypeEnum; use App\Events\NotifyAdmin; -use App\Events\NotifySubscriptions; -use App\Events\TicketStatusChanged; -use App\Jobs\SendTicketMentionMail; use App\Mail\TicketMention; +use Illuminate\Support\Str; +use App\Models\GitlabIssues; +use App\Enums\Users\RoleEnum; use App\Models\Credit\Account; use App\Models\Credit\Estimation; use App\Models\Ticket\TicketType; -use Illuminate\Database\Eloquent\Factories\HasFactory; -use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\ModelNotFoundException; -use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Collection; -use Illuminate\Support\Str; +use App\Events\NotifySubscriptions; +use App\Events\TicketStatusChanged; +use App\Jobs\SendTicketMentionMail; +use App\Enums\Tickets\TicketTypeEnum; +use App\Enums\Tickets\TicketStatusEnum; +use Illuminate\Database\Eloquent\Model; +use GrahamCampbell\GitLab\Facades\GitLab; +use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\ModelNotFoundException; class Ticket extends Model { @@ -75,23 +77,20 @@ class Ticket extends Model if ( !$ticket->original['status'] !== $ticket->status->value && $ticket->original['order'] === $ticket->order ) { + $user = auth()->user(); + event(new TicketStatusChanged( $ticket, TicketStatusEnum::make($ticket->original['status']), - auth()->user(), + $user, null, false )); - event(new NotifySubscriptions($ticket, sprintf( - '%s a modifié le statut en %s', - auth()->user()->name, - $ticket->status->label() - ))); - event(new NotifyAdmin($ticket, sprintf( - '%s a modifié le statut en %s', - auth()->user()->name, - $ticket->status->label() - ))); + + $message = $user ? sprintf('%s a modifié le statut en %s', $user->name, $ticket->status->label()) : sprintf('Le statut a été modifié en %s', $ticket->status->label()); + + event(new NotifySubscriptions($ticket, $message)); + event(new NotifyAdmin($ticket, $message)); } if ($ticket->status->equals(TicketStatusEnum::archived)) { self::setOrder($ticket, true);