<?php
namespace App\Controller;
use App\Entity\FilmProject;
use App\Entity\RecurringDonation;
use App\Entity\User;
use App\Form\DonationFormType;
use App\Repository\DonationRepository;
use App\Repository\FilmProjectRepository;
use App\Repository\RecurringDonationRepository;
use App\Service\DonationService;
use App\Service\UserBillingService;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class DonationController extends AbstractController
{
#[Route('/donation', name: 'app_donation')]
public function index(Request $request, DonationService $donationService, FilmProjectRepository $filmProjectRepository, EntityManagerInterface $em, UserBillingService $userBillingService): Response
{
$user = $this->getUser();
$wordpressId = $request->get('wpId');
$filmProject = $filmProjectRepository->findOneBy(['wordpressId' => $wordpressId]);
if (empty($filmProject) || empty($request->get('wpId'))) {
return $this->render('donation/error.html.twig', [
'title' => 'Project is not available',
'message' => 'The project that you are looking for is not available. Please select other projects to donate.',
]);
}
if ($user) {
if ($this->checkOwnershipProject($user, $filmProject)) { // Check ownership project
return $this->render('donation/error.html.twig', [
'title' => 'You are not allowed to donate to this project',
'message' => 'The owner of this project is not allowed to donate to the project that the owner created.',
]);
}
}
$isRecurringParam = $request->get('is_recurring'); // Check if is recurring donation
$recurringDetails = null;
if ($isRecurringParam == 1) {
$recurringDetails = $this->getRecurringDetails($request);
}
$amount = (float)$request->get('amount');
$supportdaf = 0; // CHECK IF THERE IS ANY DAF DONATION
if ($request->get('supportdaf')) {
$supportdaf = $request->get('supportdaf');
}
$donation = $donationService->createObject($user, $filmProject, (($request->get('amount')) * 100), $recurringDetails, ($supportdaf * 100)); // Create object
$cards = $userBillingService->getCurrentSavedCards(); // Get saved cards
$form = $this->createForm(DonationFormType::class, $donation);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityInstance = $form->getData();
$cardID = $request->request->get('card_payment');
$addCard = $request->request->get('add_card');
if ($isRecurringParam == 1) {
$addCard = 1; // FORCE ADDING PAYMENT CARD TOKEN IF DONATION IS RECURRING
}
$donationService->proceedPayment($entityInstance, $cardID, $addCard);
// if recurring
if ($isRecurringParam == 1) {
$entityInstance = $donationService->updateRecurringDonation($entityInstance);
}
$donationService->dispatchPersistEntity($entityInstance);
$em->persist($entityInstance);
$em->flush();
return $this->redirectToRoute('app_donation_thankyou', ['projectId' => $filmProject->getId()]);
}
return $this->render('donation/index.html.twig', [
'form' => $form->createView(),
'user' => $user,
'cards' => $cards,
'amount' => $amount,
'project' => $filmProject,
'product' => $filmProject->getProduct(),
'supportdaf' => $supportdaf,
'total' => $amount + $supportdaf,
'wordpressId' => $wordpressId
]);
}
#[Route('/support-our-work', name: 'app_daf_donation')]
public function dafDonation(Request $request, DonationService $donationService, EntityManagerInterface $em,
UserBillingService $userBillingService, FilmProjectRepository $filmProjectRepository): Response
{
$user = $this->getUser();
$isRecurringParam = $request->get('is_recurring'); // Check if is recurring donation
$recurringDetails = null;
if ($isRecurringParam == 1) {
$recurringDetails = $this->getRecurringDetails($request);
}
$supportdaf = (float)$request->get('supportdaf');
$supportProjectId = (float)$request->get('supportprojectid');
$supportProject = $filmProjectRepository->findOneBy(['wordpressId' => $supportProjectId]);
$donation = $donationService->createDafDonationObject($user, $supportdaf * 100, $recurringDetails, $supportProject); // Create object
if($supportProject->isIsDafProgram()) {
$donation = $donationService->createObject($user, $supportProject, $supportdaf * 100, $recurringDetails); // Create object as normal project if it's daf program
}
$cards = $userBillingService->getCurrentSavedCards(); // Get saved cards
$form = $this->createForm(DonationFormType::class, $donation);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityInstance = $form->getData();
$cardID = $request->request->get('card_payment');
$addCard = $request->request->get('add_card');
if ($isRecurringParam == 1) {
$addCard = 1; // FORCE ADDING PAYMENT CARD TOKEN IF DONATION IS RECURRING
}
$donationService->proceedPayment($entityInstance, $cardID, $addCard);
// if recurring
if ($isRecurringParam == 1) {
$entityInstance = $donationService->updateRecurringDonation($entityInstance);
}
$donationService->dispatchPersistEntity($entityInstance);
$em->persist($entityInstance);
$em->flush();
return $this->redirectToRoute('app_donation_thankyou', ['projectId' => $supportProject->getId()]);
}
return $this->render('donation/index.html.twig', [
'form' => $form->createView(),
'user' => $user,
'cards' => $cards,
'project' => null,
'amount' => $supportdaf,
'supportdaf' => $supportdaf,
'total' => $supportdaf
]);
}
#[Route('/donation/thank-you', name: 'app_donation_thankyou')]
public function finishPage(Request $request, EntityManagerInterface $em)
{
$projectRepo = $em->getRepository(FilmProject::class);
$projectId = $request->get('projectId');
$filmProject = $projectRepo->findOneBy(['id' => $projectId]);
if (empty($filmProject)) {
return $this->render('donation/thankyou.html.twig');
}
return $this->render('donation/thankyou.html.twig', [
'filmProject' => $filmProject
]);
}
#[Route('/donation/recurring-payment', name: 'app_donation_recurring_payment')]
public function recurringDonationPayment(Request $request, RecurringDonationRepository $recurringDonationRepository, DonationService $donationService, EntityManagerInterface $em): Response
{
// $page = $request->get('page'); // one page has 50 recurring entities
$recurringDonations = $recurringDonationRepository->findTodayRecurringDonation(); // Get active recurring donations
if (empty($recurringDonations)) {
return new Response('No active recurring donations');
}
$resultMsg = [];
foreach ($recurringDonations as $recurringDonation) {
$donations = $recurringDonation->getDonations(); // Get previous donations
$previousDonation = $donations[0];
$previousOrderDetails = $previousDonation->getOrderDetails();
$previousOrderBillingDetails = $previousOrderDetails->getOrderBillingDetails();
$prevFilmProject = $previousDonation->getFilmProject();
if ($prevFilmProject) {
if (!$this->checkRecurringPastCampaignDate($recurringDonation, $prevFilmProject)) { // Check if eligible to pay
array_push($resultMsg, $prevFilmProject->getTitle() . ' campaign has ended.');
continue;
}
if (!$this->checkRecurringEligible($recurringDonation)) { // Check if eligible to pay
array_push($resultMsg, 'Recurring Donation under name '. $previousOrderBillingDetails->getFullName() .' is not eligible to pay yet.');
continue;
}
}
$newDonation = $donationService->recreateDonationForRecurringDonation($previousDonation); // Recreate new object and orderDetails
$donationService->proceedPayment($newDonation, $recurringDonation->getCardId());
$donationService->updateRecurringDonationTimeline($newDonation);
// Empty Xero and Salesforce ID
$newOrderDetails = $newDonation->getOrderDetails();
$newOrderDetails
->setXeroId(null)
->setXeroContactId(null)
->setSalesforceId(null)
;
$em->persist($newOrderDetails);
$em->flush();
if ($prevFilmProject) {
$donationService->dispatchPersistEntity($newDonation);
array_push($resultMsg, 'Recurring Donation under name '. $previousOrderBillingDetails->getFullName() .' with project '. $prevFilmProject->getTitle() .' has been paid.');
} else {
$donationService->dispatchPersistEntity($newDonation, true);
array_push($resultMsg, 'Recurring Donation under name '. $previousOrderBillingDetails->getFullName() .' for DAF Donation has been paid.');
}
$donationService->updateRecurringDonation($newDonation);
}
return new JsonResponse($resultMsg);
}
#[Route('/donation/dataset', name: 'app_donation_dataset')]
public function getDonationDataset(Request $request, FilmProjectRepository $filmProjectRepository, DonationRepository $donationRepository): Response
{
$projectId = $request->get('id');
$period = $request->get('period');
$filmProject = $filmProjectRepository->findOneBy(['id' => $projectId]);
$donations = null;
if ($filmProject) {
// $donations = $filmProject->getDonations();
$donations = $donationRepository->findDonationsByProjectOrderDate($filmProject->getId());
}
$dataset = [
'dataset' => [],
'total' => [],
];
$numberOfDays = 7;
switch($period) {
case '2 weeks':
$numberOfDays = 14;
break;
case '1 month':
$numberOfDays = 30;
break;
case '3 months':
$numberOfDays = 90;
break;
case '6 months':
$numberOfDays = 180;
break;
case '1 year':
$numberOfDays = 365;
break;
case 'fiscal year':
$numberOfDays = 365;
break;
default:
break;
}
// Gather collection of datetimes
$datetimes = [];
if ($period != 'fiscal year') {
for($i = $numberOfDays - 1; $i >= 0; $i--) {
array_push($datetimes, new \DateTime('-'.$i.' days'));
}
} else {
$now = new \DateTime();
$currentYear = date('Y');
$previousyear = $currentYear - 1;
$currentFiscalYear = new \DateTime($currentYear .'-07-01');
$dateString = ( $now >= $currentFiscalYear ) ? $currentYear.'-07-01' : $previousyear.'-07-01';
// $dateString = $previousyear.'-07-01';
for($i = 0; $i < $numberOfDays; $i++) {
$newDate = new \DateTime($dateString.' +'.$i.' days');
array_push($datetimes, $newDate);
}
}
// Get all donations for each datetime
$totalDonationAmount = 0;
foreach ($datetimes as $datetime) {
$total = 0;
if ($filmProject) {
$donations = $donationRepository->findDonationsByDate($datetime, $filmProject->getId());
} else {
$donations = $donationRepository->findAllDonationsByDate($datetime);
}
foreach ($donations as $donation) {
$orderDetails = $donation->getOrderDetails();
$total += $orderDetails->getTotal() / 100;
// Need to exclude popup amount if there is one
if ($filmProject) {
if(!$filmProject->isIsDafCore()) {
$supportdaf = $donation->getSupportDaf();
if ($supportdaf) {
$total -= ($supportdaf / 100);
}
}
}
}
$totalDonationAmount += $total;
array_push($dataset['dataset'], $total);
}
array_push($dataset['total'], number_format($totalDonationAmount, 2));
return new JsonResponse($dataset);
}
/**
* Return array of recurring details
*
* @param Request $request
* @return array
*/
protected function getRecurringDetails(Request $request): array
{
$frequency = $request->get('frequency');
$totalPeriod = $request->get('total_period');
return [
'frequency' => $frequency, // Can be weekly, monthly
'totalPeriod' => $totalPeriod, // option here could be: 1,3,6,12 in months
];
}
protected function checkRecurringEligible(RecurringDonation $recurringDonation): bool
{
$nextPaymentDate = $recurringDonation->getNextPaymentDate();
$from = new \DateTime($nextPaymentDate->format("Y-m-d")." 00:00:00");
$to = new \DateTime($nextPaymentDate->format("Y-m-d")." 23:59:59");
$currentDate = new \DateTime('now');
if ($currentDate >= $from && $currentDate <= $to) {
return true;
}
return false;
}
protected function checkRecurringPastCampaignDate(RecurringDonation $recurringDonation, FilmProject $filmProject): bool
{
$filmProjectTimeline = $filmProject->getFilmProjectTimeline();
$campaignEndDate = $filmProjectTimeline->getFundraisingCampaignEndDate();
$currentDate = new \DateTime('now');
if ($currentDate <= $campaignEndDate) {
return true;
}
return false;
}
protected function checkOwnershipProject(User $user, FilmProject $filmProject)
{
$owner = $filmProject->getOwner();
if ($owner == $user) {
return true;
}
return false;
}
#[Route('/donation/custom_test', name: 'app_donation_custom_test')]
public function runDonationCustomTest(Request $request, DonationRepository $donationRepository, DonationService $donationService): Response
{
$id = 10705;
$donation = $donationRepository->findOneBy(['id' => $id]);
if (!$donation) {
var_dump('donation is empty'); exit();
}
$donationService->dispatchPersistEntity($donation);
}
}