<?php
declare(strict_types=1);
namespace App\Nolimit\Offer\Controller;
use App\Entity\Project;
use App\Entity\ProjectStatus;
use App\Nolimit\Offer\Manager\OfferManager;
use App\Nolimit\Offer\Persister\OfferBodyPersister;
use App\Nolimit\Offer\Persister\OfferPersister;
use App\Nolimit\Offer\Provider\OfferDatatableProvider;
use App\Nolimit\Pdf\PdfGenerator;
use App\Repository\CurrencyRepository;
use App\Repository\LanguageRepository;
use App\Repository\OfferBodyRepository;
use App\Repository\OfferRepository;
use App\Repository\OfferStatusRepository;
use App\Repository\ProjectRepository;
use App\Repository\TaskRepository;
use Doctrine\DBAL\Driver\Exception;
use Doctrine\ORM\EntityManagerInterface;
use Sonata\AdminBundle\Controller\CRUDController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class OfferAdminController extends CRUDController
{
private EntityManagerInterface $entityManager;
private OfferDatatableProvider $datatableProvider;
private OfferRepository $offerRepository;
private TranslatorInterface $translator;
private OfferManager $offerManager;
private OfferBodyRepository $offerBodyRepository;
private OfferStatusRepository $offerStatusRepository;
private CurrencyRepository $currencyRepository;
private ProjectRepository $projectRepository;
private OfferBodyPersister $offerBodyPersister;
private OfferPersister $offerPersister;
private PdfGenerator $pdfGenerator;
private LanguageRepository $languageRepository;
private TokenStorageInterface $tokenStorage;
private TaskRepository $taskRepository;
public function __construct(EntityManagerInterface $entityManager, OfferDatatableProvider $datatableProvider, OfferRepository $offerRepository, TranslatorInterface $translator, OfferManager $offerManager, OfferBodyRepository $offerBodyRepository, OfferStatusRepository $offerStatusRepository, CurrencyRepository $currencyRepository, ProjectRepository $projectRepository, OfferBodyPersister $offerBodyPersister, OfferPersister $offerPersister,PdfGenerator $pdfGenerator, LanguageRepository $languageRepository, TokenStorageInterface $tokenStorage, TaskRepository $taskRepository)
{
$this->entityManager = $entityManager;
$this->datatableProvider = $datatableProvider;
$this->offerRepository = $offerRepository;
$this->translator = $translator;
$this->offerManager = $offerManager;
$this->offerBodyRepository = $offerBodyRepository;
$this->offerStatusRepository = $offerStatusRepository;
$this->currencyRepository = $currencyRepository;
$this->projectRepository = $projectRepository;
$this->offerBodyPersister = $offerBodyPersister;
$this->offerPersister = $offerPersister;
$this->pdfGenerator = $pdfGenerator;
$this->languageRepository = $languageRepository;
$this->tokenStorage = $tokenStorage;
$this->taskRepository = $taskRepository;
}
public function listAction(Request $request): Response
{
$user = $this->tokenStorage->getToken()->getUser();
$isSuperAdmin = in_array("ROLE_SUPER_ADMIN", $user->getRoles());
return $this->renderWithExtraParams('/offer/offer_view.html.twig', array(
'is_super_admin' => $isSuperAdmin
));
}
/**
* @Route("/admin/app/offer/offer_list", name="offer_list", methods={"POST"} )
*/
public function offerListAction(): Response
{
$adata['data'] = $this->datatableProvider->datatable();
return $this->json($adata);
}
/**
* @Route("/admin/app/offer/offer_new_row", name="offer_new_row", methods={"POST"} )
*/
public function offerNewRowAction(Request $request): Response
{
$id = $request->get('id');
$offer = $this->offerRepository->find($id);
$lastOrderNumber=$this->offerBodyRepository->getBiggestOrderOfferBody($offer->getId());
$user = $this->tokenStorage->getToken()->getUser();
$isSuperAdmin = in_array("ROLE_SUPER_ADMIN", $user->getRoles());
return $this->renderWithExtraParams('/offer/offer_new_row.html.twig', array(
'offer' => $offer,
'title' => $this->translator->trans('Add offer new row'),
'edited' => false,
'lastOrder'=>$lastOrderNumber,
'is_super_admin'=>$isSuperAdmin,
'tasks' => $this->formatTasksForOfferSelect($offer),
'selectedTaskId' => 0,
'linkedTaskWorkedTime' => '',
));
}
/**
* @Route("/admin/app/offer/offer_edit_row", name="offer_edit_row", methods={"POST"} )
*/
public function offerEditRowAction(Request $request): Response
{
$id = $request->get('id');
$offerBody = $this->offerBodyRepository->find($id);
$lastOrderNumber=$this->offerBodyRepository->getBiggestOrderOfferBody($offerBody->getOffer()->getId());
$user = $this->tokenStorage->getToken()->getUser();
$isSuperAdmin = in_array("ROLE_SUPER_ADMIN", $user->getRoles());
$linkedTask = $this->taskRepository->findOneBy(['offerBody' => $offerBody->getId()]);
$linkedTaskWorkedTime = $linkedTask ? $this->formatWorkedMinutes((int)($linkedTask->getWorkedMinutes() ?? 0)) : '';
return $this->renderWithExtraParams('/offer/offer_new_row.html.twig', array(
'offer' => $offerBody->getOffer(),
'offerBody' => $offerBody,
'title' => $this->translator->trans('Edit offer row'),
'edited' => false,
'lastOrder'=>$lastOrderNumber,
'is_super_admin'=>$isSuperAdmin,
'tasks' => $this->formatTasksForOfferSelect($offerBody->getOffer(), $offerBody->getId()),
'selectedTaskId' => $linkedTask ? $linkedTask->getId() : 0,
'linkedTaskWorkedTime' => $linkedTaskWorkedTime,
));
}
/**
* @Route("/admin/app/offer/offer_delete_row", name="offer_delete_row", methods={"POST"} )
*/
public function offerDeleteRowAction(Request $request): Response
{
$bodyId = (int)$request->get('bodyId');
$offerId = (int)$request->get('offerId');
$offer = $this->offerRepository->find($offerId);
$offerRow = $this->offerBodyRepository->find($bodyId);
$this->entityManager->remove($offerRow);
$this->entityManager->flush();
//$this->pdfGenerator->generateOffer($offerRow->getOffer());
$data[] = $this->datatableProvider->datatableRow($offer);
return new JsonResponse(array('msg' => true, 'datatableRow' => $data[0]), 200);
}
/**
* @Route("/admin/app/offer/offer_save_new_row", name="offer_save_new_row", methods={"POST"} )
*/
public function offerSaveNewRowAction(Request $request): Response
{
$offerId = (int)$request->get('offerId');
$total = (float)$request->get('body_value');
$estimatedHour = (int)$request->get('hour');
$this->offerBodyPersister->saveUpdateOfferBody($request);
$offer = $this->offerRepository->find($offerId);
//$this->pdfGenerator->generateOffer($offer);
$data[] = $this->datatableProvider->datatableRow($offer);
$data[0]['total']=number_format(($data[0]['total']+$total),2,'.','');
$data[0]['estimatedHour'] = $data[0]['estimatedHour']+$estimatedHour;
return new JsonResponse(array('msg' => true, 'datatableRow' => $data[0]), 200);
}
/**
* @Route("/admin/app/offer/offer_accepted_row", name="offer_accepted_row", methods={"POST"} )
*/
public function offerAcceptedRowAction(Request $request): Response
{
$bodyId = (int)$request->get('bodyId');
$offerRow = $this->offerBodyRepository->find($bodyId);
$accepted = ($offerRow->isAccepted()) ? false : true;
$ok=$this->offerManager->createTaskFromOfferBody($offerRow, $accepted);
$this->entityManager->flush();
return new JsonResponse(array('msg' => $ok, 'accepted' => $accepted), 200);
}
/**
* @Route("/admin/app/offer/offer_task_data", name="offer_task_data", methods={"POST"} )
*/
public function offerTaskDataAction(Request $request): Response
{
$taskId = (int)$request->get('taskId');
$offerId = (int)$request->get('offerId');
$task = $this->taskRepository->find($taskId);
$offer = $this->offerRepository->find($offerId);
if (!$task || !$offer || $task->getProject()->getId() !== $offer->getProject()->getId()) {
return new JsonResponse(['msg' => false], 400);
}
$workedMinutes = (int)($task->getWorkedMinutes() ?? 0);
$hourlyRate = (float)$offer->getHourlyRate();
$value = round(($hourlyRate / 60) * $workedMinutes, 2);
$hours = $workedMinutes > 0 ? (int)max(1, ceil($workedMinutes / 60)) : 0;
return new JsonResponse([
'msg' => true,
'description' => $task->getName(),
'technical_description' => $task->getTechnicalDescription() ?? '',
'hour' => $hours,
'value' => $value,
'worked_minutes' => $workedMinutes,
'worked_time' => $this->formatWorkedMinutes($workedMinutes),
], 200);
}
/**
* @Route("/admin/app/offer/offer_add", name="offer_add", methods={"POST"} )
*/
public function offerAddAction(Request $request): Response
{
$projectStatus = [ProjectStatus::PROJECT_STATUS_BEFEJEZETT, ProjectStatus::PROJECT_STATUS_VISSZAUTASITOTT];
$project = $this->entityManager->getRepository(Project::class)->getProjectByStatusNotIn($projectStatus);
$offerStatus = $this->offerStatusRepository->findAll();
$currency = $this->currencyRepository->findAll();
$language = $this->languageRepository->findAll();
return $this->renderWithExtraParams('/offer/offer_add.html.twig', array(
'project' => $project,
'title' => $this->translator->trans('New offer'),
'edited' => false,
'offerStatus' => $offerStatus,
'currency' => $currency,
'language' => $language
));
}
/**
* @Route("/admin/app/offer/offer_edit", name="offer_edit", methods={"POST"} )
*/
public function offerEditAction(Request $request): Response
{
$projectStatus = [ProjectStatus::PROJECT_STATUS_BEFEJEZETT, ProjectStatus::PROJECT_STATUS_VISSZAUTASITOTT];
$project = $this->entityManager->getRepository(Project::class)->getProjectByStatusNotIn($projectStatus);
$offerStatus = $this->offerStatusRepository->findAll();
$currency = $this->currencyRepository->findAll();
$offer = $this->offerRepository->find($request->get('id'));
$language = $this->languageRepository->findAll();
return $this->renderWithExtraParams('/offer/offer_add.html.twig', array(
'project' => $project,
'title' => $this->translator->trans('Edit offer'),
'edited' => false,
'offerStatus' => $offerStatus,
'currency' => $currency,
'offer'=> $offer,
'language' => $language
));
}
/**
* @Route("/admin/app/offer/offer_accept_all", name="offer_accept_all", methods={"POST"} )
*/
public function offerAcceptAllAction(Request $request): Response
{
$offer = $this->offerRepository->find($request->get('id'));
$accepted = (int)$request->get('accepted') !== 0;
$this->offerManager->createTasksFromOffer($offer, $accepted);
// try {
// $sqlData=[ 'offer_id'=>$offer->getId(), 'accepted'=>(int)$request->get('accepted')];
// $this->entityManager->getConnection()->prepare('Update offer_body SET accepted = :accepted where offer_id=:offer_id')->executeQuery($sqlData);
// $this->offerManager->createTasksFromOffer($offer);
// } catch (Exception $e) {
//
// }
return new JsonResponse(array('msg' => true, 200));
}
/**
* @Route("/admin/app/offer/offer_project_change", name="offer_project_change", methods={"POST"} )
*/
public function offerProjectChangeAction(Request $request): Response
{
$id = $request->get('projectId');
$project = $this->projectRepository->find($id);
return new JsonResponse(array('msg' => true, 'hourRate' => $project->getHourlyRate(), 'currency' => $project->getCurrency()->getId()), 200);
}
/**
* @Route("/admin/app/offer/offer_save", name="offer_save", methods={"POST"} )
*/
public function offerSaveAction(Request $request): Response
{
$offer = $this->offerPersister->saveOffer($request);
//$this->pdfGenerator->generateOffer($offer);
$data[] = $this->datatableProvider->datatableRow($offer);
return new JsonResponse(array('msg' => true, 'datatableRow' => $data[0]), 200);
}
/**
* @Route("/admin/app/offer/offer_pdf_print", name="offer_pdf_print", methods={"POST"} )
*/
public function offerPdfPrintAction(Request $request): Response
{
$id = (int)$request->request->get("id");
$offer = $this->offerRepository->find($id);
$this->pdfGenerator->generateOffer($offer);
$protocol = stripos($_SERVER['SERVER_PROTOCOL'], 'https') === 0 ? 'https://' : 'http://';
$domainName = $_SERVER['HTTP_HOST'].'/';
$filename = 'Oferta de pret - '.$offer->getProject()->getName().' - '.$offer->getProject()->getCompany()->getName().' - '.$offer->getOfferDate()->format('d-m-Y').' - '.$offer->getId().'.pdf';
$offer = '/offer/'.$filename;
return new JsonResponse(array('filePath'=> $protocol.$domainName.$offer, 'filename'=>$filename), 200);
}
/**
* @Route("/admin/app/offer/offer_delete", name="offer_delete", methods={"POST"} )
*/
public function offerDeleteAction(Request $request): Response
{
$id = (int)$request->get('id');
$offer = $this->offerRepository->find($id);
$this->entityManager->remove($offer);
$this->entityManager->flush();
return new JsonResponse(array('msg' => true), 200);
}
/**
* @Route("/admin/app/offer/offer_duplication", name="offer_duplication", methods={"POST"} )
*/
public function offerDuplicationAction(Request $request): Response
{
$id = (int)$request->get('id');
$offer=$this->offerManager->offerDuplication($id);
$data[] = $this->datatableProvider->datatableRow($offer);
$data[0]['total']=$offer->oldTotal;
$data[0]['estimatedHour']=$offer->oldEstimatedHour;
return new JsonResponse(array('msg' => true, 'datatableRow' => $data[0]), 200);
}
private function formatTasksForOfferSelect($offer, ?int $currentOfferBodyId = null): array
{
$items = [];
foreach ($this->taskRepository->getTasksAvailableForOffer($offer->getProject()->getId(), $currentOfferBodyId) as $task) {
$workedMinutes = (int)($task->getWorkedMinutes() ?? 0);
$items[] = [
'id' => $task->getId(),
'orderTask' => $task->getOrderTask(),
'name' => $task->getOrderTask() . '. ' . strip_tags($task->getName()) . ' - ' . $this->formatWorkedMinutes($workedMinutes),
];
}
return $items;
}
private function formatWorkedMinutes(int $minutes): string
{
return sprintf('%d:%02d', intdiv($minutes, 60), $minutes % 60);
}
}