'decimal:2', 'purchased_at' => 'datetime', 'expires_at' => 'datetime', 'used_events' => 'integer', 'active' => 'boolean', 'event_warning_sent_at' => 'datetime', 'event_warning_threshold' => 'float', 'event_limit_notified_at' => 'datetime', 'expiry_warning_sent_at' => 'datetime', 'expired_notified_at' => 'datetime', ]; public function tenant(): BelongsTo { return $this->belongsTo(Tenant::class); } public function package(): BelongsTo { return $this->belongsTo(Package::class); } public function isActive(): bool { if ($this->package && $this->package->isEndcustomer()) { return (bool) $this->active; } return $this->active && (! $this->expires_at || $this->expires_at->isFuture()); } public function canCreateEvent(): bool { if (! $this->isActive()) { return false; } if (! $this->package->isReseller()) { return false; } $maxEvents = $this->package->max_events_per_year ?? 0; return $this->used_events < $maxEvents; } public function getRemainingEventsAttribute(): int { if (! $this->package->isReseller()) { return 0; } $max = $this->package->max_events_per_year ?? 0; return max(0, $max - $this->used_events); } protected static function boot() { parent::boot(); static::creating(function (self $tenantPackage) { if (! $tenantPackage->purchased_at) { $tenantPackage->purchased_at = now(); } $package = $tenantPackage->package; if ($package && $package->isReseller()) { if (! $tenantPackage->expires_at) { $tenantPackage->expires_at = now()->addYear(); } } else { $tenantPackage->expires_at = now()->addCentury(); } if ($tenantPackage->active === null) { $tenantPackage->active = true; } }); static::updating(function (self $tenantPackage) { $package = $tenantPackage->package; if ($package && $package->isReseller()) { if ( $tenantPackage->isDirty('expires_at') && $tenantPackage->expires_at instanceof CarbonInterface && $tenantPackage->expires_at->isPast() ) { $tenantPackage->active = false; } return; } if ($tenantPackage->isDirty('expires_at')) { $tenantPackage->expires_at = now()->addCentury(); } }); } }