Implement ticket details and worklog editing

This commit is contained in:
2026-03-25 08:23:08 +01:00
parent 7e767b0c6c
commit 1ff8f5d68f
25 changed files with 1585 additions and 11 deletions
@@ -0,0 +1,60 @@
<?php
namespace Database\Factories;
use App\Actions\ProjectTicketMetadata\InitializeProjectTicketMetadata;
use App\Models\Ticket;
use App\Models\TicketFieldDefinition;
use App\Models\TicketFieldValue;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<TicketFieldValue>
*/
class TicketFieldValueFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'value_number' => fake()->randomFloat(1, 1, 13),
'value_user_id' => null,
];
}
public function configure(): static
{
return $this->afterMaking(function (TicketFieldValue $ticketFieldValue): void {
$ticket = $ticketFieldValue->ticket_id === null
? Ticket::factory()->create()
: Ticket::query()->findOrFail($ticketFieldValue->ticket_id);
app(InitializeProjectTicketMetadata::class)->handle($ticket->project);
$ticketFieldDefinition = $ticketFieldValue->ticket_field_definition_id === null
? TicketFieldDefinition::factory()->for($ticket->project)->create([
'field_type' => 'number',
'label' => 'Story Points',
'position' => $ticket->project->ticketFieldDefinitions()->count() + 1,
])
: TicketFieldDefinition::query()->findOrFail($ticketFieldValue->ticket_field_definition_id);
$ticketFieldValue->ticket_id = $ticket->id;
$ticketFieldValue->ticket_field_definition_id = $ticketFieldDefinition->id;
if ($ticketFieldDefinition->field_type === 'user') {
$ticketFieldValue->value_number = null;
$ticketFieldValue->value_user_id ??= User::factory()->create()->id;
return;
}
$ticketFieldValue->value_user_id = null;
});
}
}
@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('ticket_field_values', function (Blueprint $table) {
$table->id();
$table->foreignId('ticket_id')->constrained()->cascadeOnDelete();
$table->foreignId('ticket_field_definition_id')->constrained()->cascadeOnDelete();
$table->foreignId('value_user_id')->nullable()->constrained('users')->nullOnDelete();
$table->decimal('value_number', 10, 2)->nullable();
$table->timestamps();
$table->unique(['ticket_id', 'ticket_field_definition_id']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('ticket_field_values');
}
};
+1
View File
@@ -18,6 +18,7 @@ class DatabaseSeeder extends Seeder
BoardColumnSeeder::class,
ProjectTicketMetadataSeeder::class,
TicketSeeder::class,
TicketFieldValueSeeder::class,
TicketWorklogEntrySeeder::class,
TeamSeeder::class,
ProjectAccessSeeder::class,
@@ -0,0 +1,46 @@
<?php
namespace Database\Seeders;
use App\Models\Project;
use App\Models\Ticket;
use App\Models\TicketFieldDefinition;
use App\Models\TicketFieldValue;
use App\Models\User;
use Illuminate\Database\Seeder;
class TicketFieldValueSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$defaultUser = User::query()
->orderBy('id')
->first();
Project::query()
->with(['ticketFieldDefinitions', 'tickets'])
->orderBy('id')
->get()
->each(function (Project $project) use ($defaultUser): void {
/** @var TicketFieldDefinition $fieldDefinition */
foreach ($project->ticketFieldDefinitions as $fieldDefinition) {
/** @var Ticket $ticket */
foreach ($project->tickets as $ticket) {
TicketFieldValue::factory()->create([
'ticket_field_definition_id' => $fieldDefinition->id,
'ticket_id' => $ticket->id,
'value_number' => $fieldDefinition->field_type === 'number'
? (float) ($ticket->sequence_number + 2)
: null,
'value_user_id' => $fieldDefinition->field_type === 'user'
? $defaultUser?->id
: null,
]);
}
}
});
}
}