'array', 'new_values' => 'array', 'effective_at' => 'datetime', 'processed_at' => 'datetime', 'is_processed' => 'boolean', 'metadata' => 'array', ]; protected $dates = [ 'effective_at', 'processed_at', ]; /** * Relationships */ public function subscription() { return $this->belongsTo(Subscription::class); } public function user() { return $this->belongsTo(User::class); } /** * Get human-readable change type */ public function getChangeTypeLabelAttribute(): string { return [ 'plan_change' => 'Plan Change', 'cancellation' => 'Cancellation', 'pause' => 'Pause', 'resume' => 'Resume', 'migration' => 'Migration', 'provider_change' => 'Provider Change', ][$this->change_type] ?? ucfirst($this->change_type); } /** * Mark as processed */ public function markAsProcessed(): void { $this->update([ 'is_processed' => true, 'processed_at' => now(), ]); } /** * Scope: By change type */ public function scopeByType($query, string $type) { return $query->where('change_type', $type); } /** * Scope: Processed */ public function scopeProcessed($query) { return $query->where('is_processed', true); } /** * Scope: Pending processing */ public function scopePending($query) { return $query->where('is_processed', false); } /** * Scope: By user */ public function scopeByUser($query, $userId) { return $query->where('user_id', $userId); } /** * Scope: Within date range */ public function scopeBetweenDates($query, $startDate, $endDate) { return $query->whereBetween('effective_at', [$startDate, $endDate]); } /** * Create a subscription change record */ public static function createRecord( Subscription $subscription, string $changeType, string $description, ?array $oldValues = null, ?array $newValues = null, ?string $reason = null ): self { return static::create([ 'subscription_id' => $subscription->id, 'user_id' => $subscription->user_id, 'change_type' => $changeType, 'change_description' => $description, 'old_values' => $oldValues, 'new_values' => $newValues, 'reason' => $reason, 'effective_at' => now(), ]); } }