* } */ public function summary(Workspace $workspace): array { $planProfile = $this->resolvePlanProfile($workspace); return [ 'plan_profile' => $planProfile, 'decisions' => [ self::KEY_MANAGED_TENANT_ACTIVATION_LIMIT => $this->resolve($workspace, self::KEY_MANAGED_TENANT_ACTIVATION_LIMIT, $planProfile), self::KEY_REVIEW_PACK_GENERATION_ENABLED => $this->resolve($workspace, self::KEY_REVIEW_PACK_GENERATION_ENABLED, $planProfile), ], ]; } /** * @return array{id: string, label: string, description: string, managed_tenant_limit_default: int, review_pack_generation_default: bool, is_default: bool} */ public function resolvePlanProfile(Workspace $workspace): array { $planProfileId = $this->settingsResolver->resolveValue( workspace: $workspace, domain: self::SETTING_DOMAIN, key: self::SETTING_PLAN_PROFILE, ); return $this->planProfileCatalog->resolve(is_string($planProfileId) ? $planProfileId : null); } /** * @param array{id: string, label: string, description: string, managed_tenant_limit_default: int, review_pack_generation_default: bool, is_default: bool}|null $planProfile * @return array{ * workspace_id: int, * plan_profile_id: string, * plan_profile_label: string, * plan_profile_description: string, * key: string, * effective_value: int|bool, * source: 'plan_profile_default'|'workspace_override', * rationale: string|null, * current_usage: int|null, * remaining_capacity: int|null, * is_blocked: bool, * block_reason: string|null, * last_changed_at: CarbonInterface|null, * last_changed_by: string|null * } */ public function resolve(Workspace $workspace, string $key, ?array $planProfile = null): array { $planProfile ??= $this->resolvePlanProfile($workspace); $lastChanged = $this->lastChangedMetadata($workspace); return match ($key) { self::KEY_MANAGED_TENANT_ACTIVATION_LIMIT => $this->resolveManagedTenantActivationLimitDecision($workspace, $planProfile, $lastChanged), self::KEY_REVIEW_PACK_GENERATION_ENABLED => $this->resolveReviewPackGenerationDecision($workspace, $planProfile, $lastChanged), default => throw new \InvalidArgumentException(sprintf('Unknown workspace entitlement key: %s', $key)), }; } /** * @param array{id: string, label: string, description: string, managed_tenant_limit_default: int, review_pack_generation_default: bool, is_default: bool} $planProfile * @param array{last_changed_at: CarbonInterface|null, last_changed_by: string|null} $lastChanged * @return array{ * workspace_id: int, * plan_profile_id: string, * plan_profile_label: string, * plan_profile_description: string, * key: string, * effective_value: int, * source: 'plan_profile_default'|'workspace_override', * rationale: string|null, * current_usage: int, * remaining_capacity: int, * is_blocked: bool, * block_reason: string|null, * last_changed_at: CarbonInterface|null, * last_changed_by: string|null * } */ private function resolveManagedTenantActivationLimitDecision(Workspace $workspace, array $planProfile, array $lastChanged): array { $overrideValue = $this->settingsResolver->resolveDetailed( workspace: $workspace, domain: self::SETTING_DOMAIN, key: self::SETTING_MANAGED_TENANT_LIMIT_OVERRIDE_VALUE, ); $overrideReason = $this->settingsResolver->resolveValue( workspace: $workspace, domain: self::SETTING_DOMAIN, key: self::SETTING_MANAGED_TENANT_LIMIT_OVERRIDE_REASON, ); $effectiveValue = is_int($overrideValue['value']) ? $overrideValue['value'] : (int) $planProfile['managed_tenant_limit_default']; $source = $overrideValue['source'] === 'workspace_override' ? 'workspace_override' : 'plan_profile_default'; $currentUsage = Tenant::activeQuery() ->where('workspace_id', (int) $workspace->getKey()) ->count(); $remainingCapacity = $effectiveValue - $currentUsage; $isBlocked = $currentUsage >= $effectiveValue; $rationale = $source === 'workspace_override' ? (is_string($overrideReason) && $overrideReason !== '' ? $overrideReason : null) : (string) $planProfile['description']; return [ 'workspace_id' => (int) $workspace->getKey(), 'plan_profile_id' => (string) $planProfile['id'], 'plan_profile_label' => (string) $planProfile['label'], 'plan_profile_description' => (string) $planProfile['description'], 'key' => self::KEY_MANAGED_TENANT_ACTIVATION_LIMIT, 'effective_value' => $effectiveValue, 'source' => $source, 'rationale' => $rationale, 'current_usage' => $currentUsage, 'remaining_capacity' => $remainingCapacity, 'is_blocked' => $isBlocked, 'block_reason' => $isBlocked ? $this->managedTenantLimitBlockReason($currentUsage, $effectiveValue, $source, $planProfile, $rationale) : null, 'last_changed_at' => $lastChanged['last_changed_at'], 'last_changed_by' => $lastChanged['last_changed_by'], ]; } /** * @param array{id: string, label: string, description: string, managed_tenant_limit_default: int, review_pack_generation_default: bool, is_default: bool} $planProfile * @param array{last_changed_at: CarbonInterface|null, last_changed_by: string|null} $lastChanged * @return array{ * workspace_id: int, * plan_profile_id: string, * plan_profile_label: string, * plan_profile_description: string, * key: string, * effective_value: bool, * source: 'plan_profile_default'|'workspace_override', * rationale: string|null, * current_usage: null, * remaining_capacity: null, * is_blocked: bool, * block_reason: string|null, * last_changed_at: CarbonInterface|null, * last_changed_by: string|null * } */ private function resolveReviewPackGenerationDecision(Workspace $workspace, array $planProfile, array $lastChanged): array { $overrideValue = $this->settingsResolver->resolveDetailed( workspace: $workspace, domain: self::SETTING_DOMAIN, key: self::SETTING_REVIEW_PACK_GENERATION_OVERRIDE_VALUE, ); $overrideReason = $this->settingsResolver->resolveValue( workspace: $workspace, domain: self::SETTING_DOMAIN, key: self::SETTING_REVIEW_PACK_GENERATION_OVERRIDE_REASON, ); $effectiveValue = is_bool($overrideValue['value']) ? $overrideValue['value'] : (bool) $planProfile['review_pack_generation_default']; $source = $overrideValue['source'] === 'workspace_override' ? 'workspace_override' : 'plan_profile_default'; $rationale = $source === 'workspace_override' ? (is_string($overrideReason) && $overrideReason !== '' ? $overrideReason : null) : (string) $planProfile['description']; return [ 'workspace_id' => (int) $workspace->getKey(), 'plan_profile_id' => (string) $planProfile['id'], 'plan_profile_label' => (string) $planProfile['label'], 'plan_profile_description' => (string) $planProfile['description'], 'key' => self::KEY_REVIEW_PACK_GENERATION_ENABLED, 'effective_value' => $effectiveValue, 'source' => $source, 'rationale' => $rationale, 'current_usage' => null, 'remaining_capacity' => null, 'is_blocked' => ! $effectiveValue, 'block_reason' => $effectiveValue ? null : $this->reviewPackGenerationBlockReason($source, $planProfile, $rationale), 'last_changed_at' => $lastChanged['last_changed_at'], 'last_changed_by' => $lastChanged['last_changed_by'], ]; } /** * @return array{last_changed_at: CarbonInterface|null, last_changed_by: string|null} */ private function lastChangedMetadata(Workspace $workspace): array { $record = WorkspaceSetting::query() ->where('workspace_id', (int) $workspace->getKey()) ->where('domain', self::SETTING_DOMAIN) ->whereIn('key', [ self::SETTING_PLAN_PROFILE, self::SETTING_MANAGED_TENANT_LIMIT_OVERRIDE_VALUE, self::SETTING_MANAGED_TENANT_LIMIT_OVERRIDE_REASON, self::SETTING_REVIEW_PACK_GENERATION_OVERRIDE_VALUE, self::SETTING_REVIEW_PACK_GENERATION_OVERRIDE_REASON, ]) ->whereNotNull('updated_by_user_id') ->with('updatedByUser:id,name') ->latest('updated_at') ->latest('id') ->first(); if (! $record instanceof WorkspaceSetting) { return [ 'last_changed_at' => null, 'last_changed_by' => null, ]; } return [ 'last_changed_at' => $record->updated_at, 'last_changed_by' => $record->updatedByUser?->name, ]; } /** * @param array{id: string, label: string, description: string, managed_tenant_limit_default: int, review_pack_generation_default: bool, is_default: bool} $planProfile */ private function managedTenantLimitBlockReason(int $currentUsage, int $effectiveValue, string $source, array $planProfile, ?string $rationale): string { $prefix = $source === 'workspace_override' ? 'This workspace override currently allows' : sprintf('The %s plan profile currently allows', $planProfile['label']); $message = sprintf( '%s %d active managed tenant%s, and this workspace already has %d active managed tenant%s.', $prefix, $effectiveValue, $effectiveValue === 1 ? '' : 's', $currentUsage, $currentUsage === 1 ? '' : 's', ); if ($source === 'workspace_override' && $rationale !== null) { $message .= ' Reason: '.$rationale; } return $message; } /** * @param array{id: string, label: string, description: string, managed_tenant_limit_default: int, review_pack_generation_default: bool, is_default: bool} $planProfile */ private function reviewPackGenerationBlockReason(string $source, array $planProfile, ?string $rationale): string { $message = $source === 'workspace_override' ? 'Review pack generation is disabled by workspace override.' : sprintf('Review pack generation is disabled by the %s plan profile.', $planProfile['label']); if ($source === 'workspace_override' && $rationale !== null) { $message .= ' Reason: '.$rationale; } return $message; } }