Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions backend/app/Http/Actions/Events/DeleteEventAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace HiEvents\Http\Actions\Events;

use HiEvents\DomainObjects\Enums\Role;
use HiEvents\DomainObjects\EventDomainObject;
use HiEvents\Exceptions\CannotDeleteEntityException;
use HiEvents\Http\Actions\BaseAction;
use HiEvents\Services\Application\Handlers\Event\DeleteEventHandler;
use HiEvents\Services\Application\Handlers\Event\DTO\DeleteEventDTO;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;
use Symfony\Component\HttpFoundation\Response as HttpResponse;

class DeleteEventAction extends BaseAction
{
public function __construct(
private readonly DeleteEventHandler $deleteEventHandler,
)
{
}

public function __invoke(int $eventId): Response|JsonResponse
{
$this->isActionAuthorized($eventId, EventDomainObject::class, Role::ADMIN);

try {
$this->deleteEventHandler->handle(DeleteEventDTO::fromArray([
'eventId' => $eventId,
'accountId' => $this->getAuthenticatedAccountId(),
]));
} catch (CannotDeleteEntityException $exception) {
return $this->errorResponse(
message: $exception->getMessage(),
statusCode: HttpResponse::HTTP_CONFLICT,
);
}

return $this->deletedResponse();
}
}
33 changes: 33 additions & 0 deletions backend/app/Http/Actions/Events/GetEventDeletionStatusAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace HiEvents\Http\Actions\Events;

use HiEvents\DomainObjects\EventDomainObject;
use HiEvents\Http\Actions\BaseAction;
use HiEvents\Services\Domain\Event\EventDeletionService;
use Illuminate\Http\JsonResponse;

class GetEventDeletionStatusAction extends BaseAction
{
public function __construct(
private readonly EventDeletionService $eventDeletionService,
)
{
}

public function __invoke(int $eventId): JsonResponse
{
$this->isActionAuthorized($eventId, EventDomainObject::class);

$canDelete = $this->eventDeletionService->canDeleteEvent($eventId);

return $this->jsonResponse([
'data' => [
'can_delete' => $canDelete,
'reason' => $canDelete ? null : __('This event has completed orders. Please cancel or refund all orders before deleting.'),
],
]);
}
}
43 changes: 43 additions & 0 deletions backend/app/Http/Actions/Organizers/DeleteOrganizerAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace HiEvents\Http\Actions\Organizers;

use HiEvents\DomainObjects\Enums\Role;
use HiEvents\DomainObjects\OrganizerDomainObject;
use HiEvents\Exceptions\CannotDeleteEntityException;
use HiEvents\Http\Actions\BaseAction;
use HiEvents\Services\Application\Handlers\Organizer\DeleteOrganizerHandler;
use HiEvents\Services\Application\Handlers\Organizer\DTO\DeleteOrganizerDTO;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;
use Symfony\Component\HttpFoundation\Response as HttpResponse;

