feat: warn about overlapping bookings instead of refusing them
This commit is contained in:
1 parent
fae28b1fd7
commit
5a6db29205
8 files changed
+359
-71
No files matched your search
@@ -115,7 +115,12 @@ class BookingControllerTest extends WebTestCase
|
||||
self::assertStringContainsString('ist am 01.10.2026 bereits belegt', (string) $response->getContent());
|
||||
}
|
||||
|
||||
public function testOnePersonCannotHoldTwoDesksOnTheSameDay(): void
|
||||
/**
|
||||
* A second desk at the same time used to be refused. It is allowed now -- the second one is
|
||||
* usually for the customer somebody is meeting -- and the flash is what tells them they are
|
||||
* now holding two.
|
||||
*/
|
||||
public function testASecondDeskAtTheSameTimeIsBookedAndWarnedAbout(): void
|
||||
{
|
||||
$anna = $this->user('[email protected]');
|
||||
$this->em->persist(new Booking($anna, $this->resource('D1'), new \DateTimeImmutable('2026-10-01')));
|
||||
@@ -124,12 +129,50 @@ class BookingControllerTest extends WebTestCase
|
||||
$this->client->loginUser($anna);
|
||||
|
||||
$response = $this->submitBookingModal($this->resource('D2'), '2026-10-01');
|
||||
$content = (string) $response->getContent();
|
||||
|
||||
self::assertSame(Response::HTTP_UNPROCESSABLE_ENTITY, $response->getStatusCode());
|
||||
self::assertStringContainsString('bereits D1 gebucht', (string) $response->getContent());
|
||||
self::assertSame(Response::HTTP_OK, $response->getStatusCode());
|
||||
self::assertStringContainsString('D2 gebucht', $content, 'the booking itself still succeeds');
|
||||
self::assertStringContainsString('zur gleichen Zeit bereits D1 gebucht', $content);
|
||||
}
|
||||
|
||||
public function testADeskAndAParkingSpotOnTheSameDayAreBothAllowed(): void
|
||||
public function testEveryClashingDeskIsNamedInTheWarning(): void
|
||||
{
|
||||
$anna = $this->user('[email protected]');
|
||||
$this->em->persist(new Booking($anna, $this->resource('D1'), new \DateTimeImmutable('2026-10-01')));
|
||||
$this->em->persist(new Booking($anna, $this->resource('D2'), new \DateTimeImmutable('2026-10-01')));
|
||||
$this->em->flush();
|
||||
|
||||
$this->client->loginUser($anna);
|
||||
|
||||
$response = $this->submitBookingModal($this->resource('D3'), '2026-10-01');
|
||||
|
||||
self::assertSame(Response::HTTP_OK, $response->getStatusCode());
|
||||
self::assertStringContainsString('bereits 2 weitere Schreibtische gebucht: D1, D2', (string) $response->getContent());
|
||||
}
|
||||
|
||||
public function testTwoDesksAtDifferentTimesAreNotWarnedAbout(): void
|
||||
{
|
||||
$anna = $this->user('[email protected]');
|
||||
$this->em->persist(new Booking($anna, $this->resource('D1'), new \DateTimeImmutable('2026-10-01'), TimeRange::fromMinutes(540, 720)));
|
||||
$this->em->flush();
|
||||
|
||||
$this->client->loginUser($anna);
|
||||
|
||||
$response = $this->submitBookingModal($this->resource('D2'), '2026-10-01', [
|
||||
'startTime' => '13:00',
|
||||
'endTime' => '17:00',
|
||||
]);
|
||||
|
||||
self::assertSame(Response::HTTP_OK, $response->getStatusCode());
|
||||
self::assertStringNotContainsString('Hinweis', (string) $response->getContent());
|
||||
}
|
||||
|
||||
/**
|
||||
* The deliberately quiet case: a desk and a parking space at the same time is the everyday
|
||||
* combination, and a toast for it would train everybody to ignore the toast that matters.
|
||||
*/
|
||||
public function testADeskAndAParkingSpotOnTheSameDayAreBothAllowedWithoutAWarning(): void
|
||||
{
|
||||
$anna = $this->user('[email protected]');
|
||||
$this->em->persist(new Booking($anna, $this->resource('D1'), new \DateTimeImmutable('2026-10-01')));
|
||||
@@ -140,6 +183,56 @@ class BookingControllerTest extends WebTestCase
|
||||
$response = $this->submitBookingModal($this->resource('P1', ResourceType::PARKING), '2026-10-01');
|
||||
|
||||
self::assertSame(Response::HTTP_OK, $response->getStatusCode());
|
||||
self::assertStringNotContainsString('Hinweis', (string) $response->getContent());
|
||||
}
|
||||
|
||||
public function testASeriesIsWarnedAboutOnceForAllItsClashingDays(): void
|
||||
{
|
||||
$anna = $this->user('[email protected]');
|
||||
$other = $this->resource('D2');
|
||||
// Two of the four Mondays the series lands on, and one Tuesday it does not.
|
||||
$this->em->persist(new Booking($anna, $other, new \DateTimeImmutable('2026-10-05'), TimeRange::fromMinutes(600, 660)));
|
||||
$this->em->persist(new Booking($anna, $other, new \DateTimeImmutable('2026-10-19'), TimeRange::fromMinutes(600, 660)));
|
||||
$this->em->persist(new Booking($anna, $other, new \DateTimeImmutable('2026-10-20'), TimeRange::fromMinutes(600, 660)));
|
||||
$this->em->flush();
|
||||
|
||||
$this->client->loginUser($anna);
|
||||
|
||||
$response = $this->submitBookingModal($this->resource('D1'), '2026-10-05', [
|
||||
'startTime' => '09:00',
|
||||
'endTime' => '12:00',
|
||||
'repeat' => 'weekly',
|
||||
'until' => '2026-10-30',
|
||||
]);
|
||||
$content = (string) $response->getContent();
|
||||
|
||||
self::assertSame(Response::HTTP_OK, $response->getStatusCode());
|
||||
self::assertSame(1, substr_count($content, 'Hinweis:'), 'one flash for the whole series');
|
||||
self::assertStringContainsString('An 2 von 4 Terminen', $content);
|
||||
self::assertStringContainsString('(5.10., 19.10.)', $content);
|
||||
}
|
||||
|
||||
public function testMovingABookingOntoAnotherOneWarns(): void
|
||||
{
|
||||
$anna = $this->user('[email protected]');
|
||||
$mine = new Booking($anna, $this->resource('D1'), new \DateTimeImmutable('2026-10-01'), TimeRange::fromMinutes(780, 1020));
|
||||
$this->em->persist($mine);
|
||||
$this->em->persist(new Booking($anna, $this->resource('D2'), new \DateTimeImmutable('2026-10-01'), TimeRange::fromMinutes(540, 720)));
|
||||
$this->em->flush();
|
||||
|
||||
$this->client->loginUser($anna);
|
||||
|
||||
$url = \sprintf('/bookings/%d/edit', $mine->getId());
|
||||
$crawler = $this->client->request('GET', $url, server: ['HTTP_HX-Request' => 'true']);
|
||||
$this->client->request('POST', $url, ['booking' => [
|
||||
'startTime' => '10:00',
|
||||
'endTime' => '11:00',
|
||||
'_token' => $crawler->filter('#booking__token')->attr('value'),
|
||||
]], server: ['HTTP_HX-Request' => 'true']);
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
self::assertSame(Response::HTTP_OK, $response->getStatusCode());
|
||||
self::assertStringContainsString('zur gleichen Zeit bereits D2 gebucht', (string) $response->getContent());
|
||||
}
|
||||
|
||||
public function testAnInvalidCsrfTokenIsRejected(): void
|
||||
|
||||
Reference in new issue
Block a user