Implement package limit notification system
This commit is contained in:
97
app/Services/Packages/TenantUsageTracker.php
Normal file
97
app/Services/Packages/TenantUsageTracker.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user