createDisposition($assignment, $teamer); $this->assertSame($disposition, $assignment->getActiveDispositionByTeamer($teamer)); } public function testACalledOffDispositionIsNotReturned(): void { $assignment = new Assignment(); $teamer = new Teamer(); $this ->createDisposition($assignment, $teamer) ->setStatus(Disposition::STATUS_CALLED_OFF) ; $this->assertNull($assignment->getActiveDispositionByTeamer($teamer)); } public function testTheDispositionOfAnotherTeamerIsNotReturned(): void { $assignment = new Assignment(); $this->createDisposition($assignment, new Teamer()); $this->assertNull($assignment->getActiveDispositionByTeamer(new Teamer())); } /** * A teamer can be called off and disposed again on the same assignment, so both dispositions * live side by side - the active one has to win. */ public function testTheActiveDispositionWinsOverACalledOffOne(): void { $assignment = new Assignment(); $teamer = new Teamer(); $this ->createDisposition($assignment, $teamer) ->setStatus(Disposition::STATUS_CALLED_OFF) ; $disposition = $this->createDisposition($assignment, $teamer); $this->assertSame($disposition, $assignment->getActiveDispositionByTeamer($teamer)); } /** * The "Busbegleitung ab" field stores 0 for "Keine Busbegleitung" as well as null. */ #[DataProvider('providePickups')] public function testHasBusEscort(int|string|null $pickup, bool $expected): void { $this->assertSame($expected, (new Assignment())->setPickup($pickup)->hasBusEscort()); } public static function providePickups(): iterable { yield 'none' => [null, false]; yield 'zero' => [0, false]; yield 'empty form value' => ['', false]; yield 'pickup' => [4711, true]; } public function testTheFirstPlacementTakesPlaceOne(): void { $this->assertSame(1, $this->createDisposition(new Assignment(), new Teamer())->getSlot()); } /** * The n8n feed hangs the Wechselpass off the place number: a replacement takes the number the * called-off teamer freed, and whoever stays keeps theirs. */ public function testAReplacementTakesTheFreedPlaceAndTheStayerKeepsTheirs(): void { $assignment = (new Assignment())->setAvailableDispositions(2); $first = $this->createDisposition($assignment, new Teamer()); $second = $this->createDisposition($assignment, new Teamer()); $first->setStatus(Disposition::STATUS_CALLED_OFF); $replacement = $this->createDisposition($assignment, new Teamer()); $this->assertSame(1, $replacement->getSlot()); $this->assertSame(2, $second->getSlot()); $this->assertSame([1 => $replacement, 2 => $second], $assignment->getPlaces()); } public function testACalledOffPlacementLeavesAnOpenPlace(): void { $assignment = (new Assignment())->setAvailableDispositions(2); $calledOff = $this->createDisposition($assignment, new Teamer()); $stayer = $this->createDisposition($assignment, new Teamer()); $calledOff->setStatus(Disposition::STATUS_CALLED_OFF); $this->assertSame([1 => null, 2 => $stayer], $assignment->getPlaces()); } public function testUnfilledPlacesAreOpen(): void { $assignment = (new Assignment())->setAvailableDispositions(3); $disposition = $this->createDisposition($assignment, new Teamer()); $this->assertSame([1 => $disposition, 2 => null, 3 => null], $assignment->getPlaces()); } /** * Striking a place while a high number is still held drops an open low one, not the person. */ public function testLoweringTheCountKeepsTheHeldPlace(): void { $assignment = (new Assignment())->setAvailableDispositions(2); $calledOff = $this->createDisposition($assignment, new Teamer()); $stayer = $this->createDisposition($assignment, new Teamer()); $calledOff->setStatus(Disposition::STATUS_CALLED_OFF); $assignment->setAvailableDispositions(1); $this->assertSame([2 => $stayer], $assignment->getPlaces()); } public function testAPlaceHeldBeyondTheCountIsStillListed(): void { $assignment = (new Assignment())->setAvailableDispositions(2); $first = $this->createDisposition($assignment, new Teamer()); $second = $this->createDisposition($assignment, new Teamer()); $assignment->setAvailableDispositions(1); $this->assertSame([1 => $first, 2 => $second], $assignment->getPlaces()); } public function testAnUnnumberedPlacementTakesAFreeNumberAfterTheNumberedOnes(): void { $assignment = (new Assignment())->setAvailableDispositions(2); $unnumbered = $this->createDisposition($assignment, new Teamer())->setSlot(null); $numbered = $this->createDisposition($assignment, new Teamer())->setSlot(1); $this->assertSame([1 => $numbered, 2 => $unnumbered], $assignment->getPlaces()); } private function createDisposition(Assignment $assignment, Teamer $teamer): Disposition { $disposition = new Disposition(new Application($assignment, $teamer)); $assignment->addDisposition($disposition); return $disposition; } }