<?php
namespace App\Controller;
use App\Entity\MaxTimeProject;
use App\Entity\OfferPackage;
use App\Entity\Project;
use App\Entity\ProjectOfferPackage;
use App\Entity\User;
use App\Form\CallPersonToAssignTaskType;
use App\Form\ChooseMonthInProjectType;
use App\Form\ProjectType;
use App\Form\SortProjectType;
use App\Module\Slack\SlackManager;
use App\Repository\MaxTimeProjectRepository;
use App\Repository\ProjectOfferPackageRepository;
use App\Repository\ProjectRepository;
use App\Repository\TaskRepository;
use App\Repository\UserRepository;
use App\Service\OfferPackage\OfferPackageService;
use App\Service\TimeService;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
/**
* Class ProjectController
*
* @package App\Controller
* @author Lukasz Krakowiak <lukasz94krakowiak@gmail.com>
* @Route("/projekt")
*/
class ProjectController extends AbstractController
{
/**
* @var ProjectRepository
*/
private ProjectRepository $projectRepository;
/**
* @var MaxTimeProjectRepository
*/
private MaxTimeProjectRepository $maxTimeProjectRepository;
/**
* @var ProjectOfferPackageRepository
*/
private ProjectOfferPackageRepository $projectOfferPackageRepository;
/**
* @var OfferPackageService
*/
private OfferPackageService $offerPackageService;
/**
* @var TimeService
*/
private TimeService $timeService;
private UrlGeneratorInterface $router;
/**
* @param ProjectRepository $projectRepository
* @param MaxTimeProjectRepository $maxTimeProjectRepository
*/
public function __construct(
ProjectRepository $projectRepository,
MaxTimeProjectRepository $maxTimeProjectRepository,
ProjectOfferPackageRepository $projectOfferPackageRepository,
OfferPackageService $offerPackageService,
TimeService $timeService,
UrlGeneratorInterface $router
) {
$this->projectRepository = $projectRepository;
$this->maxTimeProjectRepository = $maxTimeProjectRepository;
$this->projectOfferPackageRepository = $projectOfferPackageRepository;
$this->offerPackageService = $offerPackageService;
$this->timeService = $timeService;
$this->router = $router;
}
/**
* @Route("/", name="project_index")
*/
public function index(Request $request, ProjectRepository $projectRepository, int $category = Project::CATEGORY_ALLEGRO): Response
{
$leader = null;
$leaderForm = $this->createForm(SortProjectType::class);
$leaderForm->handleRequest($request);
if ($leaderForm->isSubmitted() && $leaderForm->isValid()) {
$leader = $leaderForm->get('leader')->getData();
}
return $this->render('project/index.html.twig', [
'projects' => $projectRepository->getProjectListByUser($this->getUser(), false, [
"id" => $request->get('id') ?? null,
"name" => $request->get('nazwa') ?? null,
"leader" => $leader,
"list" => true,
"category" => $category,
]),
'leaderForm' => $leaderForm->createView(),
]);
}
/**
* @Route("/seo", name="project_seo")
*/
public function projectSeo(Request $request, ProjectRepository $projectRepository): Response
{
$this->denyAccessUnlessGranted('CAN_SHOW_LIST', null);
return $this->index($request, $projectRepository, Project::CATEGORY_SEO);
}
/**
* @Route("/fb", name="project_fb")
*/
public function projectFb(Request $request, ProjectRepository $projectRepository): Response
{
$this->denyAccessUnlessGranted('CAN_SHOW_LIST', null);
return $this->index($request, $projectRepository, Project::CATEGORY_FB_ADS);
}
/**
* @Route("/google", name="project_google")
*/
public function projectGoogle(Request $request, ProjectRepository $projectRepository): Response
{
$this->denyAccessUnlessGranted('CAN_SHOW_LIST', null);
return $this->index($request, $projectRepository, Project::CATEGORY_GOOGLE_ADS);
}
/**
* @Route("/emag", name="project_emag")
*/
public function projectEmag(Request $request, ProjectRepository $projectRepository): Response
{
$this->denyAccessUnlessGranted('CAN_SHOW_LIST', null);
return $this->index($request, $projectRepository, Project::CATEGORY_EMAG);
}
/**
* @Route("/pobierz", name="project_download")
*/
public function download()
{
if ($this->isGranted("ROLE_CLIENT")) {
$this->addFlash("error", "Brak dostępu");
return $this->redirectToRoute('dashboard');
}
$data = $this->projectRepository->findAll();
$arr = [];
$i = 0;
/** @var Project $val */
foreach ($data as $val) {
$arr[] = [
$val->getName(),
$val->getOfferPackage() ? $val->getOfferPackage()->getName() : "Brak pakietu",
$val->getLeader() ? $val->getLeader()->getName() : "Brak opiekuna",
$val->getType() == 1 ? "Aktywny" : "Nie aktywny",
];
}
$spreadsheet = new Spreadsheet();
$spreadsheet->getActiveSheet()->fromArray($arr);
$writer = new Xlsx($spreadsheet);
$response = new StreamedResponse(
function () use ($writer) {
$writer->save('php://output');
}
);
$response->headers->set('Content-Type', 'application/vnd.ms-excel');
$response->headers->set('Content-Disposition', 'attachment;filename="projekty.xlsx"');
$response->headers->set('Cache-Control', 'max-age=0');
return $response;
}
private function getExcludedPrice(ProjectOfferPackage $projectOfferPackage)
{
$tasks = $projectOfferPackage->getOfferPackage()->getOfferPackageTasks();
$currentTime = 0;
foreach ($tasks as $task) {
$data = $projectOfferPackage->getData();
if (isset($data[$task->getId()])
&& isset($data[$task->getId()]['time'])) {
$currentTime += (float)$data[$task->getId()]['time'];
}
}
$time = $currentTime - ($projectOfferPackage->getOfferPackage()->getMaxExcludedTime() * 60);
if ($time <= 0) {
return 0;
}
return $time;
}
/**
* @Route("/pokaz/{project}", name="project_show")
*/
public function show(Request $request, Project $project, TaskRepository $taskRepository, SlackManager $slackManager, UserRepository $userRepository): Response
{
$this->denyAccessUnlessGranted('CAN_SHOW_PROJECT', $project);
$month = new \DateTime();
$monthForm = $this->createForm(ChooseMonthInProjectType::class);
$monthForm->handleRequest($request);
$defaultDateFrom = new \DateTime("midnight first day of this month");
$defaultDateTo = new \DateTime("last day of this month");
/** @var ProjectOfferPackage $projectOfferPackage */
$projectOfferPackage = $this->projectOfferPackageRepository
->getProjectOfferPackageInMonth($project, $month);
if ($monthForm->isSubmitted() && $monthForm->isValid()) {
$month = $monthForm->get('month')->getData();
$startDate = clone $month;
$endDate = clone $month;
$defaultDateFrom = $startDate->modify("midnight first day of this month");
$defaultDateTo = $endDate->modify("last day of this month 23:59");
}
$notPackageTime = $this->timeService->getTimeFormatFromNumber($this->timeService->getSumReportTime($defaultDateFrom, $defaultDateTo, $project), $this->isGranted("ROLE_CLIENT"), $this->getUser()->getTimeMultiplier());
$price = (($this->timeService->getSumReportTime($defaultDateFrom, $defaultDateTo, $project) + ($projectOfferPackage ? $this->getExcludedPrice($projectOfferPackage) : 0)) / 60) * $project->getPrice();
$form = $this->createForm(CallPersonToAssignTaskType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
/** @var User $userCall */
$userCall = $form->get('user')->getData();
$slackManager->write(
"<@".($userCall->getSlackChannelId() ?? $userCall->getName())."> - <@".($this->getUser()->getSlackChannelId() ?? $this->getUser()->getName())."> chce abyś przypisał(a) swoje zadania w projekcie: "."<https://czas.qsell.pl".$this->router->generate("project_show", ["project" => $project->getId()])."|".$project->getName().">",
$project->getSlackChannelId()
);
return $this->redirectToRoute('project_show', ["project" => $project->getId()]);
}
return $this->render('project/show.html.twig', [
'project' => $project,
'monthForm' => $monthForm->createView(),
'month' => $month,
'percentage' => $this->offerPackageService->completedPercentageOfferTask($project, $month),
'offerPackage' => $projectOfferPackage ? $projectOfferPackage->getOfferPackage() : null,
'notPackageTime' => $notPackageTime,
'callForm' => $form->createView(),
'priceNotPackageTime' => round($price, 2),
'countAssignedTask' => $this->offerPackageService->countAssignedTask($project, $month),
'employee' => $userRepository->getUserByRole("ROLE_EMPLOYER")
]);
}
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/nowy", name="project_new", methods={"GET","POST"})
*/
public function new(Request $request): Response
{
$project = new Project();
$form = $this->createForm(ProjectType::class, $project);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->projectRepository->save($project);
$projectOfferPackage = new ProjectOfferPackage();
$projectOfferPackage->setProject($project)
->setMonth(new \DateTime())
->setOfferPackage($project->getOfferPackage());
$this->projectOfferPackageRepository->save($projectOfferPackage);
return $this->redirectToRoute('project_index');
}
return $this->renderForm('project/new.html.twig', [
'project' => $project,
'form' => $form,
]);
}
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/{id}/edytuj", name="project_edit", methods={"GET","POST"})
*/
public function edit(Request $request, Project $project): Response
{
$offer = $project->getOfferPackage();
/** @var MaxTimeProject $limit */
$limit = $this->maxTimeProjectRepository->getMaxTimeInCurrentMonth($project);
$form = $this->createForm(ProjectType::class, $project, [
'limit' => $limit ? $limit->getHourLimit() : 0,
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if ($form->get("deactivate")->isClicked()) {
$project->setType(Project::TYPE_DEACTIVATE);
$this->projectRepository->save($project);
return $this->redirectToRoute('project_index', [], Response::HTTP_SEE_OTHER);
}
$this->projectRepository->save($project);
if ($project->getProjectOfferPackages()->count() == 0) {
$projectOfferPackage = new ProjectOfferPackage();
$projectOfferPackage->setProject($project)
->setMonth(new \DateTime())
->setOfferPackage($project->getOfferPackage());
$this->projectOfferPackageRepository->save($projectOfferPackage);
} elseif ($offer !== $project->getOfferPackage()) {
$projectOfferPackage = $this->projectOfferPackageRepository
->getProjectOfferPackageInCurrentMonth($project)
->setOfferPackage($project->getOfferPackage());
$this->projectOfferPackageRepository->save($projectOfferPackage);
}
return $this->redirectToRoute('project_index', [], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('project/edit.html.twig', [
'project' => $project,
'form' => $form,
]);
}
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/{id}/delete", name="project_delete", methods={"GET"})
*/
public function delete(Request $request, Project $project): Response
{
$entityManager = $this->getDoctrine()->getManager();
$entityManager->remove($project);
$entityManager->flush();
return $this->redirectToRoute('project_index');
}
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/{id}/dezaktywacja", name="project_deactive", methods={"GET"})
*/
public function deactivate(Request $request, Project $project): Response
{
$project->setType(Project::TYPE_DEACTIVATE);
$this->projectRepository->save($project);
return $this->redirectToRoute('project_index');
}
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/{id}/aktywacja", name="project_active", methods={"GET"})
*/
public function activate(Request $request, Project $project): Response
{
$project->setType(Project::TYPE_ACTIVE);
$this->projectRepository->save($project);
return $this->redirectToRoute('project_index');
}
}