namespace Lc\SovBundle\Builder\Ticket; | namespace Lc\SovBundle\Builder\Ticket; | ||||
use Doctrine\ORM\EntityManagerInterface; | use Doctrine\ORM\EntityManagerInterface; | ||||
use Lc\SovBundle\Event\Ticket\TicketEvent; | |||||
use Lc\SovBundle\Notification\MailMailjetNotification; | use Lc\SovBundle\Notification\MailMailjetNotification; | ||||
use Lc\SovBundle\Component\FormComponent; | use Lc\SovBundle\Component\FormComponent; | ||||
use Lc\SovBundle\Factory\Ticket\TicketFactory; | use Lc\SovBundle\Factory\Ticket\TicketFactory; | ||||
use Lc\SovBundle\Model\Ticket\TicketModel; | use Lc\SovBundle\Model\Ticket\TicketModel; | ||||
use Lc\SovBundle\Repository\User\UserStore; | use Lc\SovBundle\Repository\User\UserStore; | ||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; | use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; | ||||
use Symfony\Component\EventDispatcher\EventDispatcher; | |||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface; | |||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; | use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; | ||||
use Symfony\Component\Security\Core\Security; | use Symfony\Component\Security\Core\Security; | ||||
protected TicketFactory $ticketFactory; | protected TicketFactory $ticketFactory; | ||||
protected AuthorizationCheckerInterface $authorizationChecker; | protected AuthorizationCheckerInterface $authorizationChecker; | ||||
protected UserStore $userStore; | protected UserStore $userStore; | ||||
protected EventDispatcherInterface $eventDispatcher; | |||||
public function __construct( | public function __construct( | ||||
Security $security, | Security $security, | ||||
ParameterBagInterface $parameterBag, | ParameterBagInterface $parameterBag, | ||||
AuthorizationCheckerInterface $authorizationChecker, | AuthorizationCheckerInterface $authorizationChecker, | ||||
TicketFactory $ticketFactory, | TicketFactory $ticketFactory, | ||||
UserStore $userStore | |||||
UserStore $userStore, | |||||
EventDispatcherInterface $eventDispatcher | |||||
) { | ) { | ||||
$this->security = $security; | $this->security = $security; | ||||
$this->entityManager = $entityManager; | $this->entityManager = $entityManager; | ||||
$this->ticketFactory = $ticketFactory; | $this->ticketFactory = $ticketFactory; | ||||
$this->userStore = $userStore; | $this->userStore = $userStore; | ||||
$this->authorizationChecker = $authorizationChecker; | $this->authorizationChecker = $authorizationChecker; | ||||
$this->eventDispatcher = $eventDispatcher; | |||||
} | } | ||||
public function create(array $params = []): TicketInterface | public function create(array $params = []): TicketInterface | ||||
$this->init($ticket, $params); | $this->init($ticket, $params); | ||||
$user = $ticket->getUser(); | |||||
if ($ticket->getUser()) { | |||||
$email = $user->getEmail(); | |||||
$firstname = $user->getFirstname(); | |||||
} else { | |||||
$email = $params['visitorEmail']; | |||||
$firstname = $params['visitorFirstname']; | |||||
} | |||||
$this->entityManager->create($ticket); | $this->entityManager->create($ticket); | ||||
$this->entityManager->flush(); | $this->entityManager->flush(); | ||||
if (isset($params['createByAdmin']) && $params['createByAdmin']) { | |||||
// envoi email au client | |||||
$this->mailMailjetNotification->send( | |||||
[ | |||||
MailMailjetNotification::SUBJECT => 'Vous avez reçu un nouveau message', | |||||
MailMailjetNotification::TO_EMAIL => $email, | |||||
MailMailjetNotification::CONTENT_TEMPLATE => 'mail/ticket-new-by-admin', | |||||
MailMailjetNotification::CONTENT_DATA => [ | |||||
'firstname' => $firstname, | |||||
'ticket' => $ticket, | |||||
], | |||||
] | |||||
); | |||||
} else { | |||||
$this->mailMailjetNotification->send( | |||||
[ | |||||
MailMailjetNotification::SUBJECT => 'Nouvelle demande', | |||||
MailMailjetNotification::TO_EMAIL => $email, | |||||
MailMailjetNotification::CONTENT_TEMPLATE => 'mail/ticket-new', | |||||
MailMailjetNotification::CONTENT_DATA => [ | |||||
'firstname' => $firstname, | |||||
'ticket' => $ticket, | |||||
], | |||||
] | |||||
); | |||||
} | |||||
// notifyAdmin | |||||
$usersToNotify = $this->userStore->getByTicketTypesNotification($ticket->getType()); | |||||
foreach ($usersToNotify as $userToNotify) { | |||||
if ($this->authorizationChecker->isGranted('ROLE_ADMIN', $userToNotify)) { | |||||
$this->mailMailjetNotification->send( | |||||
[ | |||||
MailMailjetNotification::SUBJECT => 'Nouveau ticket sur Place du Local', | |||||
MailMailjetNotification::TO_EMAIL => $userToNotify->getEmail(), | |||||
MailMailjetNotification::CONTENT_TEMPLATE => 'mail/ticket-notification', | |||||
MailMailjetNotification::CONTENT_DATA => [ | |||||
'firstname' => $userToNotify->getFirstname(), | |||||
'ticket' => $ticket, | |||||
'ticketMessage' => $ticket->getTicketMessages()[0], | |||||
], | |||||
] | |||||
); | |||||
} | |||||
} | |||||
$this->eventDispatcher->dispatch(new TicketEvent($ticket), TicketEvent::NEW_TICKET_EVENT); | |||||
return $ticket; | return $ticket; | ||||
} | } | ||||
public function init(TicketInterface $ticket, array $params = []): void | public function init(TicketInterface $ticket, array $params = []): void | ||||
{ | { | ||||
$user = $this->security->getUser(); | $user = $this->security->getUser(); | ||||
if($user) { | |||||
if ($user) { | |||||
$ticket->setCreatedBy($user); | $ticket->setCreatedBy($user); | ||||
} | } | ||||
if (isset($params['section'])) { | |||||
$ticket->setSection($params['section']); | |||||
} | |||||
$ticket->setMerchant($params['merchant']); | |||||
if (isset($params['user'])) { | if (isset($params['user'])) { | ||||
$ticket->setUser($params['user']); | $ticket->setUser($params['user']); | ||||
} else { | } else { | ||||
$ticket->setVisitorFirstname($params['visitorFirstname']); | $ticket->setVisitorFirstname($params['visitorFirstname']); | ||||
$ticket->setVisitorLastname($params['visitorLastname']); | $ticket->setVisitorLastname($params['visitorLastname']); |
namespace Lc\SovBundle\Builder\Ticket; | namespace Lc\SovBundle\Builder\Ticket; | ||||
use Doctrine\ORM\EntityManagerInterface; | use Doctrine\ORM\EntityManagerInterface; | ||||
use Lc\SovBundle\Event\Ticket\TicketEvent; | |||||
use Lc\SovBundle\Notification\MailMailjetNotification; | use Lc\SovBundle\Notification\MailMailjetNotification; | ||||
use Lc\SovBundle\Component\FormComponent; | use Lc\SovBundle\Component\FormComponent; | ||||
use Lc\SovBundle\Factory\Ticket\TicketFactory; | use Lc\SovBundle\Factory\Ticket\TicketFactory; | ||||
use Lc\SovBundle\Model\Ticket\TicketMessageInterface; | use Lc\SovBundle\Model\Ticket\TicketMessageInterface; | ||||
use Lc\SovBundle\Model\Ticket\TicketModel; | use Lc\SovBundle\Model\Ticket\TicketModel; | ||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; | use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; | ||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface; | |||||
class TicketMessageBuilder | class TicketMessageBuilder | ||||
{ | { | ||||
protected EntityManagerInterface $entityManager; | protected EntityManagerInterface $entityManager; | ||||
protected MailMailjetNotification $mailMailjetNotification; | protected MailMailjetNotification $mailMailjetNotification; | ||||
protected TicketMessageFactory $ticketMessageFactory; | protected TicketMessageFactory $ticketMessageFactory; | ||||
protected EventDispatcherInterface $eventDispatcher; | |||||
public function __construct( | public function __construct( | ||||
EntityManagerInterface $entityManager, | EntityManagerInterface $entityManager, | ||||
MailMailjetNotification $mailMailjetNotification, | MailMailjetNotification $mailMailjetNotification, | ||||
TicketMessageFactory $ticketMessageFactory | |||||
TicketMessageFactory $ticketMessageFactory, | |||||
EventDispatcherInterface $eventDispatcher | |||||
) { | ) { | ||||
$this->entityManager = $entityManager; | $this->entityManager = $entityManager; | ||||
$this->mailMailjetNotification = $mailMailjetNotification; | $this->mailMailjetNotification = $mailMailjetNotification; | ||||
$this->ticketMessageFactory = $ticketMessageFactory; | $this->ticketMessageFactory = $ticketMessageFactory; | ||||
$this->eventDispatcher = $eventDispatcher; | |||||
} | } | ||||
public function create(array $params = []): TicketMessageInterface | public function create(array $params = []): TicketMessageInterface | ||||
$ticketMessage->setStatus(1); | $ticketMessage->setStatus(1); | ||||
$ticketMessage->setTicket($ticket); | $ticketMessage->setTicket($ticket); | ||||
$ticketMessage->setMessage($params['message']); | $ticketMessage->setMessage($params['message']); | ||||
if (isset($params['answerByAdmin']) && $params['answerByAdmin']) { | if (isset($params['answerByAdmin']) && $params['answerByAdmin']) { | ||||
$ticketMessage->setAnswerByAdmin($params['answerByAdmin']); | $ticketMessage->setAnswerByAdmin($params['answerByAdmin']); | ||||
// envoi email au client | |||||
$this->mailMailjetNotification->send( | |||||
[ | |||||
MailMailjetNotification::SUBJECT => 'Réponse à votre demande', | |||||
MailMailjetNotification::TO_EMAIL => $ticket->getUser() ? $ticket->getUser()->getEmail( | |||||
) : $ticket->getVisitorEmail(), | |||||
MailMailjetNotification::CONTENT_TEMPLATE => 'mail/ticket-response', | |||||
MailMailjetNotification::CONTENT_DATA => [ | |||||
'firstname' => $ticket->getUser() ? $ticket->getUser()->getFirstname( | |||||
) : $ticket->getVisitorFirstname(), | |||||
'ticket' => $ticket, | |||||
], | |||||
] | |||||
); | |||||
} | } | ||||
$this->entityManager->persist($ticketMessage); | $this->entityManager->persist($ticketMessage); | ||||
$ticket->setUpdatedAt(new \DateTime()); | $ticket->setUpdatedAt(new \DateTime()); | ||||
$this->entityManager->persist($ticket); | |||||
$this->entityManager->create($ticket); | |||||
$this->entityManager->flush(); | $this->entityManager->flush(); | ||||
$this->eventDispatcher->dispatch(new TicketEvent($ticket), TicketEvent::NEW_MESSAGE_EVENT); | |||||
return $ticketMessage; | return $ticketMessage; | ||||
} | } | ||||
return $this->solver; | return $this->solver; | ||||
} | } | ||||
public function getFieldDefinition(): TicketFieldDefinition | public function getFieldDefinition(): TicketFieldDefinition | ||||
{ | { | ||||
return $this->fieldDefinition; | return $this->fieldDefinition; |
use Doctrine\ORM\EntityManagerInterface; | use Doctrine\ORM\EntityManagerInterface; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection; | use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection; | use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Config\Action; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; | use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Config\Assets; | use EasyCorp\Bundle\EasyAdminBundle\Config\Assets; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; | use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext; | use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto; | use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto; | use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\DateField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator; | use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator; | ||||
use Lc\SovBundle\Container\Ticket\TicketContainer; | |||||
use Lc\SovBundle\Container\Ticket\TicketMessageContainer; | use Lc\SovBundle\Container\Ticket\TicketMessageContainer; | ||||
use Lc\SovBundle\Definition\ActionDefinition; | use Lc\SovBundle\Definition\ActionDefinition; | ||||
use Lc\SovBundle\Factory\Ticket\TicketFactory; | |||||
use Lc\SovBundle\Factory\Ticket\TicketFactoryInterface; | |||||
use Lc\SovBundle\Factory\Ticket\TicketMessageFactory; | |||||
use Lc\SovBundle\Factory\Ticket\TicketMessageFactoryInterface; | |||||
use Lc\SovBundle\Form\Ticket\TicketAdminFormType; | |||||
use Lc\SovBundle\Form\Ticket\TicketFormType; | |||||
use Lc\SovBundle\Form\Ticket\TicketMessageFormType; | |||||
use Lc\SovBundle\Event\Ticket\TicketEvent; | |||||
use Lc\SovBundle\Form\Ticket\TicketMessageAdminFormType; | |||||
use Lc\SovBundle\Form\Ticket\TicketStatusType; | use Lc\SovBundle\Form\Ticket\TicketStatusType; | ||||
use Lc\SovBundle\Model\Ticket\TicketInterface; | |||||
use Lc\SovBundle\Controller\AbstractAdminController; | use Lc\SovBundle\Controller\AbstractAdminController; | ||||
use Lc\SovBundle\Model\Ticket\TicketModel; | use Lc\SovBundle\Model\Ticket\TicketModel; | ||||
use Lc\SovBundle\Repository\RepositoryQueryInterface; | use Lc\SovBundle\Repository\RepositoryQueryInterface; | ||||
use Lc\SovBundle\Translation\TranslatorAdmin; | |||||
use Symfony\Component\HttpFoundation\JsonResponse; | use Symfony\Component\HttpFoundation\JsonResponse; | ||||
use Symfony\Component\HttpFoundation\RequestStack; | use Symfony\Component\HttpFoundation\RequestStack; | ||||
abstract class TicketAdminController extends AbstractAdminController | abstract class TicketAdminController extends AbstractAdminController | ||||
{ | { | ||||
public function getRepositoryQuery() :RepositoryQueryInterface | |||||
public function getRepositoryQuery(): RepositoryQueryInterface | |||||
{ | { | ||||
return $this->getTicketContainer()->getRepositoryQuery(); | return $this->getTicketContainer()->getRepositoryQuery(); | ||||
} | } | ||||
public function createEntity(string $entityFqcn) | public function createEntity(string $entityFqcn) | ||||
{ | { | ||||
return $this->getTicketContainer()->getFactory()->create(); | |||||
$ticket = $this->getTicketContainer()->getFactory()->create(); | |||||
return $ticket; | |||||
} | |||||
public function persistEntity(EntityManagerInterface $entityManager, $entityInstance): void | |||||
{ | |||||
parent::persistEntity($entityManager, $entityInstance); | |||||
$this->getEventDispatcher()->dispatch(new TicketEvent($entityInstance), TicketEvent::NEW_TICKET_EVENT); | |||||
} | } | ||||
public function configureCrud(Crud $crud): Crud | public function configureCrud(Crud $crud): Crud | ||||
{ | { | ||||
$crud = parent::configureCrud($crud); // TODO: Change the autogenerated stub | |||||
$crud->setDefaultSort(array('updatedAt'=> 'DESC')); | |||||
$crud = parent::configureCrud($crud); // TODO: Change the autogenerated stub | |||||
$crud->setDefaultSort(array('updatedAt' => 'DESC')); | |||||
return $crud; | return $crud; | ||||
} | } | ||||
public function configureFields(string $pageName): iterable | |||||
{ | |||||
return $this->getTicketContainer()->getFieldDefinition()->getFields($pageName); | |||||
} | |||||
public function configureAssets(Assets $assets): Assets | public function configureAssets(Assets $assets): Assets | ||||
{ | { | ||||
$assets = parent::configureAssets($assets); | $assets = parent::configureAssets($assets); | ||||
return $assets; | return $assets; | ||||
} | } | ||||
public function configureFields(string $pageName): iterable | |||||
{ | |||||
return $this->getTicketContainer()->getFieldDefinition()->getFields($pageName); | |||||
} | |||||
public function configureActions(Actions $actions): Actions | public function configureActions(Actions $actions): Actions | ||||
{ | { | ||||
$actions | |||||
->add(Crud::PAGE_INDEX, ActionDefinition::DETAIL) | |||||
->remove(Crud::PAGE_INDEX, ActionDefinition::EDIT); | |||||
$actions->add(Crud::PAGE_INDEX, ActionDefinition::DETAIL); | |||||
$actions = parent::configureActions($actions); | |||||
$actions->disable( ActionDefinition::EDIT, ActionDefinition::DUPLICATE); | |||||
return $actions; | |||||
return parent::configureActions($actions); | |||||
} | } | ||||
public function createIndexRepositoryQuery( | public function createIndexRepositoryQuery( | ||||
$repositoryQuery->filterByStatus(array( | $repositoryQuery->filterByStatus(array( | ||||
TicketModel::TICKET_STATUS_OPEN, | TicketModel::TICKET_STATUS_OPEN, | ||||
TicketModel::TICKET_STATUS_BEING_PROCESSED | |||||
TicketModel::TICKET_STATUS_BEING_PROCESSED, | |||||
TicketModel::TICKET_STATUS_PROCESSED | |||||
)); | )); | ||||
} | } | ||||
return $repositoryQuery; | return $repositoryQuery; | ||||
} | } | ||||
public function new(AdminContext $context) | |||||
{ | |||||
$adminUrlGenerator = $this->get(AdminUrlGenerator::class); | |||||
$ticket = $this->createEntity($context->getEntity()->getFqcn()); | |||||
$form = $this->createForm(TicketAdminFormType::class, $ticket); | |||||
$form->handleRequest($context->getRequest()); | |||||
if ($form->isSubmitted() && $form->isValid()) { | |||||
$ticket = $form->getData(); | |||||
$this->get(EntityManagerInterface::class)->create($ticket); | |||||
$this->get(EntityManagerInterface::class)->flush(); | |||||
$url = $adminUrlGenerator | |||||
->setAction('index') | |||||
->generateUrl(); | |||||
return $this->redirect($url); | |||||
} | |||||
return $this->render( | |||||
'@LcSov/admin/ticket/new.html.twig', | |||||
[ | |||||
'form' => $form->createView(), | |||||
] | |||||
); | |||||
} | |||||
public function detail(AdminContext $context) | public function detail(AdminContext $context) | ||||
{ | { | ||||
$ticket = $context->getEntity()->getInstance(); | $ticket = $context->getEntity()->getInstance(); | ||||
$url = $adminUrlGenerator | $url = $adminUrlGenerator | ||||
->setAction('ticketStatusAction') | |||||
->generateUrl(); | |||||
->setAction('ticketStatusAction') | |||||
->generateUrl(); | |||||
$formTicketStatus = $this->createForm( | $formTicketStatus = $this->createForm( | ||||
TicketStatusType::class, | |||||
$ticket, | |||||
[ | |||||
'action' => $url, | |||||
'method' => 'POST', | |||||
] | |||||
TicketStatusType::class, | |||||
$ticket, | |||||
[ | |||||
'action' => $url, | |||||
'method' => 'POST', | |||||
] | |||||
); | ); | ||||
$ticketMessage = $this->get(TicketMessageContainer::class)->getFactory()->create($ticket); | $ticketMessage = $this->get(TicketMessageContainer::class)->getFactory()->create($ticket); | ||||
$formAddTicketMessage = $this->createForm(TicketMessageFormType::class, $ticketMessage); | |||||
$formAddTicketMessage = $this->createForm(TicketMessageAdminFormType::class, $ticketMessage); | |||||
$formAddTicketMessage->handleRequest($this->get(RequestStack::class)->getMainRequest()); | $formAddTicketMessage->handleRequest($this->get(RequestStack::class)->getMainRequest()); | ||||
if ($formAddTicketMessage->isSubmitted() && $formAddTicketMessage->isValid()) { | if ($formAddTicketMessage->isSubmitted() && $formAddTicketMessage->isValid()) { | ||||
$ticketMessage->setAnswerByAdmin(true); | $ticketMessage->setAnswerByAdmin(true); | ||||
$this->get(EntityManagerInterface::class)->create($ticketMessage); | $this->get(EntityManagerInterface::class)->create($ticketMessage); | ||||
$this->get(EntityManagerInterface::class)->flush(); | $this->get(EntityManagerInterface::class)->flush(); | ||||
$this->getEventDispatcher()->dispatch(new TicketEvent($ticket), TicketEvent::NEW_MESSAGE_EVENT); | |||||
return $this->redirect($this->generateEaUrl()); | |||||
} | } | ||||
return $this->render( | return $this->render( | ||||
'@LcSov/admin/ticket/detail.html.twig', | |||||
[ | |||||
'form_ticket_status' => $formTicketStatus->createView(), | |||||
'form_add_ticket_message' => $formAddTicketMessage->createView(), | |||||
'ticket' => $ticket, | |||||
] | |||||
'@LcSov/admin/ticket/detail.html.twig', | |||||
[ | |||||
'form_ticket_status' => $formTicketStatus->createView(), | |||||
'form_add_ticket_message' => $formAddTicketMessage->createView(), | |||||
'ticket' => $ticket, | |||||
] | |||||
); | ); | ||||
} | } | ||||
public function ticketStatusAction(AdminContext $context, EntityManagerInterface $entityManager) | public function ticketStatusAction(AdminContext $context, EntityManagerInterface $entityManager) | ||||
{ | { | ||||
$success = false; | $success = false; | ||||
if ($formTicketStatusForm->isSubmitted() && $formTicketStatusForm->isValid()) { | if ($formTicketStatusForm->isSubmitted() && $formTicketStatusForm->isValid()) { | ||||
$entityManager->update($ticket); | $entityManager->update($ticket); | ||||
$entityManager->flush(); | $entityManager->flush(); | ||||
$success = true; | $success = true; |
namespace Lc\SovBundle\Definition\Field\Ticket; | namespace Lc\SovBundle\Definition\Field\Ticket; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; | use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; | use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField; | use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField; | use EasyCorp\Bundle\EasyAdminBundle\Field\IdField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | ||||
use Lc\SovBundle\Definition\Field\AbstractFieldDefinition; | |||||
use Lc\SovBundle\Field\Filter\Ticket\EmailTicketFilter; | |||||
use Lc\SovBundle\Field\Filter\Ticket\FirstnameTicketFilter; | |||||
use Lc\SovBundle\Field\Filter\Ticket\LastnameTicketFilter; | |||||
use Lc\SovBundle\Field\Filter\Ticket\TicketEmailFilter; | |||||
use Lc\SovBundle\Field\Filter\Ticket\TicketFirstnameFilter; | |||||
use Lc\SovBundle\Field\Filter\Ticket\TicketLastnameFilter; | |||||
use Lc\SovBundle\Form\Ticket\TicketMessageAdminFormType; | |||||
use Lc\SovBundle\Solver\Ticket\TicketSolver; | use Lc\SovBundle\Solver\Ticket\TicketSolver; | ||||
use Lc\SovBundle\Definition\Field\AbstractFieldDefinition; | |||||
use Lc\SovBundle\Field\CollectionField; | |||||
use Lc\SovBundle\Form\Ticket\TicketMessageType; | |||||
use Lc\SovBundle\Translation\TranslatorAdmin; | |||||
class TicketFieldDefinition extends AbstractFieldDefinition | class TicketFieldDefinition extends AbstractFieldDefinition | ||||
{ | { | ||||
public function __construct(TranslatorAdmin $translatorAdmin) | |||||
{ | |||||
parent::__construct($translatorAdmin); | |||||
} | |||||
public function configureIndex(): array | public function configureIndex(): array | ||||
{ | { | ||||
{ | { | ||||
return [ | return [ | ||||
'user', | 'user', | ||||
'subject' | |||||
'type', | |||||
'subject', | |||||
'ticketMessages' | |||||
]; | ]; | ||||
} | } | ||||
->hideOnForm(), | ->hideOnForm(), | ||||
'visitorFirstname' => TextField::new('visitorFirstname') | 'visitorFirstname' => TextField::new('visitorFirstname') | ||||
->setTemplatePath('@LcSov/admin/ticket/field/firstname.html.twig') | ->setTemplatePath('@LcSov/admin/ticket/field/firstname.html.twig') | ||||
->setCustomOption('filter_fqcn', FirstnameTicketFilter::class) | |||||
->setCustomOption('filter_fqcn', TicketFirstnameFilter::class) | |||||
->setSortable(true) | ->setSortable(true) | ||||
->hideOnForm(), | ->hideOnForm(), | ||||
'visitorLastname' => TextField::new('visitorLastname') | 'visitorLastname' => TextField::new('visitorLastname') | ||||
->setTemplatePath('@LcSov/admin/ticket/field/lastname.html.twig') | ->setTemplatePath('@LcSov/admin/ticket/field/lastname.html.twig') | ||||
->setCustomOption('filter_fqcn', LastnameTicketFilter::class) | |||||
->setCustomOption('filter_fqcn', TicketLastnameFilter::class) | |||||
->setSortable(true) | ->setSortable(true) | ||||
->hideOnForm(), | ->hideOnForm(), | ||||
'visitorEmail' => TextField::new('visitorEmail') | 'visitorEmail' => TextField::new('visitorEmail') | ||||
->setTemplatePath('@LcSov/admin/ticket/field/email.html.twig') | ->setTemplatePath('@LcSov/admin/ticket/field/email.html.twig') | ||||
->setCustomOption('filter_fqcn', EmailTicketFilter::class) | |||||
->setCustomOption('filter_fqcn', TicketEmailFilter::class) | |||||
->setSortable(true) | ->setSortable(true) | ||||
->hideOnForm(), | ->hideOnForm(), | ||||
'user' => AssociationField::new('user') | 'user' => AssociationField::new('user') | ||||
'Ticket', | 'Ticket', | ||||
'status' | 'status' | ||||
) | ) | ||||
) | ) | ||||
->setTemplatePath('@LcSov/admin/ticket/field/status.html.twig') | |||||
->hideOnForm(), | |||||
->setTemplatePath('@LcSov/admin/ticket/field/status.html.twig'), | |||||
'ticketMessages' => CollectionField::new('ticketMessages') | |||||
->setFormTypeOption('entry_type', TicketMessageAdminFormType::class) | |||||
->setFormTypeOption('allow_add', false) | |||||
->setFormTypeOption('allow_delete', false) | |||||
]; | ]; | ||||
} | } | ||||
use Lc\CaracoleBundle\Field\AssociationField; | use Lc\CaracoleBundle\Field\AssociationField; | ||||
use Lc\SovBundle\Definition\Field\AbstractFieldDefinition; | use Lc\SovBundle\Definition\Field\AbstractFieldDefinition; | ||||
use Lc\SovBundle\Definition\RolesDefinition; | use Lc\SovBundle\Definition\RolesDefinition; | ||||
use Lc\SovBundle\Solver\Ticket\TicketSolver; | |||||
use Lc\SovBundle\Solver\User\UserSolver; | use Lc\SovBundle\Solver\User\UserSolver; | ||||
use Lc\SovBundle\Translation\TranslatorAdmin; | use Lc\SovBundle\Translation\TranslatorAdmin; | ||||
'email', | 'email', | ||||
'phone', | 'phone', | ||||
'birthdate', | 'birthdate', | ||||
'groupUsers' | |||||
'groupUsers', | |||||
'ticketTypesNotification' | |||||
]; | ]; | ||||
} | } | ||||
'phone' => TextField::new('phone')->setSortable(true), | 'phone' => TextField::new('phone')->setSortable(true), | ||||
'birthdate' => DateField::new('birthdate')->setSortable(true), | 'birthdate' => DateField::new('birthdate')->setSortable(true), | ||||
'groupUsers' => AssociationField::new('groupUsers')->setSortable(true), | 'groupUsers' => AssociationField::new('groupUsers')->setSortable(true), | ||||
'ticketTypesNotification' => ChoiceField::new('ticketTypesNotification') | |||||
->setSortable(true) | |||||
->setFormTypeOption('expanded', false) | |||||
->setFormTypeOption('multiple', true) | |||||
->setChoices($this->translatorAdmin->transChoices( | |||||
TicketSolver::getTypeChoices(), | |||||
'Ticket', | |||||
'type' | |||||
)), | |||||
'roles' => ChoiceField::new('roles') | 'roles' => ChoiceField::new('roles') | ||||
->allowMultipleChoices() | ->allowMultipleChoices() | ||||
->autocomplete() | ->autocomplete() |
'name' => self::SETTING_MAINTENANCE_IP_AUTHORIZED, | 'name' => self::SETTING_MAINTENANCE_IP_AUTHORIZED, | ||||
] | ] | ||||
); | ); | ||||
$this->addSettingText( | |||||
[ | |||||
'category' => self::CATEGORY_EMAIL, | |||||
'name' => self::SETTING_EMAIL_FROM, | |||||
] | |||||
); | |||||
$this->addSettingText( | |||||
[ | |||||
'category' => self::CATEGORY_EMAIL, | |||||
'name' => self::SETTING_EMAIL_FROM_NAME, | |||||
] | |||||
); | |||||
} | } | ||||
public function getCategories() | public function getCategories() | ||||
{ | { | ||||
return [ | return [ | ||||
self::CATEGORY_GENERAL, | self::CATEGORY_GENERAL, | ||||
self::CATEGORY_EMAIL | |||||
]; | ]; | ||||
} | } | ||||
<?php | |||||
namespace Lc\SovBundle\Event\Ticket; | |||||
use Lc\SovBundle\Doctrine\EntityInterface; | |||||
use Lc\SovBundle\Model\Ticket\TicketInterface; | |||||
use Symfony\Contracts\EventDispatcher\Event; | |||||
/** | |||||
* class EntityEvent. | |||||
* | |||||
* @author Simon Vieille <simon@deblan.fr> | |||||
*/ | |||||
class TicketEvent extends Event | |||||
{ | |||||
const NEW_TICKET_EVENT = 'ticket_event.new_ticket'; | |||||
const NEW_MESSAGE_EVENT = 'ticket_event.new_message'; | |||||
protected TicketInterface $ticket; | |||||
public function __construct(TicketInterface $ticket) | |||||
{ | |||||
$this->ticket = $ticket; | |||||
} | |||||
public function getTicket(): TicketInterface | |||||
{ | |||||
return $this->ticket; | |||||
} | |||||
} |
{ | { | ||||
return $this->siteStore->getOneByDevAlias('default'); | return $this->siteStore->getOneByDevAlias('default'); | ||||
} | } | ||||
} | } |
<?php | |||||
namespace Lc\SovBundle\EventSubscriber\Ticket; | |||||
use Lc\SovBundle\Event\EntityManager\EntityManagerEvent; | |||||
use Lc\SovBundle\Event\Ticket\TicketEvent; | |||||
use Lc\SovBundle\Model\Ticket\TicketInterface; | |||||
use Lc\SovBundle\Model\Ticket\TicketMessageInterface; | |||||
use Lc\SovBundle\Notification\MailMailjetNotification; | |||||
use Lc\SovBundle\Repository\User\UserStore; | |||||
use Lc\SovBundle\Solver\Ticket\TicketSolver; | |||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; | |||||
class SendNotificationTicketEventSubscriber implements EventSubscriberInterface | |||||
{ | |||||
protected MailMailjetNotification $mailMailjetNotification; | |||||
protected UserStore $userStore; | |||||
protected AuthorizationCheckerInterface $authorizationChecker; | |||||
protected TicketSolver $ticketSolver; | |||||
public function __construct( | |||||
MailMailjetNotification $mailMailjetNotification, | |||||
UserStore $userStore, | |||||
AuthorizationCheckerInterface $authorizationChecker, | |||||
TicketSolver $ticketSolver | |||||
) { | |||||
$this->mailMailjetNotification = $mailMailjetNotification; | |||||
$this->userStore = $userStore; | |||||
$this->authorizationChecker = $authorizationChecker; | |||||
$this->ticketSolver = $ticketSolver; | |||||
} | |||||
public static function getSubscribedEvents() | |||||
{ | |||||
return [ | |||||
TicketEvent::NEW_MESSAGE_EVENT => ['sendNotificationAfterNewMessage'], | |||||
TicketEvent::NEW_TICKET_EVENT => ['sendNotificationAfterNewTicket'], | |||||
]; | |||||
} | |||||
public function sendNotificationAfterNewTicket(TicketEvent $ticketEvent) | |||||
{ | |||||
$ticket = $ticketEvent->getTicket(); | |||||
$lastMessage = $this->ticketSolver->getLastMessage($ticket); | |||||
if ($ticket->getUser()) { | |||||
$firstname = $ticket->getUser()->getFirstname(); | |||||
$email = $ticket->getUser()->getEmail(); | |||||
} else { | |||||
$firstname = $ticket->getVisitorFirstname(); | |||||
$email = $ticket->getVisitorEmail(); | |||||
} | |||||
if ($lastMessage->getAnswerByAdmin()) { | |||||
// envoi email au client | |||||
$this->mailMailjetNotification->send( | |||||
[ | |||||
MailMailjetNotification::SUBJECT => 'Vous avez reçu un nouveau message', | |||||
MailMailjetNotification::TO_EMAIL => $email, | |||||
MailMailjetNotification::CONTENT_TEMPLATE => 'mail/ticket-new-by-admin', | |||||
MailMailjetNotification::CONTENT_DATA => [ | |||||
'firstname' => $firstname, | |||||
'ticket' => $ticket, | |||||
], | |||||
] | |||||
); | |||||
} else { | |||||
$this->mailMailjetNotification->send( | |||||
[ | |||||
MailMailjetNotification::SUBJECT => 'Nouvelle demande', | |||||
MailMailjetNotification::TO_EMAIL => $email, | |||||
MailMailjetNotification::CONTENT_TEMPLATE => 'mail/ticket-new', | |||||
MailMailjetNotification::CONTENT_DATA => [ | |||||
'firstname' => $firstname, | |||||
'ticket' => $ticket, | |||||
], | |||||
] | |||||
); | |||||
} | |||||
$this->notifyUser($ticket); | |||||
} | |||||
public function sendNotificationAfterNewMessage(TicketEvent $ticketEvent) | |||||
{ | |||||
$ticket = $ticketEvent->getTicket(); | |||||
$lastMessage = $this->ticketSolver->getLastMessage($ticket); | |||||
if ($ticket->getUser()) { | |||||
$firstname = $ticket->getUser()->getFirstname(); | |||||
$email = $ticket->getUser()->getEmail(); | |||||
} else { | |||||
$firstname = $ticket->getVisitorFirstname(); | |||||
$email = $ticket->getVisitorEmail(); | |||||
} | |||||
if ($lastMessage->getAnswerByAdmin()) { | |||||
// envoi email au client | |||||
$this->mailMailjetNotification->send( | |||||
[ | |||||
MailMailjetNotification::SUBJECT => 'Réponse à votre demande', | |||||
MailMailjetNotification::TO_EMAIL => $email, | |||||
MailMailjetNotification::CONTENT_TEMPLATE => 'mail/ticket-response', | |||||
MailMailjetNotification::CONTENT_DATA => [ | |||||
'firstname' => $firstname, | |||||
'ticket' => $ticket, | |||||
], | |||||
] | |||||
); | |||||
} | |||||
$this->notifyUser($ticket); | |||||
} | |||||
protected function notifyUser(TicketInterface $ticket): void | |||||
{ | |||||
// notifyAdmin | |||||
$usersToNotify = $this->userStore->getByTicketTypesNotification($ticket->getType()); | |||||
foreach ($usersToNotify as $userToNotify) { | |||||
if ($this->authorizationChecker->isGranted('ROLE_ADMIN', $userToNotify)) { | |||||
$this->mailMailjetNotification->send( | |||||
[ | |||||
MailMailjetNotification::SUBJECT => 'Nouveau ticket sur Place du Local', | |||||
MailMailjetNotification::TO_EMAIL => $userToNotify->getEmail(), | |||||
MailMailjetNotification::CONTENT_TEMPLATE => 'mail/ticket-notification', | |||||
MailMailjetNotification::CONTENT_DATA => [ | |||||
'firstname' => $userToNotify->getFirstname(), | |||||
'ticket' => $ticket, | |||||
'ticketMessage' => $ticket->getTicketMessages()[0], | |||||
], | |||||
] | |||||
); | |||||
} | |||||
} | |||||
} | |||||
} |
<?php | |||||
namespace Lc\SovBundle\Field\Filter\Ticket; | |||||
use Doctrine\ORM\EntityRepository; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto; | |||||
use Lc\SovBundle\Field\Filter\FilterTrait; | |||||
use Lc\SovBundle\Repository\RepositoryQueryInterface; | |||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType; | |||||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||||
use Symfony\Component\Form\FormBuilderInterface; | |||||
/** | |||||
* @author La clic ! <contact@laclic.fr> | |||||
*/ | |||||
class EmailTicketFilter | |||||
{ | |||||
use FilterTrait; | |||||
public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array()) | |||||
{ | |||||
$builder->add( | |||||
str_replace('.', '_', $fieldDto->getProperty()), | |||||
TextType::class, | |||||
array( | |||||
'required' => false, | |||||
'attr' => array( | |||||
'class' => ' input-sm', | |||||
'form' => 'filters-form', | |||||
), | |||||
) | |||||
); | |||||
} | |||||
public function applyFilter(RepositoryQueryInterface $repositoryQuery, FieldDto $fieldDto, $filteredValue = null) | |||||
{ | |||||
$fieldProperty = $this->getFieldProperty($fieldDto); | |||||
if ($filteredValue !== null) { | |||||
$repositoryQuery->joinUser(); | |||||
$repositoryQuery->andWhere( | |||||
'.' . $fieldProperty . ' LIKE :' . $fieldProperty . ' OR user.email LIKE :' . $fieldProperty | |||||
); | |||||
$repositoryQuery->setParameter($fieldProperty, '%' . $filteredValue . '%'); | |||||
} | |||||
} | |||||
} |
<?php | |||||
namespace Lc\SovBundle\Field\Filter\Ticket; | |||||
use Doctrine\ORM\EntityRepository; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto; | |||||
use Lc\SovBundle\Field\Filter\FilterTrait; | |||||
use Lc\SovBundle\Repository\RepositoryQueryInterface; | |||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType; | |||||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||||
use Symfony\Component\Form\FormBuilderInterface; | |||||
/** | |||||
* @author La clic ! <contact@laclic.fr> | |||||
*/ | |||||
class FirstnameTicketFilter | |||||
{ | |||||
use FilterTrait; | |||||
public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array()) | |||||
{ | |||||
$builder->add( | |||||
str_replace('.', '_', $fieldDto->getProperty()), | |||||
TextType::class, | |||||
array( | |||||
'required' => false, | |||||
'attr' => array( | |||||
'class' => ' input-sm', | |||||
'form' => 'filters-form', | |||||
), | |||||
) | |||||
); | |||||
} | |||||
public function applyFilter(RepositoryQueryInterface $repositoryQuery, FieldDto $fieldDto, $filteredValue = null) | |||||
{ | |||||
$fieldProperty = $this->getFieldProperty($fieldDto); | |||||
if ($filteredValue !== null) { | |||||
$repositoryQuery->joinUser(); | |||||
$repositoryQuery->andWhere( | |||||
'.' . $fieldProperty . ' LIKE :' . $fieldProperty . ' OR user.firstname LIKE :' . $fieldProperty | |||||
); | |||||
$repositoryQuery->setParameter($fieldProperty, '%' . $filteredValue . '%'); | |||||
} | |||||
} | |||||
} |
<?php | |||||
namespace Lc\SovBundle\Field\Filter\Ticket; | |||||
use Doctrine\ORM\EntityRepository; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto; | |||||
use Lc\SovBundle\Field\Filter\FilterTrait; | |||||
use Lc\SovBundle\Repository\RepositoryQueryInterface; | |||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType; | |||||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||||
use Symfony\Component\Form\FormBuilderInterface; | |||||
/** | |||||
* @author La clic ! <contact@laclic.fr> | |||||
*/ | |||||
class LastnameTicketFilter | |||||
{ | |||||
use FilterTrait; | |||||
public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array()) | |||||
{ | |||||
$builder->add( | |||||
str_replace('.', '_', $fieldDto->getProperty()), | |||||
TextType::class, | |||||
array( | |||||
'required' => false, | |||||
'attr' => array( | |||||
'class' => ' input-sm', | |||||
'form' => 'filters-form', | |||||
), | |||||
) | |||||
); | |||||
} | |||||
public function applyFilter(RepositoryQueryInterface $repositoryQuery, FieldDto $fieldDto, $filteredValue = null) | |||||
{ | |||||
$fieldProperty = $this->getFieldProperty($fieldDto); | |||||
if ($filteredValue !== null) { | |||||
$repositoryQuery->joinUser(); | |||||
$repositoryQuery->andWhere( | |||||
'.' . $fieldProperty . ' LIKE :' . $fieldProperty . ' OR user.lastname LIKE :' . $fieldProperty | |||||
); | |||||
$repositoryQuery->setParameter($fieldProperty, '%' . $filteredValue . '%'); | |||||
} | |||||
} | |||||
} |
<?php | |||||
namespace Lc\SovBundle\Field\Filter\Ticket; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto; | |||||
use Lc\SovBundle\Field\Filter\AssociationFilter; | |||||
use Lc\SovBundle\Repository\RepositoryQueryInterface; | |||||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||||
use Symfony\Component\Form\FormBuilderInterface; | |||||
/** | |||||
* @author La clic ! <contact@laclic.fr> | |||||
*/ | |||||
class TicketEmailFilter extends AssociationFilter | |||||
{ | |||||
public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array()) | |||||
{ | |||||
$builder->add( | |||||
$fieldDto->getProperty(), | |||||
TextType::class, | |||||
array( | |||||
'required' => false, | |||||
'attr' => array( | |||||
'class' => ' input-sm', | |||||
'form' => 'filters-form', | |||||
), | |||||
) | |||||
); | |||||
} | |||||
public function applyFilter(RepositoryQueryInterface $repositoryQuery, FieldDto $fieldDto, $filteredValue = null) | |||||
{ | |||||
if ($filteredValue !== null) { | |||||
$repositoryQuery->filterByEmail($filteredValue); | |||||
} | |||||
} | |||||
} |
<?php | |||||
namespace Lc\SovBundle\Field\Filter\Ticket; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto; | |||||
use Lc\SovBundle\Field\Filter\AssociationFilter; | |||||
use Lc\SovBundle\Repository\RepositoryQueryInterface; | |||||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||||
use Symfony\Component\Form\FormBuilderInterface; | |||||
/** | |||||
* @author La clic ! <contact@laclic.fr> | |||||
*/ | |||||
class TicketFirstnameFilter extends AssociationFilter | |||||
{ | |||||
public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array()) | |||||
{ | |||||
$builder->add( | |||||
$fieldDto->getProperty(), | |||||
TextType::class, | |||||
array( | |||||
'required' => false, | |||||
'attr' => array( | |||||
'class' => ' input-sm', | |||||
'form' => 'filters-form', | |||||
), | |||||
) | |||||
); | |||||
} | |||||
public function applyFilter(RepositoryQueryInterface $repositoryQuery, FieldDto $fieldDto, $filteredValue = null) | |||||
{ | |||||
if ($filteredValue !== null) { | |||||
$repositoryQuery->filterByFirstname($filteredValue); | |||||
} | |||||
} | |||||
} |
<?php | |||||
namespace Lc\SovBundle\Field\Filter\Ticket; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto; | |||||
use Lc\SovBundle\Field\Filter\AssociationFilter; | |||||
use Lc\SovBundle\Repository\RepositoryQueryInterface; | |||||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||||
use Symfony\Component\Form\FormBuilderInterface; | |||||
/** | |||||
* @author La clic ! <contact@laclic.fr> | |||||
*/ | |||||
class TicketLastnameFilter extends AssociationFilter | |||||
{ | |||||
public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array()) | |||||
{ | |||||
$builder->add( | |||||
$fieldDto->getProperty(), | |||||
TextType::class, | |||||
array( | |||||
'required' => false, | |||||
'attr' => array( | |||||
'class' => ' input-sm', | |||||
'form' => 'filters-form', | |||||
), | |||||
) | |||||
); | |||||
} | |||||
public function applyFilter(RepositoryQueryInterface $repositoryQuery, FieldDto $fieldDto, $filteredValue = null) | |||||
{ | |||||
if ($filteredValue !== null) { | |||||
$repositoryQuery->filterByLastname($filteredValue); | |||||
} | |||||
} | |||||
} |
<?php | |||||
namespace Lc\SovBundle\Form\Ticket; | |||||
use Lc\SovBundle\Doctrine\EntityManager; | |||||
use Lc\SovBundle\Model\Ticket\TicketInterface; | |||||
use Lc\SovBundle\Model\Ticket\TicketModel; | |||||
use Lc\SovBundle\Model\User\UserInterface; | |||||
use Lc\SovBundle\Solver\Ticket\TicketSolver; | |||||
use Lc\SovBundle\Translation\TranslatorAdmin; | |||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType; | |||||
use Symfony\Component\Form\AbstractType; | |||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; | |||||
use Symfony\Component\Form\Extension\Core\Type\CollectionType; | |||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType; | |||||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||||
use Symfony\Component\Form\FormBuilderInterface; | |||||
use Symfony\Component\OptionsResolver\OptionsResolver; | |||||
class TicketAdminFormType extends AbstractType | |||||
{ | |||||
protected EntityManager $entityManager; | |||||
protected TranslatorAdmin $translatorAdmin; | |||||
public function __construct( | |||||
EntityManager $entityManager, | |||||
TranslatorAdmin $translatorAdmin | |||||
) { | |||||
$this->entityManager = $entityManager; | |||||
$this->translatorAdmin = $translatorAdmin; | |||||
} | |||||
public function buildForm(FormBuilderInterface $builder, array $options) | |||||
{ | |||||
$entityName = $this->entityManager->getEntityName(TicketInterface::class); | |||||
$builder->add( | |||||
'user', | |||||
EntityType::class, | |||||
[ | |||||
'class' => $this->entityManager->getEntityName(UserInterface::class), | |||||
] | |||||
); | |||||
$builder->add( | |||||
'subject', | |||||
TextType::class | |||||
); | |||||
$builder->add( | |||||
'type', | |||||
ChoiceType::class, | |||||
[ | |||||
'label' => 'Type', | |||||
'choices' => $this->translatorAdmin->transChoices( | |||||
TicketSolver::getTypeChoices(), | |||||
'Ticket', | |||||
'type' | |||||
), | |||||
] | |||||
); | |||||
$builder->add( | |||||
'ticketMessages', | |||||
CollectionType::class, | |||||
[ | |||||
'entry_type' => TicketMessageAdminType::class, | |||||
'allow_add' => false, | |||||
'label_attr' => ['class' => 'label-ticket'], | |||||
] | |||||
); | |||||
$builder->add( | |||||
'submit', | |||||
SubmitType::class, | |||||
[ | |||||
'label' => $this->translatorAdmin->transAction('save') | |||||
] | |||||
); | |||||
} | |||||
/** | |||||
* {@inheritdoc} | |||||
*/ | |||||
public function configureOptions(OptionsResolver $resolver) | |||||
{ | |||||
$resolver->setDefaults( | |||||
[ | |||||
'data_class' => $this->entityManager->getEntityName(TicketInterface::class), | |||||
] | |||||
); | |||||
} | |||||
} |
] | ] | ||||
); | ); | ||||
$builder->add( | |||||
'subject', | |||||
TextType::class | |||||
); | |||||
$builder->add( | $builder->add( | ||||
'type', | 'type', | ||||
ChoiceType::class, | ChoiceType::class, | ||||
] | ] | ||||
); | ); | ||||
$builder->add( | |||||
'subject', | |||||
TextType::class | |||||
); | |||||
$builder->add( | $builder->add( | ||||
'ticketMessages', | 'ticketMessages', | ||||
CollectionType::class, | CollectionType::class, |
use Lc\SovBundle\Model\Ticket\TicketMessageInterface; | use Lc\SovBundle\Model\Ticket\TicketMessageInterface; | ||||
use Lc\SovBundle\Translation\TranslatorAdmin; | use Lc\SovBundle\Translation\TranslatorAdmin; | ||||
use Symfony\Component\Form\AbstractType; | use Symfony\Component\Form\AbstractType; | ||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType; | |||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType; | use Symfony\Component\Form\Extension\Core\Type\SubmitType; | ||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType; | use Symfony\Component\Form\Extension\Core\Type\TextareaType; | ||||
use Symfony\Component\Form\FormBuilderInterface; | use Symfony\Component\Form\FormBuilderInterface; | ||||
use Symfony\Component\OptionsResolver\OptionsResolver; | use Symfony\Component\OptionsResolver\OptionsResolver; | ||||
class TicketMessageFormType extends AbstractType | |||||
class TicketMessageAdminFormType extends AbstractType | |||||
{ | { | ||||
protected $em; | protected $em; | ||||
protected $translatorAdmin; | protected $translatorAdmin; | ||||
'required' => true | 'required' => true | ||||
] | ] | ||||
); | ); | ||||
$builder->add( | $builder->add( | ||||
'submit', | |||||
SubmitType::class, | |||||
[ | |||||
'label' => $this->translatorAdmin->transAction('send') | |||||
] | |||||
'answerByAdmin', | |||||
HiddenType::class, | |||||
[ | |||||
'data' => 1 | |||||
] | |||||
); | ); | ||||
} | } | ||||
<?php | |||||
namespace Lc\SovBundle\Form\Ticket; | |||||
use Lc\SovBundle\Doctrine\EntityManager; | |||||
use Lc\SovBundle\Model\Ticket\TicketMessageInterface; | |||||
use Lc\SovBundle\Translation\TranslatorAdmin; | |||||
use Symfony\Component\Form\AbstractType; | |||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType; | |||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType; | |||||
use Symfony\Component\Form\FormBuilderInterface; | |||||
use Symfony\Component\OptionsResolver\OptionsResolver; | |||||
class TicketMessageAdminType extends AbstractType | |||||
{ | |||||
protected $em; | |||||
protected $translatorAdmin; | |||||
public function __construct(EntityManager $em, TranslatorAdmin $translatorAdmin) | |||||
{ | |||||
$this->em = $em; | |||||
$this->translatorAdmin = $translatorAdmin; | |||||
} | |||||
public function buildForm(FormBuilderInterface $builder, array $options) | |||||
{ | |||||
$builder->add( | |||||
'message', | |||||
TextareaType::class, | |||||
[ | |||||
'required' => true | |||||
] | |||||
); | |||||
} | |||||
public function configureOptions(OptionsResolver $resolver) | |||||
{ | |||||
$resolver->setDefaults( | |||||
[ | |||||
'data_class' => $this->em->getEntityName(TicketMessageInterface::class), | |||||
] | |||||
); | |||||
} | |||||
} |
namespace Lc\SovBundle\Form\Ticket; | namespace Lc\SovBundle\Form\Ticket; | ||||
use App\Entity\Address; | |||||
use App\Entity\OrderShop; | |||||
use Doctrine\ORM\EntityManagerInterface; | use Doctrine\ORM\EntityManagerInterface; | ||||
use Lc\ShopBundle\Model\Ticket; | |||||
use Lc\ShopBundle\Services\UtilsManager; | |||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType; | |||||
use Lc\SovBundle\Model\Ticket\TicketMessageInterface; | |||||
use Symfony\Component\Form\AbstractType; | use Symfony\Component\Form\AbstractType; | ||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType; | use Symfony\Component\Form\Extension\Core\Type\CheckboxType; | ||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; | |||||
use Symfony\Component\Form\Extension\Core\Type\EmailType; | |||||
use Symfony\Component\Form\Extension\Core\Type\FileType; | use Symfony\Component\Form\Extension\Core\Type\FileType; | ||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType; | use Symfony\Component\Form\Extension\Core\Type\TextareaType; | ||||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||||
use Symfony\Component\Form\FormBuilderInterface; | use Symfony\Component\Form\FormBuilderInterface; | ||||
use Symfony\Component\OptionsResolver\OptionsResolver; | use Symfony\Component\OptionsResolver\OptionsResolver; | ||||
use Symfony\Component\Security\Core\Security; | |||||
use Symfony\Component\Validator\Constraints\File; | use Symfony\Component\Validator\Constraints\File; | ||||
class TicketMessageType extends AbstractType | class TicketMessageType extends AbstractType | ||||
{ | { | ||||
protected EntityManagerInterface $entityManager; | |||||
public function __construct(EntityManagerInterface $entityManager) | |||||
{ | |||||
$this->entityManager = $entityManager; | |||||
} | |||||
public function buildForm(FormBuilderInterface $builder, array $options) | public function buildForm(FormBuilderInterface $builder, array $options) | ||||
{ | { | ||||
'label' => 'entity.TicketMessage.fields.closeTicket', | 'label' => 'entity.TicketMessage.fields.closeTicket', | ||||
'translation_domain' => 'admin', | 'translation_domain' => 'admin', | ||||
'required' => false, | 'required' => false, | ||||
'mapped' => false, | |||||
]); | ]); | ||||
} | } | ||||
public function configureOptions(OptionsResolver $resolver) | public function configureOptions(OptionsResolver $resolver) | ||||
{ | { | ||||
$resolver->setDefaults([ | $resolver->setDefaults([ | ||||
// Configure your form options here | |||||
'data_class' => $this->entityManager->getEntityName(TicketMessageInterface::class), | |||||
]); | ]); | ||||
} | } | ||||
} | } |
{ | { | ||||
use StatusTrait; | use StatusTrait; | ||||
/** | /** | ||||
* @ORM\Column(type="text") | * @ORM\Column(type="text") | ||||
*/ | */ | ||||
public function __toString() | public function __toString() | ||||
{ | { | ||||
return $this->message; | |||||
return ''.$this->message; | |||||
} | } | ||||
public function getMessage(): ?string | public function getMessage(): ?string |
return $this; | return $this; | ||||
} | } | ||||
public function getStatus(): ?string | public function getStatus(): ?string | ||||
{ | { | ||||
return $this->status; | return $this->status; | ||||
return $this; | return $this; | ||||
} | } | ||||
public function getSubject(): ?string | public function getSubject(): ?string | ||||
{ | { | ||||
return $this->subject; | return $this->subject; |
class TicketRepositoryQuery extends AbstractRepositoryQuery implements TicketRepositoryQueryInterface | class TicketRepositoryQuery extends AbstractRepositoryQuery implements TicketRepositoryQueryInterface | ||||
{ | { | ||||
protected $isJoinUser = false; | |||||
protected $isJoinUser = false; | |||||
public function __construct(TicketRepository $repository, PaginatorInterface $paginator) | public function __construct(TicketRepository $repository, PaginatorInterface $paginator) | ||||
{ | { | ||||
->setParameter('status', $statusArray); | ->setParameter('status', $statusArray); | ||||
} | } | ||||
public function filterByFirstname(string $firstname) | |||||
{ | |||||
$this->joinUser(); | |||||
return $this | |||||
->andWhere('.visitorFirstname LIKE :firstname OR u.firstname LIKE :firstname') | |||||
->setParameter('firstname', '%'.$firstname.'%'); | |||||
} | |||||
public function filterByLastname(string $lastname) | |||||
{ | |||||
$this->joinUser(); | |||||
return $this | |||||
->andWhere('.visitorLastname LIKE :lastname OR u.lastname LIKE :lastname') | |||||
->setParameter('lastname', '%'.$lastname.'%'); | |||||
} | |||||
public function filterByEmail(string $email) | |||||
{ | |||||
$this->joinUser(); | |||||
return $this | |||||
->andWhere('.visitorEmail LIKE :email OR u.email LIKE :email') | |||||
->setParameter('email', '%'.$email.'%'); | |||||
} | |||||
public function selectCount(): self | public function selectCount(): self | ||||
{ | { | ||||
return $this | return $this |
account: Mon compte | account: Mon compte | ||||
account_profile: Informations personnelles | account_profile: Informations personnelles | ||||
account_password: Mot de passe | account_password: Mot de passe | ||||
tickets: Tickets | |||||
tickets: Tickets <span class="float-right badge badge-info">%total_ticket_open%</span> | |||||
setting_global: Global | setting_global: Global | ||||
title: | title: | ||||
label: Ticket | label: Ticket | ||||
label_plurial: Tickets | label_plurial: Tickets | ||||
fields: | fields: | ||||
visitorFirstName: Nom | |||||
visitorLastName: Prénom | |||||
visitorFirstname: Nom | |||||
visitorLastname: Prénom | |||||
visitorEmail: E-mail | visitorEmail: E-mail | ||||
subject: Sujet | subject: Sujet | ||||
type: Type | type: Type | ||||
open: Ouvert | open: Ouvert | ||||
being-processed: En attente | being-processed: En attente | ||||
closed: Fermé | closed: Fermé | ||||
ticketMessages: Message | |||||
TicketModel: | TicketModel: | ||||
fields: | fields: | ||||
open: Ouvert | open: Ouvert |
<div class="col-12"> | <div class="col-12"> | ||||
{{ form_row(form_add_ticket_message.message) }} | {{ form_row(form_add_ticket_message.message) }} | ||||
</div> | </div> | ||||
<div class="col-12 text-right"> | |||||
<button type="submit" class="btn btn-primary text-right">{{ 'send'|sov_trans_admin_action }}</button> | |||||
</div> | |||||
</div> | </div> | ||||
{{ form_end(form_add_ticket_message) }} | {{ form_end(form_add_ticket_message) }} | ||||
</div> | </div> |
New | New | ||||
</span> | </span> | ||||
{% endif %} | {% endif %} | ||||
{{ ticketMessage.createdAt|date('d/m/Y H:i') }} par {{ ticketMessage.createdBy }} | |||||
{{ ticketMessage.createdAt|date('d/m/Y H:i') }} par | |||||
{% if ticketMessage.answerByAdmin %} | |||||
Équipe | |||||
{% else %} | |||||
Client | |||||
{% endif %} | |||||
{# {% set ticket = entity.instance %} #} | |||||
{# {% if ticket.ticketMessages %} #} | |||||
{# {% for message in ticket.ticketMessages %} #} | |||||
{# {% if loop.last %} #} | |||||
{# {% if message.answerByAdmin %} #} | |||||
{# Équipe #} | |||||
{# {% else %} #} | |||||
{# Client #} | |||||
{# {% endif %} #} | |||||
{# {% endif %} #} | |||||
{# {% endfor %} #} | |||||
{# {% endif %} #} | |||||
{% if item.icon is not empty %} | {% if item.icon is not empty %} | ||||
<i class="{{ item.icon }} nav-icon"></i> | <i class="{{ item.icon }} nav-icon"></i> | ||||
{% endif %} | {% endif %} | ||||
<p>{{ item.label|sov_trans_admin_menu }}</p> | |||||
<p>{{ item.label|sov_trans_admin_menu(item.translationParameters)|raw }}</p> | |||||
{% if item.hasSubItems %}<i class="right fas fa-angle-left"></i>{% endif %} | {% if item.hasSubItems %}<i class="right fas fa-angle-left"></i>{% endif %} | ||||
</a> | </a> | ||||
{% endif %} | {% endif %} | ||||
</ul> | </ul> | ||||
</nav> | </nav> | ||||
{% block main_menu_after %}{% endblock %} | |||||
{% block main_menu_after %}{% endblock %} |
{% endif %} | {% endif %} | ||||
{% endif %} | {% endif %} | ||||
{% block append_body %}{% endblock %} | {% block append_body %}{% endblock %} | ||||
</body> | </body> |
return $this->trans('action.' . $action); | return $this->trans('action.' . $action); | ||||
} | } | ||||
public function transMenu($menu): string | |||||
public function transMenu($menu, $params = []): string | |||||
{ | { | ||||
return $this->trans('menu.' . $menu); | |||||
return $this->trans('menu.' . $menu, $params); | |||||
} | } | ||||
public function transFlashMessage($type, $name, $entityClass = false, $params = []): string | public function transFlashMessage($type, $name, $entityClass = false, $params = []): string |
return $this->translatorAdmin->transCard($cardName, $entityClass); | return $this->translatorAdmin->transCard($cardName, $entityClass); | ||||
} | } | ||||
public function transAdminMenu($menuName) | |||||
public function transAdminMenu($menuName, $params = []) | |||||
{ | { | ||||
return $this->translatorAdmin->transMenu($menuName);; | |||||
return $this->translatorAdmin->transMenu($menuName, $params);; | |||||
} | } | ||||
public function transAdminAction($actionName) | public function transAdminAction($actionName) |