<?php
//----------------------------------------------------------------------
// src/Services/Ding/AdvancedNotificationTools.php
//----------------------------------------------------------------------
namespace App\Services\Ding;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Security\Core\Security;
use Doctrine\Persistence\ManagerRegistry;
use App\Entity\SocietyGroup;
use App\Entity\Ding\AdvancedNotification;
use App\Entity\Ding\AdvancedNotificationConfig;
use App\Entity\Planning\Task;
use App\Entity\Planning\TaskStatus;
use App\Entity\Planning\TaskType;
use App\Entity\Webapp\Anomaly;
use App\Entity\Webapp\AnomalyGC;
use App\Entity\Webapp\Document;
use App\Entity\Webapp\Rfi;
use App\Entity\Webapp\RfiGC;
use App\Logging\DeletionContextLogger;
use App\Services\LogTools;
class AdvancedNotificationTools
{
public function __construct(ManagerRegistry $doctrine, Security $security, LogTools $logTools, DeletionContextLogger $contextLogger)
{
$this->em = $doctrine->getManager();
$this->logTools = $logTools;
$this->security = $security;
$this->contextLogger = $contextLogger;
}
public function createAdvancedNotificationForDocument(Document $document)
{
if (!$this->security->isGranted('advanced_notification_is_active'))
{
return null;
}
// Nothing to test about the Document
// Just create the notification
$ding = new AdvancedNotification();
$ding->setSocietyGroup($document->getSocietyGroup());
$ding->setSociety($document->getSociety());
$ding->setDocument($document);
if ($document->getChild() instanceof Anomaly)
$ding->setAnomalyCode();
elseif ($document->getChild() instanceof AnomalyGC)
$ding->setAnomalyGCCode();
elseif ($document->getChild() instanceof Rfi)
$ding->setRfiCode();
elseif ($document->getChild() instanceof RfiGC)
$ding->setRfiGCCode();
else
{
// This should not happen
$this->logTools->errorlog("Wrong kind of Document. Not an Anomaly / AnomalyGC / Rfi / RfiGC ".$document->displayForLog());
return null;
}
$this->em->persist($ding);
return $ding;
}
// TODO : Try to find a better approach
// $skipVoter : Used to skip the voter in command context (No user = return false)
// $skipVoter is true ONLY in InterventionTools :: updateTasksRekto (Context Rekto Command ListingIntervention)
// Task must meet the following criteria at the same time
// - Task::$type should be checked
// - Task::$status should be checked
// - No RFI / RFIGC
public function taskNeedsNotification(Task $task, $skipVoter = false)
{
if ($skipVoter == false)
{
if (!$this->security->isGranted('advanced_notification_is_active'))
{
return null;
}
}
// Exit if the task is in future
if ($task->isFuture())
{
return false;
}
// Get config
$configs = $this->em->getRepository(AdvancedNotificationConfig::class)
->findBySocietyGroup($task->getSocietyGroup());
// Get concerned Task Statuses and concerned Task Types
$taskStatuses = new ArrayCollection();
$taskTypes = new ArrayCollection();
foreach ($configs as $config)
{
if ($config->getTaskStatus() !== null)
{
if (!$taskStatuses->contains($config->getTaskStatus()))
{
if ($config->getIsActive())
{
$taskStatuses[] = $config->getTaskStatus();
}
}
}
if ($config->getTaskType() !== null)
{
if (!$taskTypes->contains($config->getTaskType()))
{
if ($config->getIsActive())
{
$taskTypes[] = $config->getTaskType();
}
}
}
}
// We need at least one status and one type
if (empty($taskStatuses) || empty($taskTypes))
{
return false;
}
// Does the Task fit the status / type criteria ?
if (!$taskStatuses->contains($task->getStatus()))
{
return false;
}
if (!$taskTypes->contains($task->getType()))
{
return false;
}
// Does the Task have an Rfi / RfiGC
// Check also imported Rfi / RfiGC
foreach ($task->getDocuments() as $document)
{
if ($document->isRfi() || $document->isRfiGC() || $document->isArchivedRfi() || $document->isArchivedRfiGC())
{
// At least one found => Nothing to do here
return false;
}
}
return true;
}
// TODO : Try to find a better approach
// $skipVoter : Used to skip the voter in command context (No user = return false)
// $skipVoter is true ONLY in InterventionTools :: updateTasksRekto (Context Rekto Command ListingIntervention)
public function updateAdvancedNotificationForTask(Task $task, $skipVoter = false)
{
if ($skipVoter == false)
{
if (!$this->security->isGranted('advanced_notification_is_active'))
{
return null;
}
}
if ($task->isAbsence())
{
return null;
}
// Get existing Notifications if any
// Actually there should maximum one or none
$dings = $this->em->getRepository(AdvancedNotification::class)
->findByTask($task);
if (count($dings) > 1)
{
// This should not happen
$this->logTools->errorlog("Several AdvancedNotifications were found for Task ".$task->displayForLog());
}
$ding = null;
if (count($dings) >= 1)
{
$ding = $dings[0];
}
// Do we need a Notification ?
if ($this->taskNeedsNotification($task, $skipVoter))
{
// Yes, we need a notification for this task
if ($ding !== null)
{
// But one already exists => All good
return $ding;
}
// If we are here it means that we need a notification
// and none has been found
// So create it
$ding = new AdvancedNotification();
$ding->setSocietyGroup($task->getSocietyGroup());
$ding->setSociety($task->getSociety());
$ding->setTask($task);
$ding->setTaskCode();
$this->em->persist($ding);
return $ding;
}
// If we are here it means the task does not need a notification
if ($ding !== null)
{
// Logging
// Plan.io Task #3922
$ding->setLoggingData([
"info" => "rfi_auto",
]);
$this->contextLogger->storeContext($ding, [
'societyGroup' => $ding->getSocietyGroup(),
'society' => $ding->getSociety(),
'receiver' => $ding->getReceiver(),
]);
// But one exists, so remove it
$this->em->remove($ding);
return null;
}
// If we are here it means the task does not need a notification
// And none has been found
// => All good
return null;
}
// Check that we have one config for each status / type
public function updateConfig(SocietyGroup $societyGroup)
{
$flush = false;
$advancedNotificationConfigRep = $this->em->getRepository(AdvancedNotificationConfig::class);
$taskStatusRepository = $this->em->getRepository(TaskStatus::class);
$taskTypeRepository = $this->em->getRepository(TaskType::class);
$taskStatuses = $taskStatusRepository->getForITaskConfig($societyGroup);
$taskTypes = $taskTypeRepository->getForITaskConfig($societyGroup);
// Check that we have one config for each status / type
$configs = $advancedNotificationConfigRep->findBy(
array('societyGroup' => $societyGroup)
);
// TaskStatus
foreach ($taskStatuses as $taskStatus)
{
// ITaskAuto
$found = false;
foreach ($configs as $config)
{
if ($config->getTaskStatus() === null)
{
continue;
}
if ($config->getTaskStatus()->equals($taskStatus))
{
$found = true;
break;
}
}
if (!$found)
{
$newConfig = new AdvancedNotificationConfig();
$newConfig->setSocietyGroup($societyGroup);
$newConfig->setTaskStatus($taskStatus);
$this->em->persist($newConfig);
$flush = true;
}
}
// TaskType
foreach ($taskTypes as $taskType)
{
// ITaskAuto
$found = false;
foreach ($configs as $config)
{
if ($config->getTaskType() === null)
{
continue;
}
if ($config->getTaskType()->equals($taskType))
{
$found = true;
break;
}
}
if (!$found)
{
$newConfig = new AdvancedNotificationConfig();
$newConfig->setSocietyGroup($societyGroup);
$newConfig->setTaskType($taskType);
$this->em->persist($newConfig);
$flush = true;
}
}
return $flush;
}
}