Skip to content

Commit

Permalink
Merge pull request #114 from itk-dev/feature/booking-289-update-cache…
Browse files Browse the repository at this point in the history
…-table-on-create

BOOKING-289: Moved cache entry creation into message handler to enabl…
  • Loading branch information
martinyde authored Nov 14, 2023
2 parents 7f33877 + 654bf87 commit ea6f891
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 32 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ All notable changes to this project will be documented in this file.

See [keep a changelog](https://keepachangelog.com/en/1.0.0/) for information about writing changes to this log.

## [develop]
## [Unreleased]

### Added

Expand All @@ -16,6 +16,7 @@ See [keep a changelog](https://keepachangelog.com/en/1.0.0/) for information abo
- Added API for fetching cached user bookings.
- Removed Rabbit MQ (remeber to update the DSN in local .env)
- Updated docker compose setup to newest version
- Fixed issue with booking cache entries not being created.

## [1.1.2] - 2023-08-29

Expand Down
22 changes: 22 additions & 0 deletions src/Message/AddBookingToCacheMessage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace App\Message;

use App\Entity\Main\Booking;

class AddBookingToCacheMessage
{
public function __construct(private readonly Booking $booking, private readonly string $iCalUID)
{
}

public function getBooking(): Booking
{
return $this->booking;
}

public function getICalUID(): string
{
return $this->iCalUID;
}
}
49 changes: 49 additions & 0 deletions src/MessageHandler/AddBookingToCacheHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace App\MessageHandler;

use App\Message\AddBookingToCacheMessage;
use App\Service\BookingServiceInterface;
use App\Service\UserBookingCacheServiceInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Messenger\Exception\RecoverableMessageHandlingException;

/**
* @see https://github.com/itk-dev/os2forms_selvbetjening/blob/develop/web/modules/custom/os2forms_rest_api/README.md
*/
#[AsMessageHandler]
class AddBookingToCacheHandler
{
public function __construct(
private readonly BookingServiceInterface $bookingService,
private readonly UserBookingCacheServiceInterface $userBookingCacheService,
private readonly LoggerInterface $logger,
) {
}

/**
* @throws \Exception
*/
public function __invoke(AddBookingToCacheMessage $message): void
{
$this->logger->info('AddBookingToCacheHandler invoked.');

$booking = $message->getBooking();
$id = $this->bookingService->getBookingIdFromICalUid($message->getICalUID()) ?? null;

if (null != $id) {
$this->userBookingCacheService->addCacheEntryFromArray([
'subject' => $booking->getSubject(),
'id' => $id,
'body' => $booking->getBody(),
'start' => $booking->getStartTime(),
'end' => $booking->getEndTime(),
'status' => 'AWAITING_APPROVAL',
'resourceMail' => $booking->getResourceEmail(),
]);
} else {
throw new RecoverableMessageHandlingException(sprintf('Booking id could not be retrieved for booking with iCalUID: %s', $message->getICalUID()));
}
}
}
24 changes: 8 additions & 16 deletions src/MessageHandler/CreateBookingHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
use App\Entity\Resources\AAKResource;
use App\Enum\NotificationTypeEnum;
use App\Exception\BookingCreateConflictException;
use App\Message\AddBookingToCacheMessage;
use App\Message\CreateBookingMessage;
use App\Message\SendBookingNotificationMessage;
use App\Repository\Resources\AAKResourceRepository;
use App\Repository\Resources\CvrWhitelistRepository;
use App\Security\Voter\BookingVoter;
use App\Service\BookingServiceInterface;
use App\Service\UserBookingCacheServiceInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException;
Expand All @@ -31,7 +31,6 @@ public function __construct(
private readonly Security $security,
private readonly MessageBusInterface $bus,
private readonly CvrWhitelistRepository $whitelistRepository,
private readonly UserBookingCacheServiceInterface $userBookingCacheService,
) {
}

Expand Down Expand Up @@ -96,8 +95,6 @@ public function __invoke(CreateBookingMessage $message): void
$booking,
NotificationTypeEnum::REQUEST_RECEIVED
));

$id = $response['id'];
} else {
$response = $this->bookingService->createBookingForResource(
$booking->getResourceEmail(),
Expand All @@ -114,20 +111,15 @@ public function __invoke(CreateBookingMessage $message): void
$booking,
NotificationTypeEnum::SUCCESS
));

