Files
fotospiel-app/app/Services/Packages/TenantUsageTracker.php
2025-11-01 13:19:07 +01:00

98 lines
3.3 KiB
PHP

<?php
namespace App\Services\Packages;
use App\Events\Packages\TenantCreditsLow;
use App\Events\Packages\TenantPackageEventLimitReached;
use App\Events\Packages\TenantPackageEventThresholdReached;
use App\Models\Tenant;
use App\Models\TenantPackage;
use Illuminate\Contracts\Events\Dispatcher;
class TenantUsageTracker
{
public function __construct(private readonly Dispatcher $dispatcher) {}
public function recordEventUsage(TenantPackage $tenantPackage, int $previousUsed, int $delta = 1): void
{
$limit = $tenantPackage->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;
}
}
}
}