plan; $oldValues = [ 'plan_id' => $subscription->plan_id, 'plan_name' => $oldPlan?->name, 'price' => $oldPlan?->price, ]; // Update subscription with new plan $subscription->update([ 'plan_id' => $newPlan->id, 'updated_at' => now(), ]); // Record the change SubscriptionChange::createRecord( $subscription, 'plan_change', "Migrated from {$oldPlan?->name} to {$newPlan->name}", $oldValues, [ 'plan_id' => $newPlan->id, 'plan_name' => $newPlan->name, 'price' => $newPlan->price, ], $reason ); DB::commit(); Log::info('Subscription plan migration completed', [ 'subscription_id' => $subscription->id, 'old_plan_id' => $oldPlan?->id, 'new_plan_id' => $newPlan->id, 'reason' => $reason, ]); return true; } catch (\Exception $e) { DB::rollBack(); Log::error('Subscription plan migration failed', [ 'subscription_id' => $subscription->id, 'new_plan_id' => $newPlan->id, 'error' => $e->getMessage(), ]); return false; } } /** * Migrate subscription to a new provider */ public function migrateToProvider(Subscription $subscription, string $newProvider, array $providerData = []): bool { try { DB::beginTransaction(); $oldProvider = $subscription->provider; $oldValues = [ 'provider' => $oldProvider, 'provider_subscription_id' => $subscription->provider_subscription_id, ]; // Cancel subscription with old provider if needed if ($oldProvider && $subscription->isActive()) { $this->orchestrator->cancelSubscription($subscription, 'Provider migration'); } // Update subscription with new provider $subscription->update([ 'provider' => $newProvider, 'provider_subscription_id' => $providerData['subscription_id'] ?? null, 'provider_data' => array_merge($subscription->provider_data ?? [], $providerData), 'last_provider_sync' => now(), ]); // Record the change SubscriptionChange::createRecord( $subscription, 'provider_change', "Migrated from {$oldProvider} to {$newProvider}", $oldValues, [ 'provider' => $newProvider, 'provider_subscription_id' => $providerData['subscription_id'] ?? null, ], 'Provider migration for better service' ); DB::commit(); Log::info('Subscription provider migration completed', [ 'subscription_id' => $subscription->id, 'old_provider' => $oldProvider, 'new_provider' => $newProvider, ]); return true; } catch (\Exception $e) { DB::rollBack(); Log::error('Subscription provider migration failed', [ 'subscription_id' => $subscription->id, 'new_provider' => $newProvider, 'error' => $e->getMessage(), ]); return false; } } /** * Pause subscription */ public function pauseSubscription(Subscription $subscription, string $reason = ''): bool { try { DB::beginTransaction(); $oldValues = [ 'status' => $subscription->status, 'paused_at' => null, ]; // Update subscription status $subscription->update([ 'status' => 'paused', 'paused_at' => now(), ]); // Record the change SubscriptionChange::createRecord( $subscription, 'pause', 'Subscription paused', $oldValues, [ 'status' => 'paused', 'paused_at' => now()->format('Y-m-d H:i:s'), ], $reason ); DB::commit(); Log::info('Subscription paused', [ 'subscription_id' => $subscription->id, 'reason' => $reason, ]); return true; } catch (\Exception $e) { DB::rollBack(); Log::error('Failed to pause subscription', [ 'subscription_id' => $subscription->id, 'error' => $e->getMessage(), ]); return false; } } /** * Resume subscription */ public function resumeSubscription(Subscription $subscription, string $reason = ''): bool { try { DB::beginTransaction(); $oldValues = [ 'status' => $subscription->status, 'paused_at' => $subscription->paused_at, 'resumed_at' => null, ]; // Update subscription status $subscription->update([ 'status' => 'active', 'resumed_at' => now(), ]); // Record the change SubscriptionChange::createRecord( $subscription, 'resume', 'Subscription resumed', $oldValues, [ 'status' => 'active', 'resumed_at' => now()->format('Y-m-d H:i:s'), ], $reason ); DB::commit(); Log::info('Subscription resumed', [ 'subscription_id' => $subscription->id, 'reason' => $reason, ]); return true; } catch (\Exception $e) { DB::rollBack(); Log::error('Failed to resume subscription', [ 'subscription_id' => $subscription->id, 'error' => $e->getMessage(), ]); return false; } } /** * Bulk migrate subscriptions */ public function bulkMigrate(array $subscriptionIds, callable $migrationCallback): array { $results = [ 'success' => 0, 'failed' => 0, 'errors' => [], ]; foreach ($subscriptionIds as $subscriptionId) { try { $subscription = Subscription::findOrFail($subscriptionId); if ($migrationCallback($subscription)) { $results['success']++; } else { $results['failed']++; $results['errors'][] = "Migration failed for subscription {$subscriptionId}"; } } catch (\Exception $e) { $results['failed']++; $results['errors'][] = "Error processing subscription {$subscriptionId}: {$e->getMessage()}"; } } return $results; } /** * Get migration history for a subscription */ public function getMigrationHistory(Subscription $subscription): \Illuminate\Database\Eloquent\Collection { return $subscription->subscriptionChanges() ->whereIn('change_type', ['plan_change', 'provider_change', 'migration']) ->orderBy('effective_at', 'desc') ->get(); } /** * Get pending migrations */ public function getPendingMigrations(): \Illuminate\Database\Eloquent\Collection { return SubscriptionChange::query() ->whereIn('change_type', ['plan_change', 'provider_change', 'migration']) ->pending() ->with(['subscription', 'user']) ->orderBy('effective_at', 'asc') ->get(); } /** * Process pending migrations */ public function processPendingMigrations(): int { $pending = $this->getPendingMigrations(); $processedCount = 0; foreach ($pending as $change) { try { // Here you would implement the actual migration logic // based on the change type and data $change->markAsProcessed(); $processedCount++; } catch (\Exception $e) { Log::error('Failed to process pending migration', [ 'change_id' => $change->id, 'error' => $e->getMessage(), ]); } } return $processedCount; } }