diff --git a/app/Actions/Notifications/BuildTicketAssigneeChangedPayload.php b/app/Actions/Notifications/BuildTicketAssigneeChangedPayload.php index 6302327..75e8e3e 100644 --- a/app/Actions/Notifications/BuildTicketAssigneeChangedPayload.php +++ b/app/Actions/Notifications/BuildTicketAssigneeChangedPayload.php @@ -2,7 +2,6 @@ namespace App\Actions\Notifications; -use App\Enums\NotificationEventType; use App\Models\Project; use App\Models\Ticket; use App\Models\TicketStatus; @@ -20,11 +19,10 @@ class BuildTicketAssigneeChangedPayload ?int $toAssigneeId, ?string $toAssigneeName, CarbonImmutable $occurredAt, - ): TicketStatusChangedPayload { + ): TicketAssigneeChangedPayload { $ticket->loadMissing('ticketStatus.boardColumn'); - return new TicketStatusChangedPayload( - eventType: NotificationEventType::TicketAssigneeChanged, + return new TicketAssigneeChangedPayload( projectId: $project->id, projectKey: $project->key, projectName: $project->name, diff --git a/app/Actions/Notifications/TicketAssigneeChanged.php b/app/Actions/Notifications/TicketAssigneeChanged.php index 5bbfcec..d49643e 100644 --- a/app/Actions/Notifications/TicketAssigneeChanged.php +++ b/app/Actions/Notifications/TicketAssigneeChanged.php @@ -11,7 +11,7 @@ final readonly class TicketAssigneeChanged implements NotificationEvent, ShouldD use Dispatchable; public function __construct( - public TicketStatusChangedPayload $payload, + public TicketAssigneeChangedPayload $payload, ) {} public function eventType(): NotificationEventType diff --git a/app/Actions/Notifications/TicketAssigneeChangedPayload.php b/app/Actions/Notifications/TicketAssigneeChangedPayload.php new file mode 100644 index 0000000..0eceb6b --- /dev/null +++ b/app/Actions/Notifications/TicketAssigneeChangedPayload.php @@ -0,0 +1,129 @@ +projectId; + } + + /** + * @return array + */ + public function deliveryMetadata(): array + { + return [ + 'project_key' => $this->projectKey, + 'ticket_key' => $this->ticketKey, + ]; + } + + /** + * @return array + */ + public function discordTemplateVariables(): array + { + return [ + '$url' => $this->ticketUrl, + '$ticket_key' => $this->ticketKey, + '$ticket_title' => $this->ticketTitle, + '$project_name' => $this->projectName, + '$status_from' => $this->fromStatusLabel ?? '', + '$status_to' => $this->toStatusLabel, + '$actor_name' => $this->actorName ?? '', + '$assignee_from' => $this->fromAssigneeName ?? '', + '$assignee_to' => $this->toAssigneeName ?? '', + ]; + } + + /** + * @return array{ + * event_type: string, + * project: array{id: int, key: string, name: string}, + * ticket: array{id: int, key: string, title: string}, + * actor: array{id: int, name: string}|null, + * assignee: array{ + * from: array{id: int, name: string}|null, + * to: array{id: int, name: string}|null + * }, + * from: array{id: int, label: string}|null, + * to: array{id: int, label: string}, + * ticket_url: string, + * occurred_at: string + * } + */ + public function toArray(): array + { + return [ + 'event_type' => NotificationEventType::TicketAssigneeChanged->value, + 'project' => [ + 'id' => $this->projectId, + 'key' => $this->projectKey, + 'name' => $this->projectName, + ], + 'ticket' => [ + 'id' => $this->ticketId, + 'key' => $this->ticketKey, + 'title' => $this->ticketTitle, + ], + 'actor' => $this->actorId === null || $this->actorName === null + ? null + : [ + 'id' => $this->actorId, + 'name' => $this->actorName, + ], + 'assignee' => [ + 'from' => $this->fromAssigneeId === null || $this->fromAssigneeName === null + ? null + : [ + 'id' => $this->fromAssigneeId, + 'name' => $this->fromAssigneeName, + ], + 'to' => $this->toAssigneeId === null || $this->toAssigneeName === null + ? null + : [ + 'id' => $this->toAssigneeId, + 'name' => $this->toAssigneeName, + ], + ], + 'from' => $this->fromStatusId === null || $this->fromStatusLabel === null + ? null + : [ + 'id' => $this->fromStatusId, + 'label' => $this->fromStatusLabel, + ], + 'to' => [ + 'id' => $this->toStatusId, + 'label' => $this->toStatusLabel, + ], + 'ticket_url' => $this->ticketUrl, + 'occurred_at' => $this->occurredAt->toISOString(), + ]; + } +} diff --git a/app/Actions/Notifications/TicketStatusChangedPayload.php b/app/Actions/Notifications/TicketStatusChangedPayload.php index 2d1e9b3..cc6997b 100644 --- a/app/Actions/Notifications/TicketStatusChangedPayload.php +++ b/app/Actions/Notifications/TicketStatusChangedPayload.php @@ -17,16 +17,11 @@ final readonly class TicketStatusChangedPayload implements NotificationEventPayl public string $ticketUrl, public ?int $actorId, public ?string $actorName, - public ?int $fromStatusId, - public ?string $fromStatusLabel, + public int $fromStatusId, + public string $fromStatusLabel, public int $toStatusId, public string $toStatusLabel, public CarbonImmutable $occurredAt, - public ?int $fromAssigneeId = null, - public ?string $fromAssigneeName = null, - public ?int $toAssigneeId = null, - public ?string $toAssigneeName = null, - public NotificationEventType $eventType = NotificationEventType::TicketStatusChanged, ) {} public function projectId(): int @@ -55,11 +50,9 @@ final readonly class TicketStatusChangedPayload implements NotificationEventPayl '$ticket_key' => $this->ticketKey, '$ticket_title' => $this->ticketTitle, '$project_name' => $this->projectName, - '$status_from' => $this->fromStatusLabel ?? '', + '$status_from' => $this->fromStatusLabel, '$status_to' => $this->toStatusLabel, '$actor_name' => $this->actorName ?? '', - '$assignee_from' => $this->fromAssigneeName ?? '', - '$assignee_to' => $this->toAssigneeName ?? '', ]; } @@ -69,11 +62,7 @@ final readonly class TicketStatusChangedPayload implements NotificationEventPayl * project: array{id: int, key: string, name: string}, * ticket: array{id: int, key: string, title: string}, * actor: array{id: int, name: string}|null, - * assignee: array{ - * from: array{id: int, name: string}|null, - * to: array{id: int, name: string}|null - * }, - * from: array{id: int, label: string}|null, + * from: array{id: int, label: string}, * to: array{id: int, label: string}, * ticket_url: string, * occurred_at: string @@ -82,7 +71,7 @@ final readonly class TicketStatusChangedPayload implements NotificationEventPayl public function toArray(): array { return [ - 'event_type' => $this->eventType->value, + 'event_type' => NotificationEventType::TicketStatusChanged->value, 'project' => [ 'id' => $this->projectId, 'key' => $this->projectKey, @@ -99,26 +88,10 @@ final readonly class TicketStatusChangedPayload implements NotificationEventPayl 'id' => $this->actorId, 'name' => $this->actorName, ], - 'assignee' => [ - 'from' => $this->fromAssigneeId === null || $this->fromAssigneeName === null - ? null - : [ - 'id' => $this->fromAssigneeId, - 'name' => $this->fromAssigneeName, - ], - 'to' => $this->toAssigneeId === null || $this->toAssigneeName === null - ? null - : [ - 'id' => $this->toAssigneeId, - 'name' => $this->toAssigneeName, - ], + 'from' => [ + 'id' => $this->fromStatusId, + 'label' => $this->fromStatusLabel, ], - 'from' => $this->fromStatusId === null || $this->fromStatusLabel === null - ? null - : [ - 'id' => $this->fromStatusId, - 'label' => $this->fromStatusLabel, - ], 'to' => [ 'id' => $this->toStatusId, 'label' => $this->toStatusLabel, diff --git a/tests/Feature/Notifications/DeliverNotificationActionTest.php b/tests/Feature/Notifications/DeliverNotificationActionTest.php index d60c295..d693f5a 100644 --- a/tests/Feature/Notifications/DeliverNotificationActionTest.php +++ b/tests/Feature/Notifications/DeliverNotificationActionTest.php @@ -558,10 +558,6 @@ class DeliverNotificationActionTest extends TestCase * project: array{id: int, key: string, name: string}, * ticket: array{id: int, key: string, title: string}, * actor: array{id: int, name: string}, - * assignee: array{ - * from: array{id: int, name: string}|null, - * to: array{id: int, name: string}|null - * }, * from: array{id: int, label: string}, * to: array{id: int, label: string}, * ticket_url: string, @@ -586,10 +582,6 @@ class DeliverNotificationActionTest extends TestCase 'id' => 7, 'name' => 'Erica Example', ], - 'assignee' => [ - 'from' => null, - 'to' => null, - ], 'from' => [ 'id' => 1, 'label' => 'Backlog', diff --git a/tests/Feature/Notifications/RenderDiscordMessageTemplateTest.php b/tests/Feature/Notifications/RenderDiscordMessageTemplateTest.php index ae5616b..2ff69b9 100644 --- a/tests/Feature/Notifications/RenderDiscordMessageTemplateTest.php +++ b/tests/Feature/Notifications/RenderDiscordMessageTemplateTest.php @@ -3,8 +3,8 @@ namespace Tests\Feature\Notifications; use App\Actions\Notifications\RenderDiscordMessageTemplate; -use App\Actions\Notifications\TicketStatusChanged; -use App\Actions\Notifications\TicketStatusChangedPayload; +use App\Actions\Notifications\TicketAssigneeChanged; +use App\Actions\Notifications\TicketAssigneeChangedPayload; use Carbon\CarbonImmutable; use PHPUnit\Framework\Attributes\DataProvider; use Tests\TestCase; @@ -80,9 +80,9 @@ class RenderDiscordMessageTemplateTest extends TestCase $this->assertSame('[CORE-42] $unknown moved to Doing', $renderedMessage); } - private function event(): TicketStatusChanged + private function event(): TicketAssigneeChanged { - return new TicketStatusChanged(new TicketStatusChangedPayload( + return new TicketAssigneeChanged(new TicketAssigneeChangedPayload( projectId: 10, projectKey: 'CORE', projectName: 'Core Platform', diff --git a/tests/Feature/Notifications/TicketAssigneeChangedNotificationDispatchTest.php b/tests/Feature/Notifications/TicketAssigneeChangedNotificationDispatchTest.php index ea6136b..ec8ef39 100644 --- a/tests/Feature/Notifications/TicketAssigneeChangedNotificationDispatchTest.php +++ b/tests/Feature/Notifications/TicketAssigneeChangedNotificationDispatchTest.php @@ -3,6 +3,7 @@ namespace Tests\Feature\Notifications; use App\Actions\Notifications\DeliverNotificationAction; +use App\Actions\Notifications\TicketAssigneeChangedPayload; use App\Actions\ProjectTicketMetadata\InitializeProjectTicketMetadata; use App\Actions\Tickets\Support\AcceptanceCriteriaChecklistMapper; use App\Enums\NotificationDeliveryStatus; @@ -158,6 +159,7 @@ class TicketAssigneeChangedNotificationDispatchTest extends TestCase $payload = $job->event->payload(); return $job->notificationActionId === $webhookAction->id + && $payload instanceof TicketAssigneeChangedPayload && $payload->projectId === $project->id && $payload->projectKey === 'CORE' && $payload->projectName === 'Core Platform' @@ -175,7 +177,7 @@ class TicketAssigneeChangedNotificationDispatchTest extends TestCase && $payload->fromAssigneeName === 'Alex Analyst' && $payload->toAssigneeId === $toAssignee->id && $payload->toAssigneeName === 'Priya Planner' - && $payload->eventType === NotificationEventType::TicketAssigneeChanged + && $payload->toArray()['event_type'] === NotificationEventType::TicketAssigneeChanged->value && $job->notificationDeliveryLogId !== null; }); Queue::assertPushed(DeliverNotificationAction::class, fn (DeliverNotificationAction $job): bool => $job->notificationActionId === $discordAction->id