settings ?? []; $plan = (string) ($settings['plan'] ?? 'free'); if (in_array($plan, ['pro', 'enterprise'], true) && ! empty($settings['plan_expires_at'])) { if (Carbon::parse($settings['plan_expires_at'])->isPast()) { return 'free'; } } return array_key_exists($plan, config('care.plans', [])) ? $plan : 'free'; } public function plan(Organization $organization): string { return $this->planKey($organization); } public function isPro(Organization $organization): bool { return $this->planKey($organization) === 'pro'; } public function isEnterprise(Organization $organization): bool { return $this->planKey($organization) === 'enterprise'; } public function hasPaidPlan(Organization $organization): bool { return in_array($this->planKey($organization), ['pro', 'enterprise'], true); } /** Lab, pharmacy, billing, and Ladill Queue integration require Pro or Enterprise. */ public function canUseProModules(Organization $organization): bool { return $this->hasPaidPlan($organization); } public function canUseQueueIntegration(Organization $organization): bool { return $this->hasPaidPlan($organization); } public function hasFeature(Organization $organization, string $feature): bool { $features = config('care.plans.'.$this->planKey($organization).'.features', []); return in_array($feature, $features, true); } public function activeBranchCount(Organization $organization): int { return Branch::query() ->where('organization_id', $organization->id) ->where('is_active', true) ->count(); } public function maxBranches(Organization $organization): ?int { $plan = config('care.plans.'.$this->planKey($organization)); $max = $plan['max_branches'] ?? null; return $max === null ? null : (int) $max; } public function canAddBranch(Organization $organization, int $currentCount): bool { $max = $this->maxBranches($organization); return $max === null || $currentCount < $max; } public function branchLimitMessage(Organization $organization): string { $max = $this->maxBranches($organization); $key = $this->planKey($organization); if ($key === 'free') { return 'Your Free plan allows 1 branch. Upgrade to Care Pro for unlimited branches (billed per branch).'; } if ($key === 'pro' && $max !== null) { return "Your Pro plan allows up to {$max} branches (billed per branch)."; } return 'Branch limit reached for your current plan.'; } public function proPricePerBranchMinor(): int { return (int) config( 'care.plans.pro.price_minor_per_branch', config('care.plans.pro.price_minor', 199000), ); } /** @deprecated Prefer proPricePerBranchMinor() — Pro is billed per branch. */ public function proPriceMinor(): int { return $this->proPricePerBranchMinor(); } public function enterprisePricePerBranchMinor(): int { return (int) config( 'care.plans.enterprise.price_minor_per_branch', config('care.plans.enterprise.price_minor', 499000), ); } /** Total monthly amount for Pro = active branches × per-branch rate (min 1). */ public function proPriceTotalMinor(Organization $organization): int { return $this->priceForBranches('pro', $this->activeBranchCount($organization)); } /** Total monthly amount for Enterprise = active branches × per-branch rate (min 1). */ public function enterprisePriceMinor(Organization $organization): int { return $this->priceForBranches('enterprise', $this->activeBranchCount($organization)); } public function monthlyPriceMinor(Organization $organization, string $plan): int { return $this->priceForBranches($plan, $this->activeBranchCount($organization)); } /** Fixed branch count × per-branch rate (for checkout when the user picks branch seats). */ public function priceForBranches(string $plan, int $branches): int { $branches = max(1, $branches); $rate = $plan === 'enterprise' ? $this->enterprisePricePerBranchMinor() : $this->proPricePerBranchMinor(); return $branches * $rate; } public function resolveCheckoutBranches(Organization $organization, int $requested): int { $branches = max(1, $requested); // Don't under-bill vs sites already configured in the account. $active = max(1, $this->activeBranchCount($organization)); return max($branches, $active); } public function canSubscribeEnterprise(Organization $organization): bool { // Enterprise is a feature tier (not branch-gated). min_branches defaults to 1. return $this->activeBranchCount($organization) >= (int) config('care.enterprise.min_branches', 1); } }