$id = $this->bookingService->getBookingIdFromICalUid($response['iCalUId']) ?? null;
}

if (null != $id) {
$this->userBookingCacheService->addCacheEntryFromArray([
'subject' => $booking->getSubject(),
'id' => $id,
'body' => $booking->getBody(),
'start' => $booking->getStartTime(),
'end' => $booking->getEndTime(),
'status' => 'AWAITING_APPROVAL',
'resourceMail' => $booking->getResourceEmail(),
]);
if (isset($response['iCalUId'])) {
$this->bus->dispatch(new AddBookingToCacheMessage(
$booking,
$response['iCalUId'],
));
} else {
$this->logger->error(sprintf('Booking iCalUID could not be retrieved for booking with subject: %s', $booking->getSubject()));
}
} catch (BookingCreateConflictException $exception) {
// If it is a BookingCreateConflictException the booking should be rejected.
Expand Down
34 changes: 19 additions & 15 deletions tests/Api/BookingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Entity\Resources\AAKResource;
use App\Message\CreateBookingMessage;
use App\Message\WebformSubmitMessage;
use App\MessageHandler\AddBookingToCacheHandler;
use App\MessageHandler\CreateBookingHandler;
use App\MessageHandler\WebformSubmitHandler;
use App\Repository\Resources\AAKResourceRepository;
Expand All @@ -15,7 +16,6 @@
use App\Service\BookingServiceInterface;
use App\Service\MicrosoftGraphBookingService;
use App\Service\NotificationServiceInterface;
use App\Service\UserBookingCacheServiceInterface;
use App\Service\WebformService;
use App\Tests\AbstractBaseApiTestCase;
use App\Utils\ValidationUtils;
Expand Down Expand Up @@ -76,7 +76,7 @@ public function testBookingVoter(): void

public function testBookingWebform(): void
{
$this->messenger('async')->queue()->assertEmpty();
$this->transport('async')->queue()->assertEmpty();

$client = $this->getAuthenticatedClient();

Expand All @@ -102,23 +102,23 @@ public function testBookingWebform(): void
$this->assertResponseStatusCodeSame(201);

/** @var WebformSubmitMessage $message */
$message = $this->messenger('async')->queue()->first(WebformSubmitMessage::class)->getMessage();
$message = $this->transport('async')->queue()->first(WebformSubmitMessage::class)->getMessage();
$this->assertEquals('booking', $message->getWebformId());
$this->assertEquals('795f5a1c-a0ac-4f8a-8834-bb71fca8585d', $message->getSubmissionUuid());
$this->assertEquals('https://bookaarhus.local.itkdev.dk', $message->getSender());
$this->assertEquals('https://bookaarhus.local.itkdev.dk/webform_rest/booking/submission/123123123', $message->getSubmissionUrl());
$this->assertEquals(1, $message->getApiKeyUserId());

$this->messenger('async')->queue()->assertCount(1);
$this->messenger('async')->queue()->assertContains(WebformSubmitMessage::class);
$this->transport('async')->queue()->assertCount(1);
$this->transport('async')->queue()->assertContains(WebformSubmitMessage::class);
}

/**
* @throws \Exception
*/
public function testWebformSubmitMessageHandler(): void
{
$this->messenger('async')->queue()->assertEmpty();
$this->transport('async')->queue()->assertEmpty();

$webformServiceMock = $this->getMockBuilder(WebformService::class)
->onlyMethods(['getWebformSubmission', 'getData'])
Expand Down Expand Up @@ -208,22 +208,20 @@ public function testWebformSubmitMessageHandler(): void
$testUser->getId()
));

$this->messenger('async')->queue()->assertContains(CreateBookingMessage::class);
$this->messenger('async')->queue()->assertCount(1);
$this->transport('async')->queue()->assertContains(CreateBookingMessage::class);
$this->transport('async')->queue()->assertCount(1);
}

