175 lines
6.8 KiB
PHP
175 lines
6.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests\Service\Assignment;
|
|
|
|
use App\Entity\Assignment;
|
|
use App\Entity\Destination;
|
|
use App\Entity\Fee;
|
|
use App\Entity\JobProfile;
|
|
use App\Entity\StaffingRule;
|
|
use App\Enum\StaffingFee;
|
|
use App\Enum\StaffingRole;
|
|
use App\Model\PlannedAssignment;
|
|
use App\Model\StaffingCandidate;
|
|
use App\Repository\AssignmentRepository;
|
|
use App\Repository\DestinationRepository;
|
|
use App\Repository\StaffingRuleRepository;
|
|
use App\Service\Assignment\AssignmentGenerator;
|
|
use App\Service\Assignment\AssignmentPlanner;
|
|
use App\Service\Assignment\StaffingResolver;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use PHPUnit\Framework\TestCase;
|
|
use Psr\Log\NullLogger;
|
|
|
|
class AssignmentGeneratorTest extends TestCase
|
|
{
|
|
public function testThePreviewSeesDisabledRowsAndTheCommandDoesNot(): void
|
|
{
|
|
$enabled = self::rule('DKIMP', enabled: true);
|
|
$disabled = self::rule('DGSMP', enabled: false);
|
|
|
|
$asked = [];
|
|
$destinationRepository = $this->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<StaffingRule> $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;
|
|
}
|
|
}
|