diff --git a/app/Filament/Pages/CustomerAnalytics.php b/app/Filament/Pages/CustomerAnalytics.php index dbbe99d..d1f2320 100644 --- a/app/Filament/Pages/CustomerAnalytics.php +++ b/app/Filament/Pages/CustomerAnalytics.php @@ -8,11 +8,11 @@ use App\Models\Subscription; use Filament\Actions\Action; use Filament\Actions\Concerns\InteractsWithActions; use Filament\Forms\Components\DatePicker; -use Filament\Forms\Components\Grid; use Filament\Forms\Components\Select; use Filament\Forms\Concerns\InteractsWithForms; use Filament\Forms\Contracts\HasForms; use Filament\Pages\Page; +use Filament\Schemas\Components\Grid; use Filament\Tables\Columns\TextColumn; use Filament\Tables\Concerns\InteractsWithTable; use Filament\Tables\Contracts\HasTable; @@ -129,19 +129,19 @@ class CustomerAnalytics extends Page implements HasForms, HasTable $this->getCustomerAnalyticsQuery() ) ->columns([ - TextColumn::make('user_name') + TextColumn::make('user.name') ->label('Customer') ->searchable() ->sortable() ->weight('medium'), - TextColumn::make('user_email') + TextColumn::make('user.email') ->label('Email') ->searchable() ->copyable() ->toggleable(), - TextColumn::make('plan_name') + TextColumn::make('plan.name') ->label('Plan') ->searchable() ->sortable() @@ -173,7 +173,7 @@ class CustomerAnalytics extends Page implements HasForms, HasTable TextColumn::make('subscription_age') ->label('Age') - ->formatStateUsing(function ($record) { + ->state(function ($record) { $started = $record->starts_at ?? $record->created_at; return $started ? $started->diffForHumans() : 'Unknown'; @@ -188,19 +188,20 @@ class CustomerAnalytics extends Page implements HasForms, HasTable TextColumn::make('trial_extensions_count') ->label('Trial Extensions') - ->formatStateUsing(fn ($record) => $record->trial_extensions_count ?? 0) + ->state(fn ($record) => $record->trial_extensions_count ?? 0) ->alignCenter() ->toggleable(), TextColumn::make('subscription_changes_count') ->label('Changes') - ->formatStateUsing(fn ($record) => $record->subscription_changes_count ?? 0) + ->state(fn ($record) => $record->subscription_changes_count ?? 0) ->alignCenter() ->toggleable(), TextColumn::make('mrr') ->label('MRR') ->money('USD') + ->state(fn ($record) => $record->calculateMRR()) ->sortable() ->toggleable(), ]) @@ -226,7 +227,7 @@ class CustomerAnalytics extends Page implements HasForms, HasTable ]), Filter::make('date_range') - ->form([ + ->schema([ DatePicker::make('start_date') ->label('Start Date') ->required(), @@ -316,7 +317,7 @@ class CustomerAnalytics extends Page implements HasForms, HasTable $subscription->couponUsages()->sum('discount_amount'), $subscription->trialExtensions()->count(), $subscription->subscriptionChanges()->count(), - $subscription->plan?->monthly_price ?? 0, + $subscription->calculateMRR(), $subscription->created_at->toDateTimeString(), $subscription->trial_ends_at?->toDateTimeString() ?? 'N/A', $subscription->ends_at?->toDateTimeString() ?? 'N/A', diff --git a/app/Models/Plan.php b/app/Models/Plan.php index 3478208..a37a05a 100644 --- a/app/Models/Plan.php +++ b/app/Models/Plan.php @@ -264,6 +264,34 @@ class Plan extends Model return $this->monthly_billing ? 'Monthly' : 'Yearly'; } + /** + * Calculate Monthly Recurring Revenue (MRR) for this plan + */ + public function calculateMRR(): float + { + if (! $this->price) { + return 0; + } + + // Use the new billing cycle system if available + if ($this->billing_cycle_days) { + return ($this->price / $this->billing_cycle_days) * 30; + } + + // Fallback to legacy system + $cycleDays = $this->monthly_billing ? 30 : 365; + + return ($this->price / $cycleDays) * 30; + } + + /** + * Get monthly price attribute for compatibility + */ + public function getMonthlyPriceAttribute(): float + { + return $this->calculateMRR(); + } + /** * Get plan metadata value */ diff --git a/app/Models/Subscription.php b/app/Models/Subscription.php index 2824e4c..cf75b09 100644 --- a/app/Models/Subscription.php +++ b/app/Models/Subscription.php @@ -473,4 +473,79 @@ class Subscription extends Model return $processedCount; } + + /** + * Calculate Monthly Recurring Revenue (MRR) for this subscription + */ + public function calculateMRR(): float + { + // Only active and trialing subscriptions contribute to MRR + if (! in_array($this->status, ['active', 'trialing'])) { + return 0; + } + + // Check if subscription has ended + if ($this->ends_at && $this->ends_at->isPast()) { + return 0; + } + + // Get the plan's MRR calculation + if ($this->plan) { + return $this->plan->calculateMRR(); + } + + // Fallback: try to calculate from legacy data or provider data + $price = $this->getLegacyPrice(); + if ($price > 0) { + $cycleDays = $this->getLegacyBillingCycleDays(); + + return ($price / $cycleDays) * 30; + } + + return 0; + } + + /** + * Get price from legacy data or provider data + */ + private function getLegacyPrice(): float + { + // Try to get price from plan first + if ($this->plan && $this->plan->price) { + return (float) $this->plan->price; + } + + // Try provider data + if ($this->provider_data && isset($this->provider_data['plan_details']['price'])) { + return (float) $this->provider_data['plan_details']['price']; + } + + // Try legacy stripe_price field + if ($this->stripe_price) { + // This would need additional logic to get price from Stripe + // For now, return 0 as we can't easily get the amount + return 0; + } + + return 0; + } + + /** + * Get billing cycle days from legacy data + */ + private function getLegacyBillingCycleDays(): int + { + // Try to get from plan first + if ($this->plan && $this->plan->billing_cycle_days) { + return (int) $this->plan->billing_cycle_days; + } + + // Try provider data + if ($this->provider_data && isset($this->provider_data['plan_details']['billing_cycle_days'])) { + return (int) $this->provider_data['plan_details']['billing_cycle_days']; + } + + // Fallback to legacy monthly_billing + return $this->plan && $this->plan->monthly_billing ? 30 : 365; + } } diff --git a/resources/views/filament/pages/customer-analytics.blade.php b/resources/views/filament/pages/customer-analytics.blade.php index 10ffe4a..c56d132 100644 --- a/resources/views/filament/pages/customer-analytics.blade.php +++ b/resources/views/filament/pages/customer-analytics.blade.php @@ -1,28 +1,5 @@ -
-
- {{ $this->form }} - -
- - - Apply Filters - - - - Reset - -
-
-
-
{{ $this->table }}
-
\ No newline at end of file +