<?php
namespace App\Controller\Customer\Delivery;
use App\Entity\DeliveryPoint;
use App\Entity\EventOrder;
use App\Entity\Package;
use App\Entity\CodeLocationPackage;
use App\Entity\PackageCodeSenderDelivery;
use App\Entity\EventPackageStateChange;
use App\Entity\PackageDelivery;
use App\Classes\Dictionaries\PackageState;
use DateTimeInterface;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use App\Entity\PackageCode;
use App\Form\Customer\TrackAndTraceSearchType;
use Symfony\Contracts\Translation\TranslatorInterface;
class TrackAndTraceController extends AbstractController
{
/*
* @var Pokud někdo do get parametru vloží nevalidní kód, pak true
*/
public bool $warning = false;
/**
* Slouží k získání kódu balíku, pokud uživatel použije formulář.
* @param Request $request
* @param EntityManagerInterface $em
* @param TranslatorInterface $translator
* @return Response
* @throws Exception
*/
public function trackAndTracePageGet(Request $request, EntityManagerInterface $em, TranslatorInterface $translator): Response
{
$form = $this->createForm(TrackAndTraceSearchType::class, [], []);
$form->handleRequest($request);
$packageCodeString = $request->query->get("code");
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
$packageCodeString = $data['packageCode'];
return $this->redirectToRoute(
'customer_delivery_track_and_trace_get_parameter',
['code' => $packageCodeString]
);
}
if (strlen($packageCodeString) > 64) {
$this->warning = true;
}
if ($packageCodeString === null) {
$packageCodeString = "";
$this->warning = true;
}
return $this->trackAndTracePage($packageCodeString, $em, $translator);
}
/**
* Stranka zobrazuje zakaznikovy stav jeho balilu
* @param string $packageCodeString
* @param EntityManagerInterface $em
* @param TranslatorInterface $translator
* @return Response
* @throws Exception
*/
public function trackAndTracePage(string $packageCodeString, EntityManagerInterface $em, TranslatorInterface $translator): Response
{
$form = $this->createForm(TrackAndTraceSearchType::class, [], []);
$package = null;
$holidays = null;
$eventsViewMap = null;
if (!$this->warning) {
$packageCodeRepo = $em->getRepository(PackageCode::class);
$delPointRepo = $em->getRepository(DeliveryPoint::class);
$packageCode = $packageCodeRepo->findPackageCodeByString(mb_strtoupper($packageCodeString));
if ($packageCode instanceof PackageCodeSenderDelivery) {
$codeLocation = $packageCode->getCodeLocation();
if ($codeLocation instanceof CodeLocationPackage) {
$package = $codeLocation->getPackage();
}
if (!is_null($package)) {
$eventsViewMap = $this->getTrackAndTraceEvents($package, $em, $translator);
$holidays = $delPointRepo->getFutureOrActiveHolidays($package->getOrder()->getDeliveryPoint());
}
}
}
return $this->render(
'Customer/Delivery/track_and_trace.html.twig',
[
'packageCode' => $packageCodeString,
'package' => $package,
'missingCode' => $this->warning,
'events' => $eventsViewMap,
'form' => $form->createView(),
'holidays' => $holidays
]
);
}
/**
* Funkce vybere udalosti z baliku
* vrati pole hodnot [timestamp, description] pro view
* @param Package $package
* @param EntityManagerInterface $em
* @param TranslatorInterface $translator
* @return array<array{created:DateTimeInterface,description:string,info:string}>
*/
private function getTrackAndTraceEvents(Package $package, EntityManagerInterface $em, TranslatorInterface $translator): array
{
$filteredEvents = [];
$packageEvents = $package->getPackageEvents();
$wantedPackageEvents = [
EventPackageStateChange::class
];
foreach ($packageEvents as $event) {
if (in_array(get_class($event), $wantedPackageEvents, true)) {
$filteredEvents[] = $event;
}
}
usort($filteredEvents, static function ($a, $b) {
$diff = $a->getCreated()->getTimestamp() - $b->getCreated()->getTimestamp();
if ($diff === 0) {
return $a->getId() - $b->getId();
}
return $diff;
});
// slouzi k popisu dle id stavu baliku
$eventId = [
[
'id' => PackageState::STATE_UNRECEIVED,
'desc' => $translator->trans('Obdrželi jsme data, čekáme na přijetí zásilky na depo.', [], 'support'),
'info' => $translator->trans('je nyní zpracováván.', [], 'support')
],
[
'id' => PackageState::STATE_CANCELED,
'desc' => $translator->trans('Doručení zásilky bylo zrušeno.', [], 'support'),
'info' => $translator->trans('byl zrušen.', [], 'support')
],
[
'id' => PackageState::STATE_IN_BOX,
'desc' => $translator->trans('Zásilka je na cestě na výdejnu.', [], 'support'),
'info' => $translator->trans('bude již brzy na výdejně.', [], 'support')
],
[
'id' => PackageState::STATE_PICKED_UP,
'desc' => $translator->trans('Balík byl vyzvednut.', [], 'support'),
'info' => $translator->trans('již je ve vašich rukou.', [], 'support')
],
];
if ($package instanceof PackageDelivery && $package->getLastDateForPickup() !== null) {
$date = $package->getLastDateForPickup();
$eventId[] = [
'id' => PackageState::STATE_ON_DELIVERY_POINT,
'desc' => $translator->trans('Balík lze vyzvednout na výdejně.', [], 'support'),
'info' => $translator->trans('si můžete vyzvednout na výdejně do %lastDate%', ['%lastDate%' =>$date->format("j. n. Y.")], 'support')
];
} else {
$eventId[] = [
'id' => PackageState::STATE_ON_DELIVERY_POINT,
'desc' => $translator->trans('Balík lze vyzvednout na výdejně.', [], 'support'),
'info' => $translator->trans('na vás již čeká na výdejně.', [], 'support')
];
}
$orderId = $package->getOrder()->getId();
$orderEvent = $em->getRepository(EventOrder::class)->findOneBy(['order' => $orderId], ['id' => 'ASC']);
$firstEvent[] = [
"created" => $orderEvent->getCreated(),
"description" => $eventId[0]['desc'],
"info" => $eventId[0]['info']
];
$restEvents = [];
foreach ($filteredEvents as $event) {
foreach ($eventId as $number) {
if ($event instanceof EventPackageStateChange && $event->getNewState() === $number['id']) {
$restEvents[] = [
"created" => $event->getCreated(),
"description" => $number['desc'],
"info" => $number['info']
];
}
}
}
return array_merge($firstEvent, $restEvents);
}
}