where('post_platforms.status', PostPlatformStatus::Pending) ->enabled() // Mirrors VerifyUpcomingPostConnections::atRiskPostPlatforms() — // a paused account can't be the reason to dispatch a job for its // workspace, since the job itself will skip it too. whereHas() // already excludes a null social_account_id (nothing to join to). ->whereHas('socialAccount', fn ($query) => $query->where('is_active', true)) ->where(function ($query) { $query->whereNull('post_platforms.connection_warning_sent_at') ->orWhere('post_platforms.connection_warning_sent_at', '<', now()->subDay()); }) ->join('posts', 'posts.id', '=', 'post_platforms.post_id') ->where('posts.status', PostStatus::Scheduled) ->whereBetween('posts.scheduled_at', [now(), now()->addHour()]) ->distinct() ->pluck('posts.workspace_id'); foreach ($workspaceIds as $workspaceId) { VerifyUpcomingPostConnections::dispatch($workspaceId); } $this->info("Dispatched {$workspaceIds->count()} upcoming-post connection checks."); } }