Files
myep-team/src/Service/Assignment/AssignmentGenerator.php
T

115 lines
3.8 KiB
PHP

<?php
namespace App\Service\Assignment;
use App\Entity\Assignment;
use App\Model\StaffingCandidate;
use App\Repository\AssignmentRepository;
use App\Repository\DestinationRepository;
use App\Repository\StaffingRuleRepository;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
/**
* Creates the draft assignments the staffing matrix calls for. Shared by app:assignment-generate
* and the admin preview, so what the stakeholders confirm is what gets generated.
*/
class AssignmentGenerator
{
public function __construct(
private readonly StaffingRuleRepository $staffingRuleRepository,
private readonly DestinationRepository $destinationRepository,
private readonly AssignmentRepository $assignmentRepository,
private readonly AssignmentPlanner $planner,
private readonly StaffingResolver $resolver,
private readonly EntityManagerInterface $entityManager,
private readonly LoggerInterface $logger,
) {
}
/**
* @param bool $enabledOnly false for the preview, which shows rows not yet switched on
*
* @return list<StaffingCandidate>
*/
public function getCandidates(bool $enabledOnly, ?\DateTimeImmutable $today = null): array
{
$rules = [];
foreach ($this->staffingRuleRepository->getList() as $rule) {
if (false === $enabledOnly || true === $rule->isEnabled()) {
$rules[$rule->getProductCode()] = $rule;
}
}
$destinations = $this->destinationRepository->getStaffingCandidates(
array_map('strval', array_keys($rules)),
$today ?? new \DateTimeImmutable('today'),
);
$skipped = array_flip($this->assignmentRepository->getDestinationIdsWithAnyAssignment($destinations));
$candidates = [];
foreach ($destinations as $destination) {
$rule = $rules[$destination->getProductCode()];
$candidates[] = new StaffingCandidate(
$destination,
$rule,
$this->planner->plan($rule, $destination),
isset($skipped[$destination->getId()]),
);
}
return $candidates;
}
/**
* Persists and flushes the candidate's drafts.
*
* @return list<Assignment>
*
* @throws StaffingConfigurationException when a configured job profile or fee is missing
*/
public function generate(StaffingCandidate $candidate): array
{
if (true === $candidate->skipped) {
return [];
}
$assignments = [];
foreach ($candidate->planned as $planned) {
$assignment = (new Assignment())
->setDestination($candidate->destination)
->setJobProfile($this->resolver->jobProfile($planned->role))
->setAvailableDispositions($planned->places)
->setPickup($planned->pickup)
;
foreach ($planned->fees as $fee) {
$assignment->addFee($this->resolver->fee($fee));
}
$this->entityManager->persist($assignment);
$assignments[] = $assignment;
}
$this->entityManager->flush();
foreach ($assignments as $assignment) {
$this->logger->info('Generate assignment', [
'assignment_id' => $assignment->getId(),
'destination_id' => $candidate->destination->getId(),
'destination_code' => $candidate->destination->getCode(),
'product_code' => $candidate->rule->getProductCode(),
'job_profile' => $assignment->getJobProfile()->getName(),
'places' => $assignment->getAvailableDispositions(),
'pickup' => $assignment->getPickup(),
]);
}
return $assignments;
}
}