443 lines
16 KiB
PHP
443 lines
16 KiB
PHP
<?php
|
|
|
|
namespace App\Controller;
|
|
|
|
use App\Core\Controller\Admin\Crud\CrudController;
|
|
use App\Core\Crud\CrudConfiguration;
|
|
use App\Core\Crud\Field;
|
|
use App\Core\Entity\EntityInterface;
|
|
use App\Core\Form\FileUploadHandler;
|
|
use App\Core\Manager\EntityManager;
|
|
use App\Entity\ExpenseReport as Entity;
|
|
use App\Event\EntityManagerEvent;
|
|
use App\Factory\ExpenseReportFactory as Factory;
|
|
use App\Form\ExpenseReportType as Type;
|
|
use App\Repository\ExpenseReportRepositoryQuery as RepositoryQuery;
|
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
|
use Symfony\Component\Filesystem\Filesystem;
|
|
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
|
use Symfony\Component\Form\FormInterface;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\HttpFoundation\Session\Session;
|
|
use Symfony\Component\Routing\Annotation\Route;
|
|
|
|
class ExpenseReportAdminController extends CrudController
|
|
{
|
|
protected FileUploadHandler $fileUpload;
|
|
protected Filesystem $fs;
|
|
|
|
public function __construct(FileUploadHandler $fileUpload, Filesystem $fs)
|
|
{
|
|
$this->fileUpload = $fileUpload;
|
|
$this->fs = $fs;
|
|
}
|
|
|
|
#[Route(path: '/admin/expense_report/{page}', name: 'admin_expense_report_index', methods: ['GET'], requirements: ['page' => '\d+'])]
|
|
public function index(RepositoryQuery $query, Request $request, Session $session, int $page = 1): Response
|
|
{
|
|
if (!$this->isGranted('ROLE_TREASURER')) {
|
|
$query->filterByUser($this->getUser());
|
|
}
|
|
|
|
return $this->doIndex($page, $query, $request, $session);
|
|
}
|
|
|
|
#[Route(path: '/admin/expense_report/new', name: 'admin_expense_report_new', methods: ['GET', 'POST'])]
|
|
public function new(Factory $factory, EntityManager $entityManager, Request $request): Response
|
|
{
|
|
return $this->doNew($factory->create($this->getUser()), $entityManager, $request);
|
|
}
|
|
|
|
#[Route(path: '/admin/expense_report/show/{entity}', name: 'admin_expense_report_show', methods: ['GET'])]
|
|
public function show(Entity $entity): Response
|
|
{
|
|
if (!$this->isGranted('ROLE_TREASURER')) {
|
|
if ($entity->getUser()->getId() !== $this->getUser()->getId()) {
|
|
throw $this->createAccessDeniedException();
|
|
}
|
|
}
|
|
|
|
return $this->doShow($entity);
|
|
}
|
|
|
|
#[Route(path: '/admin/expense_report/filter', name: 'admin_expense_report_filter', methods: ['GET'])]
|
|
public function filter(Session $session): Response
|
|
{
|
|
return $this->doFilter($session);
|
|
}
|
|
|
|
#[Route(path: '/admin/expense_report/edit/{entity}', name: 'admin_expense_report_edit', methods: ['GET', 'POST'])]
|
|
public function edit(Entity $entity, EntityManager $entityManager, Request $request): Response
|
|
{
|
|
if (!$this->isGranted('ROLE_TREASURER')) {
|
|
if ($entity->getUser()->getId() !== $this->getUser()->getId()) {
|
|
throw $this->createAccessDeniedException();
|
|
}
|
|
|
|
if ($entity->getIsRequestedPayment()) {
|
|
return $this->redirectToRoute('admin_expense_report_show', [
|
|
'entity' => $entity->getId(),
|
|
]);
|
|
}
|
|
}
|
|
|
|
if (!$entity->getIsRequestedPayment()) {
|
|
$form = $this->createFormBuilder()
|
|
->add('message', TextareaType::class, [
|
|
'required' => false,
|
|
'label' => 'Message',
|
|
'help' => 'Message à ajouter dans le mail de notification (optionnel)',
|
|
])
|
|
->getForm()
|
|
->createView()
|
|
;
|
|
|
|
$route = 'admin_expense_report_request_payment';
|
|
$tokenName = 'request_payment';
|
|
} elseif ($entity->getIsRequestedPayment() && !$entity->getIsPaid()) {
|
|
$form = $this->createFormBuilder()
|
|
->add('message', TextareaType::class, [
|
|
'required' => false,
|
|
'label' => 'Message',
|
|
'help' => 'Message à ajouter dans le mail de notification (optionnel)',
|
|
])
|
|
->getForm()
|
|
->createView()
|
|
;
|
|
|
|
$route = 'admin_expense_report_paid';
|
|
$tokenName = 'paid';
|
|
|
|
$form2 = $this->createFormBuilder()
|
|
->add('message', TextareaType::class, [
|
|
'required' => false,
|
|
'label' => 'Message',
|
|
'help' => 'Message à ajouter dans le mail de notification (optionnel)',
|
|
])
|
|
->getForm()
|
|
->createView()
|
|
;
|
|
|
|
$route2 = 'admin_expense_report_missing_proofs';
|
|
$tokenName2 = 'missingProofs';
|
|
}
|
|
|
|
if (isset($form)) {
|
|
$this->getConfiguration()
|
|
->addViewData('edit', 'mailFormRoute', $route)
|
|
->addViewData('edit', 'mailFormTokenName', $tokenName)
|
|
->addViewData('edit', 'mailForm', $form)
|
|
;
|
|
}
|
|
|
|
if (isset($form2)) {
|
|
$this->getConfiguration()
|
|
->addViewData('edit', 'mail2FormRoute', $route2)
|
|
->addViewData('edit', 'mail2FormTokenName', $tokenName2)
|
|
->addViewData('edit', 'mail2Form', $form2)
|
|
;
|
|
}
|
|
|
|
return $this->doEdit($entity, $entityManager, $request, [$this, 'beforeUpdate']);
|
|
}
|
|
|
|
#[Route(path: '/admin/expense_report/request_payment/{entity}/{token}', name: 'admin_expense_report_request_payment', methods: ['POST'])]
|
|
public function requestPayment(
|
|
Entity $entity,
|
|
string $token,
|
|
EntityManager $entityManager,
|
|
Request $request,
|
|
EventDispatcherInterface $eventDispatcher
|
|
): Response {
|
|
if (!$this->isGranted('ROLE_TREASURER')) {
|
|
if ($entity->getUser()->getId() !== $entity->getUser()->getId()) {
|
|
throw $this->createAccessDeniedException();
|
|
}
|
|
}
|
|
|
|
if (!$this->isCsrfTokenValid('request_payment', $token)) {
|
|
throw $this->createAccessDeniedException();
|
|
}
|
|
|
|
if ($entity->getTotalAmount() === 0.0) {
|
|
$this->addFlash('warning', 'Cette action est interdite car le total de la note de frais est 0.');
|
|
|
|
return $this->redirectToRoute('admin_expense_report_edit', [
|
|
'entity' => $entity->getId(),
|
|
]);
|
|
}
|
|
|
|
$message = $request->request->get('form')['message'] ?? null;
|
|
$entity->setIsRequestedPayment(true);
|
|
$entityManager->update($entity);
|
|
|
|
$eventDispatcher->dispatch(new EntityManagerEvent($entity, [
|
|
'message' => $message,
|
|
'user' => $this->getUser(),
|
|
]), 'expense_report.requested_payment');
|
|
|
|
$this->addFlash('success', 'La demande a été envoyée.');
|
|
|
|
return $this->redirectToRoute('admin_expense_report_show', [
|
|
'entity' => $entity->getId(),
|
|
]);
|
|
}
|
|
|
|
#[Route(path: '/admin/expense_report/paid/{entity}/{token}', name: 'admin_expense_report_paid', methods: ['POST'])]
|
|
public function paid(
|
|
Entity $entity,
|
|
string $token,
|
|
EntityManager $entityManager,
|
|
Request $request,
|
|
EventDispatcherInterface $eventDispatcher
|
|
): Response {
|
|
if (!$this->isGranted('ROLE_TREASURER')) {
|
|
throw $this->createAccessDeniedException();
|
|
}
|
|
|
|
if (!$this->isCsrfTokenValid('paid', $token)) {
|
|
throw $this->createAccessDeniedException();
|
|
}
|
|
|
|
if ($entity->getTotalAmount() === 0.0) {
|
|
$this->addFlash('warning', 'Cette action est interdite car le total de la note de frais est 0.');
|
|
|
|
return $this->redirectToRoute('admin_expense_report_edit', [
|
|
'entity' => $entity->getId(),
|
|
]);
|
|
}
|
|
|
|
$message = $request->request->get('form')['message'] ?? null;
|
|
$entity->setIsPaid(true);
|
|
|
|
if (!$entity->getPaidAt()) {
|
|
$entity->setPaidAt(new \DateTime());
|
|
}
|
|
|
|
$entityManager->update($entity);
|
|
|
|
$eventDispatcher->dispatch(new EntityManagerEvent($entity, [
|
|
'message' => $message,
|
|
'user' => $this->getUser(),
|
|
]), 'expense_report.paid');
|
|
|
|
$this->addFlash('success', 'The data has been saved.');
|
|
|
|
return $this->redirectToRoute('admin_expense_report_show', [
|
|
'entity' => $entity->getId(),
|
|
]);
|
|
}
|
|
|
|
#[Route(path: '/admin/expense_report/missing_proofs/{entity}/{token}', name: 'admin_expense_report_missing_proofs', methods: ['POST'])]
|
|
public function missingProofs(
|
|
Entity $entity,
|
|
string $token,
|
|
EntityManager $entityManager,
|
|
Request $request,
|
|
EventDispatcherInterface $eventDispatcher
|
|
): Response {
|
|
if (!$this->isGranted('ROLE_TREASURER')) {
|
|
throw $this->createAccessDeniedException();
|
|
}
|
|
|
|
if (!$this->isCsrfTokenValid('missingProofs', $token)) {
|
|
throw $this->createAccessDeniedException();
|
|
}
|
|
|
|
$message = $request->request->get('form')['message'] ?? null;
|
|
$entity->setIsRequestedPayment(false);
|
|
|
|
$entityManager->update($entity);
|
|
|
|
$eventDispatcher->dispatch(new EntityManagerEvent($entity, [
|
|
'message' => $message,
|
|
'user' => $this->getUser(),
|
|
]), 'expense_report.missing_proofs');
|
|
|
|
$this->addFlash('success', 'The data has been saved.');
|
|
|
|
return $this->redirectToRoute('admin_expense_report_edit', [
|
|
'entity' => $entity->getId(),
|
|
]);
|
|
}
|
|
|
|
protected function beforeUpdate(EntityInterface $entity, FormInterface $form, Request $request)
|
|
{
|
|
$deleteBills = $request->request->get($form->getName())['deleteBills']['bills'] ?? [];
|
|
$bills = $entity->getBills();
|
|
|
|
foreach ($bills as $key => $value) {
|
|
if (in_array($value, $deleteBills)) {
|
|
unset($bills[$key]);
|
|
$this->fs->remove($value);
|
|
}
|
|
}
|
|
|
|
$directory = sprintf(
|
|
'uploads/Notes de frais/%d/%d',
|
|
$this->getUser()->getId(),
|
|
$entity->getId()
|
|
);
|
|
|
|
$newBills = $request->files->get($form->getName())['newBills'] ?? [];
|
|
|
|
foreach ($newBills as $data) {
|
|
$this->fileUpload->handleForm(
|
|
$data['file'],
|
|
$directory,
|
|
function ($filename) use ($directory, &$bills) {
|
|
$bills[] = $directory.'/'.$filename;
|
|
},
|
|
true
|
|
);
|
|
}
|
|
|
|
$entity->setBills($bills);
|
|
}
|
|
|
|
#[Route(path: '/admin/expense_report/sort/{page}', name: 'admin_expense_report_sort', methods: ['POST'], requirements: ['page' => '\d+'])]
|
|
public function sort(RepositoryQuery $query, EntityManager $entityManager, Request $request, Session $session, int $page = 1): Response
|
|
{
|
|
return $this->doSort($page, $query, $entityManager, $request, $session);
|
|
}
|
|
|
|
#[Route(path: '/admin/expense_report/batch/{page}', name: 'admin_expense_report_batch', methods: ['POST'], requirements: ['page' => '\d+'])]
|
|
public function batch(RepositoryQuery $query, EntityManager $entityManager, Request $request, Session $session, int $page = 1): Response
|
|
{
|
|
if (!$this->isGranted('ROLE_TREASURER')) {
|
|
$query->filterByUser($this->getUser());
|
|
}
|
|
|
|
return $this->doBatch($page, $query, $entityManager, $request, $session);
|
|
}
|
|
|
|
#[Route(path: '/admin/expense_report/delete/{entity}', name: 'admin_expense_report_delete', methods: ['DELETE'])]
|
|
public function delete(Entity $entity, EntityManager $entityManager, Request $request): Response
|
|
{
|
|
if (!$this->isGranted('ROLE_TREASURER')) {
|
|
if ($entity->getUser()->getId() !== $entity->getUser()->getId()) {
|
|
throw $this->createAccessDeniedException();
|
|
}
|
|
}
|
|
|
|
return $this->doDelete($entity, $entityManager, $request);
|
|
}
|
|
|
|
protected function getConfiguration(): CrudConfiguration
|
|
{
|
|
return CrudConfiguration::create()
|
|
->setPageTitle('index', 'Notes de frais')
|
|
->setPageTitle('edit', 'NDF #{id} de {user.displayName}')
|
|
->setPageTitle('new', 'Nouvelle note de frais')
|
|
->setPageTitle('show', 'NDF #{id} de {user.displayName}')
|
|
|
|
->setPageRoute('index', 'admin_expense_report_index')
|
|
->setPageRoute('new', 'admin_expense_report_new')
|
|
->setPageRoute('edit', 'admin_expense_report_edit')
|
|
->setPageRoute('show', 'admin_expense_report_show')
|
|
->setPageRoute('sort', 'admin_expense_report_sort')
|
|
->setPageRoute('batch', 'admin_expense_report_batch')
|
|
->setPageRoute('delete', 'admin_expense_report_delete')
|
|
->setPageRoute('filter', 'admin_expense_report_filter')
|
|
->setPageRoute('requestPayment', 'admin_expense_report_request_payment')
|
|
->setPageRoute('paid', 'admin_expense_report_paid')
|
|
|
|
->setFormOptions('new', [
|
|
'is_treasurer' => $this->isGranted('ROLE_TREASURER'),
|
|
])
|
|
->setFormOptions('edit', [
|
|
'is_treasurer' => $this->isGranted('ROLE_TREASURER'),
|
|
])
|
|
->setView('form', 'admin/expense_report/_form.html.twig')
|
|
->setView('show_entity', 'admin/expense_report/_show.html.twig')
|
|
->setView('edit', 'admin/expense_report/edit.html.twig')
|
|
->setView('show', 'admin/expense_report/show.html.twig')
|
|
|
|
->setForm('edit', Type::class, [])
|
|
->setForm('new', Type::class)
|
|
// ->setForm('filter', Type::class)
|
|
|
|
->setAction('index', 'edit', function (EntityInterface $entity) {
|
|
if ($entity->getIsRequestedPayment() && !$this->isGranted('ROLE_TREASURER')) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
})
|
|
->setAction('index', 'delete', function (EntityInterface $entity) {
|
|
if ($entity->getIsPaid() && !$this->isGranted('ROLE_TREASURER')) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
})
|
|
|
|
->setAction('show', 'edit', function (EntityInterface $entity) {
|
|
if ($entity->getIsRequestedPayment() && !$this->isGranted('ROLE_TREASURER')) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
})
|
|
->setDefaultSort('index', 'dateTo', 'desc')
|
|
|
|
->setField('index', 'Personne', Field\TextField::class, [
|
|
'property_builder' => function (EntityInterface $entity) {
|
|
return $entity->getUser()->getDisplayName();
|
|
},
|
|
'attr' => ['class' => 'col-md-3'],
|
|
])
|
|
->setField('index', 'Date from', Field\DateField::class, [
|
|
'property' => 'dateFrom',
|
|
'sort' => ['dateFrom', '.dateFrom'],
|
|
'format' => 'd/m/Y',
|
|
'attr' => ['class' => 'col-md-3'],
|
|
])
|
|
->setField('index', 'Date to', Field\DateField::class, [
|
|
'property' => 'dateTo',
|
|
'sort' => ['dateTo', '.dateTo'],
|
|
'format' => 'd/m/Y',
|
|
'attr' => ['class' => 'col-md-3'],
|
|
])
|
|
->setField('index', 'Statut', Field\ButtonField::class, [
|
|
'property_builder' => function (EntityInterface $entity) {
|
|
if ($entity->getIsPaid()) {
|
|
return 'Payée';
|
|
}
|
|
|
|
if ($entity->getIsRequestedPayment()) {
|
|
return 'En attente de paiement';
|
|
}
|
|
|
|
return 'Brouillon';
|
|
},
|
|
'attr' => ['class' => 'col-md-3'],
|
|
'button_attr_builder' => function (EntityInterface $entity) {
|
|
$class = 'light';
|
|
|
|
if ($entity->getIsPaid()) {
|
|
$class = 'success';
|
|
} elseif ($entity->getIsRequestedPayment()) {
|
|
$class = 'warning';
|
|
}
|
|
|
|
return ['class' => 'btn btn-sm btn-'.$class];
|
|
},
|
|
])
|
|
->setBatchAction('index', 'delete', 'Delete', function (EntityInterface $entity, EntityManager $manager) {
|
|
if ($entity->getIsPaid() && !$this->isGranted('ROLE_TREASURER')) {
|
|
return;
|
|
}
|
|
|
|
$manager->delete($entity);
|
|
})
|
|
;
|
|
}
|
|
|
|
protected function getSection(): string
|
|
{
|
|
return 'expense_report';
|
|
}
|
|
}
|