$selectedIds * @param array $excludedIds * @return Collection */ public function resolveRecipients(bool $sendToAll, array $selectedIds = [], array $excludedIds = []): Collection { $excludedIds = array_values(array_unique(array_map('intval', $excludedIds))); if ($sendToAll) { $query = Coupon::query(); } else { $selectedIds = array_values(array_unique(array_map('intval', $selectedIds))); $query = Coupon::query()->whereIn('id', $selectedIds); } if ($excludedIds !== []) { $query->whereNotIn('id', $excludedIds); } return $query->orderBy('id')->get(); } public function startCampaign( User $admin, string $message, bool $sendToAll, array $selectedIds = [], array $excludedIds = [], ): SmsCampaign { $recipients = $this->resolveRecipients($sendToAll, $selectedIds, $excludedIds); $mode = $sendToAll ? 'all' : 'selected'; return DB::transaction(function () use ($admin, $message, $mode, $recipients): SmsCampaign { $campaign = SmsCampaign::query()->create([ 'message' => $message, 'mode' => $mode, 'recipient_count' => $recipients->count(), 'created_by' => $admin->id, ]); $jobs = []; foreach ($recipients as $coupon) { if (! is_valid_coupon_phone($coupon->phone)) { $this->createLog($campaign, $coupon, SmsSendStatus::SkippedInvalid); $campaign->increment('skipped_count'); continue; } $this->createLog($campaign, $coupon, SmsSendStatus::Pending); $jobs[] = new SendSmsToCouponJob($campaign, $coupon); } if ($jobs === []) { $campaign->update(['completed_at' => now()]); return $campaign->fresh(); } Bus::chain($jobs) ->onQueue('sms') ->dispatch(); return $campaign->fresh(); }); } protected function createLog(SmsCampaign $campaign, Coupon $coupon, SmsSendStatus $status): SmsSendLog { return SmsSendLog::query()->create([ 'sms_campaign_id' => $campaign->id, 'coupon_id' => $coupon->id, 'phone' => $coupon->phone, 'message' => $campaign->message, 'status' => $status, 'attempted_at' => $status === SmsSendStatus::Pending ? null : now(), ]); } }