onQueue('notifications'); } public function handle(): void { $features = PlanFeatures::for($this->user); // Step 3: channels that pass tier + user-pref + daily-limit checks $allowed = $features->channelsFor($this->triggerType); // Step 4: send and log sent notifications foreach ($allowed as $channel) { // TODO: $this->user->notify(new FuelPriceAlert($this->triggerType, $this->fuelType, $this->price)); $this->log($channel, sent: true); } // Channels not in the allowed set — split into missed reasons $notAllowed = array_diff(self::ALL_CHANNELS, $allowed); foreach ($notAllowed as $channel) { if (! $this->userHasEnabledPref($channel)) { // User intentionally disabled — do not log (noise) continue; } if ($features->canUseChannel($channel)) { // Step 5: tier allows but daily limit exhausted $this->log($channel, sent: false, missedReason: 'daily_limit'); } else { // Step 6: tier does not allow the channel the user wanted $this->log($channel, sent: false, missedReason: 'tier_restricted'); } } } private function log(string $channel, bool $sent, ?string $missedReason = null): void { NotificationLog::create([ 'user_id' => $this->user->id, 'channel' => $channel, 'trigger_type' => $this->triggerType, 'fuel_type' => $this->fuelType, 'price' => $this->price, 'sent' => $sent, 'missed_reason' => $missedReason, 'created_at' => now(), ]); } private function userHasEnabledPref(string $channel): bool { return UserNotificationPreference::where('user_id', $this->user->id) ->where('channel', $channel) ->where('enabled', true) ->exists(); } }