From 88457bb44ab5089cba5e2cc821d6c4de758aa625 Mon Sep 17 00:00:00 2001 From: Vincent BRIDIER Date: Tue, 27 May 2025 10:29:56 +0200 Subject: [PATCH] feat: Add Tickets state export notification --- .env.example | 4 +- app/Console/Commands/CreateUser.php | 2 +- app/Console/Commands/ExportTicketsState.php | 38 ++++++ app/Console/Commands/TestMail.php | 4 +- app/Console/Kernel.php | 2 + app/Jobs/ExportTicketsState.php | 117 ++++++++++++++++++ app/Models/Ticket.php | 11 ++ .../ExportTicketsStateNotification.php | 60 +++++++++ composer.json | 2 +- composer.lock | 2 +- config/mail.php | 4 +- 11 files changed, 237 insertions(+), 9 deletions(-) create mode 100644 app/Console/Commands/ExportTicketsState.php create mode 100644 app/Jobs/ExportTicketsState.php create mode 100644 app/Notifications/ExportTicketsStateNotification.php diff --git a/.env.example b/.env.example index 0152884..3867f99 100644 --- a/.env.example +++ b/.env.example @@ -30,8 +30,8 @@ MAIL_PASSWORD=null MAIL_ENCRYPTION=null MAIL_FROM_ADDRESS=noreply-sw@ldc.fr MAIL_FROM_NAME="${APP_NAME}" -MAIL_LIST_SERVICEWEB=equipe.web@ldc.fr -MAIL_ADMIN=equipe.web@ldc.fr +MAIL_LIST_SERVICEWEB=digital@ldc.fr +MAIL_ADMIN=digital@ldc.fr # Sentry SENTRY_LARAVEL_DSN= diff --git a/app/Console/Commands/CreateUser.php b/app/Console/Commands/CreateUser.php index 127f606..e2fa154 100644 --- a/app/Console/Commands/CreateUser.php +++ b/app/Console/Commands/CreateUser.php @@ -117,7 +117,7 @@ class CreateUser extends Command { while (is_null($this->email)) { try { - $tmp = $this->ask('Type the wanted user email', 'equipe.web@ldc.fr'); + $tmp = $this->ask('Type the wanted user email', 'digital@ldc.fr'); $validator = Validator::make(['email' => $tmp], [ 'email' => 'required|unique:users,email|email:rfc,dns' ]); diff --git a/app/Console/Commands/ExportTicketsState.php b/app/Console/Commands/ExportTicketsState.php new file mode 100644 index 0000000..f2cecdd --- /dev/null +++ b/app/Console/Commands/ExportTicketsState.php @@ -0,0 +1,38 @@ +info('Running the Job, this could take some time.'); + $job = new JobsExportTicketsState(); + $job->handle(); + $this->info('Job completed'); + + return 0; + } +} diff --git a/app/Console/Commands/TestMail.php b/app/Console/Commands/TestMail.php index ae0936b..0bcbec8 100644 --- a/app/Console/Commands/TestMail.php +++ b/app/Console/Commands/TestMail.php @@ -19,7 +19,7 @@ class TestMail extends Command * * @var string */ - protected $description = 'Send test email to equipe.web@ldc.fr'; + protected $description = 'Send test email to digital@ldc.fr'; /** * Execute the console command. @@ -29,7 +29,7 @@ class TestMail extends Command public function handle() { Mail::raw(sprintf('UWIL mail-test from %s %s', \config('app.name'), \config('app.url')), function ($msg) { - $msg->to('equipe.web@ldc.fr')->subject('Test Email'); + $msg->to('digital@ldc.fr')->subject('Test Email'); }); return 0; } diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index c356b30..deaa85a 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -3,6 +3,7 @@ namespace App\Console; use App\Jobs\AutoCloseOldTickets; +use App\Jobs\ExportTicketsState; use App\Jobs\WarnBeforeAutoCloseTicket; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; @@ -24,6 +25,7 @@ class Kernel extends ConsoleKernel */ protected function schedule(Schedule $schedule) { + $schedule->job(ExportTicketsState::class)->weekly()->mondays()->at('07:00'); $schedule->job(AutoCloseOldTickets::class)->dailyAt('08:00'); $schedule->job(WarnBeforeAutoCloseTicket::class)->dailyAt('08:05'); } diff --git a/app/Jobs/ExportTicketsState.php b/app/Jobs/ExportTicketsState.php new file mode 100644 index 0000000..7d9ec7b --- /dev/null +++ b/app/Jobs/ExportTicketsState.php @@ -0,0 +1,117 @@ +header; + + // Récupération des tickets. + Ticket::query() + ->whereNotIn( + 'status', + [TicketStatusEnum::archived, TicketStatusEnum::production] + ) + ->orderBy(Site::select('name') + ->whereColumn('sites.id', 'tickets.site_id')) + ->orderBy('order')->get()->each(function (Ticket $ticket) use (&$csvlines, &$lastSiteId, &$order) { + $csvlines[] = [ + "", + $ticket->site->name, + $ticket->id, + $lastSiteId === $ticket->site_id ? $order + 1 : 1, + $ticket->date_mep?->format('d-m-Y') ?? 'No MEP Date', + $ticket->type->label(), + $ticket->title, + $ticket->status->label(), + $ticket->projectManager->name ?? 'No PM', + $ticket->assignedUser()->name ?? 'No Assigned User', + Carbon::create($ticket->getRawOriginal('last_activity'))->format('d-m-Y H:i:s'), + $ticket->created_at->format('d-m-Y H:i:s'), + route('bo.ticket.show', $ticket->id), + $ticket->gitlab_issue ?? 'No GitLab Issue' + ]; + + $order = $lastSiteId === $ticket->site_id ? $order + 1 : 1; + $lastSiteId = $ticket->site_id; + }); + + Notification::route('mail', config('mail.MAIL_ADMIN')) + ->notify(new ExportTicketsStateNotification($this->array2csv($csvlines, ";"))); + } + + /** + * converts an array to a csv stream + * + * @param array $data + * @param string $delimiter + * @param string $enclosure + * @param string $escape_char + * + * @return string + */ + protected function array2csv( + array $data, + string $delimiter = ',', + string $enclosure = '"', + string $escape_char = "\\" + ) { + $f = fopen('php://memory', 'r+'); + + // UTF-8 BOM. + $BOM = "\xEF\xBB\xBF"; + fwrite($f, $BOM); + + foreach ($data as $item) { + fputcsv($f, $item, $delimiter, $enclosure, $escape_char); + } + rewind($f); + return stream_get_contents($f); + } +} diff --git a/app/Models/Ticket.php b/app/Models/Ticket.php index 5eda697..c74230e 100644 --- a/app/Models/Ticket.php +++ b/app/Models/Ticket.php @@ -152,6 +152,17 @@ class Ticket extends Model return $this->belongsTo(User::class, 'assigned_to'); } + /** + * BelongsTo User relation + * The user that is in charge of the site linked to this ticket + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function projectManager() + { + return $this->belongsTo(User::class, 'project_manager_id'); + } + /** * HasMany Message relation * diff --git a/app/Notifications/ExportTicketsStateNotification.php b/app/Notifications/ExportTicketsStateNotification.php new file mode 100644 index 0000000..ed889c7 --- /dev/null +++ b/app/Notifications/ExportTicketsStateNotification.php @@ -0,0 +1,60 @@ +csvContent = $csvContent; + } + + /** + * Get the notification's delivery channels. + * + * @return array + */ + public function via(): array + { + return ['mail']; + } + + /** + * Get the mail representation of the notification. + * + * @return \Illuminate\Notifications\Messages\MailMessage + */ + public function toMail(): \Illuminate\Notifications\Messages\MailMessage + { + return (new MailMessage()) + ->subject(trans("Export de l'état des lieux des tickets")) + ->line(trans("Vous trouverez ci-joint le fichier CSV contenant l'état des tickets.")) + ->attachData( + $this->csvContent, + sprintf('tickets_state_%s.csv', Carbon::now()->format('Y-m-d_H-i-s')), + [ + 'mime' => 'text/csv', + ] + ); + } +} diff --git a/composer.json b/composer.json index c29be5d..1ec1a34 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "type": "project", "description": "Support web", "support": { - "email": "equipe.web@ldc.fr" + "email": "digital@ldc.fr" }, "keywords": [ "framework", diff --git a/composer.lock b/composer.lock index 12380b4..adc9497 100644 --- a/composer.lock +++ b/composer.lock @@ -8700,7 +8700,7 @@ "authors": [ { "name": "Equipe Web", - "email": "equipe.web@ldc.fr", + "email": "digital@ldc.fr", "homepage": "https://www.ldc.fr" } ], diff --git a/config/mail.php b/config/mail.php index 7e619ed..030c464 100644 --- a/config/mail.php +++ b/config/mail.php @@ -16,7 +16,7 @@ return [ 'default' => env('MAIL_MAILER', 'smtp'), // * Mail admin - 'MAIL_ADMIN' => env('MAIL_ADMIN', 'equipe.web@ldc.fr'), + 'MAIL_ADMIN' => env('MAIL_ADMIN', 'digital@ldc.fr'), /* |-------------------------------------------------------------------------- @@ -100,7 +100,7 @@ return [ ], 'contactsList' => [ - 'serviceweb' => env('MAIL_LIST_SERVICEWEB', 'equipe.web@ldc.fr') + 'serviceweb' => env('MAIL_LIST_SERVICEWEB', 'digital@ldc.fr') ], /*