<?php
/**
* Created by PhpStorm.
* User: SUSAN MEDINA
* Date: 21/03/2019
* Time: 11:53 AM
*/
namespace App\EventSubscriber\Task;
use App\Interfaces\CustomFieldServiceInterface;
use App\Services\CustomField\EntityWithCustomFieldService;
use App\Services\TimeSlot\TimeSlotHistoryService;
use DateTime;
use DateTimeZone;
use App\Entity\App\MediaObject;
use App\Entity\App\Ticket\Ticket;
use App\MessageHandler\LogMessage;
use App\MessageHandler\Message;
use App\Services\ChatService;
use App\Services\VendorService;
use Doctrine\ORM\EntityManager;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ViewEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\KernelEvents;
use Doctrine\ORM\EntityManagerInterface;
use ApiPlatform\Core\EventListener\EventPriorities;
use App\Repository\App\MaintenanceElementRepository;
use App\Repository\App\Task\WorkerBudgetRepository;
use App\Repository\App\Task\TaskConceptRepository;
use App\Repository\App\Task\TaskResourceRepository;
use App\Repository\App\VendorStaffRepository;
use App\Repository\App\MediaObjectRepository;
use App\Repository\App\ScheduleRepository;
use App\Repository\App\UserRepository;
use App\Repository\App\RoleRepository;
use App\Repository\App\ResourceRepository;
use App\Entity\App\Task\TaskResource;
use App\Entity\App\Task\Task;
use App\Entity\App\Task\TaskStatusLog;
use App\Entity\App\Task\WorkerBudget;
use App\Entity\App\Role;
use App\Entity\Chat\Chat;
use App\Entity\App\User;
use App\Entity\Chat\ChatMessage;
use App\Exception\NotFoundException;
use App\Services\LogService;
use App\Services\UtilsService;
class TaskPostWriteSubscriber implements EventSubscriberInterface
{
protected $serviceContainer;
private $tokenStorage;
private $entityManager;
private $userRepository;
private $vendorStaffRepository;
private $roleRepository;
private $workerBudgetRepository;
private $mediaObjectRepository;
private $scheduleRepository;
private $conceptRepository;
private $taskResourceRepository;
private $resourceRepository;
private $maintenanceRepository;
private $chatService;
private $utilsService;
private $logService;
private $vendorService;
private $messageBus;
private $translator;
private $timeSlotHistoryService;
private $customFieldService;
public function __construct(
ContainerInterface $serviceContainer,
TokenStorageInterface $tokenStorage,
UserRepository $userRepository,
VendorStaffRepository $vendorStaffRepository,
RoleRepository $roleRepository,
WorkerBudgetRepository $workerBudgetRepository,
MediaObjectRepository $mediaObjectRepository,
ScheduleRepository $scheduleRepository,
TaskConceptRepository $conceptRepository,
TaskResourceRepository $taskResourceRepository,
ResourceRepository $resourceRepository,
MaintenanceElementRepository $maintenanceRepository,
ChatService $chatService,
EntityManagerInterface $entityManager,
UtilsService $utilsService,
LogService $logService,
VendorService $vendorService,
MessageBusInterface $messageBus,
TranslatorInterface $translator,
TimeSlotHistoryService $timeSlotHistoryService,
CustomFieldServiceInterface $customFieldService
) {
$this->serviceContainer = $serviceContainer;
$this->tokenStorage = $tokenStorage;
$this->userRepository = $userRepository;
$this->vendorStaffRepository = $vendorStaffRepository;
$this->roleRepository = $roleRepository;
$this->workerBudgetRepository = $workerBudgetRepository;
$this->entityManager = $entityManager;
$this->mediaObjectRepository = $mediaObjectRepository;
$this->scheduleRepository = $scheduleRepository;
$this->conceptRepository = $conceptRepository;
$this->taskResourceRepository = $taskResourceRepository;
$this->resourceRepository = $resourceRepository;
$this->maintenanceRepository = $maintenanceRepository;
$this->chatService = $chatService;
$this->utilsService = $utilsService;
$this->logService = $logService;
$this->vendorService = $vendorService;
$this->messageBus = $messageBus;
$this->translator = $translator;
$this->timeSlotHistoryService = $timeSlotHistoryService;
$this->customFieldService = $customFieldService;
}
/**
* @param ViewEvent $event
* @throws NotFoundException
* @throws \Doctrine\Common\Persistence\Mapping\MappingException
* @throws \Doctrine\ORM\NonUniqueResultException
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
*/
public function onKernelView(ViewEvent $event)
{
if ($this->utilsService->isAPublicRequest($event)) {
return;
}
$task = $event->getControllerResult();
if(!($task instanceof Task)) return;
$request = $event->getRequest();
$method = $request->getMethod();
$entityWithCustomFieldService = new EntityWithCustomFieldService($task, $this->customFieldService);
if($entityWithCustomFieldService->areCustomFieldsRequiredOnResponse($request)){
$entityWithCustomFieldService->loadAndSetCustomFields();
}
if (Request::METHOD_POST !== $method && Request::METHOD_PUT !== $method)
return;
$userCurrent = $this->tokenStorage->getToken()->getUser();
if(!$userCurrent instanceof User)
throw new NotFoundException($this->translator->trans('User current not found'));
if (Request::METHOD_POST == $method) {
$state = TaskStatusLog::STATUS_TASK_IN_PROCESS;
$task->setState($state);
$identify = $this->utilsService->generateIdentify($task);
$task->setIdentify($identify);
$this->entityManager->persist($task);
}
$content = $request->getContent();
$params = json_decode($content, true);
$authorizationManager = false;
$authorizationOperator = false;
$vendor = $task->getTicket()->getVendor();
if ($this->vendorService->isUserRoleInToVendor($vendor, $userCurrent, [Role::ROLE_ADMIN, Role::ROLE_TASKMASTER])) {
$authorizationManager = true;
$authorizationOperator = true;
}
if (Request::METHOD_PUT === $method && !$authorizationManager) {
$role[] = $this->roleRepository->findOneBy(['name' => Role::ROLE_OPERATOR]);
//operator authorization to edit the task if it belongs to this
if ($this->workerBudgetRepository->findGroupByRoles($role, $task, $userCurrent->getId())) {
$authorizationOperator = true;
}
}
if ($authorizationManager) {
//WORKERBUDGET
if (isset($params['workerBudgets']) && is_array($params['workerBudgets'])) {
$getWorkerBudgets = $this->workerBudgetRepository->findBy(['task' => $task->getId(), "deletedAt" => null]);
$workerBudgetArray = [];
foreach ($params['workerBudgets'] as &$wb) {
if (isset($wb['role']) && isset($wb['vendorStaff'])) {
$workerBudgetArray[] = [
'role' => $wb['role'],
'vendorStaff' => $wb['vendorStaff']
];
if (isset($wb['user'])) {
unset($wb['user']);
}
}
}
foreach ($getWorkerBudgets as $workerBudget) {
$workerBudgetFormat = [
'role' => $workerBudget->getRole()->getId(),
'vendorStaff' => $workerBudget->getVendorStaff()->getId()
];
if (!in_array($workerBudgetFormat, $workerBudgetArray)) {
$userName = '-';
$userWorkerBudget = $workerBudget->getVendorStaff()->getUser() ?? null;
if ($userWorkerBudget instanceof User) {
$userName = $userWorkerBudget->getFullName();
}
//ToDo Refactizar para quitar el identifier de cementerios
$ticketIdentify = $task->getTicket()->getType()->getStage() !== 'cemetery' ? $task->getTicket()->getIdentify() : $task->getTicket()->getTitle();
$body = array(
'message' => 'task.messages.delete_worker_budget',
'parameters' => array(
'%userName%' => $userName,
'%taskIdentify%' => $ticketIdentify.'-'.$task->getIdentify(),
'%title%' => ''
),
'parametersTrans' => array(
'%roleTitle%' => 'role.list.title.'.$workerBudget->getRole()->getName()
)
);
$this->sendNewMessage($task->getChat(), $body);
if ($task->getTicket() instanceof Ticket &&
$task->getTicket()->getChat() instanceof Chat
) {
$this->sendNewMessage($task->getTicket()->getChat(), $body);
}
$this->entityManager->remove($workerBudget);
$dataWorkerBudget = [];
if ($userWorkerBudget && in_array($userWorkerBudget->getNotificationWorkerAssignedTask(), [1,2,3])) {
$dataWorkerBudget['user_id'] = $userWorkerBudget->getId();
$dataWorkerBudget['task_id'] = $task->getId();
$message_body = $body;
$message_body['parameters']['%title%'] = $task->getTitle();
$message_body['author'] = $userCurrent->getFullName();
$dataWorkerBudget['message_body'] = json_encode($message_body);
if ($userCurrent !== $userWorkerBudget) {
$this->messageBus->dispatch(
new Message(Message::WORKER_REMOVED_TASK, $dataWorkerBudget)
);
}
}
}
}
foreach ($params['workerBudgets'] as $workerBudgetRequest) {
if (isset($workerBudgetRequest['role']) && isset($workerBudgetRequest['vendorStaff'])) {
$role = $this->roleRepository->find($workerBudgetRequest['role']);
$vendorStaff = $this->vendorStaffRepository->find($workerBudgetRequest['vendorStaff']);
$workerBudget = $this->workerBudgetRepository->findOneBy(
[
'vendorStaff' => $vendorStaff,
'role' => $role,
'task' => $task
]
);
if ($workerBudget && !$workerBudget->isDeleted()) {
$workerBudget->setEstimatedHours($workerBudgetRequest['estimatedHours']);
if (isset($workerBudgetRequest['estimatedHours']) &&
is_numeric($workerBudgetRequest['estimatedHours'])
) {
$workerBudget->setEstimatedHours($workerBudgetRequest['estimatedHours']);
}
if (isset($workerBudgetRequest['realHours']) && $role->getName() === Role::ROLE_TASKMASTER) {
$workerBudget->setRealHours($workerBudgetRequest['realHours']);
}
if(!is_null($workerBudget->getDeletedAt())){
$workerBudget->setDeletedAt(null);
}
} else {
//Creamos un workerBudget
if(!is_null($workerBudget) && $workerBudget->isDeleted()){
$workerBudget->setDeletedAt(null);
}else{
$workerBudget = new WorkerBudget();
$workerBudget->setTask($task);
$workerBudget->setRole($role);
$workerBudget->setVendorStaff($vendorStaff);
$workerBudget->setCostHour($vendorStaff->getCostPerHour());
}
if (isset($workerBudgetRequest['estimatedHours']) &&
is_numeric($workerBudgetRequest['estimatedHours'])
) {
$workerBudget->setEstimatedHours($workerBudgetRequest['estimatedHours']);
} else {
$workerBudget->setEstimatedHours(0);
}
if (isset($workerBudgetRequest['realHours']) && $role->getName(
) === Role::ROLE_TASKMASTER) {
$workerBudget->setRealHours($workerBudgetRequest['realHours']);
}
//state init of task by operator
$this->entityManager->persist($workerBudget);
//Creamos el estado inicial de la tarea esperando por ti
$status = new TaskStatusLog();
$status->setState(TaskStatusLog::STATUS_TASK_IN_PROCESS);
$status->setWorkerBudget($workerBudget);
$status->setDate(new DateTime('now'));
$this->entityManager->persist($status);
//Creamos la franja horaria para este workerBudget
//Obtenemos la franja horaria del user
$timeSlotUser = $vendorStaff->getUser()->getTimeSlot();
//Creamos el histórico de la franja horaria
if (!is_null($timeSlotUser)) {
$defaultCost = $timeSlotUser->getDefaultCost();
$extraHourPrice = $timeSlotUser->getExtraHourlyPrice();
if (count($timeSlotUser->getTimeSlotItems()) > 0) {
foreach ($timeSlotUser->getTimeSlotItems() as $timeSlot) {
$timeSlotHistory = $this->timeSlotHistoryService->createTimeSlotHistory($workerBudget,$timeSlot,$defaultCost,$extraHourPrice);
$this->entityManager->persist($timeSlotHistory);
}
} else {
$timeSlotHistory = $this->timeSlotHistoryService->createTimeSlotHistory($workerBudget,null,$defaultCost,$extraHourPrice);
$this->entityManager->persist($timeSlotHistory);
}
}
}
}
}
}
$mediaContent = [];
if (isset($params['mediaContent']) && is_array($params['mediaContent'])) {
foreach ($params['mediaContent'] as $mediaId) {
$mediaObject = $this->mediaObjectRepository->find($mediaId);
if ($mediaObject instanceof MediaObject && $mediaObject->getType() === MediaObject::TYPE_TASK) {
$mediaContent[] = $mediaId;
}
}
}
if (isset($params['mediaContent']) && is_array($mediaContent)) {
$getMediaObjects = $this->mediaObjectRepository->findBy(['task' => $task->getId()]);
foreach ($getMediaObjects as $media) {
if (!in_array($media->getId(), $mediaContent)) {
$this->entityManager->remove($media);
}
}
foreach ($mediaContent as $mediaId) {
$mediaObject = $this->mediaObjectRepository->find($mediaId);
if ($mediaObject instanceof MediaObject && $mediaObject->getType() === MediaObject::TYPE_TASK) {
$mediaObject->setTask($task);
$this->entityManager->persist($mediaObject);
}
}
}
}
if ($authorizationOperator && isset($params['resources']) && is_array($params['resources'])) {
if (Request::METHOD_PUT === $method) {
$getTaskResources = $this->taskResourceRepository->findByTask($task);
} else {
$getTaskResources = [];
}
// Se comprueba si está eliminado estoy añadiendo 1 recurso
foreach ($getTaskResources as $taskResource) {
if (!$taskResource->isDeleted()) {
$search = array_search(
$taskResource->getResource()->getId(),
array_column($params['resources'], 'id')
);
if (!is_integer($search) && !$search) {
//ToDo Refactizar para quitar el identifier de cementerios
$ticketIdentify = $task->getTicket()->getType()->getStage() !== 'cemetery' ? $task->getTicket()->getIdentify() : $task->getTicket()->getTitle();
$body = array(
'message' => 'task.messages.delete_resource',
'parameters' => array(
'%resourceName%' => $taskResource->getResource()->getName(),
'%taskIdentify%' => $ticketIdentify.'-'.$task->getIdentify()
),
'parametersTrans' => array()
);
$this->sendNewMessage($task->getChat(), $body);
if ($task->getTicket() instanceof Ticket &&
$task->getTicket()->getChat() instanceof Chat
) {
$this->sendNewMessage($task->getTicket()->getChat(), $body);
}
$taskResource->setTask(null);
$this->entityManager->remove($taskResource);
}
}
}
// Recorremos todos los recursos y los coincidentes los sobrescribimos y los nuevos se añaden
// esto actualiza el array cuando se modifican varios y se actualizan todos a la vez
foreach ($params['resources'] as $resource) {
if (isset($resource['id']) && is_integer($resource['id'])) {
$getResource = $this->resourceRepository->find($resource['id']);
if (!$getResource->isDeleted()) {
$newTaskResource = $this->taskResourceRepository->findOneByTaskAndResource($task, $getResource);
if (!$newTaskResource) {
$newTaskResource = new TaskResource();
$newTaskResource->setTask($task);
$newTaskResource->setResource($getResource);
$newTaskResource->setUseValue((float)$getResource->getUseValue());
}
$newTaskResource->setQuantity($resource['quantity']);
$this->entityManager->persist($newTaskResource);
}
}
}
}
if (!$task->getChat()) {
$chat = new Chat();
$chat->setType(Chat::TYPE_TASK);
$this->entityManager->persist($chat);
$task->setChat($chat);
$this->entityManager->persist($task);
}
$this->entityManager->flush();
if (isset($task->oldMaintenanceElements)) {
foreach ($task->oldMaintenanceElements as $maintenanceElement) {
if (isset($maintenanceElement['id'])) {
$maintenanceElement = $this->maintenanceRepository->find($maintenanceElement['id']);
$search = array_search($maintenanceElement, $task->getMaintenanceElements()->toArray());
if (!is_integer($search) && !$search) {
$this->registerLog('remove', $maintenanceElement, ['task.maintenanceElement.delete' => $task->getId()]);
//ToDo Refactizar para quitar el identifier de cementerios
$ticketIdentify = $task->getTicket()->getType()->getStage() !== 'cemetery' ? $task->getTicket()->getIdentify() : $task->getTicket()->getTitle();
$body = array(
'message' => 'task.messages.delete_maintenance_element',
'parameters' => array(
'%maintenanceElement%' => $maintenanceElement->getName(),
'%taskIdentify%' => $ticketIdentify.'-'.$task->getIdentify()
),
'parametersTrans' => array()
);
$this->sendNewMessage($task->getChat(), $body);
if ($task->getTicket() instanceof Ticket &&
$task->getTicket()->getChat() instanceof Chat
) {
$this->sendNewMessage($task->getTicket()->getChat(), $body);
}
}
}
}
}
foreach ($task->getMaintenanceElements() as $maintenanceElement) {
$search = array_search(['id' => $maintenanceElement->getId()], $task->oldMaintenanceElements);
if (!is_integer($search) && !$search) {
$this->registerLog('create', $maintenanceElement, ['task.maintenanceElement.create' => $task->getId()]);
//ToDo Refactizar para quitar el identifier de cementerios
$ticketIdentify = $task->getTicket()->getType()->getStage() !== 'cemetery' ? $task->getTicket()->getIdentify() : $task->getTicket()->getTitle();
$body = array(
'message' => 'task.messages.new_maintenance_element',
'parameters' => array(
'%maintenanceElement%' => $maintenanceElement->getName(),
'%taskIdentify%' => $ticketIdentify.'-'.$task->getIdentify()
),
'parametersTrans' => array()
);
$this->sendNewMessage($task->getChat(), $body);
if ($task->getTicket() instanceof Ticket &&
$task->getTicket()->getChat() instanceof Chat
) {
$this->sendNewMessage($task->getTicket()->getChat(), $body);
}
}
}
if (isset($task->oldConcepts)) {
foreach ($task->oldConcepts as $concept) {
if (isset($concept['id'])) {
$conceptCost = $this->conceptRepository->find($concept['id']);
$search = array_search($conceptCost, $task->getConcepts()->toArray());
if ($search === false) {
//ToDo Refactizar para quitar el identifier de cementerios
$ticketIdentify = $task->getTicket()->getType()->getStage() !== 'cemetery' ? $task->getTicket()->getIdentify() : $task->getTicket()->getTitle();
$body = array(
'message' => 'task.messages.delete_concept',
'parameters' => array(
'%conceptName%' => $conceptCost->getName(),
'%taskIdentify%' => $ticketIdentify.'-'.$task->getIdentify()
),
'parametersTrans' => array()
);
$this->sendNewMessage($task->getChat(), $body);
if ($task->getTicket() instanceof Ticket &&
$task->getTicket()->getChat() instanceof Chat
) {
$this->sendNewMessage($task->getTicket()->getChat(), $body);
}
//$this->entityManager->remove($concept);
}
}
}
}
if ($task->changeDateStart || $task->changeDateEnd) {
$data = ['dateStart' => $task->getDateStart(), 'dateEnd' => $task->getDateEnd()];
$this->registerLog('update', $task, $data);
$vendorTimezone = $task->getTicket()->getVendor()->getTimezone();
if (empty($vendorTimezone)) {$vendorTimezone = 'UTC';}
$dateStart = '-';
$dateEnd = '-';
if (!is_null($task->getDateStart())) {
$dateStart = $task->getDateStart()
->setTimezone(new DateTimeZone($vendorTimezone))->format('d-m-Y');
}
if (!is_null($task->getDateEnd())) {
$dateEnd = $task->getDateEnd()
->setTimezone(new DateTimeZone($vendorTimezone))->format('d-m-Y');
}
//ToDo Refactizar para quitar el identifier de cementerios
$ticketIdentify = $task->getTicket()->getType()->getStage() !== 'cemetery' ? $task->getTicket()->getIdentify() : $task->getTicket()->getTitle();
$body = array(
'message' => 'task.messages.change_range_date',
'parameters' => array(
'%dateStart%' => $dateStart,
'%dateEnd%' => $dateEnd,
'%taskIdentify%' => $ticketIdentify.'-'.$task->getIdentify()
),
'parametersTrans' => array()
);
$this->sendNewMessage($task->getChat(), $body);
if ($task->getTicket() instanceof Ticket &&
$task->getTicket()->getChat() instanceof Chat
) {
$this->sendNewMessage($task->getTicket()->getChat(), $body);
}
}
if ($task->getTicket() instanceof Ticket) {
$ticket = $task->getTicket();
$allTasks = $ticket->getTasks();
$countWorkerBudgets = 0;
$indicatorData = $ticket->getIndicatorData();
if (!isset($indicatorData['performance.time']['dateOfAssignment'])) {
$indicatorData['performance.time']['dateOfAssignment'] = null;
}
foreach ($allTasks as $task) {
$countWorkerBudgets += $task->getWorkerBudgets()->count();
}
if ($countWorkerBudgets > 0) {
$indicatorData['performance.time']['dateOfAssignment'] = new DateTime('now');
} else {
$indicatorData['performance.time']['dateOfAssignment'] = null;
}
$ticket->setIndicatorData($indicatorData);
$this->entityManager->persist($ticket);
$this->entityManager->flush();
}
//$this->entityManager->clear();
}
/**
* @param $chat
* @param $body
* @throws NotFoundException
*/
protected function sendNewMessage($chat, $body)
{
$newMessage = new ChatMessage();
$newMessage->setChat($chat);
$newMessage->setType('log');
$newMessage->setBody(json_encode($body));
$this->entityManager->persist($newMessage);
$this->entityManager->flush();
$userCurrent = $this->tokenStorage->getToken()->getUser();
if(!$userCurrent instanceof User)
throw new NotFoundException($this->translator->trans('User current not found'));
$this->chatService->markMessagesAsReadByChatAndUser($chat, $userCurrent);
$data['chatMessage_id'] = $newMessage->getId();
$this->messageBus->dispatch(new LogMessage(LogMessage::NEW_LOG_MESSAGE_IN_CHAT, $data));
}
/**
* @param $action
* @param $entity
* @param array $data
* @throws \Doctrine\ORM\NonUniqueResultException
*/
protected function registerLog($action, $entity, $data = [])
{
$this->logService->registerLog(
$action,
$entity,
$data
);
}
public static function getSubscribedEvents()
{
return [
KernelEvents::VIEW => ['onKernelView', EventPriorities::POST_WRITE]
];
}
/*protected function loadScheduleMatrix(WorkerBudget $workerBudget)
{
$schedule = $workerBudget->getSchedule();
$standardPrice = $workerBudget->getCostHour();
$hours = array_fill(0,24, $standardPrice);
$scheduleMatrix = array_fill(0, 7, $hours);
$additionalSchedules = $workerBudget->getVendorStaff()->getSchedules();
foreach ($additionalSchedules as $additionalSchedule) {
$costHourDecision = $workerBudget->getCostHour() != $additionalSchedule->getHourCost() ;
$ifDecision = !is_null($schedule) ? $additionalSchedule !== $schedule : $costHourDecision;
if (($ifDecision) && ($additionalSchedule->getType() == Schedule::TYPE_EXTRAORDINARY)) {
$startDayOfWeek = date('N', strtotime($additionalSchedule->getStartDayWeek())) - 1;
$endDayOfWeek = date('N', strtotime($additionalSchedule->getEndDayWeek())) -1;
$hourTest= $additionalSchedule->getStartHourDay();
$startHour = date('G', strtotime($additionalSchedule->getStartHourDay()));
$endHour = date('G', strtotime($additionalSchedule->getEndHourDay()));
$price = $additionalSchedule->getHourCost();
for ($day = $startDayOfWeek; $day <= $endDayOfWeek; $day++) {
for ($hour = $startHour; $hour <= $endHour; $hour++) {
$scheduleMatrix[$day][$hour] = $price;
}
}
}
}
return $scheduleMatrix;
}*/
}