'decimal:2', 'has_reports' => 'boolean', 'has_api_access' => 'boolean', 'has_priority_support' => 'boolean', 'starts_at' => 'datetime', 'ends_at' => 'datetime', 'cancelled_at' => 'datetime', 'features' => 'array', ]; public function user(): BelongsTo { return $this->belongsTo(User::class); } /** * Check if subscription is active */ public function isActive(): bool { if ($this->status !== 'active') { return false; } if ($this->ends_at && $this->ends_at->isPast()) { return false; } return $this->starts_at->isPast(); } /** * Check if subscription is expired */ public function isExpired(): bool { return $this->ends_at && $this->ends_at->isPast(); } /** * Check if subscription is cancelled */ public function isCancelled(): bool { return $this->status === 'cancelled' || $this->cancelled_at !== null; } /** * Get days until expiry */ public function daysUntilExpiry(): ?int { if (!$this->ends_at) { return null; } return max(0, now()->diffInDays($this->ends_at, false)); } /** * Check if user has exceeded device limit */ public function hasExceededDeviceLimit(): bool { return $this->user->devices()->count() > $this->device_limit; } /** * Check if user has a specific feature */ public function hasFeature(string $feature): bool { return in_array($feature, $this->features ?? []); } /** * Cancel subscription */ public function cancel(): void { $this->update([ 'status' => 'cancelled', 'cancelled_at' => now(), ]); } /** * Renew subscription */ public function renew(Carbon $newEndDate): void { $this->update([ 'status' => 'active', 'ends_at' => $newEndDate, 'cancelled_at' => null, ]); } }