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> $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']); }); } }