## Summary\n- Implements the ReviewPublicationResolutionWorkflow for Spec 386.\n- Adds resolution case/step persistence, policies, services, audit action IDs, and Filament integration.\n- Updates specs, UI/UX documentation, screenshots, and Pest coverage.\n\n## Tests\n- Not run during this handoff; branch was already clean and pushed.\n\n## Target\n- Base: platform-dev\n- Head/topic: 386-review-publication-resolution-workflow-v1 Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #457
155 lines
4.1 KiB
PHP
155 lines
4.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Support\ReviewPublicationResolution\ReviewPublicationResolutionCaseStatus;
|
|
use App\Support\ReviewPublicationResolution\ReviewPublicationResolutionStepKey;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
|
|
class ReviewPublicationResolutionCase extends Model
|
|
{
|
|
public const string ACTION_KEY = 'review.publication';
|
|
|
|
protected $guarded = [];
|
|
|
|
/**
|
|
* @return array<string, string>
|
|
*/
|
|
protected function casts(): array
|
|
{
|
|
return [
|
|
'summary' => 'array',
|
|
'metadata' => 'array',
|
|
'last_evaluated_at' => 'datetime',
|
|
'started_at' => 'datetime',
|
|
'completed_at' => 'datetime',
|
|
'cancelled_at' => 'datetime',
|
|
'superseded_at' => 'datetime',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @return BelongsTo<Workspace, $this>
|
|
*/
|
|
public function workspace(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Workspace::class);
|
|
}
|
|
|
|
/**
|
|
* @return BelongsTo<ManagedEnvironment, $this>
|
|
*/
|
|
public function tenant(): BelongsTo
|
|
{
|
|
return $this->belongsTo(ManagedEnvironment::class, 'managed_environment_id');
|
|
}
|
|
|
|
/**
|
|
* @return BelongsTo<EnvironmentReview, $this>
|
|
*/
|
|
public function environmentReview(): BelongsTo
|
|
{
|
|
return $this->belongsTo(EnvironmentReview::class);
|
|
}
|
|
|
|
/**
|
|
* @return BelongsTo<User, $this>
|
|
*/
|
|
public function creator(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class, 'created_by_user_id');
|
|
}
|
|
|
|
/**
|
|
* @return BelongsTo<User, $this>
|
|
*/
|
|
public function assignee(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class, 'assigned_to_user_id');
|
|
}
|
|
|
|
/**
|
|
* @return HasMany<ReviewPublicationResolutionStep, $this>
|
|
*/
|
|
public function steps(): HasMany
|
|
{
|
|
return $this->hasMany(ReviewPublicationResolutionStep::class, 'case_id')
|
|
->orderBy('position')
|
|
->orderBy('id');
|
|
}
|
|
|
|
public function currentStep(): ?ReviewPublicationResolutionStep
|
|
{
|
|
$currentStepKey = $this->current_step_key;
|
|
|
|
if (! is_string($currentStepKey) || $currentStepKey === '') {
|
|
return null;
|
|
}
|
|
|
|
if ($this->relationLoaded('steps')) {
|
|
$step = $this->steps->firstWhere('step_key', $currentStepKey);
|
|
|
|
return $step instanceof ReviewPublicationResolutionStep ? $step : null;
|
|
}
|
|
|
|
return $this->steps()->where('step_key', $currentStepKey)->first();
|
|
}
|
|
|
|
public function statusEnum(): ReviewPublicationResolutionCaseStatus
|
|
{
|
|
return ReviewPublicationResolutionCaseStatus::tryFrom((string) $this->status)
|
|
?? ReviewPublicationResolutionCaseStatus::Open;
|
|
}
|
|
|
|
public function isActive(): bool
|
|
{
|
|
return $this->statusEnum()->isActive();
|
|
}
|
|
|
|
public function currentStepKeyEnum(): ?ReviewPublicationResolutionStepKey
|
|
{
|
|
return ReviewPublicationResolutionStepKey::tryFrom((string) $this->current_step_key);
|
|
}
|
|
|
|
/**
|
|
* @param Builder<self> $query
|
|
* @return Builder<self>
|
|
*/
|
|
public function scopeForWorkspace(Builder $query, int $workspaceId): Builder
|
|
{
|
|
return $query->where('workspace_id', $workspaceId);
|
|
}
|
|
|
|
/**
|
|
* @param Builder<self> $query
|
|
* @return Builder<self>
|
|
*/
|
|
public function scopeForTenant(Builder $query, int $tenantId): Builder
|
|
{
|
|
return $query->where('managed_environment_id', $tenantId);
|
|
}
|
|
|
|
/**
|
|
* @param Builder<self> $query
|
|
* @return Builder<self>
|
|
*/
|
|
public function scopeForReview(Builder $query, EnvironmentReview|int $review): Builder
|
|
{
|
|
return $query->where('environment_review_id', $review instanceof EnvironmentReview ? (int) $review->getKey() : $review);
|
|
}
|
|
|
|
/**
|
|
* @param Builder<self> $query
|
|
* @return Builder<self>
|
|
*/
|
|
public function scopeActive(Builder $query): Builder
|
|
{
|
|
return $query->whereIn('status', ReviewPublicationResolutionCaseStatus::activeValues());
|
|
}
|
|
}
|