createStub(DestinationRepository::class); $destinationRepository->method('getStaffingCandidates')->willReturnCallback( static function (array $productCodes) use (&$asked): array { $asked[] = $productCodes; return []; } ); $generator = $this->generator([$enabled, $disabled], $destinationRepository); $generator->getCandidates(enabledOnly: false); $generator->getCandidates(enabledOnly: true); $this->assertSame([['DKIMP', 'DGSMP'], ['DKIMP']], $asked); } public function testADateWithAnAssignmentIsMarkedSkipped(): void { $staffed = self::destination(1, 'DKIMP'); $open = self::destination(2, 'DKIMP'); $destinationRepository = $this->createStub(DestinationRepository::class); $destinationRepository->method('getStaffingCandidates')->willReturn([$staffed, $open]); $assignmentRepository = $this->createStub(AssignmentRepository::class); $assignmentRepository->method('getDestinationIdsWithAnyAssignment')->willReturn([1]); $candidates = $this ->generator([self::rule('DKIMP', enabled: true)], $destinationRepository, $assignmentRepository) ->getCandidates(enabledOnly: true) ; $this->assertTrue($candidates[0]->skipped); $this->assertFalse($candidates[1]->skipped); } public function testGenerateBuildsDraftsFromThePlan(): void { $destination = self::destination(1, 'DKIMP'); $guide = new JobProfile(); $course = new JobProfile(); $guidingFee = new Fee(); $courseFee = new Fee(); $resolver = $this->createStub(StaffingResolver::class); $resolver->method('jobProfile')->willReturnCallback( static fn (StaffingRole $role): JobProfile => StaffingRole::GUIDE === $role ? $guide : $course ); $resolver->method('fee')->willReturnCallback( static fn (StaffingFee $fee): Fee => StaffingFee::GUIDING === $fee ? $guidingFee : $courseFee ); $persisted = []; $entityManager = $this->createMock(EntityManagerInterface::class); $entityManager->method('persist')->willReturnCallback(static function (object $entity) use (&$persisted): void { $persisted[] = $entity; }); $entityManager->expects($this->once())->method('flush'); $generator = $this->generator([], resolver: $resolver, entityManager: $entityManager); $assignments = $generator->generate(new StaffingCandidate($destination, self::rule('DKIMP', enabled: true), [ new PlannedAssignment(StaffingRole::GUIDE, 2, 5, [StaffingFee::GUIDING]), new PlannedAssignment(StaffingRole::SKI_BEGINNER, 1, null, [StaffingFee::COURSE]), ], false)); $this->assertSame($persisted, $assignments); $this->assertCount(2, $assignments); $this->assertSame($destination, $assignments[0]->getDestination()); $this->assertSame($guide, $assignments[0]->getJobProfile()); $this->assertSame(2, $assignments[0]->getAvailableDispositions()); $this->assertSame(5, $assignments[0]->getPickup()); $this->assertSame([$guidingFee], $assignments[0]->getFees()->toArray()); $this->assertSame(Assignment::STATUS_DRAFT, $assignments[0]->getStatus()); $this->assertSame($course, $assignments[1]->getJobProfile()); $this->assertSame(0, $assignments[1]->getPickup()); $this->assertSame([$courseFee], $assignments[1]->getFees()->toArray()); } public function testASkippedCandidateGeneratesNothing(): void { $entityManager = $this->createMock(EntityManagerInterface::class); $entityManager->expects($this->never())->method('persist'); $entityManager->expects($this->never())->method('flush'); $assignments = $this->generator([], entityManager: $entityManager)->generate(new StaffingCandidate( self::destination(1, 'DKIMP'), self::rule('DKIMP', enabled: true), [new PlannedAssignment(StaffingRole::GUIDE, 1)], true, )); $this->assertSame([], $assignments); } /** * @param list $rules */ private function generator( array $rules, ?DestinationRepository $destinationRepository = null, ?AssignmentRepository $assignmentRepository = null, ?StaffingResolver $resolver = null, ?EntityManagerInterface $entityManager = null, ): AssignmentGenerator { $staffingRuleRepository = $this->createStub(StaffingRuleRepository::class); $staffingRuleRepository->method('getList')->willReturn($rules); if (null === $assignmentRepository) { $assignmentRepository = $this->createStub(AssignmentRepository::class); $assignmentRepository->method('getDestinationIdsWithAnyAssignment')->willReturn([]); } return new AssignmentGenerator( $staffingRuleRepository, $destinationRepository ?? $this->createStub(DestinationRepository::class), $assignmentRepository, new AssignmentPlanner(), $resolver ?? $this->createStub(StaffingResolver::class), $entityManager ?? $this->createStub(EntityManagerInterface::class), new NullLogger(), ); } private static function rule(string $productCode, bool $enabled): StaffingRule { return (new StaffingRule())->setProductCode($productCode)->setGuides(1)->setEnabled($enabled); } private static function destination(int $id, string $productCode): Destination { $destination = (new Destination())->setProductCode($productCode)->setCode($productCode.'110127'); (new \ReflectionProperty(Destination::class, 'id'))->setValue($destination, $id); return $destination; } }