<?php
declare(strict_types=1);
namespace App\Bundles\EpidemiologicalSurveillanceBundle\EventSubscriber;
use App\Bundles\EpidemiologicalSurveillanceBundle\Enum\SurveillanceCaseTypeEnum;
use App\Bundles\EpidemiologicalSurveillanceBundle\Repository\SurveillanceCaseRepository;
use App\Bundles\EpidemiologicalSurveillanceBundle\Service\Template\WeekReportService;
use App\Bundles\LocationBundle\Entity\Location;
use App\Bundles\LocationBundle\Enum\LocationTypeEnum;
use App\Bundles\LocationBundle\Repository\LocationRepository;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
class SurveillanceCaseTypeSubscriber implements EventSubscriberInterface
{
public function __construct(
private readonly LocationRepository $locationRepository,
private readonly SurveillanceCaseRepository $surveillanceCaseRepository,
) {
}
public static function getSubscribedEvents(): array
{
return [
FormEvents::PRE_SUBMIT => 'onFormSubmit',
];
}
public function onFormSubmit(FormEvent $event): void
{
/** @var SurveillanceCaseTypeEnum $type */
$type = $event->getForm()->getConfig()->getOption('type');
$data = $event->getData();
$this->setValidIndividualNumberAndYear($type, $data);
$this->resolveLocationData($data);
$event->setData($data);
}
private function resolveLocationData(array &$data): void
{
$filters = $data['filters'] ?? [];
if (empty($filters)) {
return;
}
$data['location'] = $filters['clinicalData']['state'];
}
private function setValidIndividualNumberAndYear(SurveillanceCaseTypeEnum $type, array &$data): void
{
$filters = $data['filters'] ?? [];
if (empty($filters)) {
return;
}
$week = (int) $filters['week'];
$year = (int) $filters['year'];
$locationId = $data['location'];
/** @var Location $location */
$location = $this->locationRepository->find($locationId);
/** @var Location $location */
$location = $this->resolveLocation($location);
$latestIndividualNumber = $this->surveillanceCaseRepository->getLatestIndividualNumber(
$type,
$location,
$this->getStartSeason($year, $week),
$this->getEndSeason($year, $week)
);
$data['individualNumber'] = $latestIndividualNumber + 1;
}
private function resolveLocation(Location $location): ?Location
{
return match ($location->getType()) {
LocationTypeEnum::DISTRICT, LocationTypeEnum::SUB_DISTRICT => $location->getState(),
LocationTypeEnum::CITY_DISTRICT => $location->getCity(),
default => $location,
};
}
private function getStartSeason(int $year, int $week): int
{
if ($week >= WeekReportService::START_SEASON_START_WEEK) {
return $year;
}
return $year - 1;
}
private function getEndSeason(int $year, int $week): int
{
if ($week >= WeekReportService::START_SEASON_START_WEEK) {
return $year + 1;
}
return $year;
}
}