Deploy Ladill Meet / deploy (push) Failing after 7s
Phases 0–18: core meetings, webinar, breakouts, team chat, live streaming, town hall, billing, and Ladill Mail calendar wiring. Co-authored-by: Cursor <cursoragent@cursor.com>
68 lines
2.0 KiB
PHP
68 lines
2.0 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Meet;
|
|
|
|
use App\Models\Organization;
|
|
use App\Models\UsageRecord;
|
|
|
|
class LicenseService
|
|
{
|
|
/** @var array<string, array<string, int>> */
|
|
public const TIERS = [
|
|
'standard' => [
|
|
'participant_minutes' => 10000,
|
|
'recording_storage_bytes' => 5_368_709_120, // 5 GB
|
|
'ai_minutes' => 120,
|
|
],
|
|
'professional' => [
|
|
'participant_minutes' => 50000,
|
|
'recording_storage_bytes' => 26_843_545_600, // 25 GB
|
|
'ai_minutes' => 600,
|
|
],
|
|
'enterprise' => [
|
|
'participant_minutes' => 500000,
|
|
'recording_storage_bytes' => 107_374_182_400, // 100 GB
|
|
'ai_minutes' => 5000,
|
|
],
|
|
];
|
|
|
|
public function quotas(Organization $organization): array
|
|
{
|
|
$tier = $organization->license_tier ?? 'standard';
|
|
$defaults = self::TIERS[$tier] ?? self::TIERS['standard'];
|
|
|
|
return array_merge($defaults, (array) ($organization->usage_quotas ?? []));
|
|
}
|
|
|
|
public function withinQuota(Organization $organization, string $metric, int $additional = 0, ?int $branchId = null): bool
|
|
{
|
|
$quotas = $this->quotas($organization);
|
|
$limit = (int) ($quotas[$metric] ?? 0);
|
|
if ($limit <= 0) {
|
|
return true;
|
|
}
|
|
|
|
$since = now()->startOfMonth();
|
|
$query = UsageRecord::where('organization_id', $organization->id)
|
|
->where('metric', $metric)
|
|
->where('recorded_at', '>=', $since);
|
|
|
|
if ($branchId) {
|
|
$query->where('branch_id', $branchId);
|
|
}
|
|
|
|
$used = (int) $query->sum('quantity');
|
|
|
|
return ($used + $additional) <= $limit;
|
|
}
|
|
|
|
public function assertCanStartSession(Organization $organization, ?int $branchId = null): void
|
|
{
|
|
abort_unless(
|
|
$this->withinQuota($organization, 'participant_minutes', 60, $branchId),
|
|
402,
|
|
'Participant-minute quota exceeded for this billing period.',
|
|
);
|
|
}
|
|
}
|