, * assignee_user_id?: int|null, * author_user_id?: int|null, * blocked_comment?: string|null, * description: string|null, * field_values?: array, * is_blocked?: bool, * parent_ticket_id?: int|null, * story_points?: int|null, * ticket_priority_id: int, * ticket_status_id: int, * ticket_type_id: int, * title: string * } $attributes */ public function handle(Project $project, array $attributes, ?User $actor = null): Ticket { return DB::transaction(function () use ($actor, $attributes, $project): Ticket { $acceptanceCriteria = AcceptanceCriteriaChecklistMapper::normalize( Arr::get($attributes, 'acceptance_criteria'), ); $nextSequenceNumber = (int) Ticket::query() ->where('project_id', $project->id) ->max('sequence_number') + 1; $ticketStatusQuery = TicketStatus::query()->where('project_id', $project->id); $ticketStatus = $ticketStatusQuery->findOrFail(Arr::get($attributes, 'ticket_status_id')); $isBlocked = (bool) Arr::get($attributes, 'is_blocked', false); $ticket = Ticket::query()->create([ 'assignee_user_id' => Arr::get($attributes, 'assignee_user_id'), 'author_user_id' => Arr::get($attributes, 'author_user_id', $actor?->id), 'blocked_comment' => $isBlocked ? Arr::get($attributes, 'blocked_comment') : null, 'description' => Arr::get($attributes, 'description'), 'is_blocked' => $isBlocked, 'parent_ticket_id' => Arr::get($attributes, 'parent_ticket_id'), 'project_id' => $project->id, 'sequence_number' => $nextSequenceNumber, 'ticket_key' => "{$project->key}-{$nextSequenceNumber}", 'ticket_priority_id' => Arr::get($attributes, 'ticket_priority_id'), 'ticket_status_id' => $ticketStatus->id, 'ticket_type_id' => Arr::get($attributes, 'ticket_type_id'), 'title' => Arr::get($attributes, 'title'), 'story_points' => Arr::get($attributes, 'story_points'), ]); AcceptanceCriteriaChecklistMapper::syncTicket($ticket, $acceptanceCriteria); $fieldValues = Arr::get($attributes, 'field_values', []); if ($fieldValues !== []) { $this->syncProjectTicketFieldValues->handle( $ticket, $project->ticketFieldDefinitions()->get()->keyBy('id'), collect(), $fieldValues, ); } $occurredAt = CarbonImmutable::now(); if ($actor !== null) { $this->createTicketWorklogEntry->handle( $ticket, $actor, TicketWorklogEntryType::Created, "Ticket was created in {$ticketStatus->name}.", [ 'from' => null, 'to' => [ 'label' => $ticketStatus->name, 'ticket_status_id' => $ticketStatus->id, ], ], ); } TicketCreated::dispatch( $this->buildTicketCreatedPayload->handle( $project, $ticket, $ticketStatus, $actor, $occurredAt, ), ); return $ticket; }); } }