feat: add two- and four-weekly series and drop the weekday picker
This commit is contained in:
1 parent
8b88384d68
commit
faef4d70a8
10 files changed
+166
-103
No files matched your search
@@ -101,27 +101,62 @@ class BookingManagerTest extends KernelTestCase
|
||||
|
||||
public function testASeriesMaterialisesOneBookingPerOccurrence(): void
|
||||
{
|
||||
// 2026-10-05 is a Monday.
|
||||
$series = new BookingSeries(
|
||||
$this->user('[email protected]'),
|
||||
$this->resource('D1'),
|
||||
RecurrenceRule::WEEKLY,
|
||||
new \DateTimeImmutable('2026-10-05'),
|
||||
new \DateTimeImmutable('2026-10-30'),
|
||||
TimeRange::fromMinutes(540, 720),
|
||||
[1, 4],
|
||||
);
|
||||
// 2026-10-05 is a Monday; the Mondays up to the 30th are the 5th, 12th, 19th and 26th.
|
||||
$series = $this->weeklySeries();
|
||||
|
||||
$result = $this->manager->bookSeries($series);
|
||||
|
||||
self::assertSame(8, $result->createdCount());
|
||||
self::assertSame(4, $result->createdCount());
|
||||
self::assertSame(0, $result->skippedCount());
|
||||
foreach ($result->created as $booking) {
|
||||
self::assertContains((int) $booking->getDate()->format('N'), [1, 4]);
|
||||
self::assertSame(1, (int) $booking->getDate()->format('N'));
|
||||
self::assertSame($series, $booking->getSeries());
|
||||
}
|
||||
}
|
||||
|
||||
public function testATwoWeeklySeriesSkipsEveryOtherWeek(): void
|
||||
{
|
||||
$result = $this->manager->bookSeries(new BookingSeries(
|
||||
$this->user('[email protected]'),
|
||||
$this->resource('D1'),
|
||||
RecurrenceRule::TWO_WEEKLY,
|
||||
new \DateTimeImmutable('2026-10-05'),
|
||||
new \DateTimeImmutable('2026-11-30'),
|
||||
TimeRange::fromMinutes(540, 720),
|
||||
));
|
||||
|
||||
self::assertSame(5, $result->createdCount());
|
||||
self::assertSame(
|
||||
['2026-10-05', '2026-10-19', '2026-11-02', '2026-11-16', '2026-11-30'],
|
||||
array_map(static fn (Booking $booking): string => $booking->getDate()->format('Y-m-d'), $result->created),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The property the weekday field was removed in favour of: a stride that is a whole number of
|
||||
* weeks lands on the same weekday every time, so nothing has to store which one it is. A
|
||||
* four-weekly series is the one where this is easy to get wrong by reaching for months.
|
||||
*/
|
||||
public function testAFourWeeklySeriesAlwaysLandsOnTheSameWeekday(): void
|
||||
{
|
||||
$result = $this->manager->bookSeries(new BookingSeries(
|
||||
$this->user('[email protected]'),
|
||||
$this->resource('D1'),
|
||||
RecurrenceRule::FOUR_WEEKLY,
|
||||
new \DateTimeImmutable('2026-10-05'),
|
||||
new \DateTimeImmutable('2026-12-31'),
|
||||
TimeRange::fromMinutes(540, 720),
|
||||
));
|
||||
|
||||
self::assertSame(4, $result->createdCount());
|
||||
foreach ($result->created as $booking) {
|
||||
self::assertSame(1, (int) $booking->getDate()->format('N'), 'every occurrence is a Monday');
|
||||
}
|
||||
// Crossing a month boundary is where a "monthly" reading would diverge: 28 days after
|
||||
// 2 November is 30 November, not 2 December.
|
||||
self::assertSame('2026-11-30', $result->created[2]->getDate()->format('Y-m-d'));
|
||||
}
|
||||
|
||||
public function testADailySeriesCoversEveryDay(): void
|
||||
{
|
||||
$result = $this->manager->bookSeries(new BookingSeries(
|
||||
@@ -142,7 +177,8 @@ class BookingManagerTest extends KernelTestCase
|
||||
public function testASeriesSkipsDaysThatAreAlreadyTaken(): void
|
||||
{
|
||||
$desk = $this->resource('D1');
|
||||
$this->manager->book($this->user('[email protected]'), $desk, new \DateTimeImmutable('2026-10-08'), TimeRange::fromMinutes(600, 660));
|
||||
// The 12th is one of the series' own Mondays.
|
||||
$this->manager->book($this->user('[email protected]'), $desk, new \DateTimeImmutable('2026-10-12'), TimeRange::fromMinutes(600, 660));
|
||||
|
||||
$result = $this->manager->bookSeries(new BookingSeries(
|
||||
$this->user('[email protected]'),
|
||||
@@ -151,11 +187,10 @@ class BookingManagerTest extends KernelTestCase
|
||||
new \DateTimeImmutable('2026-10-05'),
|
||||
new \DateTimeImmutable('2026-10-30'),
|
||||
TimeRange::fromMinutes(540, 720),
|
||||
[1, 4],
|
||||
));
|
||||
|
||||
self::assertSame(7, $result->createdCount());
|
||||
self::assertSame(['8.10.'], $result->skippedDates());
|
||||
self::assertSame(3, $result->createdCount());
|
||||
self::assertSame(['12.10.'], $result->skippedDates());
|
||||
self::assertFalse($result->isCompletelyBlocked());
|
||||
}
|
||||
|
||||
@@ -232,7 +267,7 @@ class BookingManagerTest extends KernelTestCase
|
||||
|
||||
$removed = $this->manager->endSeries($series, new \DateTimeImmutable('2026-10-05'));
|
||||
|
||||
self::assertSame(8, $removed);
|
||||
self::assertSame(4, $removed);
|
||||
self::assertSame([], $this->em->getRepository(Booking::class)->findBy(['series' => $id]));
|
||||
// Nothing of the series is left, so the series row goes too -- note $series has no id
|
||||
// any more at this point, which is why the lookup goes through the captured one.
|
||||
@@ -244,10 +279,11 @@ class BookingManagerTest extends KernelTestCase
|
||||
$series = $this->weeklySeries();
|
||||
$this->manager->bookSeries($series);
|
||||
|
||||
// Leaves the Mondays on the 5th and 12th, removes the 19th and 26th.
|
||||
$removed = $this->manager->endSeries($series, new \DateTimeImmutable('2026-10-15'));
|
||||
|
||||
self::assertSame(5, $removed);
|
||||
self::assertCount(3, $this->em->getRepository(Booking::class)->findBy(['series' => $series]));
|
||||
self::assertSame(2, $removed);
|
||||
self::assertCount(2, $this->em->getRepository(Booking::class)->findBy(['series' => $series]));
|
||||
self::assertSame('2026-10-14', $series->getEndDate()->format('Y-m-d'));
|
||||
}
|
||||
|
||||
@@ -260,7 +296,6 @@ class BookingManagerTest extends KernelTestCase
|
||||
new \DateTimeImmutable('2026-10-05'),
|
||||
new \DateTimeImmutable('2026-10-30'),
|
||||
TimeRange::fromMinutes(540, 720),
|
||||
[1, 4],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user