Publication initiale de RelaisSMS : documentation et sources nettoyees

This commit is contained in:
2026-10-21 09:29:39 +02:00
commit ac186b03b1
158 changed files with 24818 additions and 0 deletions
@@ -0,0 +1,99 @@
<?php
namespace App\Services\Sms;
use App\Models\CalendarReminder;
use App\Models\SmsCampaign;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class SmsCampaignReconciler
{
public function __construct(private readonly OvhSmsProvider $provider) {}
public function reconcile(SmsCampaign $campaign): SmsCampaign
{
try {
$messages = $this->provider->outgoing($campaign);
} catch (SmsProviderException $exception) {
Log::warning('SMS campaign verification unavailable.', [
'sms_campaign_id' => $campaign->id,
'reason' => $exception->getMessage(),
]);
return $campaign;
}
return $this->applyOutgoing($campaign, $messages);
}
/** @param array<int, array<string, mixed>> $messages */
public function applyOutgoing(SmsCampaign $campaign, array $messages): SmsCampaign
{
return DB::transaction(function () use ($campaign, $messages): SmsCampaign {
$campaign = SmsCampaign::query()->lockForUpdate()->findOrFail($campaign->id);
if (! in_array($campaign->status, ['uncertain', 'sending'], true)) {
return $campaign;
}
$byNumber = [];
foreach ($messages as $message) {
if (($message['tag'] ?? null) !== $campaign->provider_tag
|| ($message['message'] ?? null) !== $campaign->message
|| empty($message['id']) || empty($message['receiver'])) {
continue;
}
$byNumber[(string) $message['receiver']] = $message;
}
foreach ($campaign->deliveries()->whereIn('status', ['uncertain', 'queued'])->get() as $delivery) {
$message = $byNumber[$delivery->number] ?? null;
if ($message === null) {
$delivery->update(['status' => 'uncertain']);
continue;
}
// "sent" records acceptance by OVH, not delivery to the handset.
$delivery->update([
'status' => 'sent',
'provider_message_id' => (string) $message['id'],
'provider_response' => $message,
'error_message' => null,
'sent_at' => $message['sentAt'] ?? $message['creationDatetime'] ?? now(),
]);
}
$sentCount = $campaign->deliveries()->where('status', 'sent')->count();
$failedCount = $campaign->deliveries()->where('status', 'failed')->count();
$unconfirmed = $campaign->deliveries()->whereIn('status', ['uncertain', 'queued'])->exists();
$status = $unconfirmed ? 'uncertain' : ($failedCount > 0 ? ($sentCount > 0 ? 'partial' : 'failed') : 'sent');
$campaign->update([
'status' => $status,
'sent_count' => $sentCount,
'failed_count' => $failedCount,
'sent_at' => $campaign->deliveries()->where('status', 'sent')->min('sent_at'),
'response_payload' => ['verification' => 'OVH outgoing history', 'confirmed_recipients' => $sentCount],
'error_message' => $unconfirmed
? 'Certains envois restent a verifier chez OVH. Aucun renvoi automatique ; ne pas renvoyer cette campagne.'
: null,
]);
CalendarReminder::query()->where('sms_campaign_id', $campaign->id)->where('status', 'uncertain')->update([
'status' => $status === 'uncertain' ? 'uncertain' : ($sentCount > 0 ? 'sent' : 'failed'),
'last_error' => $campaign->error_message,
'sent_at' => $campaign->sent_at,
]);
Log::info('SMS campaign verified against OVH history.', [
'sms_campaign_id' => $campaign->id,
'sent_count' => $sentCount,
'status' => $status,
]);
return $campaign->fresh(['deliveries', 'user']);
});
}
}