<?php
namespace App\Controller;
use App\Document\Appeal;
use App\Document\AppealExecution;
use App\Document\Location;
use App\Finder\Appeals\AppealsFinder;
use App\Form\Type\AppealsExecutionType;
use App\Form\Type\AppealsType;
use App\Service\AttributeResolver;
use App\Service\AttributesUpdater;
use App\Service\RatingUpdater;
use App\Service\ResourceFinders\CarriageResourcesFinders\PartiallyBedPlacesResourcesFinder;
use App\Service\ResourceFinders\ResourceFinderFactory\ResourceFinderFactory;
use App\Service\Statuses;
use App\Service\ResourceFinders\CarriageResourcesFinders\StrictlyCarriageHouseResourcesFinder;
use App\Service\Workflow;
use Doctrine\ODM\MongoDB\DocumentManager;
use Exception;
use Knp\Component\Pager\PaginatorInterface;
use Psr\Log\LoggerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
class AppealController extends AbstractController
{
public function __construct(
private DocumentManager $dm,
private LoggerInterface $logger,
private AttributeResolver $resolver,
private Workflow $workflow,
private AppealsFinder $finder,
private Statuses $statuses,
private RatingUpdater $rating,
private AttributesUpdater $updater,
private PaginatorInterface $paginator,
private ResourceFinderFactory $finderFactory
) {
}
#[Route('/appeals', name: 'appeals', methods: ['GET',])]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
public function index(Request $request): Response
{
$appealsExecute = $this->finder->doFind(
$this->dm->createQueryBuilder(Appeal::class),
$request->query->all()
);
$appealsCount = count($appealsExecute->getQuery()->execute()->toArray());
$appealsPaginator = $this->paginator->paginate(
$appealsExecute->getQuery()->toArray(),
$request->query->getInt('page', 1),
$request->query->get('pageSize',Appeal::NUMBERS_ON_PAGE),
);
return $this->render('appeals/index.html.twig', [
'appeals' => $appealsPaginator,
'appealsCount' => $appealsCount,
'types' => $this->resolver->getTypes(),
'locations' => $this->dm->getRepository(Location::class)->findAll(),
'statuses' => $this->statuses->get(new Appeal()),
'title' => 'Заявки',
'pageSize' => Appeal::pageSize(),
]);
}
#[Route('/my-appeals', name: 'my-appeals', methods: ['GET',])]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
public function myAppeals(Request $request): Response
{
$appealsExecute = $this->finder->doFind(
$this->dm->createQueryBuilder(Appeal::class)
->field('author.id')->equals($this->getUser()->getId()),
$request->query->all()
);
$appealsCount = count($appealsExecute->getQuery()->execute()->toArray());
$appealsPaginator = $this->paginator->paginate(
$appealsExecute->getQuery()->toArray(),
$request->query->getInt('page', 1),
$request->query->get('pageSize',Appeal::NUMBERS_ON_PAGE),
);
return $this->render('appeals/index.html.twig', [
'appeals' => $appealsPaginator,
'appealsCount' => $appealsCount,
'types' => $this->resolver->getTypes(),
'locations' => $this->dm->getRepository(Location::class)->findAll(),
'statuses' => $this->statuses->get(new Appeal()),
'title' => 'Мои заявки',
'pageSize' => Appeal::pageSize(),
]);
}
#[Route('/appeals/new', name: 'new_appeal', methods: ['POST', 'GET'])]
#[Security("is_granted('ROLE_ADMIN') or is_granted('ROLE_APPLICANT')")]
public function create(Request $request): Response
{
$appeal = new Appeal();
$appeal->setAuthor($this->getUser());
$appeal->setType($request->query->get('type'));
$form = $this->createForm(AppealsType::class, $appeal);
$form->add('attributes', $this->resolver->resolve($request->query->get('type')));
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if($request->query->get('type') == 'special-equipment'){
if(empty($form->get('attributes')->get('auctionType')->getData())) {
$this->addFlash('warning', 'Выберите тип аукциона');
return $this->redirect($request->headers->get('referer'));
}
if($size = $form->get('attributes')->get('additionalFeature')->get('dimension')->getData()) {
foreach ($size as $value) {
if (empty($value)){
$attr = $appeal->getAttributes()->getAdditionalFeature();
$attr->setDimension([]);
break;
}
}
}
}
$appeal->setStatus(Appeal::STATUS_SEARCH);
$this->dm->persist($appeal);
$this->dm->flush();
return $this->redirectToRoute('show_appeal', ['id' => $appeal->getId()]);
}
return $this->render('appeals/create.html.twig', [
'form' => $form->createView(),
'type' => $request->query->get('type'),
]);
}
#[Route('/appeals/{id}', name: 'show_appeal', methods: ['GET',])]
#[ParamConverter('appeal', class: Appeal::class)]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
public function show(Appeal $appeal, Request $request): Response
{
$this->finderFactory->setAppealType($appeal->getType());
$strictlyFinder = $this->finderFactory->createStrictlyFinder();
$partiallyFinder = $this->finderFactory->createPartiallyResourceFinder();
return $this->render('appeals/show.html.twig', [
'appeal' => $appeal,
'strictlyResources' => $strictlyFinder->find($appeal),
'partiallyResourcesWithComments' => $partiallyFinder->find($appeal),
'bookedToResource' => $this->dm->getRepository(AppealExecution::class)
->getBookedToResource($appeal),
'bookingCancelled' => $this->dm->getRepository(AppealExecution::class)
->getBookingCancelled($appeal),
]);
}
#[Route('/appeals/{id}/edit', name: 'edit_appeal', methods: ['GET', 'POST'])]
#[ParamConverter('appeal', class: Appeal::class)]
#[Security("is_granted('ROLE_ADMIN') or appeal.isAuthor(user)")]
public function edit(Appeal $appeal, Request $request): Response
{
$form = $this->createForm(AppealsType::class, $appeal);
$form->add('attributes', $this->resolver->resolve($appeal->getType()));
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$appeal->setStatus(Appeal::STATUS_NEW);
$this->updater->update($appeal, $form->get('attributes')->getData());
$this->dm->persist($appeal);
$this->dm->flush();
return $this->redirectToRoute('show_appeal', ['id' => $appeal->getId()]);
}
return $this->render('appeals/edit.html.twig', [
'form' => $form->createView()
]);
}
#[Route('appeals/{id}/remove', name: 'remove_appeal', methods: ['GET', 'POST'])]
#[ParamConverter('appeal', class: Appeal::class)]
#[Security("is_granted('ROLE_ADMIN') or appeal.isAuthor(user)")]
public function remove(Appeal $appeal, Request $request): RedirectResponse|Response
{
try {
$executionsForAppeal = $this->dm->createQueryBuilder(AppealExecution::class)
->field('appeal.id')->equals($appeal->getId())
->field('status')->in(['booked', 'in_work', 'in_confirmation'])
->getQuery()->execute();
if (count($executionsForAppeal->toArray()) > 0) {
$this->addFlash('warning', 'Не получилось удалить заявку: '
. 'она забронирована или на согласовании');
} else {
$this->dm->remove($appeal);
$this->dm->flush();
}
} catch (Exception $e) {
$this->logger->error('Appeal remove error', [$e->getCode(), $e->getMessage(),]);
}
return $this->redirect($request->headers->get('referer'));
}
#[Route('appeals/{id}/done', name: 'rating_appeal', methods: ['GET', 'POST',])]
#[ParamConverter('execution', class: AppealExecution::class)]
#[Security("is_granted('ROLE_ADMIN')")]
public function done(AppealExecution $execution, Request $request): Response
{
$form = $this->createForm(AppealsExecutionType::class, $execution);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
try {
$this->workflow->doneByApplicant($execution);
$this->dm->flush();
$this->rating->updateResourceRating($execution);
$this->rating->updateAuthorRating($execution);
} catch (Exception $e) {
$this->logger->error('Can not done appeal by applicant', [$e->getMessage(), $e->getCode()]);
}
return $this->redirectToRoute('desktop');
}
return $this->render('appeals/rating.html.twig', [
'execution' => $execution,
'form' => $form->createView(),
]);
}
}