class DeleteOrganizerAction extends BaseAction
{
public function __construct(
private readonly DeleteOrganizerHandler $deleteOrganizerHandler,
)
{
}

public function __invoke(int $organizerId): Response|JsonResponse
{
$this->isActionAuthorized($organizerId, OrganizerDomainObject::class, Role::ADMIN);

try {
$this->deleteOrganizerHandler->handle(DeleteOrganizerDTO::fromArray([
'organizerId' => $organizerId,
'accountId' => $this->getAuthenticatedAccountId(),
]));
} catch (CannotDeleteEntityException $exception) {
return $this->errorResponse(
message: $exception->getMessage(),
statusCode: HttpResponse::HTTP_CONFLICT,
);
}

return $this->deletedResponse();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace HiEvents\Http\Actions\Organizers;

use HiEvents\DomainObjects\OrganizerDomainObject;
use HiEvents\Http\Actions\BaseAction;
use HiEvents\Services\Domain\Organizer\OrganizerDeletionService;
use Illuminate\Http\JsonResponse;

class GetOrganizerDeletionStatusAction extends BaseAction
{
public function __construct(
private readonly OrganizerDeletionService $organizerDeletionService,
)
{
}

public function __invoke(int $organizerId): JsonResponse
{
$this->isActionAuthorized($organizerId, OrganizerDomainObject::class);

$accountId = $this->getAuthenticatedAccountId();
$canDelete = $this->organizerDeletionService->canDeleteOrganizer($organizerId, $accountId);
$reason = $canDelete ? null : $this->organizerDeletionService->getCannotDeleteReason($organizerId, $accountId);

return $this->jsonResponse([
'data' => [
'can_delete' => $canDelete,
'reason' => $reason,
],
]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use HiEvents\DomainObjects\OrganizerDomainObject;
use HiEvents\Exceptions\AccountNotVerifiedException;
use HiEvents\Exceptions\CannotDeleteEntityException;
use HiEvents\Http\Actions\BaseAction;
use HiEvents\Http\Request\Organizer\UpdateOrganizerStatusRequest;
use HiEvents\Http\ResponseCodes;
Expand Down Expand Up @@ -32,6 +33,8 @@ public function __invoke(UpdateOrganizerStatusRequest $request, int $organizerId
]));
} catch (AccountNotVerifiedException $e) {
return $this->errorResponse($e->getMessage(), ResponseCodes::HTTP_UNPROCESSABLE_ENTITY);
} catch (CannotDeleteEntityException $e) {
return $this->errorResponse($e->getMessage(), ResponseCodes::HTTP_CONFLICT);
}

return $this->resourceResponse(OrganizerResource::class, $updatedOrganizer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
use HiEvents\Repository\Interfaces\EmailTemplateRepositoryInterface;
use HiEvents\Services\Application\Handlers\EmailTemplate\DTO\UpsertEmailTemplateDTO;
use HiEvents\Services\Domain\Email\EmailTemplateService;
use HiEvents\Services\Infrastructure\HtmlPurifier\HtmlPurifierService;

class CreateEmailTemplateHandler
{
public function __construct(
private readonly EmailTemplateRepositoryInterface $emailTemplateRepository,
private readonly EmailTemplateService $emailTemplateService,
private readonly HtmlPurifierService $purifier,
)
{
}
Expand Down Expand Up @@ -50,7 +52,7 @@ public function handle(UpsertEmailTemplateDTO $dto): EmailTemplateDomainObject
'event_id' => $dto->event_id,
'template_type' => $dto->template_type->value,
'subject' => $dto->subject,
'body' => $dto->body,
'body' => $this->purifier->purify($dto->body),
'cta' => $dto->cta,
'engine' => $dto->engine->value,
'is_active' => $dto->is_active,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
use HiEvents\Repository\Interfaces\EmailTemplateRepositoryInterface;
use HiEvents\Services\Application\Handlers\EmailTemplate\DTO\UpsertEmailTemplateDTO;
use HiEvents\Services\Domain\Email\EmailTemplateService;
use HiEvents\Services\Infrastructure\HtmlPurifier\HtmlPurifierService;

class UpdateEmailTemplateHandler
{
public function __construct(
private readonly EmailTemplateRepositoryInterface $emailTemplateRepository,
private readonly EmailTemplateService $emailTemplateService
private readonly EmailTemplateService $emailTemplateService,
private readonly HtmlPurifierService $purifier,
) {
}

Expand Down Expand Up @@ -47,7 +49,7 @@ public function handle(UpsertEmailTemplateDTO $dto): EmailTemplateDomainObject

return $this->emailTemplateRepository->updateFromArray($template->getId(), [
'subject' => $dto->subject,
'body' => $dto->body,
'body' => $this->purifier->purify($dto->body),
'cta' => $dto->cta,
'engine' => $dto->engine->value,
'is_active' => $dto->is_active,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace HiEvents\Services\Application\Handlers\Event\DTO;

use HiEvents\DataTransferObjects\BaseDTO;

class DeleteEventDTO extends BaseDTO
{
public function __construct(
public int $eventId,
public int $accountId,
)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace HiEvents\Services\Application\Handlers\Event;

use HiEvents\Exceptions\CannotDeleteEntityException;
use HiEvents\Services\Application\Handlers\Event\DTO\DeleteEventDTO;
use HiEvents\Services\Domain\Event\EventDeletionService;
use Throwable;

class DeleteEventHandler
{
public function __construct(
private readonly EventDeletionService $eventDeletionService,
)
{
}

/**
* @throws CannotDeleteEntityException
* @throws Throwable
*/
public function handle(DeleteEventDTO $dto): void
{
$this->eventDeletionService->deleteEvent($dto->eventId, $dto->accountId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace HiEvents\Services\Application\Handlers\Organizer\DTO;

use HiEvents\DataTransferObjects\BaseDTO;

class DeleteOrganizerDTO extends BaseDTO
{
public function __construct(
public int $organizerId,
public int $accountId,
)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace HiEvents\Services\Application\Handlers\Organizer;

use HiEvents\Exceptions\CannotDeleteEntityException;
use HiEvents\Services\Application\Handlers\Organizer\DTO\DeleteOrganizerDTO;
use HiEvents\Services\Domain\Organizer\OrganizerDeletionService;
use Throwable;

class DeleteOrganizerHandler
{
public function __construct(
private readonly OrganizerDeletionService $organizerDeletionService,
)
{
}

/**
* @throws CannotDeleteEntityException
* @throws Throwable
*/
public function handle(DeleteOrganizerDTO $dto): void
{
$this->organizerDeletionService->deleteOrganizer($dto->organizerId, $dto->accountId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@
namespace HiEvents\Services\Application\Handlers\Organizer;

use HiEvents\DomainObjects\OrganizerDomainObject;
use HiEvents\DomainObjects\Status\EventStatus;
use HiEvents\DomainObjects\Status\OrganizerStatus;
use HiEvents\Exceptions\AccountNotVerifiedException;
use HiEvents\Exceptions\CannotDeleteEntityException;
use HiEvents\Repository\Interfaces\AccountRepositoryInterface;
use HiEvents\Repository\Interfaces\EventRepositoryInterface;
use HiEvents\Repository\Interfaces\OrganizerRepositoryInterface;
use HiEvents\Services\Application\Handlers\Organizer\DTO\UpdateOrganizerStatusDTO;
use Illuminate\Database\DatabaseManager;
Expand All @@ -16,14 +20,15 @@ class UpdateOrganizerStatusHandler
public function __construct(
private readonly OrganizerRepositoryInterface $organizerRepository,
private readonly AccountRepositoryInterface $accountRepository,
private readonly EventRepositoryInterface $eventRepository,
private readonly LoggerInterface $logger,
private readonly DatabaseManager $databaseManager,
)
{
}

/**
* @throws AccountNotVerifiedException|Throwable
* @throws AccountNotVerifiedException|CannotDeleteEntityException|Throwable
*/
public function handle(UpdateOrganizerStatusDTO $updateOrganizerStatusDTO): OrganizerDomainObject
{
Expand All @@ -33,7 +38,7 @@ public function handle(UpdateOrganizerStatusDTO $updateOrganizerStatusDTO): Orga
}

/**
* @throws AccountNotVerifiedException
* @throws AccountNotVerifiedException|CannotDeleteEntityException
*/
private function updateOrganizerStatus(UpdateOrganizerStatusDTO $updateOrganizerStatusDTO): OrganizerDomainObject
{
Expand All @@ -46,6 +51,19 @@ private function updateOrganizerStatus(UpdateOrganizerStatusDTO $updateOrganizer
);
}

if ($updateOrganizerStatusDTO->status === OrganizerStatus::ARCHIVED->name) {
$activeOrganizerCount = $this->organizerRepository->countWhere([
'account_id' => $updateOrganizerStatusDTO->accountId,
['status', '!=', OrganizerStatus::ARCHIVED->name],
]);

if ($activeOrganizerCount <= 1) {
throw new CannotDeleteEntityException(
__('You cannot archive the last active organizer on your account.')
);
}
}

$this->organizerRepository->updateWhere(
attributes: ['status' => $updateOrganizerStatusDTO->status],
where: [
Expand All @@ -54,6 +72,20 @@ private function updateOrganizerStatus(UpdateOrganizerStatusDTO $updateOrganizer
]
);

if ($updateOrganizerStatusDTO->status === OrganizerStatus::ARCHIVED->name) {
$this->eventRepository->updateWhere(
attributes: ['status' => EventStatus::ARCHIVED->name],
where: [
'organizer_id' => $updateOrganizerStatusDTO->organizerId,
'account_id' => $updateOrganizerStatusDTO->accountId,
]
);

$this->logger->info('All events archived for organizer', [
'organizerId' => $updateOrganizerStatusDTO->organizerId,
]);
}

$this->logger->info('Organizer status updated', [
'organizerId' => $updateOrganizerStatusDTO->organizerId,
'status' => $updateOrganizerStatusDTO->status
Expand Down
Loading
Loading