<?php
namespace App\Controller;
use App\Interface\Services\AccountantInterface;
use App\Interface\UseCase\VacationListInterface;
use App\Interface\UseCase\Absence\AbsenceInterface;
use Blh\Bundle\Entity\Country;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Blh\Bundle\Entity\EmployeeAbsenceType;
use Blh\Bundle\Entity\EmployeeVacationTaken;
use Blh\Bundle\Entity\Employee;
use Blh\Bundle\Entity\VwEmployeeVacation;
use Blh\Bundle\Entity\EntityContract;
use Ramsey\Uuid\Uuid;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Workflow\Registry;
use Blh\Bundle\Handler\MailHandler;
use Blh\Bundle\Entity\Email;
use Blh\Bundle\Handler\FileHandler;
use Blh\Bundle\Repository\FileCategoryRepository;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Blh\Bundle\Entity\EmployeeVacationTakenFile;
use Blh\Bundle\Entity\File;
use Blh\Bundle\Repository\VwEmployeeVacationRepository;
use Blh\Bundle\Repository\EmployeeRepository;
#[Route('/absence', name: 'absence_')]
class AbsenceController extends AbstractController
{
private $AbsencesRequireFile = [1,2]; // estos son los ids de tipos de ausencia que requieren archivos anexos.
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly Registry $workflow,
private readonly MailHandler $mailHandler,
private readonly ParameterBagInterface $parameters,
private readonly AccountantInterface $accountant
) {}
#[Route('/list', name: 'index')]
public function index(): Response
{
$employeeId = $this->getUser()->getEmployee()->getId();
$contractType = $this->entityManager->getRepository(Employee::class)->hasContractActive($employeeId)[0]->getContractType($employeeId);
return $this->render(
'absence/index.html.twig',
['contractTypeCode' => $contractType->getCode(),
'absenceTypes' => $this->entityManager->getRepository(EmployeeAbsenceType::class)->findBy(['isActive' => 1]),
]);
}
#[Route('/report', name: 'report')]
public function report(): Response
{
return $this->render('absence/report.html.twig');
}
#[Route('/register', name: 'register', methods: ['GET', 'POST'])]
public function registerAction(EmployeeRepository $employeeRepository): Response
{
//Buscamos si el usuario tiene supervisor.
$immediateBoss = $this->getUser()->getEmployee()->getImmediateBoss();
$contract = null;
$whitSupervisor = true;
$whitAccountant = 'yes';
// Si tiene supervisor verificamos que tenga contrato activo y que no este de vacaciones.
if ($immediateBoss) {
$supervisorId = $this->getUser()->getEmployee()->getImmediateBoss()->getId();
$contract = $this->entityManager->getRepository(Employee::class)->hasContractActive($supervisorId);
$inVacation = $this->entityManager->getRepository(Employee::class)->isInVacation($supervisorId);
// Si tiene contrato activo obtenemos los nombres.
if ($contract) {
$supervisor = $contract[0]->getEmployee();
$supervisorName = $supervisor->getFirstName() . " " . $supervisor->getSurname();
}
if (!$contract) {
$supervisorName = "No Supervisor with active contract";
$whitSupervisor = false;
}
if ($inVacation) {
$supervisorName = "Supervisor is in vacation currently";
$whitSupervisor = false;
}
}
if (!$immediateBoss) {
$supervisorName = "No associated supervisor";
$whitSupervisor = false;
}
//Verificamos si el pais de donde es el empelado tiene contador.
$employee = $this->getUser()->getEmployee();
$contract = $this->entityManager->getRepository(Employee::class)->hasContractActive($employee->getId());
// Esta seccion de codigo es para determinar el pais del empleado y buscar el contador correspondiente.
$contractEntity = $this->entityManager->getRepository(EntityContract::class)->findBy(['contract' => $contract[0]->getId(), 'isPrincipal' => 1]);
// Buscamos quien es el accountan del pais donde tiene contrato el solicitante de ausencia.
$Accountant = $this->accountant->getAccountant($contractEntity[0]);
//En caso que no hayan contadores se coloca la condicion, para dejar un arreglo vacio.
$accountantEmployeeIds = ($Accountant) ? implode(',', array_column($Accountant, 'employeeId')) : [];
$accountantActive = $this->entityManager->getRepository(Employee::class)->hasContractActive($accountantEmployeeIds);
$accountantInVacation = $this->entityManager->getRepository(Employee::class)->isInVacation($accountantEmployeeIds);
//Se indica que no tiene contador asociado si nadie tiene la posicion correspondiente
//O (hay contador con vacaciones y la cantidad de contadores que existe para dicho pais, es igual a la cantidad de sulicitudes actuales de vacaciones)
if (!$accountantActive || ($accountantInVacation && count($accountantInVacation) == count($Accountant))) {
$whitAccountant = 'no';
}
$employeeVacations = $this->entityManager->getRepository(VwEmployeeVacation::class)->find($employee->getId());
$employeeVacationTaken = $employeeVacations?->getVacationTaken();
$employeeVacationDays = empty($employeeVacations) ? 100 : $employeeVacations->getVacationDays();
$vacationDaysPending = $employeeVacationDays - $employeeVacationTaken;
if (
!empty($employee->getCity()) &&
!empty($employee->getCity()->getCountry()) &&
$employee->getCity()->getCountry()->getId() == Country::BR
) {
$vacationDaysPending = $employeeVacationDays - ($employeeVacationTaken + ($employeeVacationDays - 30) );
}
return $this->render('absence/register.html.twig', [
'controller_name' => 'AbsenceController',
'supervisorName' => $supervisorName,
'absenceUuid' => Uuid::uuid4()->toString(),
'absenceTypes' => $this->entityManager->getRepository(EmployeeAbsenceType::class)->findBy(['isActive' => 1]),
'employeeVacationDays' => $employeeVacationDays,
'employeeVacationTaken' => $employeeVacationTaken,
'whitSupervisor' => $whitSupervisor,
'whitAccountant' => $whitAccountant,
'minDaysToRequestVacations' => $this->getParameter('minDaysToRequestVacations'),
'activeEmployees' => $employeeRepository->selectActiveEmployees(),
'vacationDaysPending' => $vacationDaysPending
]);
}
#[Route('/create', name: 'create', methods: ['POST'])]
public function createAction(AbsenceInterface $absenceInterface, FileHandler $fileHandler,FileCategoryRepository $fileCategoryRepository, Request $request): JsonResponse
{
$parameters = $request->request->all();
try {
$employeeReplacement = $this->entityManager->getRepository(Employee::class)->find($parameters['absence-register-replace']);
$startDate = new \DateTime($parameters['absence-register-date-start'], new \DateTimeZone('UTC'));
$startEnd = new \DateTime($parameters['absence-register-date-end'], new \DateTimeZone('UTC'));
$vacationsEmployee = $this->entityManager->getRepository(EmployeeVacationTaken::class)->vacationByEmployeeIdAndDates($this->getUser()->getEmployee()->getId(), $startDate, $startEnd);
//Si tiene vacaciones que coinciden con las fechas que intenta registrar ahora se generara un error, para mostrar en el front.
if ($vacationsEmployee) {
throw new \Exception('Coincidence in dates with others absence requested.');
}
//Validamos que venga el arcihvo que caso de no ser una vacacion:
$uploadedFiles = $request->files->get('file-licence-absence');
// Si no se subio el archivo y el tipo de ausencia requiere archivo
if (!$uploadedFiles && (in_array($parameters['absence-register-absence-type'], $this->AbsencesRequireFile))) {
throw new \Exception("No file in the request, this is required");
}
// Si el tipo de ausencia requiere archivo y hay un error al cargarla.
if ( (in_array($parameters['absence-register-absence-type'], $this->AbsencesRequireFile)) && !$uploadedFiles[0]->isValid() ) {
throw new \Exception('Error uploading file: ' . $uploadedFiles[0]->getErrorMessage());
}
$arrayFiles = [];
if ($uploadedFiles) {
$uploadDir = $this->getParameter('kernel.project_dir') . '/public/assets/temp/';
$arrayFiles = $absenceInterface->relocateFiles($uploadedFiles, $uploadDir);
/*$arrayFiles = [];
foreach($uploadedFiles as $fileValue) {
// Generar un nombre único para evitar conflictos
$newFilename = "abs_".$fileValue->getClientOriginalName().'.' . $fileValue->guessExtension();
$fileValue->move($uploadDir, $newFilename);
$arrayFiles[] =[
'originFilePath' => $uploadDir.$newFilename,
'fileName' => $fileValue->getClientOriginalName(),
];
}*/
}
$employee = $this->entityManager->getRepository(Employee::class)->find($this->getUser()->getEmployee()->getId());
$absence = new EmployeeVacationTaken();
$absence->setStartDate($startDate);
$absence->setEndDate($startEnd);
$absence->setComment($parameters['absence-register-comments']);
$absence->setReplacement(trim($employeeReplacement->getFirstName()).' '. trim($employeeReplacement->getSurname()));
$absence->setEmployeeReplacement($employeeReplacement);
$absence->setEmployee($employee);
$absence->setEmployeeAbsenceType($this->entityManager->getRepository(EmployeeAbsenceType::class)->find($parameters['absence-register-absence-type']));
$absence->setDaysTaken($parameters['absence-register-days-absence']);
$absence->setWorkflowStep('Pending_Supervisor_Approval');
$absence->setActive();
$this->entityManager->persist($absence);
$this->entityManager->flush();
//Si el empleado anexo archivo se regitra en la tabla de file
if ($arrayFiles) {
$absenceInterface->registerAndUploadFile($fileCategoryRepository,$fileHandler, $absence, $this->entityManager, $arrayFiles );
/*$fileCategory = $fileCategoryRepository->getFileCategory(43);
foreach($arrayFiles as $fileToUpload) {
$file = $fileHandler->uploadAditionalEmployeeFile(
$fileToUpload['originFilePath'],
$fileToUpload['fileName'],
$fileCategory,
$employee
);
//Insertamos en registro en la tabla intermedia entre Ausencias y Vacaciones.
$employeeVacationTakenFile = new EmployeeVacationTakenFile();
$employeeVacationTakenFile->setVacation($absence);
$employeeVacationTakenFile->setFile($file);
$this->entityManager->persist($employeeVacationTakenFile);
$this->entityManager->flush();
}*/
}
// Se envia la notificacino:
$this->sendNotificationMail($absence, 'absence-Pending_Supervisor_Approval');
return new JsonResponse([
'message' => 'OK'
], 200);
} catch (\Exception $e) {
//dd($e);
return new JsonResponse([
'message' => $e->getMessage()
], 500);
}
}
#[Route('/edit/{absence}', name: 'edit', methods: ['GET', 'POST'])]
public function editAction(Request $request, EmployeeRepository $employeeRepository, VwEmployeeVacationRepository $vwEmployeeVacationRepository, EmployeeVacationTaken $absence): Response
{
$idCurrentEmployee = $this->getUser()->getEmployee()->getId();
$rolesCurrentUser = $this->getUser()->getRoles();
$dataEmpleado = $vwEmployeeVacationRepository->findEmployeeDetailsById($absence->getEmployee()->getId());
//$employeeVacations = $this->entityManager->getRepository(VwEmployeeVacation::class)->find($this->getUser()->getEmployee()->getId());
$employeeVacationTaken = $dataEmpleado['vacation_taken'];
$employeeVacationDays = empty($dataEmpleado['vacation_days']) ? 100 : $dataEmpleado['vacation_days'];
$supervisorName = ($dataEmpleado['boss_id']) ?
$dataEmpleado['boss_first_name'] . ' ' . $dataEmpleado['boss_surname']
: 'Not asociated supervisor';
$allowActions = [];
//Variable que nos determina si los campos estaran activos o inactivos
$fieldsDisabledEnabled = 'disabled';
//Queremos saber si este usuario tendra la accion de Accountant localmente.
$contract = $this->entityManager->getRepository(Employee::class)->hasContractActive($idCurrentEmployee);
$contractEntity = $this->entityManager->getRepository(EntityContract::class)->findBy(['contract' => $dataEmpleado['contract_id'], 'isPrincipal' => 1]);
$accountant = $this->accountant->getAccountant($contractEntity[0]);
//Si hay contador y es el usuario actual.
$currentUserIsAccountant = ($accountant && in_array($this->getUser()->getEmployee()->getId(), array_column($accountant, 'employeeId'))) ? 1 : 0;
date_default_timezone_set('UTC');
$currencyDate = new \DateTime();
//Si el que ingresa al registro es el solicitante
if (($dataEmpleado['employee_id'] == $idCurrentEmployee && in_array($absence->getWorkflowStep(), ['Pending_Supervisor_Approval', 'Approved_by_Supervisor']))
|| (in_array("ROL_EMPLOYEE_ABSENCE_CANCEL", $this->getUser()->getRoles()) && $absence->getWorkflowStep() != 'canceled')
) {
array_push($allowActions, "cancel");
}
//Si tiene supervisor asociado y Si el que ingresa es el supervisor y esta en estatus pendiente.
if ($dataEmpleado['boss_id'] && $dataEmpleado['boss_id'] == $idCurrentEmployee && $absence->getWorkflowStep() == 'Pending_Supervisor_Approval') {
array_push($allowActions, "approve");
array_push($allowActions, "reject");
}
// otro rol que podra editar una ausencia, solo si, tiene el rol ROL_EMPLOYEE_ABSENCE_EDIT
if (in_array("ROL_EMPLOYEE_ABSENCE_EDIT", $rolesCurrentUser)) {
$fieldsDisabledEnabled = '';
array_push($allowActions, "update");
array_push($allowActions, "cancel");
}
if (in_array("ROL_EMPLOYEE_ABSENCE_REJECT", $rolesCurrentUser)) {
$fieldsDisabledEnabled = '';
if ($absence->getWorkflowStep() == 'Pending_Supervisor_Approval') {
array_push($allowActions, "reject");
}
}
if (in_array("ROL_EMPLOYEE_ABSENCE_APPROVE", $rolesCurrentUser)) {
$fieldsDisabledEnabled = '';
if ($absence->getWorkflowStep() == 'Pending_Supervisor_Approval') {
array_push($allowActions, "approve");
}
}
// Se podra ELIMINAR una ausencia, solo si, tiene el rol ROL_EMPLOYEE_ABSENCE_DELETE
// Si la fecha de inicio es mayor a la fecha actual
// Si esta pendiente.
if (
in_array("ROL_EMPLOYEE_ABSENCE_DELETE", $rolesCurrentUser) &&
($absence->getStartDate() >= $currencyDate)
) {
if ($absence->getWorkflowStep() == 'Pending_Supervisor_Approval') {
$fieldsDisabledEnabled = '';
array_push($allowActions, "delete");
}
}
//Buscamos el archivo en caso que tenga uno asociado.
$fileAsociatedToAbsece = $absence->getFiles()->toArray();
return $this->render('absence/edit.html.twig', [
'controller_name' => 'AbsenceController',
'absence' => $absence,
'supervisorName' => $supervisorName,
'absenceTypes' => $this->entityManager->getRepository(EmployeeAbsenceType::class)->findBy(["isActive" => 1]),
'allowActions' => $allowActions,
'fieldsDisabledEnabled' => $fieldsDisabledEnabled,
'employeeVacationDays' => $employeeVacationDays,
'employeeVacationTaken' => $employeeVacationTaken,
'currentUserIsAccountant' => $currentUserIsAccountant,
'backFromAccountingRegistered' => ($request->query->get('ori') == "registerAccountant") ? 1 : 0,
'backFromUpdated' => ($request->query->get('ori') == "update") ? 1 : 0,
'activeEmployees' => $employeeRepository->selectActiveEmployees(),
'files' =>$fileAsociatedToAbsece
]);
}
#[Route('/update/{absence}', name: 'update', methods: ['POST'])]
public function updateAction( AbsenceInterface $absenceInterface, FileHandler $fileHandler,FileCategoryRepository $fileCategoryRepository, Request $request, EmployeeVacationTaken $absence): Response
{
$parameters = $request->request->all();
$remplacement = $this->entityManager->getRepository(Employee::class)->find((int)$request->get("absence-register-replace"));
//try {
//Validamos que venga el arcihvo que caso de no ser una vacacion:
$uploadedFiles = $request->files->get('file-licence-absence');
$filesToDelete = (trim($parameters['absence-edit-files-to-delete'])!="")?explode(",", $parameters['absence-edit-files-to-delete']):null;
// Si no se subio el archivo y el tipo de ausencia requiere archivo
/*if (!$uploadedFiles && (in_array($absence->getEmployeeAbsenceType()->getId(), $this->AbsencesRequireFile))) {
throw new \Exception("No file in the request, this is required");
}
// Si el tipo de ausencia requiere archivo y hay un error al cargarla.
if ( (in_array($absence->getEmployeeAbsenceType()->getId(), $this->AbsencesRequireFile)) && !$uploadedFiles[0]->isValid() ) {
throw new \Exception(message: 'Error uploading file: ' . $uploadedFiles[0]->getErrorMessage());
}*/
$arrayFiles = [];
if ($uploadedFiles) {
$uploadDir = $this->getParameter('kernel.project_dir') . '/public/assets/temp/';
$arrayFiles = $absenceInterface->relocateFiles($uploadedFiles, $uploadDir);
/*foreach($uploadedFiles as $fileValue) {
// Generar un nombre único para evitar conflictos
$newFilename = "abs_".$fileValue->getClientOriginalName().'.' . $fileValue->guessExtension();
$fileValue->move($uploadDir, $newFilename);
$arrayFiles[] =[
'originFilePath' => $uploadDir.$newFilename,
'fileName' => $fileValue->getClientOriginalName(),
];
}*/
}
if ($request->get("absence-edit-action") == "update") {
date_default_timezone_set('UTC');
$absence->setStartDate(new \DateTimeImmutable($request->get("absence-register-date-start")));
$absence->setEndDate(new \DateTimeImmutable($request->get("absence-register-date-end")));
$absence->setComment($request->get("absence-register-comments"));
$absence->setReplacement(trim($remplacement->getFirstName()).' '. trim($remplacement->getSurname()));
$absence->setEmployeeReplacement($remplacement);
$absence->setEmployeeAbsenceType($this->entityManager->getRepository(EmployeeAbsenceType::class)->find($request->get("absence-register-absence-type")));
$absence->setDaysTaken($request->get("absence-register-days-absence"));
$this->entityManager->persist($absence);
$this->sendNotificationMail($absence, 'absence-updated');
$edited = true;
}
if ($request->get("absence-edit-action") == "delete") {
$this->entityManager->remove($absence);
// $this->entityManager->persist($absence);
}
$stateMachine = $this->workflow->get($absence, 'absenceVacation');
if ($request->get("absence-edit-action") == "cancel") {
// Se le agrega esta propiedad para ver desde el workflow, si fue RRHH que cancelo y enviar las notificaciones al Contabilidad.
if ($absence->getWorkflowStep() != 'Pending_Supervisor_Approval') {
$absence->cancelByHR = true;
}
if ($stateMachine->can($absence, 'to_canceled')) {
$stateMachine->apply($absence, 'to_canceled');
}
}
if ($request->get("absence-edit-action") == "approve") {
$approvedDate = new \DateTime(date('Y-m-d'), new \DateTimeZone('UTC'));
$absence->setApprovedDate($approvedDate);
if ($stateMachine->can($absence, 'to_Approved_by_Supervisor')) {
$stateMachine->apply($absence, 'to_Approved_by_Supervisor');
}
$this->entityManager->persist($absence);
}
if ($request->get("absence-edit-action") == "reject") {
if ($stateMachine->can($absence, 'to_rejected')) {
$stateMachine->apply($absence, 'to_rejected');
}
}
if ($request->get("absence-edit-action") == "registerAccountant") {
$accountingRecordedDate = new \DateTime(date('Y-m-d'), new \DateTimeZone('UTC'));
$absence->setAccountingRecordedDate($accountingRecordedDate);
$absence->setAccountingRecorded(1);
}
$this->entityManager->flush();
//Si el empleado anexó archivo se regitra en la tabla de file
if ($arrayFiles) {
$absenceInterface->registerAndUploadFile($fileCategoryRepository,$fileHandler, $absence, $this->entityManager, $arrayFiles );
/*$fileCategory = $fileCategoryRepository->getFileCategory(43);
foreach($arrayFiles as $fileToUpload) {
$file = $fileHandler->uploadAditionalEmployeeFile(
$fileToUpload['originFilePath'],
$fileToUpload['fileName'],
$fileCategory,
$absence->getEmployee()
);
//Insertamos en registro en la tabla intermedia entre Ausencias y Vacaciones.
$employeeVacationTakenFile = new EmployeeVacationTakenFile();
$employeeVacationTakenFile->setVacation($absence);
$employeeVacationTakenFile->setFile($file);
$this->entityManager->persist($employeeVacationTakenFile);
$this->entityManager->flush();
}*/
}
//Si el usuario requirio eliminar archivos ya existentes
if ($filesToDelete){
foreach ($filesToDelete as $fileId) {
$dataFile = $this->entityManager->getRepository(File::class)->find( $fileId);
$fileHandler->simpleDeleteFile($dataFile);
$dataEmployeeVacationTakenFile = $this->entityManager->getRepository(EmployeeVacationTakenFile::class)->findBy(['file' => $fileId ] );
//Eliminar registros de File.
$this->entityManager->remove($dataFile);
//Eliminamos de la tabla employee_vacation_taken_file
$this->entityManager->remove($dataEmployeeVacationTakenFile[0]);
$this->entityManager->flush();
}
}
return ($request->get("absence-edit-action") == "delete") ?
$this->redirect($this->generateUrl('absence_index') . '?id=' . $absence->getId()) :
$this->redirect($this->generateUrl('absence_edit', ["absence" => $absence->getId()]) . "&ori=" . $request->get("absence-edit-action"));
/*} catch (\Exception $e) {
//dd($e);
return new JsonResponse([
'message' => $e->getMessage()
], 500);
}*/
}
#[Route('/{isPendingAccounting}/table/{year}/{month}/{day}/{absenceType}', name: 'table', methods: ['GET'], defaults: ["year" => 0, "month" => 0, "day" => 0, "isPendingAccounting" => 0, "absenceType" => 0])]
public function table(
VacationListInterface $vacationList,
int $year,
int $month,
int $day,
int $isPendingAccounting,
int $absenceType
): Response {
return $this->json($vacationList->getData($year, $month, $day, $isPendingAccounting, $absenceType));
}
public function sendNotificationMail(EmployeeVacationTaken $absence, $typeNotify)
{
$emailToSend = $this->entityManager->getRepository(Email::class)->findOneBy([
'name' => $typeNotify
]);
$employee = $absence->getEmployee();
$EmployeeName = $employee->getFirstName() . ' ' . $employee->getSurName();
$cmEmail = $this->entityManager->getRepository(Employee::class)->findEmailsByPositionInCountry($employee, 'CM');
$ccEmail = $this->entityManager->getRepository(Employee::class)->findEmailsByPositionInCountry($employee, 'CC');
$cmEmail = array_merge($cmEmail, $ccEmail);
if ($typeNotify == 'absence-updated') {
$contract = $this->entityManager->getRepository(Employee::class)->hasContractActive($employee->getId());
$entityContract = $this->entityManager->getRepository(EntityContract::class)->findOneBy(['contract' => $contract[0]->getId(), 'isPrincipal' => 1]);
$a3code = $entityContract->getEntity()->getCountry()->getA3code();
$positionAccountant = $this->parameters->get('absence_position_notification_by_country')[$a3code];
$employeeAccountant = $this->entityManager->getRepository(Employee::class)->getEmployeeByCountryAndPosition($entityContract->getEntity()->getCountry()->getId(), $positionAccountant);
foreach ($employeeAccountant as $contract) {
$sendTo[] = $contract->getEmployee()->getCorporateEmail();
}
//$sendTo[] = ($employeeAccountant)?$employeeAccountant[0]->getEmployee()->getCorporateEmail():"";
//$sendTo[] = 'mjordan+100@bizlatinhub.com';
array_push($sendTo, $employee->getCorporateEmail());
array_push($sendTo, $employee->getImmediateBoss()->getCorporateEmail());
$sendTo = array_merge($sendTo, $cmEmail);
}
if ($typeNotify == 'absence-Pending_Supervisor_Approval') {
$sendTo = [$employee->getImmediateBoss()->getCorporateEmail()];
}
$emailsForNotification =
[
MailHandler::RECEIVER_TO => $sendTo,
MailHandler::RECEIVER_CC => explode(",", $emailToSend->getSendCc()),
MailHandler::RECEIVER_BCC => explode(",", $emailToSend->getSendBcc())
];
$subject = str_replace('{{employeeName}}', $EmployeeName, $emailToSend->getSubject());
$this->mailHandler->sendEmailByApi(
$emailToSend->setSubject($subject),
$emailsForNotification,
['process' => $absence]
);
$this->entityManager->detach($emailToSend);
}
}