<?php
namespace App\Controller;
use App\Controller\Admin\FilmProjectCrudController;
use App\Controller\Admin\FilmProjectProgressReportCrudController;
use App\Entity\FilmProject;
use App\Entity\FilmProjectProgressReport;
use App\Entity\FilmProjectProgressReportFile;
use App\Entity\RecurringDonation;
use App\Entity\Setting;
use App\Entity\User;
use App\Form\ProgressReportFormType;
use App\Repository\DonationRepository;
use App\Repository\FilmProjectRepository;
use App\Repository\RecurringDonationRepository;
use App\Service\DonationService;
use App\Service\UserBillingService;
use App\Service\MailService;
use App\Service\SettingService;
use App\Service\ProgressReportService;
use App\String\Constant;
use Doctrine\ORM\EntityManagerInterface;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
class ProgressReportController extends AbstractController
{
public const FILE_DIRECTORY = __DIR__ . '/../../public/uploads/progress_reports/'; //choose the folder in which the uploaded file will be stored
#[Route('/progress-report', name: 'app_progress_report')]
public function index(Request $request, EntityManagerInterface $em): Response
{
$user = $this->getUser();
$projectRepo = $em->getRepository(FilmProject::class);
$projectId = $request->get('projectId');
$filmProject = $projectRepo->findOneBy(['id' => $projectId]);
if (!$filmProject) {
return $this->render('progressReport/error.html.twig', [
'title' => 'Project doesn\'t exist.',
'message' => 'This project doesn\'t exist. Please try again.',
]);
}
$progressReport = (new FilmProjectProgressReport())
->setFilmProject($filmProject)
;
$form = $this->createForm(ProgressReportFormType::class, $progressReport);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityInstance = $form->getData();
$entityInstance->setCreatedAt(new \DateTime('now'));
$entityInstance->setModifiedAt(new \DateTime('now'));
$em->persist($entityInstance); // Save data before handling file
$em->flush();
// handle files
$files = $form->get('files')->getData();
foreach ($files as $file) {
// Handle each uploaded file
// For example, move it to a directory
$fileName = md5(uniqid()) . '.' . $file->guessExtension();
try {
$file->move(self::FILE_DIRECTORY, $fileName);
} catch (FileException $e) {
dd($e);
}
// And then we save the entity
$progressReportFile = (new FilmProjectProgressReportFile())
->setFilmProjectProgressReport($entityInstance)
// ->setFilePath(self::FILE_DIRECTORY)
->setFileName($fileName)
->setOriginalName($file->getClientOriginalName())
->setCreatedAt(new \DateTime('now'))
->setModifiedAt(new \DateTime('now'))
// ->setStatus('completed')
;
$em->persist($progressReportFile);
}
$em->persist($entityInstance);
$em->flush();
return $this->redirectToRoute('app_progress_report_thankyou');
}
return $this->render('progressReport/index.html.twig', [
'form' => $form->createView(),
'user' => $user,
'project' => $filmProject,
]);
}
#[Route('/progress-report/thank-you', name: 'app_progress_report_thankyou')]
public function finishPage(Request $request)
{
return $this->render('donation/thankyou.html.twig');
}
#[Route('/progress-report/{currentYear}', name: 'app_progress_report_edit')]
public function edit(Request $request, EntityManagerInterface $em, ProgressReportService $progressReportService, AdminUrlGenerator $adminUrlGenerator, SettingService $settingService, $currentYear): Response
{
$projectId = $request->get('projectId');
$user = $this->getUser();
$progressReportRepo = $em->getRepository(FilmProjectProgressReport::class);
$progressReport = $progressReportRepo->findByYear((int)$currentYear, $projectId);
if (!$progressReport) {
return $this->render('progressReport/error.html.twig', [
'title' => 'Progress report doesn\'t exist.',
'message' => 'This progress report doesn\'t exist. Please try again.',
]);
}
// If opened, set status to receive
if ($progressReport->getStatus() == 'created') {
$progressReport->setStatus('received');
$em->persist($progressReport);
$em->flush();
}
$form = $this->createForm(ProgressReportFormType::class, $progressReport);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityInstance = $form->getData();
$entityInstance->setModifiedAt(new \DateTime('now'));
$em->persist($entityInstance); // Save data before handling file
$em->flush();
if (!$entityInstance->isIsDraft()) {
// $entityInstance->setCreatedAt(new \DateTime('now'));
$entityInstance->setModifiedAt(new \DateTime('now'));
// handle files
$files = $form->get('files')->getData();
foreach ($files as $file) {
// Handle each uploaded file
// For example, move it to a directory
$fileName = md5(uniqid()) . '.' . $file->guessExtension();
try {
$file->move(self::FILE_DIRECTORY, $fileName);
} catch (FileException $e) {
dd($e);
}
// And then we save the entity
$progressReportFile = (new FilmProjectProgressReportFile())
->setFilmProjectProgressReport($entityInstance)
// ->setFilePath(self::FILE_DIRECTORY)
->setOriginalName($file->getClientOriginalName())
->setFileName($fileName)
->setCreatedAt(new \DateTime('now'))
->setModifiedAt(new \DateTime('now'))
// ->setStatus('completed')
;
$em->persist($progressReportFile);
}
$entityInstance->setStatus('completed');
$em->persist($entityInstance);
$em->flush();
$progressReportService->dispatchPersistEntity($entityInstance);
$this->addFlash('success', 'Progress report has been submitted successfully.');
// return $this->redirectToRoute('app_progress_report_thankyou');
$filmProjectIndexUrl = $adminUrlGenerator->setController(FilmProjectCrudController::class)
->setAction(Action::INDEX)
->generateUrl();
return new RedirectResponse($filmProjectIndexUrl);
} else {
$this->addFlash('success', 'This progress report has been saved to draft.');
}
}
$progressReportIntroCopy = $settingService->getOptionValue('progress_report_intro_copy');
return $this->render('progressReport/edit.html.twig', [
'form' => $form->createView(),
'user' => $user,
'progressReport' => $progressReport,
'project' => $progressReport->getFilmProject(),
'progressReportIntroCopy' => $progressReportIntroCopy,
]);
}
#[Route('/progress-report/workflow/send-email', name: 'app_progress_report_send_email')]
public function sendEmail(Request $request, AdminUrlGenerator $adminUrlGenerator, EntityManagerInterface $em, MailService $mailService): Response
{
set_time_limit(0); // Long running task to avoid timeout
$progressReportIndexUrl = $adminUrlGenerator->setController(FilmProjectProgressReportCrudController::class)
->setAction(Action::INDEX)
->generateUrl();
$filmProjectRepo = $em->getRepository(FilmProject::class);
// For testing
// $filmProjects = $filmProjectRepo->findBy(['id' => 1]);
$filmProjects = $filmProjectRepo->findActiveProjects();
foreach($filmProjects as $filmProject) {
$mailService->sendDefaultProgressReportEmail($filmProject);
}
$this->addFlash('success', 'Notification email(s) have been sent to project owners.');
return new RedirectResponse($progressReportIndexUrl);
}
#[Route('/progress-report/workflow/send-weekly-email', name: 'app_progress_report_send_weekly_email')]
public function sendWeeklyEmail(Request $request, EntityManagerInterface $em, SettingService $settingService, MailService $mailService): Response
{
$user = $this->getUser();
$filmProjectRepo = $em->getRepository(FilmProject::class);
$progressReportRepo = $em->getRepository(FilmProjectProgressReport::class);
$filmProjects = $filmProjectRepo->findBy(['wordpressStatus' => [
Constant::WP_STATUS_PUBLISH, // published projects
Constant::WP_STATUS_PROTECTED, // protected projects with password
Constant::WP_STATUS_PRIVATE, // private or hidden projects
]]);
$isProgressReport = $settingService->getOptionValue('is_progress_report');
$progressReportStartDate = $settingService->getOptionValue('progress_report_start_date');
if (!$isProgressReport || !$progressReportStartDate) { // handle empty cases
$response = new Response('Progress report is inactive.', Response::HTTP_OK);
return $response;
}
if ($isProgressReport != '1') { // handle non-empty cases
$response = new Response('Progress report is inactive.', Response::HTTP_OK);
return $response;
}
$startDate = new \DateTime($progressReportStartDate);
$startDate->modify('next Monday');
$dayOfMonth = $startDate->format('j'); // Get the day of the month
$weekOfMonth = ceil($dayOfMonth / 7); // Determine the week of the month starting from the next week
$slug = 'progress-report-notification-week-1';
switch($weekOfMonth) {
case 1:
$slug = 'progress-report-notification-week-1';
break;
case 2:
$slug = 'progress-report-notification-week-2';
break;
case 3:
$slug = 'progress-report-notification-week-3';
break;
case 4:
$slug = 'progress-report-notification-week-4';
break;
default:
break;
}
// If more than 4 weeks, don't send emails at all
if ($weekOfMonth > 4) {
$response = new Response('All autogen emails have been sent.', Response::HTTP_OK);
return $response;
}
foreach($filmProjects as $filmProject) {
$mailService->sendDefaultWeeklyProgressReportEmail($filmProject, $slug);
}
$response = new Response('Email(s) sent.', Response::HTTP_OK);
return $response;
}
#[Route('/progress-report/workflow/send-weekly-email-testing', name: 'app_progress_report_send_weekly_email')]
public function sendWeeklyEmailTesting(Request $request, EntityManagerInterface $em, SettingService $settingService, MailService $mailService): Response
{
$filmProjectRepo = $em->getRepository(FilmProject::class);
$filmProjects = $filmProjectRepo->findBy(['isProgressReportActive' => 1]);
foreach($filmProjects as $filmProject) {
$startDate = new \DateTime($filmProject->getProgressReportStartDate());
$startDate->modify('next Monday');
$dayOfMonth = $startDate->format('j'); // Get the day of the month
$weekOfMonth = ceil($dayOfMonth / 7); // Determine the week of the month starting from the next week
$slug = 'progress-report-notification-week-1';
switch($weekOfMonth) {
case 1:
$slug = 'progress-report-notification-week-1';
break;
case 2:
$slug = 'progress-report-notification-week-2';
break;
case 3:
$slug = 'progress-report-notification-week-3';
break;
case 4:
$slug = 'progress-report-notification-week-4';
break;
default:
break;
}
// If more than 4 weeks, don't send emails at all
if ($weekOfMonth > 4) {
$response = new Response('All autogen emails have been sent.', Response::HTTP_OK);
return $response;
}
$mailService->sendDefaultWeeklyProgressReportEmail($filmProject, $slug);
}
$response = new Response('Email(s) sent.', Response::HTTP_OK);
return $response;
}
#[Route('/admin/progress-report/workflow/cron', name: 'app_progress_report_cron')]
public function startProgressReport(Request $request, EntityManagerInterface $em, ProgressReportService $progressReportService, AdminUrlGenerator $adminUrlGenerator, SettingService $settingService): Response
{
$progressReportIndexUrl = $adminUrlGenerator->setController(FilmProjectProgressReportCrudController::class)
->setAction(Action::INDEX)
->generateUrl();
// Toggle on and off for is_progress_report
$progressReportService->toggleIsProgressReport();
if (!$progressReportService->checkIfProgressReportStarts()) {
// Set all active projects' isProgressReportActive to false
$filmProjectRepo = $em->getRepository(FilmProject::class);
$activeProjects = $filmProjectRepo->findActiveProjectsProgressReport();
foreach ($activeProjects as $activeProject) {
$activeProject->setIsProgressReportActive(false);
$em->persist($activeProject);
}
$em->flush();
$this->addFlash('success', 'Progress report has been turned off.');
// return new Response('Progress report is turned off', Response::HTTP_OK);
return new RedirectResponse($progressReportIndexUrl);
}
$filmProjectRepo = $em->getRepository(FilmProject::class);
$progressReportRepo = $em->getRepository(FilmProjectProgressReport::class);
$activeProjects = $filmProjectRepo->findActiveProjects();
foreach($activeProjects as $activeProject) {
$projectId = $activeProject->getId();
$progressReport = $progressReportRepo->findByYear((int)date("Y"), $projectId);
if ($progressReport) continue;
$progressReport = (new FilmProjectProgressReport)
->setFilmProject($activeProject)
->setCreatedAt(new \DateTime('now'))
->setModifiedAt(new \DateTime('now'))
->setStatus('created')
;
$em->persist($progressReport);
}
$em->flush();
$todayStr = date("Y-m-d H:i:s");
// set progress report start date
$settingService->setOptionValue("progress_report_start_date", $todayStr);
// $response = new Response('Progress report(s) created and sent.', Response::HTTP_OK);
// return $response;
$this->addFlash('success', 'Progress report has been turned on.');
return new RedirectResponse($progressReportIndexUrl);
}
#[Route('/admin/progress-report/workflow/cron/single/{projectId}', name: 'app_progress_report_cron_single')]
public function startSingleProgressReport(Request $request, EntityManagerInterface $em, ProgressReportService $progressReportService, AdminUrlGenerator $adminUrlGenerator, SettingService $settingService, $projectId): Response
{
$progressReportIndexUrl = $adminUrlGenerator->setController(FilmProjectProgressReportCrudController::class)
->setAction(Action::INDEX)
->generateUrl();
$filmProjectRepo = $em->getRepository(FilmProject::class);
$progressReportRepo = $em->getRepository(FilmProjectProgressReport::class);
$activeProject = $filmProjectRepo->findOneBy(['id' => $projectId]);
// First check if progress report status is active
$isProgressReportActive = $activeProject->isIsProgressReportActive();
if ($isProgressReportActive) {
$activeProject->setIsProgressReportActive(false); // turn off progress report status
$em->persist($activeProject);
$em->flush();
$this->addFlash('success', 'The progress report for project '. $activeProject->getTitle() .' has been turned off.');
return new RedirectResponse($progressReportIndexUrl);
}
$activeProject
->setIsProgressReportActive(true)
->setProgressReportStartDate(new \DateTime('now'))
; // turn on progress report status
$em->persist($activeProject);
$em->flush();
// Then create progress report if needed
$progressReport = $progressReportRepo->findByYear((int)date("Y"), $projectId);
if ($progressReport) {
$this->addFlash('success', 'The progress report for project '. $activeProject->getTitle() .' has been turned on.');
return new RedirectResponse($progressReportIndexUrl);
}
$progressReport = (new FilmProjectProgressReport)
->setFilmProject($activeProject)
->setCreatedAt(new \DateTime('now'))
->setModifiedAt(new \DateTime('now'))
->setStatus('created')
;
$em->persist($progressReport);
$em->flush();
$this->addFlash('success', 'The progress report for project '. $activeProject->getTitle() .' has been turned on.');
return new RedirectResponse($progressReportIndexUrl);
}
}