<?php
namespace App\Service;
use App\Entity\Checklist;
use App\Entity\ChecklistActivity;
use App\Entity\ChecklistHowTo;
use App\Entity\ChecklistTask;
use App\Entity\ChecklistTaskDependency;
use App\Repository\ChecklistRepository;
use App\Repository\ChecklistTaskRepository;
use App\Repository\CourseAutoEnrollmentRepository;
use App\Repository\CourseRepository;
use App\Repository\CourseUserEnrollmentRepository;
use App\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Security;
use App\Service\MailgunService;
use Doctrine\Common\Collections\ArrayCollection;
use Firebase\JWT\JWT;
class ChecklistService
{
private $em;
private $params;
private $mailgunService;
private $translator;
private $checklistRepository;
private $authChecker;
private $userRepository;
private $checklistTaskRepository;
private $httpClient;
private $courseService;
private $security;
private $userService;
public function __construct(EntityManagerInterface $em, ParameterBagInterface $params, MailgunService $mailgunService, TranslatorInterface $translator, ChecklistRepository $checklistRepository, AuthorizationCheckerInterface $authChecker, UserRepository $userRepository, ChecklistTaskRepository $checklistTaskRepository, HttpClientInterface $httpClientInterface, CourseService $courseService, Security $security, UserService $userService)
{
$this->em = $em;
$this->params = $params;
$this->mailgunService = $mailgunService;
$this->translator = $translator;
$this->checklistRepository = $checklistRepository;
$this->authChecker = $authChecker;
$this->userRepository = $userRepository;
$this->checklistTaskRepository = $checklistTaskRepository;
$this->httpClient = $httpClientInterface;
$this->courseService = $courseService;
$this->security = $security;
$this->userService = $userService;
}
/*
public function createChecklistFromTemplate($user = null, $project = null, $checklist)
{
// try {
$checklistTemplate = $this->checklistRepository->find($checklist->getId());
$newChecklist = new Checklist();
$newChecklist->setName($checklist->getName());
$newChecklist->setDescription($checklist->getDescription());
$newChecklist->setDueDate($checklist->getDueDate());
$newChecklist->setType($checklist->getType());
$newChecklist->setDepartment($checklist->getDepartment());
$newChecklist->setTemplate($checklist);
$newChecklist->setStatus($checklist->getStatus());
$newChecklist->setPosition($checklist->getPosition());
$project ? $newChecklist->setProject($project) : $newChecklist->setProject($checklist->getProject());
$newChecklist->setDefaultAssignee($checklist->getDefaultAssignee());
$newChecklist->setOwner($checklist->getOwner());
$newChecklist->setMattermostUrl($checklist->getMattermostUrl());
$newChecklist->setIsPrivate($checklist->isIsPrivate());
$newChecklist->setOnboardUser($user);
$newChecklist->setIsTemplate(false);
$this->em->persist($newChecklist);
foreach ($checklist->getTasks() as $task) {
$newTask = new ChecklistTask();
$newTask->setChecklist($newChecklist);
$newTask->setName($task->getName());
$newTask->setDescription($task->getDescription());
$newTask->setPriority($task->getPriority());
$newTask->setDueDate($task->getDueDate());
$newTask->setStatus($task->getStatus());
$newTask->setVisibility($task->getVisibility());
$newTask->setRequireDocument($task->isRequireDocument());
$newTask->setDocument($task->getDocument());
$newTask->setPosition($task->getPosition());
$newTask->setDefaultAssignee($task->getDefaultAssignee());
$newTask->setVerifier($task->getVerifier());
$this->em->persist($newTask);
$newChecklist->getTasks()->add($newTask);
foreach ($task->getChecklistHowTos() as $howTo) {
$newHowTo = new ChecklistHowTo();
$newHowTo->setTask($newTask);
$newHowTo->setValue($howTo->getValue());
$this->em->persist($newHowTo);
$newTask->getChecklistHowTos()->add($newHowTo);
}
}
foreach ($checklist->getTasks() as $task) {
foreach ($task->getTaskDependencyAsParent() as $dependency) {
$newTaskId = $taskMap[$task->getId()] ?? null;
$newDependsOnTaskId = $taskMap[$dependency->getTaskDependsOn()->getId()] ?? null;
if ($newTaskId && $newDependsOnTaskId) {
$dependencyEntity = new ChecklistTaskDependency();
$dependencyEntity->setTask($newTaskId);
$dependencyEntity->setTaskParent($newDependsOnTaskId);
$this->em->persist($dependencyEntity);
}
}
}
$this->em->flush();
// return $newChecklist;
// } catch (\Exception $e) {
// throw $e;
// }
}
*/
public function createChecklistFromTemplate($user = null, $project = null, $checklist)
{
$HRManager = $this->userService->getHRManager();
$modifierDays = $checklist->getType() == 'OFFBOARDING' ? 15 : 5;
$currentUser = $this->security->getUser();
$initialState = [
'data' => [
'role' => $currentUser->getRoles(),
'id' => $currentUser->getId(),
],
'exp' => time() + 30 * 24 * 60 * 60,
];
$jwt = JWT::encode($initialState, $this->params->get('JWT_SECRET'));
if($user){
$editedPersonalInfo = $user->getPersonalInfo();
}
$startDate = null;
$endDate = null;
if($checklist->getType() == 'ONBOARDING'){
$startDate = $editedPersonalInfo->getJobJoinDate()->format('Y-m-d\TH:i:s\Z');
$endDate = $this->courseService->addWorkdays($editedPersonalInfo->getJobJoinDate()->format('Y-m-d'), $modifierDays, $user->getOffice()->getCountry());
$endDate = new \DateTime($endDate);
$endDate = $endDate->format('Y-m-d\T00:00:00\Z');
}elseif($checklist->getType() == 'PERMANENT'){
$startDate = $editedPersonalInfo->getJobPermanentDate()->format('Y-m-d\TH:i:s\Z');
$endDate = $this->courseService->addWorkdays($editedPersonalInfo->getJobPermanentDate()->format('Y-m-d'), $modifierDays, $user->getOffice()->getCountry());
$endDate = new \DateTime($endDate);
$endDate = $endDate->format('Y-m-d\TH:i:s\Z');
// $endDate = $endDate->format('Y-m-d\T00:00:00\Z');
}elseif($checklist->getType() == 'OFFBOARDING'){
$endDate = $editedPersonalInfo->getJobTerminateDate()->format('Y-m-d\TH:i:s\Z');
$startDate = $this->subtractWorkdays(new \DateTime($editedPersonalInfo->getJobTerminateDate()->format('Y-m-d')), 15);
$startDate = new \DateTime($startDate);
$startDate = $startDate->format('Y-m-d\T00:00:00\Z');
}else{
$startDate = new \DateTime();
$startDate->setTime(0,0,0);
$startDateData = $startDate;
$startDate = $startDate->format('Y-m-d\T00:00:00\Z');
$endDate = $this->courseService->addWorkdays($startDateData->format('Y-m-d'), $modifierDays);
}
if($checklist->getType() == 'PROJECT'){
$checklistName = $checklist->getName() . '-' . $project->getGeneratedId();
} else {
$checklistName = $checklist->getName().' - ' . $user->getPersonalInfo()->getShortFullName();
}
$postData = [
"name" => $checklistName,
"type" => $checklist->getType(),
"start_date" => $startDate,
"due_date" => $endDate,
"status" => "ACTIVE",
"position" => 1,
"template_id" => null,
"project_id" => $project ? $project->getId() : null,
"onboard_user_id" => $user ? $user->getId() : null,
"department_id" => $checklist->getDepartment() ? $checklist->getDepartment()->getId() : null,
"default_assignee_id" => $HRManager->getId(),
"owner_id" => $HRManager->getId()
];
try {
$response = $this->httpClient->request('POST', 'https://hrp-api.mediatropy.com/checklist/from-template/'.$checklist->getId(), [
'headers' => [
'Authorization' => $jwt,
'Content-Type' => 'application/json',
],
'json' => $postData,
]);
return $response;
} catch (\Exception $e) {
return false;
}
}
public function subtractWorkdays(\DateTime $date, int $days): string
{
while ($days > 0) {
$date->modify('-1 day');
if ($date->format('N') < 6) {
$days--;
}
}
return $date->format('Y-m-d');
}
public function checklistTransferOwnership($userId, $managerId = null, bool $isTest = false): array
{
$user = $this->userRepository->find($userId);
$manager = $managerId ? $this->userRepository->find($managerId) : null;
$userManager = $manager ? $manager : $user->getManager();
$summary = [
'status' => 'success',
'message' => '',
'transferredTasks' => 0,
'transferredTasksAsAssignee' => 0,
'transferredTasksAsVerifier' => 0,
'transferredTasksAsAssigneeAndVerifier' => 0,
'affectedChecklists' => 0,
'details' => [],
];
if (!$user) {
return [
'status' => 'error',
'message' => 'Source user not found',
'transferredTasks' => 0,
'transferredTasksAsAssignee' => 0,
'transferredTasksAsVerifier' => 0,
'transferredTasksAsAssigneeAndVerifier' => 0,
'affectedChecklists' => 0,
'details' => [],
];
}
$qb = $this->checklistTaskRepository->createQueryBuilder('ct')
->leftJoin('ct.checklist', 'c')
->leftJoin('c.project', 'p')
->where('ct.status = :status')
->andWhere('c.type = :type')
->andWhere('c.status = :cstatus')
->andWhere('c.project IS NOT NULL')
->andWhere('ct.defaultAssignee = :assignee OR ct.verifier = :assignee')
->setParameter('cstatus', 'ACTIVE')
->setParameter('status', 'TO_DO')
->setParameter('type', 'PROJECT')
->setParameter('assignee', $user->getId());
$tasks = $qb->getQuery()->getResult();
if (empty($tasks)) {
return [
'status' => 'info',
'message' => 'No tasks found for the specified user',
'transferredTasks' => 0,
'transferredTasksAsAssignee' => 0,
'transferredTasksAsVerifier' => 0,
'transferredTasksAsAssigneeAndVerifier' => 0,
'affectedChecklists' => 0,
'details' => [],
];
}
$tasksByChecklist = [];
foreach ($tasks as $task) {
$checklist = $task->getChecklist();
if (!isset($tasksByChecklist[$checklist->getId()])) {
$tasksByChecklist[$checklist->getId()] = [
'checklist' => $checklist,
'tasks' => []
];
}
$tasksByChecklist[$checklist->getId()]['tasks'][] = $task;
}
foreach ($tasksByChecklist as $checklistId => $checklistData) {
$checklist = $checklistData['checklist'];
$tasks = $checklistData['tasks'];
foreach ($tasks as $task) {
if ($task->getDefaultAssignee() === $user && $task->getVerifier() === $user) {
$task->setVerifier($userManager);
$task->setDefaultAssignee($userManager);
$summary['transferredTasksAsAssigneeAndVerifier']++;
} elseif ($task->getDefaultAssignee() === $user) {
$task->setDefaultAssignee($userManager);
$summary['transferredTasksAsAssignee']++;
} elseif ($task->getVerifier() === $user) {
$task->setVerifier($userManager);
$summary['transferredTasksAsVerifier']++;
}
}
$summary['details'][$checklistId] = [
'name' => $checklist->getName(),
'tasks' => count($tasks),
];
$summary['transferredTasks'] += count($tasks);
}
$summary['affectedChecklists'] = count($tasksByChecklist);
if (!$isTest) {
$this->em->flush();
if (!empty($tasksByChecklist)) {
foreach ($tasksByChecklist as $checklistId => $checklistData) {
$checklistActivity = new ChecklistActivity();
$checklistActivity->setChecklist($checklistData['checklist']);
$checklistActivity->setDescription('Ownership transferred: ' . count($checklistData['tasks']) . ' tasks from' . $user->getPersonalInfo()->getFirstName() . ' to ' . $userManager->getPersonalInfo()->getFirstName());
$checklistActivity->setCreatedAt(new \DateTimeImmutable());
$this->em->persist($checklistActivity);
}
$this->em->flush();
}
} else {
$summary['message'] = 'Test mode: No changes were saved to the database.';
}
return $summary;
}
}