<?php
namespace App\Controller;
use App\Entity\Action;
use App\Entity\Actioncategory;
use App\Entity\Settings;
use App\Entity\Appointments;
use App\Entity\Appointmentscategory;
use App\Entity\User;
use App\Entity\Actionlog;
use App\Entity\Orderstatus;
use App\Form\ActionType;
use App\Repository\ActionRepository;
use App\Repository\AppointmentsRepository;
use App\Repository\OrderRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\SearchType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Validator\Constraints\File;
use App\Service\FileUploader;
use App\Service\ActionReminder;
use App\Service\ActionService;
use Doctrine\DataTables;
/**
* @Route("/action")
*/
class ActionController extends AbstractController
{
/**
* @Route("/", name="action_index", methods={"GET"})
*/
public function index(): Response
{
return $this->render('action/index.html.twig');
}
/**
* @Route("/ssp", name="action_ssp", methods={"GET"})
*/
public function ssp(): Response
{
$em = $this->getDoctrine()->getManager();
$datatables = (new DataTables\Builder())
->withColumnAliases([
'a_duedate' => 'a.duedate',
'u_username' => 'u.username',
'a_title' => 'a.title',
'o_ordernumber' => 'o.ordernumber',
'c_name' => 'c.name',
'c_city' => 'c.city',
'a_completedate' => 'a.completedate',
])
->withIndexColumn('a.id')
->withQueryBuilder(
$em->createQueryBuilder()
->select('a','o','c','u')
->from(Action::class, 'a')
->leftjoin('a.actionholder','u')
->leftjoin('a.orderid','o')
->leftjoin('o.customer','c')
->where('a.status = 1')
->andWhere('a.isfinished = false')
)
->withRequestParams($_GET);
#echo "<pre>";
#echo json_encode($datatables->getResponse(), JSON_PRETTY_PRINT);
#exit();
return new Response(json_encode($datatables->getResponse()));
}
/**
* @Route("/personalview", name="action_index_personal", methods={"GET"})
*/
public function personalview(): Response
{
return $this->render('action/indexpersonal.html.twig');
}
/**
* @Route("/personalhiddenview", name="action_index_personalhidden", methods={"GET"})
*/
public function personalhiddenview(): Response
{
return $this->render('action/indexpersonalhidden.html.twig');
}
/**
* @Route("/personalssp", name="action_personal_ssp", methods={"GET"})
*/
public function personalssp(): Response
{
$em = $this->getDoctrine()->getManager();
$datatables = (new DataTables\Builder())
->withColumnAliases([
'a_duedate' => 'a.duedate',
'u_username' => 'u.username',
'a_title' => 'a.title',
'o_ordernumber' => 'o.ordernumber',
'c_name' => 'c.name',
'c_city' => 'c.city',
'a_completedate' => 'a.completedate',
])
->withIndexColumn('a.id')
->withQueryBuilder(
$em->createQueryBuilder()
->select('a','o','c','u','k')
->from(Action::class, 'a')
->leftjoin('a.actionholder','u')
->leftjoin('a.orderid','o')
->leftjoin('o.customer','c')
->leftjoin('a.category','k')
->where('a.status = 1')
->andWhere(':userId NOT MEMBER OF k.hiddenbyusers')
->andWhere('a.actionholder = ' . $this->getUser()->getId())
->andWhere('a.isfinished = false')
->setParameter("userId", $this->getUser()->getId())
)
->withRequestParams($_GET);
return new Response(json_encode($datatables->getResponse()));
}
/**
* @Route("/personalhiddenssp", name="action_personalhidden_ssp", methods={"GET"})
*/
public function personalhiddenssp(): Response
{
$em = $this->getDoctrine()->getManager();
$datatables = (new DataTables\Builder())
->withColumnAliases([
'a_duedate' => 'a.duedate',
'u_username' => 'u.username',
'a_title' => 'a.title',
'o_ordernumber' => 'o.ordernumber',
'c_name' => 'c.name',
'c_city' => 'c.city',
'a_completedate' => 'a.completedate',
])
->withIndexColumn('a.id')
->withQueryBuilder(
$em->createQueryBuilder()
->select('a','o','c','u','k')
->from(Action::class, 'a')
->leftjoin('a.actionholder','u')
->leftjoin('a.orderid','o')
->leftjoin('o.customer','c')
->leftjoin('a.category','k')
->where('a.status = 1')
->andWhere(':userId MEMBER OF k.hiddenbyusers')
->andWhere('a.actionholder = ' . $this->getUser()->getId())
->andWhere('a.isfinished = false')
->setParameter("userId", $this->getUser()->getId())
)
->withRequestParams($_GET);
return new Response(json_encode($datatables->getResponse()));
}
/**
* @Route("/filteredview", name="action_index_filtered", methods={"GET","POST"})
*/
public function filteredview(Request $request, ActionRepository $actionRepository): Response
{
$form = $this->createFormBuilder()
->add('category', EntityType::class, [
'label_attr' => array('class' => ''),
'attr' => array('class' => 'form-control selectpicker','data-live-search' => 'true'),
'required' => false,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->where('u.status = 1')
->orderBy('u.priority', 'DESC');
},
'class' => Actioncategory::class,
'choice_label' => 'name',
'placeholder' => 'Alle categoriën',
'label' => 'Filter op actiecategorie(ën)',
'multiple' => true,
])
->add('user', EntityType::class, [
'label_attr' => array('class' => ''),
'attr' => array('class' => 'form-control selectpicker','data-live-search' => 'true'),
'required' => false,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->where('u.status = 1');
},
'class' => User::class,
'choice_label' => 'username',
'placeholder' => 'Alle gebruikers',
'label' => 'Filter op actiehouder',
])
->add('finished', ChoiceType::class, [
'label' => 'Filter op lopend of afgerond',
'attr' => array('class' => 'form-control selectpicker'),
'placeholder' => 'Alles tonen',
'required' => false,
'choices' => [
'Lopend' => 1,
'Lopend (over tijd)' => 2,
'Afgerond' => 3,
]])
->add('showdeleted', ChoiceType::class, [
'label' => 'Verwijderde acties tonen',
'attr' => array('class' => 'form-control selectpicker'),
'placeholder' => 'Alles tonen',
'required' => false,
'data' => 2,
'choices' => [
'Alleen bestaande' => 2,
'Uitsluitend verwijderde' => 1,
]])
->add('startdate', DateType::class, array(
'widget'=> 'single_text',
'label' => 'Streefdatum na',
'attr' => array('class' => 'form-control'),
'required' => false,
))
->add('enddate', DateType::class, array(
'widget'=> 'single_text',
'label' => 'Streefdatum voor',
'attr' => array('class' => 'form-control'),
'required' => false,
))
->add('createstartdate', DateType::class, array(
'widget'=> 'single_text',
'label' => 'Actie aangemaakt na',
'attr' => array('class' => 'form-control'),
'required' => false,
))
->add('createenddate', DateType::class, array(
'widget'=> 'single_text',
'label' => 'Actie aangemaakt voor',
'attr' => array('class' => 'form-control'),
'required' => false,
))
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$category = $form['category']->getData();
$user = $form['user']->getData();
$isfinished = $form['finished']->getData();
$showdeleted = $form['showdeleted']->getData();
$startdate = $form['startdate']->getData();
$enddate = $form['enddate']->getData();
$createstartdate = $form['createstartdate']->getData();
$createenddate = $form['createenddate']->getData();
$query = $actionRepository->createQueryBuilder('a');
if (!$category->isEmpty()) {
$query->andWhere('a.category IN (:category)')
->setParameter('category', $category);
}
if ($user) {
$query->andWhere('a.actionholder = :user')->setParameter('user', $user);
}
if ($startdate) {
$query->andWhere('a.duedate >= :startdate')->setParameter('startdate', $startdate);
}
if ($enddate) {
$query->andWhere('a.duedate <= :enddate')->setParameter('enddate', $enddate);
}
if ($createstartdate) {
$query->andWhere('a.createdate >= :createstartdate')->setParameter('createstartdate', $createstartdate);
}
if ($createenddate) {
$query->andWhere('a.createdate <= :createenddate')->setParameter('createenddate', $createenddate);
}
$today = new \DateTime();
if ($isfinished == 1) {
$query->andWhere('a.isfinished = false');
} elseif ($isfinished == 2) {
$query->andWhere('a.isfinished = false');
$query->andWhere('a.duedate < :today')->setParameter('today', $today);
} elseif ($isfinished == 3) {
$query->andWhere('a.isfinished = true');
}
if ($showdeleted == 2) {
$query->andWhere('a.status = 1');
} elseif ($showdeleted == 1) {
$query->andWhere('a.status = 0');
}
// limit the result to ensure speed
$query->setMaxResults(250);
$result = $query->getQuery()->execute();
return $this->render('action/indexfiltered.html.twig', [
'filteredview' => true,
'actions' => $result,
'form' => $form->createView(),
]);
}
return $this->render('action/indexfiltered.html.twig', [
'filteredview' => false,
'form' => $form->createView(),
]);
}
/**
* @Route("/new", name="action_new", methods={"GET","POST"})
*/
public function new(Request $request, OrderRepository $orderRepository, ActionReminder $actionReminder, ActionService $actionService): Response
{
$action = new Action();
# get max upload size to be indicated to the user
$maxfilesize = ini_get("upload_max_filesize");
$form = $this->createForm(ActionType::class, $action);
$form = $form->add('reminder', EntityType::class, [
'label_attr' => array('class' => ''),
'attr' => array('class' => 'form-control'),
'required' => false,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->where('u.status = 1')
->andWhere('u.microsoft IS NOT NULL');
},
'class' => User::class,
'placeholder' => 'Kies een agenda',
'label' => 'Agenda reminder op streefdatum toevoegen (optioneel)',
'mapped' => false,
]);
$form = $form->add('orderid', SearchType::class, [
'label_attr' => array('class' => ''),
'attr' => array('class' => 'form-control','autocomplete'=>'off'),
'required' => true,
'label' => 'Gerelateerde order *',
'mapped' => false,
]);
$form = $form->add('uploads', FileType::class, [
'attr' => array('class' => 'custom-file'),
'label' => 'Bestanden uploaden (max ' . $maxfilesize . 'B)',
'mapped' => false,
'multiple' => true,
'required' => false,
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$selectedid = $request->request->get('selectedid');
$order = $orderRepository->find($selectedid);
$action = $actionService->saveAction($form,$order);
return $this->redirectToRoute('action_show',array('id'=>$action->getId()));
}
return $this->render('action/new.html.twig', [
'action' => $action,
'form' => $form->createView(),
]);
}
/**
* @Route("/triggered/{id}", name="action_new_triggered", methods={"GET","POST"})
*/
public function newtriggered(Request $request, AppointmentsRepository $appointmentsRepository, ActionRepository $actionRepository, $id=null, ActionService $actionService): Response
{
$previousaction = $actionRepository->findOneBy(['id' => $id ]);
$previousactioncategory = $previousaction->getCategory();
# get the entity manager $em
$em = $this->getDoctrine()->getManager();
# get repository for all actioncategories
$repoActioncategory = $em->getRepository(Actioncategory::class);
$triggercategory = $repoActioncategory->findOneBy([
'id' => $previousactioncategory->getTriggercategory(),
]);
$order = $previousaction->getOrderid();
# get upcoming appointments for this action to show upcoming appointments for the user
$today = new \DateTime("today midnight");
# build query and execute, get list with appointment
$queryAppointments= $appointmentsRepository->createQueryBuilder('a')
->where('a.status = 1')
->andWhere('a.startdate >= :now')
->andWhere('a.orderid = ' . $order->getId())
->setParameter('now',$today->format('Y-m-d'))
->orderBy('a.startdate','ASC');
$appointments = $queryAppointments->getQuery()->execute();
$action = new Action();
if ($triggercategory) {
$action->setActionholder($triggercategory->getDefaultuser());
$action->setCategory($triggercategory);
$action->setTitle($triggercategory->getName());
# get due date and more
$returnarray = $actionService->getDuedate($triggercategory, $order);
$duedate = $returnarray['duedate'];
$determinedby = $returnarray['determinedby'];
$appointmentscategory = $returnarray['appointmentscategory'];
if ($determinedby == 'appointment') {
$appointmentscategorybool = true;
} else {
$appointmentscategorybool = false;
}
# check if it is duplicate action
$duplicate = $actionService->checkDuplicate($triggercategory, $order);
$action->setDuedate(new \DateTime($duedate));
} else {
# set bools to false
$appointmentscategorybool = false;
$duplicate = false;
}
# get max upload size to be indicated to the user
$maxfilesize = ini_get("upload_max_filesize");
$form = $this->createFormBuilder($action)
->add('title', TextType::class, array(
'attr' => array('class' => 'form-control'),
'label' => 'Titel *',
'required' => true,
))
->add('category', EntityType::class, [
'label_attr' => array('class' => ''),
'attr' => array('class' => 'form-control'),
'required' => true,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->where('u.status = 1')
->orderBy('u.priority', 'DESC');
},
'class' => Actioncategory::class,
'choice_label' => 'name',
'placeholder' => 'Kies een actiecategorie',
'label' => 'Actiecategorie *',
])
->add('description', TextareaType::class, array(
'attr' => array('class' => 'form-control'),
'label' => 'Opmerkingen',
'required' => false,
))
->add('duedate', DateType::class, array(
'widget'=> 'single_text',
'attr' => array('class' => 'form-control'),
'input' => 'datetime',
'label' => 'Streefdatum *',
'required' => true,
))
->add('actionholder', EntityType::class, [
'label_attr' => array('class' => ''),
'attr' => array('class' => 'form-control'),
'required' => true,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->where('u.status = 1');
},
'class' => User::class,
'choice_label' => 'username',
'placeholder' => 'Selecteer actiehouder',
'label' => 'Actie bij *',
])
->add('uploads', FileType::class, [
'attr' => array('class' => 'custom-file'),
'label' => 'Bestanden uploaden (max ' . $maxfilesize . 'B)',
'mapped' => false,
'multiple' => true,
'required' => false,
])
->add('reminder', EntityType::class, [
'label_attr' => array('class' => ''),
'attr' => array('class' => 'form-control'),
'required' => false,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->where('u.status = 1')
->andWhere('u.microsoft IS NOT NULL');
},
'class' => User::class,
'placeholder' => 'Kies een agenda',
'label' => 'Agenda reminder op streefdatum toevoegen (optioneel)',
'mapped' => false,
])
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$action = $actionService->saveAction($form,$order);
return $this->redirectToRoute('action_show',array('id'=>$action->getId()));
}
return $this->render('order/subpages/triggered.html.twig', [
'appointmentscategorybool' => $appointmentscategorybool,
'duplicate' => $duplicate,
'order' => $order,
'form' => $form->createView(),
'appointments' => $appointments,
'action' => $previousaction,
]);
}
/**
* @Route("/{id}", name="action_show", methods={"GET","POST"})
*/
public function show(Action $action, Request $request, FileUploader $fileUploader, ActionReminder $actionReminder, AppointmentsRepository $appointmentsRepository): Response
{
$order = $action->getOrderid();
$relatedappointment = $action->getAppointment();
if ($relatedappointment) {
$appointmenthost = $relatedappointment->getHost();
} else {
$appointmenthost = null;
}
# get max upload size to be indicated to the user
$maxfilesize = ini_get("upload_max_filesize");
# get upcoming appointments for this action
$today = new \DateTime("today midnight");
# build query and execute, get list with appointment
$queryAppointments= $appointmentsRepository->createQueryBuilder('a')
->where('a.status = 1')
->andWhere('a.startdate >= :now')
->andWhere('a.orderid = ' . $order->getId())
->setParameter('now',$today->format('Y-m-d'))
->orderBy('a.startdate','ASC');
$appointments = $queryAppointments->getQuery()->execute();
$form = $this->createFormBuilder()
->add('title', TextType::class, array(
'attr' => array('class' => 'form-control'),
'label' => 'Titel *',
'data' => $action->getTitle(),
'required' => true,
))
->add('description', TextareaType::class, array(
'attr' => array('class' => 'form-control'),
'data' => '',
'label' => 'Beschrijving',
'required' => false,
))
->add('duedate', DateType::class, array(
'widget'=> 'single_text',
'label' => 'Streefdatum',
'attr' => array('class' => 'form-control'),
'data' => $action->getDuedate(),
'required' => true,
))
->add('actionholder', EntityType::class, [
'label_attr' => array('class' => ''),
'attr' => array('class' => 'form-control'),
'required' => true,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->where('u.status = 1');
},
'class' => User::class,
'data' => $action->getActionholder(),
'choice_label' => 'username',
'placeholder' => 'Kies een actiehouder',
'label' => 'Actie bij *',
])
->add('orderstatus', EntityType::class, [
'label_attr' => array('class' => ''),
'attr' => array('class' => 'form-control'),
'required' => true,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->where('u.status = 1');
},
'class' => Orderstatus::class,
'choice_label' => 'name',
'placeholder' => 'Kies een orderstatus',
'label' => 'Status van de order aanpassen',
'data' => $order->getOrderstatus(),
])
->add('isfinished', CheckboxType::class, [
'required' => false,
'label_attr' => array('class' => 'mr-3'),
'attr' => array('class' => 'mt-3'),
'data' => $action->getIsfinished(),
'label' => 'Actie afgerond',
])
->add('reminder', EntityType::class, [
'label_attr' => array('class' => ''),
'attr' => array('class' => 'form-control'),
'required' => false,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->where('u.status = 1')
->andWhere('u.microsoft IS NOT NULL');
},
'class' => User::class,
'placeholder' => 'Kies een agenda',
'data' => $appointmenthost,
'label' => 'Agenda reminder op streefdatum toevoegen (optioneel)',
'mapped' => false,
])
->add('uploads', FileType::class, [
'attr' => array('class' => 'custom-file'),
'label' => 'Bestanden uploaden (max ' . $maxfilesize . 'B)',
'mapped' => false,
'multiple' => true,
'required' => false,
])
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$action->setDescription(nl2br($form['description']->getData()));
$action->setDuedate($form['duedate']->getData()->setTime(23, 59));
$action->setActionholder($form['actionholder']->getData());
$action->setTitle($form['title']->getData());
$agenda = $form['reminder']->getData();
if ($agenda) {
$appointment = $actionReminder->add($action, $agenda);
$action->setAppointment($appointment);
} else {
$action->setAppointment(null);
# Eigenlijk moet de afspraak ook weggegooid worden.. To be done one day!
}
$actionlog = new Actionlog();
if ($form['isfinished']->getData()) {
$action->setCompletedate(new \DateTime());
$action->setIsfinished(true);
$actionlog->setCompletedate(new \DateTime());
$actionlog->setIsfinished(true);
}
else {
$action->setCompletedate(null);
$actionlog->setCompletedate(null);
$action->setIsfinished(false);
$actionlog->setIsfinished(false);
}
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($action);
$entityManager->flush();
$uploads = $form['uploads']->getData();
if ($uploads) {
foreach ($uploads as $upload) {
$uploadFileName = $fileUploader->upload($upload);
$uploads_array[]= $uploadFileName;
}
# setUpload is not used anymore since multi upload is required
$actionlog->setUploads($uploads_array);
}
$actionlog->setActionid($action);
$actionlog->setTitle($form['title']->getData());
$actionlog->setDescription(nl2br($form['description']->getData()));
$actionlog->setActionholder($form['actionholder']->getData());
$actionlog->setDuedate($form['duedate']->getData());
$actionlog->setCreatedbyuser($this->getUser());
$actionlog->setCreatedate(new \DateTime());
$actionlog->setStatus(1);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($actionlog);
$entityManager->flush();
$order->setOrderstatus($form['orderstatus']->getData());
$entityManager->persist($order);
$entityManager->flush();
if ($action->getIsfinished()){
return $this->redirectToRoute('action_new_triggered',array('id'=>$action->getId()));
}
else {
return $this->redirectToRoute('action_show',array('id'=>$action->getId()));
}
} else if ($form->isSubmitted()) {
// form submit not valid, most likely to do with upload size!
echo '<script>alert("Kan niet opslaan. Controleer of de bestanden die je upload niet te groot zijn")</script>';
return $this->render('action/showinorder.html.twig', [
'appointments' => $appointments,
'action' => $action,
'order' => $order,
'form' => $form->createView(),
]);
}
return $this->render('action/showinorder.html.twig', [
'appointments' => $appointments,
'action' => $action,
'order' => $order,
'form' => $form->createView(),
]);
}
/**
* @Route("/{id}/edit", name="action_edit", methods={"GET","POST"})
*/
public function edit(Request $request, Action $action): Response
{
$form = $this->createForm(ActionType::class, $action);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('action_show',array('id'=>$action->getId()));
}
return $this->render('action/edit.html.twig', [
'action' => $action,
'form' => $form->createView(),
]);
}
/**
* @Route("/{id}", name="action_delete", methods={"DELETE"})
*/
public function delete(Request $request, Action $action): Response
{
$orderid = $action->getOrderid()->getId();
if ($this->isCsrfTokenValid('delete'.$action->getId(), $request->request->get('_token'))) {
$entityManager = $this->getDoctrine()->getManager();
#$action->setCompletedate(new \DateTime());
#$action->setIsfinished(true);
$action->setStatus(0);
$entityManager->flush();
}
return $this->redirectToRoute('order_show_acties',['id' => $orderid] );
}
}