subscription(); $plan = $this->account->plan; if ($subscription !== null && $plan?->stripe_yearly_price_id !== null && $subscription->stripe_price === $plan->stripe_yearly_price_id ) { return 12; } return 1; } public function creditAllotment(): int { $base = (int) ($this->account->plan?->monthly_credits_limit ?? 0); $months = $this->onTrial() ? 1 : $this->intervalMonths(); return $base * $this->account->workspaces()->count() * $months; } public function usedCredits(): int { return AiUsageLog::creditsUsedBetween( (string) $this->account->id, $this->periodStart(), $this->periodEnd(), ); } public function periodStart(): CarbonImmutable { return $this->window()[0]; } public function periodEnd(): CarbonImmutable { return $this->window()[1]; } /** * @return array{0: CarbonImmutable, 1: CarbonImmutable} */ private function window(): array { return $this->window ??= $this->computeWindow(); } /** * @return array{0: CarbonImmutable, 1: CarbonImmutable} */ private function computeWindow(): array { $subscription = $this->subscription(); if ($subscription !== null && $subscription->onTrial()) { return [ CarbonImmutable::parse($subscription->created_at), CarbonImmutable::parse($subscription->trial_ends_at), ]; } $anchor = $this->anchor(); $now = CarbonImmutable::now(); $step = $this->intervalMonths(); $periods = 0; while ($anchor->addMonthsNoOverflow(($periods + 1) * $step)->lessThanOrEqualTo($now)) { $periods++; } return [ $anchor->addMonthsNoOverflow($periods * $step), $anchor->addMonthsNoOverflow(($periods + 1) * $step), ]; } private function anchor(): CarbonImmutable { $subscription = $this->subscription(); $anchor = $subscription?->trial_ends_at ?? $subscription?->created_at ?? $this->account->created_at ?? CarbonImmutable::now(); return CarbonImmutable::parse($anchor); } private function onTrial(): bool { return (bool) $this->subscription()?->onTrial(); } private function subscription(): ?Subscription { if (! $this->subscriptionResolved) { $this->subscription = $this->account->subscription(Account::SUBSCRIPTION_NAME); $this->subscriptionResolved = true; } return $this->subscription; } }