<?php
namespace App\Controller\Admin;
use App\Entity\Donation;
use App\Message\ExportDonation;
use App\Filter\OrderDetailsStatusFilter;
use App\Filter\OrderDetailsTotalFilter;
use App\Filter\DonationDateFilter;
use App\Form\AdminOrderItemsFormType;
use App\Repository\FilmProjectRepository;
use App\Service\DonationService;
use App\Service\UserService;
use App\String\Constant;
use App\Utility\DropdownValues;
use App\Utility\PdfExporter;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Config\Filters;
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Dto\BatchActionDto;
use EasyCorp\Bundle\EasyAdminBundle\Factory\FilterFactory;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Field\BooleanField;
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
use EasyCorp\Bundle\EasyAdminBundle\Field\CollectionField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
use EasyCorp\Bundle\EasyAdminBundle\Field\MoneyField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Filter\BooleanFilter;
use EasyCorp\Bundle\EasyAdminBundle\Orm\EntityRepository;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Twig\Environment;
use Knp\Snappy\Pdf;
use Symfony\Component\Messenger\MessageBusInterface;
class DonationCrudController extends AbstractCrudController
{
private UserService $userService;
private DonationService $donationService;
private $adminUrlGenerator;
public function __construct(UserService $userService, DonationService $donationService, AdminUrlGenerator $adminUrlGenerator)
{
$this->userService = $userService;
$this->donationService = $donationService;
$this->adminUrlGenerator = $adminUrlGenerator;
}
public static function getEntityFqcn(): string
{
return Donation::class;
}
public function configureFields(string $pageName): iterable
{
return [
FormField::addPanel('Donor Details'),
TextField::new('orderDetails.orderBillingDetails.firstName', 'First Name')->setRequired(true)->setColumns(3)->hideOnIndex(),
TextField::new('orderDetails.orderBillingDetails.LastName', 'Last Name')->setRequired(true)->setColumns(3)->hideOnIndex(),
TextField::new('orderDetails.orderBillingDetails.emailAddress', 'Email')->setRequired(true)->setColumns(3)->hideOnIndex(),
TextField::new('orderDetails.orderBillingDetails.phoneNumber', 'Phone Number')->setRequired(true)->setColumns(3)->hideOnIndex(),
TextField::new('wordpressDonorName', 'Wordpress Donor Name')->setColumns(6)->hideOnIndex()->setHelp('If empty, project page will show default donor or organisation name.')->setPermission(Constant::ROLE_FINANCE),
BooleanField::new('isDisplayOrganisation', 'Display donor organisation on project page and receipt')->setColumns(12)->renderAsSwitch(false)->addCssClass('fw-bold')->hideOnIndex()->addCssClass('display-organisation-tickbox'),
TextField::new('orderDetails.orderBillingDetails.organisation', 'Organisation / Company')->setColumns(12)->hideOnIndex()->setHelp('Leave blank if no organisation/company applicable')->addCssClass('display-organisation-input'),
TextField::new('orderDetails.orderBillingDetails.street', 'Street')->setRequired(true)->setColumns(12)->hideOnIndex(),
TextField::new('orderDetails.orderBillingDetails.suburb', 'Suburb')->setRequired(true)->setColumns(3)->hideOnIndex(),
ChoiceField::new('orderDetails.orderBillingDetails.state', 'State')->setRequired(true)->setColumns(3)->setChoices(DropdownValues::$states)->hideOnIndex(),
ChoiceField::new('orderDetails.orderBillingDetails.country', 'Country')->setColumns(3)->hideOnIndex()->setRequired(true)->setChoices(DropdownValues::$countries),
TextField::new('orderDetails.orderBillingDetails.postcode', 'Postcode')->setRequired(true)->setColumns(3)->hideOnIndex(),
FormField::addPanel('Donation Details'),
AssociationField::new('filmProject', 'Project')->setRequired(true)->setColumns(12)->setPermission(Constant::ADMIN_ROLE)->setFormTypeOptions([
'query_builder' => function (FilmProjectRepository $er) {
return $er->createQueryBuilder('e')
->andWhere('e.status = :approved')
->setParameter('approved', 'approved')
->orderBy('e.title', 'ASC')
;
}
])->hideOnIndex()->onlyWhenCreating(),
AssociationField::new('filmProject', 'Project')->setRequired(true)->setColumns(12)->setPermission(Constant::ADMIN_ROLE)->setFormTypeOptions([
'query_builder' => function (FilmProjectRepository $er) {
return $er->createQueryBuilder('e')
->andWhere('e.status = :approved')
->setParameter('approved', 'approved')
->orderBy('e.title', 'ASC')
;
}
])->hideOnIndex()->onlyWhenUpdating(),
CollectionField::new('orderDetails.orderItems', 'Product')
->showEntryLabel()
->setEntryIsComplex()
->setEntryType(AdminOrderItemsFormType::class)
->renderExpanded()
->setColumns('col-12')
->addCssClass('custom-collection-form product-selection-form')
->hideOnIndex()
->allowAdd(false)
->allowDelete(false),
ChoiceField::new('orderDetails.paymentDetails.type', 'Payment type')->setChoices([
Constant::PAYMENT_EFT => Constant::PAYMENT_EFT,
Constant::PAYMENT_CREDIT_CARD => Constant::PAYMENT_CREDIT_CARD,
])->setColumns(4)->hideOnIndex(),
MoneyField::new('orderDetails.total', 'Donation Amount')->setRequired(true)->setColumns(8)->setCurrency('AUD')->addCssClass('custom-money-field')->setTextAlign('left')->hideOnIndex()->onlyWhenCreating(),
MoneyField::new('orderDetails.total', 'Donation Amount')->setRequired(true)->setColumns(8)->setCurrency('AUD')->addCssClass('custom-money-field')->setTextAlign('left')->hideOnIndex()->onlyWhenUpdating()->setFormTypeOption('disabled','disabled'),
DateTimeField::new('modifiedAt', 'Date')->setFormat('dd MMM yyyy HH:mm:ss')->setColumns('col-4')->addCssClass('custom-date-field')->hideOnIndex(),
FormField::addPanel('Additional Information'),
ChoiceField::new('isDonationEmail', 'Is donation acknowledgement email and receipt required to donor?')->setChoices([
'Yes' => true,
'No' => false,
])->renderExpanded()->setColumns(12)->hideOnIndex()->setRequired(true),
ChoiceField::new('isOrganisationConsent', 'Consent to having my name or organisation listed on the project page or any public list of donations for this project.')->setChoices([
'I consent' => true,
'I do not consent (this donation will be listed as anonymous)' => false,
])->renderExpanded()->setColumns(12)->hideOnIndex()->setRequired(true),
ChoiceField::new('isContactShared', 'Consent to having my name and contact details shared with the filmmaker for the purpose of receiving communications from the filmmaker.')->setChoices([
'I consent' => true,
'I do not consent' => false,
])->renderExpanded()->setColumns(12)->hideOnIndex()->setRequired(true),
ChoiceField::new('isNameApproved', 'Consent for my name as above to be listed in relevant project credits and/or organisational reporting as appropriate.')->setChoices([
'I consent' => true,
'I do not consent' => false,
])->renderExpanded()->setColumns(12)->hideOnIndex()->setRequired(true),
FormField::addPanel('Xero Details')->setHelp('Leave Xero ID field blank to create a Xero ID object.'),
TextField::new('orderDetails.xeroId', 'Xero ID')->setColumns(4)->hideOnIndex(),
TextField::new('orderDetails.xeroContactId', 'Xero Contact ID')->setColumns(4)->hideOnIndex(),
TextField::new('orderDetails.invoiceNumber', 'Invoice Number')->setColumns(4)->hideOnIndex(),
FormField::addPanel('Salesforce Details')->setHelp('Leave this field blank to create a Salesforce object.'),
TextField::new('orderDetails.salesforceId', 'Salesforce ID')->setColumns(6)->hideOnIndex(),
// Index field
IdField::new('orderDetails.id', 'Order Id')->hideOnForm()->setTemplatePath('admin/field/order_mw_id.html.twig')->setSortable(true)->setPermission(Constant::ADMIN_ROLE),
TextField::new('orderDetails.invoiceNumber', 'Receipt Id')->setSortable(true)->hideOnForm()->setTemplatePath('admin/field/order_details_id.html.twig'),
TextField::new('orderDetails.orderBillingDetails.fullName', 'Donor Name')->setSortable(false)->hideOnForm(),
TextField::new('orderDetails.orderBillingDetails.organisation', 'Organisation')->setSortable(false)->hideOnForm()->setTemplatePath('admin/field/organisation.html.twig'),
TextField::new('filmProject.title', 'Donation to')->setSortable(true)->hideOnForm()->setTemplatePath('admin/field/donation_project_title.html.twig'),
BooleanField::new('isOrganisationConsent', 'Displayed Anonymous Status')->hideOnForm()->setTemplatePath('admin/field/is_organisation_consent.html.twig')->setTextAlign('left'),
MoneyField::new('orderDetails.total', 'Total Amount')->setSortable(true)->setCurrency('USD')->hideOnForm()->setTextAlign('left'),
MoneyField::new('totalDonation', 'Project Amount')->setSortable(true)->setCurrency('USD')->hideOnForm()->setTextAlign('left'),
MoneyField::new('popupAmount', 'Pop-up Amount')->setCurrency('USD')->hideOnForm()->setTextAlign('left')->setTemplatePath('admin/field/project_title.html.twig'),
DateField::new('modifiedAt', 'Date')->hideOnForm()->setFormat('dd MMM yyyy'),
TextField::new('orderDetails.paymentDetails.status', 'Status')->hideOnForm()->setTemplatePath('admin/field/payment_status.html.twig'),
TextField::new('orderDetails.paymentDetails.type', 'Method')->hideOnForm(),
// TextField::new('orderDetails.paymentDetails.type', 'Payment Type')->hideOnForm()->setTemplatePath('admin/field/payment_type.html.twig'),
];
}
public function createEntity(string $entityFqcn)
{
$user = $this->userService->getCurrentUser();
$donation = $this->donationService->createObject(null);
$orderDetails = $donation->getOrderDetails();
$paymentDetails = $orderDetails->getPaymentDetails();
$paymentDetails->setEftType();
return $donation;
}
public function persistEntity(EntityManagerInterface $entityManager, $entityInstance): void
{
$orderDetails = $entityInstance->getOrderDetails();
$orderDetails->setCreatedAt($entityInstance->getModifiedAt());
$orderDetails->setModifiedAt($entityInstance->getModifiedAt());
$entityInstance->setCreatedAt($entityInstance->getModifiedAt());
$entityManager->persist($orderDetails);
$entityManager->flush();
// Since it's manual donation, we have to make sure that the payment details is completed as well
$paymentDetails = $orderDetails->getPaymentDetails();
$paymentDetails
->setStatus('Completed')
->setIsPaid(true)
;
$this->donationService->dispatchPersistEntity($entityInstance);
$entityManager->persist($entityInstance);
$entityManager->persist($paymentDetails);
$entityManager->flush();
$orderDetails = $entityInstance->getOrderDetails();
$invoiceNumber = $orderDetails->getInvoiceNumber();
// Finally, update the project donations on the Wordpress
$this->addFlash('Donation Confirmed', 'donation '. $invoiceNumber .' has successfully been processed.');
}
public function updateEntity(EntityManagerInterface $entityManager, $entityInstance): void
{
$uow = $entityManager->getUnitOfWork();
$originalEntityData = $uow->getOriginalEntityData( $entityInstance ); // Get original data before edit
$oldProjectId = null;
if (isset($originalEntityData['film_project_id'])) {
if ($originalEntityData['film_project_id'] != $entityInstance->getFilmProject()->getId()) {
$oldProjectId = $originalEntityData['film_project_id'];
}
} // Check if project is changed
$orderDetails = $entityInstance->getOrderDetails();
// Rare case to cover changes from DAF Core to filmmaker projects and full amount of support daf is converted.
$filmProject = $entityInstance->getFilmProject();
if (!$filmProject->isIsDafCore() && $entityInstance->getSupportDaf() >= $orderDetails->getTotal()) {
$entityInstance->setSupportDaf(null);
}
$entityManager->persist($entityInstance);
$entityManager->flush();
if ($orderDetails->getXeroId()) {
$this->donationService->updateDonation($entityInstance, $oldProjectId);
} else {
$this->donationService->dispatchPersistEntity($entityInstance);
}
$this->addFlash('Receipt updated', 'The receipt has been updated.');
}
public function deleteEntity(EntityManagerInterface $entityManager, $entityInstance): void
{
$orderDetails = $entityInstance->getOrderDetails();
if ($orderDetails) {
$paymentDetails = $orderDetails->getPaymentDetails();
$paymentDetails->setStatus('archived');
$entityManager->persist($entityInstance);
$entityManager->flush();
}
$this->donationService->archiveDonation($entityInstance);
$this->addFlash('Receipt removed', 'The receipt has been removed.');
}
public function createIndexQueryBuilder(SearchDto $searchDto, EntityDto $entityDto, FieldCollection $fields, FilterCollection $filters): QueryBuilder
{
$request = $this->container->get('request_stack')->getCurrentRequest();
$recurringDonationId = $request->query->get('recurringDonationId');
$user = $this->getUser();
$response = $this->container->get(EntityRepository::class)->createQueryBuilder($searchDto, $entityDto, $fields, $filters);
if ($user->isAdmin()) {
$response
->leftJoin('entity.orderDetails','od')
->leftJoin('od.paymentDetails','p')
->andWhere('p.status != :archived')
->setParameter('archived', 'archived')
->addOrderBy('entity.modifiedAt', 'DESC')
->groupBy('od.modifiedAt')
->groupBy('od.id')
;
if ($queryVal = $searchDto->getQuery()) {
$queryVal = str_replace('MW', '', $queryVal);
$queryVal = str_replace('"', '', $queryVal);
$response
->orWhere('od.id LIKE :query')
->setParameter('query', $queryVal)
;
}
} else {
$response
->leftJoin('entity.orderDetails','od')
->leftJoin('od.orderBillingDetails','ob')
->leftJoin('od.paymentDetails','p')
->andWhere('(ob.emailAddress = :email) or (od.user = :userId)')
->andWhere('p.status != :archived')
->setParameter('email', $user->getEmail())
->setParameter('userId', $user->getId())
->setParameter('archived', 'archived')
->addOrderBy('entity.modifiedAt', 'DESC')
->groupBy('od.modifiedAt')
->groupBy('od.id')
;
}
if ($recurringDonationId) {
$response
->leftJoin('entity.recurringDonation','r')
->andWhere('entity.isRecurringDonation IS NOT NULL')
->andWhere('r.id = :recurringDonationId')
->setParameter('recurringDonationId', $recurringDonationId)
;
}
return $response;
}
public function configureCrud(Crud $crud): Crud
{
$crud
->setSearchFields(['orderDetails.id', 'orderDetails.invoiceNumber', 'orderDetails.orderBillingDetails.firstName', 'orderDetails.orderBillingDetails.lastName', 'filmProject.title'])
->setPageTitle('index', 'Donations')
->setPageTitle('new', 'Add New Donation')
->setPageTitle('edit', 'Edit Donation')
->overrideTemplate('flash_messages', 'admin/crud/flash_messages_alt.html.twig')
->overrideTemplate('crud/index', 'admin/index/donation_index.html.twig')
->overrideTemplate('crud/new', 'admin/form/new_donation_form_theme.html.twig')
->overrideTemplate('crud/edit', 'admin/form/edit_donation_form_theme.html.twig')
;
// If recurring donation
$request = $this->container->get('request_stack')->getCurrentRequest();
$recurringDonationId = $request->query->get('recurringDonationId');
if ($recurringDonationId) {
$crud->setPageTitle('index', 'View Recurring Donation(s)');
}
return $crud;
}
public function configureActions(Actions $actions): Actions
{
$appearAsAnonymous = Action::new('appearAsAnonymous', 'Appear as anonymous on project page')
->linkToCrudAction('appearAsAnonymous')
->displayIf(static function ($entity) {
$orderDetails = $entity->getOrderDetails();
$paymentDetails = $orderDetails->getPaymentDetails();
return ($entity->isIsOrganisationConsent() && $paymentDetails->getStatus() != Constant::PAYMENT_STATUS_REFUNDED);
})
;
$appearAsOrganisation = Action::new('appearAsOrganisation', 'Appear as organisation on project page')
->linkToCrudAction('appearAsOrganisation')
->displayIf(static function ($entity) {
$orderDetails = $entity->getOrderDetails();
$paymentDetails = $orderDetails->getPaymentDetails();
return (!$entity->isIsOrganisationConsent() && $paymentDetails->getStatus() != Constant::PAYMENT_STATUS_REFUNDED);
})
;
$setAmountInvisible = Action::new('setAmountInvisible', 'Make Donation Amount Invisible')
->linkToCrudAction('setAmountInvisible')
->displayIf(static function ($entity) {
$orderDetails = $entity->getOrderDetails();
$paymentDetails = $orderDetails->getPaymentDetails();
return (!$entity->isIsAmountInvisible() && $paymentDetails->getStatus() != Constant::PAYMENT_STATUS_REFUNDED);
})
;
$setAmountVisible = Action::new('setAmountVisible', 'Make Donation Amount Visible')
->linkToCrudAction('setAmountVisible')
->displayIf(static function ($entity) {
$orderDetails = $entity->getOrderDetails();
$paymentDetails = $orderDetails->getPaymentDetails();
return ($entity->isIsAmountInvisible() && $paymentDetails->getStatus() != Constant::PAYMENT_STATUS_REFUNDED);
})
;
$viewInvoice = Action::new('viewInvoice', 'View Receipt', '')
->setHtmlAttributes(['target' => '_blank'])
->linkToCrudAction('viewInvoice')
->displayIf(static function($entity) {
$orderDetails = $entity->getOrderDetails();
$paymentDetails = $orderDetails->getPaymentDetails();
return ($paymentDetails->getStatus() == Constant::PAYMENT_STATUS_PAID && !empty($orderDetails->getXeroId()));
})
;
$downloadInvoice = Action::new('downloadInvoice', 'Download Receipt', '')
->linkToCrudAction('downloadInvoice')
->displayIf(static function($entity) {
$orderDetails = $entity->getOrderDetails();
$paymentDetails = $orderDetails->getPaymentDetails();
return ($paymentDetails->getStatus() == Constant::PAYMENT_STATUS_PAID && !empty($orderDetails->getXeroId()));
})
;
$sendInvoice = Action::new('sendInvoice', 'Send Receipt', '')
->linkToCrudAction('sendInvoice')
->displayIf(static function($entity) {
$orderDetails = $entity->getOrderDetails();
$paymentDetails = $orderDetails->getPaymentDetails();
return ($paymentDetails->getStatus() == Constant::PAYMENT_STATUS_PAID && !empty($orderDetails->getXeroId()));
})
;
$sendInvoiceBatch = Action::new('sendInvoiceBatch', 'Send Receipt', '')
->linkToCrudAction('sendInvoiceBatch')
->createAsGlobalAction()
->displayIf(static function($entity) {
$orderDetails = $entity->getOrderDetails();
$paymentDetails = $orderDetails->getPaymentDetails();
return ($paymentDetails->getStatus() == Constant::PAYMENT_STATUS_PAID && !empty($orderDetails->getXeroId()));
})
;
$generateCustomInvoice = Action::new('generateCustomInvoice', 'Download Receipt', '')
->linkToCrudAction('generateCustomInvoice')
->displayIf(static function($entity) {
$orderDetails = $entity->getOrderDetails();
$paymentDetails = $orderDetails->getPaymentDetails();
return ($paymentDetails->getStatus() == Constant::PAYMENT_STATUS_PAID && !empty($orderDetails->getXeroId()));
})
;
$refundDonation = Action::new('refundDonation', 'Refund', '')
->linkToCrudAction('refundDonation')
->displayIf(static function ($entity) {
$orderDetails = $entity->getOrderDetails();
$paymentDetails = $orderDetails->getPaymentDetails();
$paymentStatus = $paymentDetails->getStatus();
$isRefund = false;
if ($paymentStatus == Constant::PAYMENT_STATUS_PAID && ($paymentDetails->getType() != Constant::PAYMENT_EFT)) {
$isRefund = true;
}
return $isRefund;
})
;
$refundModalDonation = Action::new('refundModalDonation', 'Refund', '')
->linkToUrl('/')
->displayIf(static function ($entity) {
$orderDetails = $entity->getOrderDetails();
$paymentDetails = $orderDetails->getPaymentDetails();
$paymentStatus = $paymentDetails->getStatus();
$isRefund = false;
if ($paymentStatus == Constant::PAYMENT_STATUS_PAID && ($paymentDetails->getType() != Constant::PAYMENT_EFT)) {
$isRefund = true;
}
return $isRefund;
})
;
$partialRefundDonation = Action::new('partialRefundDonation', 'Partial Refund', '')
->linkToCrudAction('partialRefundDonation')
->displayIf(static function ($entity) {
$orderDetails = $entity->getOrderDetails();
$paymentDetails = $orderDetails->getPaymentDetails();
$paymentStatus = $paymentDetails->getStatus();
$isRefund = false;
if ($paymentStatus == Constant::PAYMENT_STATUS_PAID && ($paymentDetails->getType() != Constant::PAYMENT_EFT) && (!empty($entity->getSupportDaf()))) {
$isRefund = true;
}
return $isRefund;
})
;
$partialRefundModalDonation = Action::new('partialRefundModalDonation', 'Partial Refund', '')
->linkToUrl('/')
->displayIf(static function ($entity) {
$orderDetails = $entity->getOrderDetails();
$paymentDetails = $orderDetails->getPaymentDetails();
$paymentStatus = $paymentDetails->getStatus();
$isRefund = false;
if ($paymentStatus == Constant::PAYMENT_STATUS_PAID && ($paymentDetails->getType() != Constant::PAYMENT_EFT) && (!empty($entity->getSupportDaf()))) {
$isRefund = true;
}
return $isRefund;
})
;
$getRefundInvoice = Action::new('getRefundInvoice', 'Download Refund Bill', '')
->linkToCrudAction('getRefundInvoice')
->displayIf(static function ($entity) {
$orderDetails = $entity->getOrderDetails();
$isRefund = $orderDetails->isIsRefund();
return $isRefund;
})
;
$exportBatchDonations = Action::new('exportBatchDonations', 'Export Donations', '')
->linkToCrudAction('exportBatchDonations')
->createAsGlobalAction()
;
return $actions
->add(Crud::PAGE_INDEX, $appearAsAnonymous)
->add(Crud::PAGE_INDEX, $appearAsOrganisation)
->add(Crud::PAGE_INDEX, $setAmountInvisible)
->add(Crud::PAGE_INDEX, $setAmountVisible)
->add(Crud::PAGE_INDEX, $viewInvoice)
// ->add(Crud::PAGE_INDEX, $downloadInvoice)
->add(Crud::PAGE_INDEX, $generateCustomInvoice)
->add(Crud::PAGE_INDEX, $sendInvoice)
->add(Crud::PAGE_INDEX, $refundDonation)
->add(Crud::PAGE_INDEX, $refundModalDonation)
->add(Crud::PAGE_INDEX, $partialRefundDonation)
->add(Crud::PAGE_INDEX, $partialRefundModalDonation)
->add(Crud::PAGE_INDEX, $getRefundInvoice)
->add(Crud::PAGE_INDEX, $exportBatchDonations)
->addBatchAction($sendInvoiceBatch)
->remove(Crud::PAGE_NEW, Action::SAVE_AND_ADD_ANOTHER)
->remove(Crud::PAGE_EDIT, Action::SAVE_AND_CONTINUE)
->update(Crud::PAGE_INDEX, Action::NEW, function (Action $action) {
return $action
->setLabel('Create New')
;
})
->update(Crud::PAGE_INDEX, $refundDonation, function (Action $action) {
return $action->addCssClass('d-none action-refundDonation');
})
->update(Crud::PAGE_INDEX, $partialRefundDonation, function (Action $action) {
return $action->addCssClass('d-none action-partialRefundDonation');
})
->update(Crud::PAGE_INDEX, $exportBatchDonations, function (Action $action) {
return $action->addCssClass('btn btn-secondary');
})
->reorder(Crud::PAGE_INDEX, [Action::EDIT, 'appearAsAnonymous', 'appearAsOrganisation', 'setAmountInvisible', 'setAmountVisible', 'viewInvoice', 'generateCustomInvoice', 'sendInvoice', 'refundDonation', 'refundModalDonation', 'partialRefundDonation', 'partialRefundModalDonation', 'getRefundInvoice', Action::DELETE])
->setPermission(Action::NEW, Constant::ADMIN_ROLE)
->setPermission($refundDonation, Constant::ROLE_FINANCE)
->setPermission($partialRefundDonation, Constant::ROLE_FINANCE)
->setPermission($refundModalDonation, Constant::ROLE_FINANCE)
->setPermission($partialRefundModalDonation, Constant::ROLE_FINANCE)
->setPermission($getRefundInvoice, Constant::ROLE_FINANCE)
->setPermission($exportBatchDonations, Constant::ROLE_FINANCE)
->setPermission(Action::EDIT, Constant::ADMIN_ROLE)
->setPermission(Action::DELETE, Constant::ROLE_FINANCE)
->setPermission(Action::BATCH_DELETE, Constant::ROLE_FINANCE)
->setPermission($sendInvoiceBatch, Constant::ADMIN_ROLE)
;
}
public function configureFilters(Filters $filters): Filters
{
return $filters
->add(DonationDateFilter::new('modifiedAt'))
->add(BooleanFilter::new('isDonationEmail', 'Donation Email required to donor'))
->add(BooleanFilter::new('isOrganisationConsent', 'Consent to display Organisation on project page'))
->add(BooleanFilter::new('isContactShared', 'Consent to share contact details with filmmaker'))
->add(BooleanFilter::new('isNameApproved', 'Consent name to be listed in relevant project credits'))
->add(OrderDetailsTotalFilter::new('orderDetails', 'Total'))
// ->add(OrderDetailsStatusFilter::new('orderDetails', 'Payment Status'))
;
}
// Custom Actions
public function appearAsAnonymous(AdminContext $context): Response
{
$entityInstance = $context->getEntity()->getInstance();
$this->donationService->appearAsAnonymous($entityInstance);
$this->addFlash('Success', 'This donation is now appearing as anonymous on project page.' );
$donationIndexUrl = $this->adminUrlGenerator->setController(DonationCrudController::class)
->setAction(Action::INDEX)
->generateUrl();
return new RedirectResponse($donationIndexUrl);
}
public function appearAsOrganisation(AdminContext $context): Response
{
$entityInstance = $context->getEntity()->getInstance();
$this->donationService->appearAsNonAnonymous($entityInstance);
$this->addFlash('Success', 'This donation is now appearing as organisation on project page.' );
$donationIndexUrl = $this->adminUrlGenerator->setController(DonationCrudController::class)
->setAction(Action::INDEX)
->generateUrl();
return new RedirectResponse($donationIndexUrl);
}
public function setAmountInvisible(AdminContext $context): Response
{
$entityInstance = $context->getEntity()->getInstance();
$this->donationService->setAmountVisibility($entityInstance, true);
$this->addFlash('Success', 'This donation amount is now invisible on project page.' );
$donationIndexUrl = $this->adminUrlGenerator->setController(DonationCrudController::class)
->setAction(Action::INDEX)
->generateUrl();
return new RedirectResponse($donationIndexUrl);
}
public function setAmountVisible(AdminContext $context): Response
{
$entityInstance = $context->getEntity()->getInstance();
$this->donationService->setAmountVisibility($entityInstance, false);
$this->addFlash('Success', 'This donation amount is now visible on project page.' );
$donationIndexUrl = $this->adminUrlGenerator->setController(DonationCrudController::class)
->setAction(Action::INDEX)
->generateUrl();
return new RedirectResponse($donationIndexUrl);
}
public function viewInvoice(AdminContext $context): Response
{
$entityInstance = $context->getEntity()->getInstance();
$orderDetails = $entityInstance->getOrderDetails();
$xeroId = $orderDetails->getXeroId();
return $this->redirectToRoute('app_view_custom_invoice', ['invoiceId' => $xeroId]);
}
public function downloadInvoice(AdminContext $context): Response
{
$entityInstance = $context->getEntity()->getInstance();
$orderDetails = $entityInstance->getOrderDetails();
$xeroId = $orderDetails->getXeroId();
return $this->redirectToRoute('app_xero_invoice', ['invoiceId' => $xeroId]);
}
public function sendInvoice(AdminContext $context, DonationService $donationService): Response
{
$entityInstance = $context->getEntity()->getInstance();
$orderDetails = $entityInstance->getOrderDetails();
$donationService->sendInvoice($entityInstance);
$donationIndexUrl = $this->adminUrlGenerator->setController(DonationCrudController::class)
->setAction(Action::INDEX)
->generateUrl();
$this->addFlash('Success', 'Receipt MW'. $orderDetails->getId() .' has been sent to its recipient.' );
return new RedirectResponse($donationIndexUrl);
}
public function sendInvoiceBatch(BatchActionDto $batchActionDto, DonationService $donationService): Response
{
$className = $batchActionDto->getEntityFqcn();
$entityManager = $this->container->get('doctrine')->getManagerForClass($className);
foreach ($batchActionDto->getEntityIds() as $id) {
$entityInstance = $entityManager->find($className, $id);
$orderDetails = $entityInstance->getOrderDetails();
$donationService->sendInvoice($entityInstance);
}
$this->addFlash('Success', 'Receipt MW'. $orderDetails->getId() .' has been sent to its recipient.' );
return $this->redirect($batchActionDto->getReferrerUrl());
}
/**
* Generates invoice through custom pdf exporter
*/
public function generateCustomInvoice(AdminContext $context, Environment $twig = null, Pdf $pdf)
{
$donation = $context->getEntity()->getInstance();
$orderDetails = $donation->getOrderDetails();
$pdfExporter = new PdfExporter($twig, $pdf);
$pdfExporter->convertDonationReceiptPdf($orderDetails);
}
public function refundDonation(AdminContext $context): Response
{
$entityInstance = $context->getEntity()->getInstance();
$this->donationService->refundDonation($entityInstance);
$orderDetails = $entityInstance->getOrderDetails();
$donationIndexUrl = $this->adminUrlGenerator->setController(DonationCrudController::class)
->setAction(Action::INDEX)
->generateUrl();
$this->addFlash('success', 'Donation '. $orderDetails->getInvoiceNumber() .' has been refunded.');
return new RedirectResponse($donationIndexUrl);
}
public function partialRefundDonation(AdminContext $context): Response
{
$entityInstance = $context->getEntity()->getInstance();
$this->donationService->partialRefundDonation($entityInstance);
$orderDetails = $entityInstance->getOrderDetails();
$donationIndexUrl = $this->adminUrlGenerator->setController(DonationCrudController::class)
->setAction(Action::INDEX)
->generateUrl();
$this->addFlash('success', 'Donation '. $orderDetails->getInvoiceNumber() .' has been refunded.');
return new RedirectResponse($donationIndexUrl);
}
public function getRefundInvoice(AdminContext $context): Response
{
$entityInstance = $context->getEntity()->getInstance();
$orderDetails = $entityInstance->getOrderDetails();
$xeroId = $orderDetails->getRefundXeroId();
return $this->redirectToRoute('app_xero_refund_invoice', ['invoiceId' => $xeroId]);
}
public function exportBatchDonations(AdminContext $context, MessageBusInterface $messageBus)
{
$fields = FieldCollection::new($this->configureFields(Crud::PAGE_INDEX));
$filters = $this->container->get(FilterFactory::class)->create($context->getCrud()->getFiltersConfig(), $fields, $context->getEntity());
$donations = $this->createIndexQueryBuilder($context->getSearch(), $context->getEntity(), $fields, $filters)
->getQuery()
->getResult();
;
$message = new ExportDonation($donations);
$messageBus->dispatch($message);
}
}