feat: ✨ add new status + sync of g-wip label with in development

This commit is contained in:
Corentin Huet 2026-02-11 13:21:29 +01:00
parent 1794076c91
commit 95b69e9496
4 changed files with 76 additions and 28 deletions

View file

@ -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();
}
}
}

View file

@ -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');
}
/**

View file

@ -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',
];
/**

View file

@ -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(
'<b>%s</b> a modifié le statut en <b>%s</b>',
auth()->user()->name,
$ticket->status->label()
)));
event(new NotifyAdmin($ticket, sprintf(
'<b>%s</b> a modifié le statut en <b>%s</b>',
auth()->user()->name,
$ticket->status->label()
)));
$message = $user ? sprintf('<b>%s</b> a modifié le statut en <b>%s</b>', $user->name, $ticket->status->label()) : sprintf('Le statut a été modifié en <b>%s</b>', $ticket->status->label());
event(new NotifySubscriptions($ticket, $message));
event(new NotifyAdmin($ticket, $message));
}
if ($ticket->status->equals(TicketStatusEnum::archived)) {
self::setOrder($ticket, true);