public function testCreateBookingHandler(): void
{
$microsoftGraphServiceMock = $this->getMockBuilder(MicrosoftGraphBookingService::class)
->disableOriginalConstructor()
->onlyMethods(['createBookingForResource', 'getBookingIdFromICalUid'])
->onlyMethods(['createBookingForResource'])
->getMock();
$microsoftGraphServiceMock->expects($this->exactly(1))->method('createBookingForResource')->willReturn([
'iCalUId' => '12345',
]);

$microsoftGraphServiceMock->expects($this->exactly(1))->method('getBookingIdFromICalUid')->willReturn('12345');

$container = self::getContainer();
$logger = $container->get(LoggerInterface::class);
$bus = $container->get(MessageBusInterface::class);
Expand Down Expand Up @@ -276,19 +274,25 @@ public function testCreateBookingHandler(): void

$container->set(AAKResourceRepository::class, $aakResourceRepositoryMock);

$addBookingToCacheHandlerMock = $this->getMockBuilder(AddBookingToCacheHandler::class)
->disableOriginalConstructor()
->onlyMethods(['__invoke'])
->getMock();
$addBookingToCacheHandlerMock->expects($this->exactly(1))->method('__invoke');
$container->set(AddBookingToCacheHandler::class, $addBookingToCacheHandlerMock);

$notificationServiceMock = $this->createMock(NotificationServiceInterface::class);
$container->set(NotificationServiceInterface::class, $notificationServiceMock);

$cvrWhitelistRepositoryMock = $this->createMock(CvrWhitelistRepository::class);

$userBookingCacheService = $container->get(UserBookingCacheServiceInterface::class);
$createBookingHandler = new CreateBookingHandler($microsoftGraphServiceMock, $logger, $aakResourceRepositoryMock, $security, $bus, $cvrWhitelistRepositoryMock, $userBookingCacheService);
$createBookingHandler = new CreateBookingHandler($microsoftGraphServiceMock, $logger, $aakResourceRepositoryMock, $security, $bus, $cvrWhitelistRepositoryMock);
$createBookingHandler->__invoke(new CreateBookingMessage($booking));
}

public function testInvalidBookingWebform(): void
{
$this->messenger('async')->queue()->assertEmpty();
$this->transport('async')->queue()->assertEmpty();

$client = $this->getAuthenticatedClient();

Expand All @@ -309,6 +313,6 @@ public function testInvalidBookingWebform(): void

$this->assertResponseStatusCodeSame(400);

$this->messenger('async')->queue()->assertCount(0);
$this->transport('async')->queue()->assertCount(0);
}
}
62 changes: 62 additions & 0 deletions tests/Handler/AddBookingToCacheHandlerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace App\Tests\Handler;

use App\Entity\Main\Booking;
use App\Message\AddBookingToCacheMessage;
use App\MessageHandler\AddBookingToCacheHandler;
use App\Security\Voter\BookingVoter;
use App\Service\BookingServiceInterface;
use App\Service\UserBookingCacheServiceInterface;
use App\Tests\AbstractBaseApiTestCase;
use Psr\Log\LoggerInterface;

class AddBookingToCacheHandlerTest extends AbstractBaseApiTestCase
{
public function testHandlerVoter(): void
{
$bookingServiceMock = $this->getMockBuilder(BookingServiceInterface::class)
->disableOriginalConstructor()
->getMock();
$bookingServiceMock->expects($this->exactly(1))->method('getBookingIdFromICalUid')->willReturn('abcde');

$userBookingCacheServiceMock = $this->getMockBuilder(UserBookingCacheServiceInterface::class)
->disableOriginalConstructor()
->getMock();
$userBookingCacheServiceMock->expects($this->exactly(1))->method('addCacheEntryFromArray');

$loggerMock = $this->createMock(LoggerInterface::class);

$handler = new AddBookingToCacheHandler(
$bookingServiceMock,
$userBookingCacheServiceMock,
$loggerMock,
);

$booking = new Booking();
$booking->setBody('test');
$booking->setSubject('test');
$booking->setResourceName('test');
$booking->setResourceEmail('[email protected]');
$booking->setStartTime(new \DateTime());
$booking->setEndTime(new \DateTime());
$booking->setUserName('author1');
$booking->setUserMail('[email protected]');
$booking->setMetaData([
'meta_data_4' => '1, 2, 3',
'meta_data_5' => 'a1, b2, c3',
'meta_data_1' => 'This is a metadata field',
'meta_data_2' => 'This is also metadata',
'meta_data_3' => 'Lorem ipsum metadata',
]);
$booking->setUserPermission(BookingVoter::PERMISSION_CITIZEN);
$booking->setUserId('1234567890');

$message = new AddBookingToCacheMessage(
$booking,
'12345'
);

$handler->__invoke($message);
}
}

0 comments on commit ea6f891

Please sign in to comment.