assertMatchesRegularExpression('/^[0-9a-f-]{36}$/', $first->getUuid()); $this->assertNotSame($first->getUuid(), $second->getUuid()); } public function testANewSeasonAssignmentIsNotDeleted(): void { $this->assertFalse((new SeasonAssignment())->isDeleted()); } /** * The list only ever hides soft-deleted records, so deleting must not detach the teamer - * the placement has to stay readable for whoever looks at it afterwards. */ public function testSoftDeletingKeepsTheRecordIntact(): void { $teamer = (new Teamer())->setFirstName('Ada')->setLastName('Musterfrau'); $seasonAssignment = (new SeasonAssignment())->setTeamer($teamer); $seasonAssignment->setDeleted(); $this->assertTrue($seasonAssignment->isDeleted()); $this->assertSame($teamer, $seasonAssignment->getTeamer()); } public function testTheInverseSideIsKeptInSync(): void { $teamer = new Teamer(); $seasonAssignment = new SeasonAssignment(); $teamer->addSeasonAssignment($seasonAssignment); $this->assertCount(1, $teamer->getSeasonAssignments()); $this->assertSame($teamer, $seasonAssignment->getTeamer()); // adding the same one twice must not duplicate it $teamer->addSeasonAssignment($seasonAssignment); $this->assertCount(1, $teamer->getSeasonAssignments()); $teamer->removeSeasonAssignment($seasonAssignment); $this->assertCount(0, $teamer->getSeasonAssignments()); $this->assertNull($seasonAssignment->getTeamer()); } /** * Administrative users lay the season's assignments out first and place teamers on them * later, so an assignment without a teamer is a normal state rather than a half built one. */ public function testAnAssignmentStartsWithoutATeamer(): void { $seasonAssignment = new SeasonAssignment(); $this->assertNull($seasonAssignment->getTeamer()); } public function testATeamerCanBePlacedAndRemovedAgain(): void { $teamer = (new Teamer())->setFirstName('Ada')->setLastName('Musterfrau'); $seasonAssignment = new SeasonAssignment(); $seasonAssignment->setTeamer($teamer); $this->assertSame($teamer, $seasonAssignment->getTeamer()); $seasonAssignment->setTeamer(null); $this->assertNull($seasonAssignment->getTeamer()); } /** * The period and the house live on the assignment itself - it is not cut from a travel, so * there is no Destination to read them from. */ public function testItCarriesItsOwnPeriodAndHouse(): void { $seasonAssignment = (new SeasonAssignment()) ->setTeamer((new Teamer())->setFirstName('Ada')->setLastName('Musterfrau')) ->setDateFrom(new \DateTimeImmutable('2026-11-01')) ->setDateTo(new \DateTimeImmutable('2027-04-30')) ->setHotelCode('AGR') ->setJobProfile((new JobProfile())->setName('Guide')) ; $this->assertSame('2026-11-01', $seasonAssignment->getDateFrom()->format('Y-m-d')); $this->assertSame('2027-04-30', $seasonAssignment->getDateTo()->format('Y-m-d')); $this->assertSame('AGR', $seasonAssignment->getHotelCode()); } public function testApplyingDeadlinesCopiesBothOverridesOntoOpenEntriesOnly(): void { $seasonAssignment = new SeasonAssignment(); $source = (new SeasonAssignmentTask()) ->setDeadlineOverride1(new \DateTimeImmutable('2026-11-15')) ->setDeadlineOverride2(new \DateTimeImmutable('2026-11-30')); $open = new SeasonAssignmentTask(); $done = (new SeasonAssignmentTask()) ->setDone(true) ->setDeadlineOverride1(new \DateTimeImmutable('2026-10-01')); $seasonAssignment->addTask($source)->addTask($open)->addTask($done); $this->assertSame(1, $seasonAssignment->applyDeadlinesToOpenTasks($source)); $this->assertSame('2026-11-15', $open->getDeadlineOverride1()?->format('Y-m-d')); $this->assertSame('2026-11-30', $open->getDeadlineOverride2()?->format('Y-m-d')); $this->assertSame('2026-10-01', $done->getDeadlineOverride1()?->format('Y-m-d')); $this->assertNull($done->getDeadlineOverride2()); } /** * Empty fields are applied as well: that is how the office resets every entry to its * computed deadline in one go. */ public function testApplyingEmptyDeadlinesResetsTheOverrides(): void { $seasonAssignment = new SeasonAssignment(); $source = new SeasonAssignmentTask(); $other = (new SeasonAssignmentTask()) ->setDeadlineOverride1(new \DateTimeImmutable('2026-11-15')) ->setDeadlineOverride2(new \DateTimeImmutable('2026-11-30')); $seasonAssignment->addTask($source)->addTask($other); $seasonAssignment->applyDeadlinesToOpenTasks($source); $this->assertNull($other->getDeadlineOverride1()); $this->assertNull($other->getDeadlineOverride2()); } }