Files
L-Ami-Fiduciaire/app/Http/Controllers/BulkNotificationController.php

107 lines
3.8 KiB
PHP
Raw Normal View History

<?php
namespace App\Http\Controllers;
use App\Concerns\HasWorkspaceScope;
use App\Enums\DeclarationStatus;
use App\Http\Requests\BulkNotifyRequest;
use App\Mail\DeclarationFileRequestMail;
use App\Models\Declaration;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
class BulkNotificationController extends Controller
{
use HasWorkspaceScope;
public function store(BulkNotifyRequest $request): RedirectResponse
{
$workspace = $this->currentWorkspace();
$user = $request->user();
$workspaceUser = $user->currentWorkspaceUser();
$declarations = Declaration::where('workspace_id', $workspace->id)
->forUser($user, $workspaceUser)
->where('status', DeclarationStatus::EnAttenteClient)
->whereIn('id', $request->validated('declaration_ids'))
->with('client')
->get()
->filter(fn (Declaration $d) => $d->client !== null);
if ($declarations->isEmpty()) {
return back()->with('flash', [
'type' => 'warning',
'message' => 'Aucune déclaration éligible trouvée.',
]);
}
// DB transaction for invitation creation/update, collect mail data for queuing after commit
$mailJobs = DB::transaction(function () use ($declarations) {
$jobs = [];
foreach ($declarations as $declaration) {
$clientEmail = $declaration->client->contact_email;
$invitation = $declaration->invitations()
->whereNull('used_at')
->latest()
->first();
if ($invitation && $invitation->isValid()) {
if ($invitation->email !== $clientEmail) {
$invitation->update(['email' => $clientEmail]);
$invitation->refresh();
}
} elseif ($invitation && ! $invitation->isValid()) {
$invitation->update([
'email' => $clientEmail,
'expires_at' => now()->addDays(30),
]);
$invitation->refresh();
} else {
$invitation = $declaration->invitations()->create([
'email' => $clientEmail,
'expires_at' => now()->addDays(30),
]);
}
$body = 'Nous vous invitons à déposer les documents complémentaires pour votre déclaration "'
. $declaration->title . '".';
$jobs[] = [
'email' => $declaration->client->contact_email,
'mailable' => new DeclarationFileRequestMail($declaration, $invitation, $body),
];
}
return $jobs;
});
// Queue emails outside transaction (Redis is not transactional with MySQL)
foreach ($mailJobs as $job) {
Mail::to($job['email'])->queue($job['mailable']);
}
activity()
->performedOn($workspace)
->causedBy($user)
->withProperties([
'count' => $declarations->count(),
'declaration_ids' => $declarations->pluck('id')->all(),
])
->log('bulk_client_notification');
// Invalidate notification caches for workspace users
$workspace->users->each(function ($wsUser) use ($workspace) {
Cache::forget("user:{$wsUser->id}:workspace:{$workspace->id}:unread_notifications");
});
return back()->with('flash', [
'type' => 'success',
'message' => $declarations->count() . ' notifications envoyées',
]);
}
}