TenantAtlas/apps/platform/app/Models/Policy.php
Ahmed Darrazi 91f327a7c2
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 1m40s
feat(specs/261): add provider missing policy visibility
2026-05-01 22:17:29 +02:00

132 lines
3.6 KiB
PHP

<?php
namespace App\Models;
use App\Support\Concerns\DerivesWorkspaceIdFromTenant;
use App\Support\Concerns\InteractsWithODataTypes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Policy extends Model
{
use DerivesWorkspaceIdFromTenant;
use HasFactory;
use InteractsWithODataTypes;
public const VISIBILITY_ACTIVE = 'active';
public const VISIBILITY_IGNORED_LOCALLY = 'ignored_locally';
public const VISIBILITY_PROVIDER_MISSING = 'provider_missing';
public const VISIBILITY_IGNORED_LOCALLY_PROVIDER_MISSING = 'ignored_locally_provider_missing';
protected $guarded = [];
protected $casts = [
'metadata' => 'array',
'last_synced_at' => 'datetime',
'ignored_at' => 'datetime',
'missing_from_provider_at' => 'datetime',
];
public function tenant(): BelongsTo
{
return $this->belongsTo(Tenant::class);
}
public function versions(): HasMany
{
return $this->hasMany(PolicyVersion::class);
}
public function backupItems(): HasMany
{
return $this->hasMany(BackupItem::class);
}
public function scopeActive(Builder $query): Builder
{
return $query
->whereNull('ignored_at')
->whereNull('missing_from_provider_at');
}
public function scopeIgnored(Builder $query): Builder
{
return $query->whereNotNull('ignored_at');
}
public function scopeProviderMissing(Builder $query): Builder
{
return $query->whereNotNull('missing_from_provider_at');
}
public function scopeCurrentBackupEligible(Builder $query): Builder
{
return $query
->whereNull('ignored_at')
->whereNull('missing_from_provider_at');
}
public function isIgnoredLocally(): bool
{
return $this->ignored_at !== null;
}
public function isProviderMissing(): bool
{
return $this->missing_from_provider_at !== null;
}
public function visibilityState(): string
{
return match (true) {
$this->isIgnoredLocally() && $this->isProviderMissing() => self::VISIBILITY_IGNORED_LOCALLY_PROVIDER_MISSING,
$this->isIgnoredLocally() => self::VISIBILITY_IGNORED_LOCALLY,
$this->isProviderMissing() => self::VISIBILITY_PROVIDER_MISSING,
default => self::VISIBILITY_ACTIVE,
};
}
public function isCurrentBackupEligible(): bool
{
return ! $this->isIgnoredLocally() && ! $this->isProviderMissing();
}
public function currentBackupBlockedReason(): ?string
{
if ($this->isProviderMissing()) {
return self::VISIBILITY_PROVIDER_MISSING;
}
if ($this->isIgnoredLocally()) {
return self::VISIBILITY_IGNORED_LOCALLY;
}
return null;
}
public function currentBackupBlockedReasonLabel(): ?string
{
return match ($this->currentBackupBlockedReason()) {
self::VISIBILITY_PROVIDER_MISSING => 'Provider missing - current provider-backed capture is unavailable.',
self::VISIBILITY_IGNORED_LOCALLY => 'Ignored locally - restore local visibility before fresh capture.',
default => null,
};
}
public function ignore(): void
{
$this->update(['ignored_at' => now()]);
}
public function unignore(): void
{
$this->update(['ignored_at' => null]);
}
}