settings ?? []; $plan = (string) ($settings['plan'] ?? 'free'); if ($plan === 'pro' && ! empty($settings['plan_expires_at'])) { $expires = Carbon::parse($settings['plan_expires_at']); if ($expires->isPast()) { return 'free'; } } return array_key_exists($plan, config('frontdesk.plans', [])) ? $plan : 'free'; } public function isPro(Organization $organization): bool { return $this->planKey($organization) === 'pro'; } /** @return array */ public function plan(Organization $organization): array { $key = $this->planKey($organization); return [ 'key' => $key, ...(array) config('frontdesk.plans.'.$key, []), ]; } /** Null means unlimited included host emails (Pro). */ public function freeEmailsPerMonth(Organization $organization): ?int { $value = config('frontdesk.plans.'.$this->planKey($organization).'.free_emails_per_month', 100); return $value === null ? null : (int) $value; } public function canAddBranch(Organization $organization, int $currentCount): bool { $limit = config('frontdesk.plans.'.$this->planKey($organization).'.max_branches'); return $limit === null || $currentCount < (int) $limit; } public function canAddKiosk(Organization $organization): bool { $limit = config('frontdesk.plans.'.$this->planKey($organization).'.max_kiosk_devices'); if ($limit === null) { return true; } $count = Device::query() ->where('organization_id', $organization->id) ->where('type', 'kiosk') ->count(); return $count < (int) $limit; } public function hasFeature(Organization $organization, string $feature): bool { $features = config('frontdesk.plans.'.$this->planKey($organization).'.features', []); return in_array($feature, $features, true); } public function proPriceMinor(): int { return (int) config('frontdesk.plans.pro.price_minor', 7900); } }