package?->max_events_per_year; if ($limit === null || $limit <= 0) { return; } $newUsed = (int) $tenantPackage->used_events; $thresholds = collect(config('package-limits.event_thresholds', [])) ->filter(fn (float $value) => $value > 0 && $value < 1) ->sort() ->values(); if ($limit > 0) { $previousRatio = $previousUsed / $limit; $newRatio = $newUsed / $limit; $currentThreshold = $tenantPackage->event_warning_threshold ?? null; foreach ($thresholds as $threshold) { if ($previousRatio < $threshold && $newRatio >= $threshold) { if ($currentThreshold !== null && $currentThreshold >= $threshold) { continue; } $tenantPackage->forceFill([ 'event_warning_sent_at' => now(), 'event_warning_threshold' => $threshold, ])->save(); $this->dispatcher->dispatch(new TenantPackageEventThresholdReached( $tenantPackage, $threshold, $limit, $newUsed, )); $currentThreshold = $threshold; } } } if ($newUsed >= $limit && $previousUsed < $limit) { if (! $tenantPackage->event_limit_notified_at) { $tenantPackage->forceFill([ 'event_limit_notified_at' => now(), ])->save(); } $this->dispatcher->dispatch(new TenantPackageEventLimitReached($tenantPackage, $limit)); } } public function recordCreditBalance(Tenant $tenant, int $previousBalance, int $newBalance): void { $thresholds = collect(config('package-limits.credit_thresholds', [])) ->filter(fn ($value) => is_numeric($value) && $value >= 0) ->map(fn ($value) => (int) $value) ->sortDesc() ->values(); $currentThreshold = $tenant->credit_warning_threshold ?? null; foreach ($thresholds as $threshold) { if ($previousBalance > $threshold && $newBalance <= $threshold) { if ($currentThreshold !== null && $threshold >= $currentThreshold) { continue; } $tenant->forceFill([ 'credit_warning_sent_at' => now(), 'credit_warning_threshold' => $threshold, ])->save(); $this->dispatcher->dispatch(new TenantCreditsLow($tenant, $newBalance, $threshold)); break; } } } }