Implement ticket statuses

This commit is contained in:
2026-04-14 03:09:12 +02:00
parent 2dc12c5d60
commit 8f4a8276ac
40 changed files with 1602 additions and 100 deletions
+14 -3
View File
@@ -8,6 +8,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
#[Fillable(['name', 'position', 'project_id'])]
class BoardColumn extends Model
@@ -20,9 +21,19 @@ class BoardColumn extends Model
return $this->belongsTo(Project::class);
}
public function tickets(): HasMany
public function ticketStatuses(): HasMany
{
return $this->hasMany(Ticket::class)
->orderByDesc('sequence_number');
return $this->hasMany(TicketStatus::class)
->orderBy('position');
}
public function tickets(): HasManyThrough
{
return $this->hasManyThrough(
Ticket::class,
TicketStatus::class,
'board_column_id',
'ticket_status_id',
)->orderByDesc('tickets.sequence_number');
}
}
+7
View File
@@ -68,6 +68,13 @@ class Project extends Model
->orderBy('position');
}
public function ticketStatuses(): HasMany
{
return $this->hasMany(TicketStatus::class)
->orderBy('board_column_id')
->orderBy('position');
}
public function ticketTypes(): HasMany
{
return $this->hasMany(TicketType::class)
+6 -6
View File
@@ -13,7 +13,6 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
'acceptance_criteria',
'assignee_user_id',
'author_user_id',
'board_column_id',
'blocked_comment',
'description',
'is_blocked',
@@ -22,6 +21,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
'sequence_number',
'ticket_key',
'ticket_priority_id',
'ticket_status_id',
'ticket_type_id',
'title',
'story_points',
@@ -41,11 +41,6 @@ class Ticket extends Model
];
}
public function boardColumn(): BelongsTo
{
return $this->belongsTo(BoardColumn::class);
}
public function assignee(): BelongsTo
{
return $this->belongsTo(User::class, 'assignee_user_id');
@@ -95,6 +90,11 @@ class Ticket extends Model
return $this->belongsTo(TicketPriority::class);
}
public function ticketStatus(): BelongsTo
{
return $this->belongsTo(TicketStatus::class);
}
public function ticketType(): BelongsTo
{
return $this->belongsTo(TicketType::class);
+84
View File
@@ -0,0 +1,84 @@
<?php
namespace App\Models;
use Database\Factories\TicketStatusFactory;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Str;
#[Fillable(['board_column_id', 'name', 'position', 'project_id', 'slug'])]
class TicketStatus extends Model
{
/** @use HasFactory<TicketStatusFactory> */
use HasFactory;
protected static function booted(): void
{
static::saving(function (self $ticketStatus): void {
$ticketStatus->slug = Str::slug($ticketStatus->name);
});
static::created(function (self $ticketStatus): void {
$statusIds = self::query()
->where('project_id', $ticketStatus->project_id)
->pluck('id');
$ticketStatus->allowedTargetStatuses()->syncWithoutDetaching($statusIds);
self::query()
->where('project_id', $ticketStatus->project_id)
->whereKeyNot($ticketStatus->id)
->get()
->each(fn (self $existingStatus): array => $existingStatus
->allowedTargetStatuses()
->syncWithoutDetaching([$ticketStatus->id]));
});
}
public function allowedSourceStatuses(): BelongsToMany
{
return $this->belongsToMany(
self::class,
'ticket_status_transitions',
'to_ticket_status_id',
'from_ticket_status_id',
)
->orderBy('board_column_id')
->orderBy('position')
->withTimestamps();
}
public function allowedTargetStatuses(): BelongsToMany
{
return $this->belongsToMany(
self::class,
'ticket_status_transitions',
'from_ticket_status_id',
'to_ticket_status_id',
)
->orderBy('board_column_id')
->orderBy('position')
->withTimestamps();
}
public function boardColumn(): BelongsTo
{
return $this->belongsTo(BoardColumn::class);
}
public function project(): BelongsTo
{
return $this->belongsTo(Project::class);
}
public function tickets(): HasMany
{
return $this->hasMany(Ticket::class)
->orderByDesc('sequence_number');
}
}