<?php
namespace App\Controller;
use App\Entity\BillingAddress;
use App\Traits\Tools;
use App\Entity\Company;
use App\Entity\Contact;
use App\Entity\DeliveryAddress;
use App\Entity\Status;
use App\Entity\User;
use App\Form\CompanyType;
use App\Service\FileUploader;
use App\Repository\CompanyRepository;
use App\Repository\StatusRepository;
use App\Repository\UserRepository;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\HttpFoundation\File\UploadedFile;
/**
* @Route("/company")
*/
class CompanyController extends AbstractController
{
use Tools;
private $mailerInterface;
public function __construct(MailerInterface $mailerInterface)
{
$this->mailerInterface = $mailerInterface;
}
/**
* @Route("/", name="company_index", methods={"GET", "POST"})
* @Security("is_granted('ROLE_COMMERCIAL') or is_granted('ROLE_ACCOUNTANT')")
*
* @param CompanyRepository $companyRepository
*
* @return Response
*/
public function index(CompanyRepository $companyRepository, StatusRepository $statusRepository): Response
{
if (isset($_POST['submitFilter']) && isset($_POST['filter'])) {
$_SESSION['filter'] = $_POST['filter'];
} elseif (isset($_POST['submitFilter']) && !isset($_POST['filter'])) {
unset($_SESSION['filter']);
} else{
$_SESSION['filter'] = [1, 2, 3]; // Default filters for hide archived companies
}
switch ($this->checkAccess()) {
case 'admin':
case 'accountant':
$companies = isset($_SESSION['filter'])
? $companyRepository->findByStatus($_SESSION['filter'],["id" => "DESC"])
: $companyRepository->findBy([], ["id" => "DESC"]);
break;
case 'commercial':
$companies = isset($_SESSION['filter'])
? $companyRepository->findByCommercialAndStatus($this->getUser()->getId(), $_SESSION['filter'])
: $companyRepository->findByCommercial($this->getUser()->getId());
break;
default:
$companies = [];
break;
}
$statusArray = [];
foreach ($statusRepository->findAll() as $status) {
$statusArray[] = [
'label' => $status->getName(),
'value' => $status->getId(),
'selected' => isset($_SESSION['filter']) && in_array($status->getId(), $_SESSION['filter'])
];
}
return $this->render('company/index.html.twig', [
'companies' => $companies,
'statusArray' => $statusArray
]);
}
/**
* @Route("/new", name="company_new", methods={"GET","POST"})
*
* @param Request $request
* @param UserPasswordEncoderInterface $passwordEncoder
* @param FileUploader $fileUploader
* @param UserRepository $userRepository
*
* @return Response
*/
public function new(Request $request, UserPasswordEncoderInterface $passwordEncoder, FileUploader $fileUploader, UserRepository $userRepository): Response
{
$this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
$company = new Company();
$form = $this->createForm(CompanyType::class, $company)->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager = $this->getDoctrine()->getManager();
$company->setCommercial($this->getUser());
// Create associated user owner company and add error if duplicate emails
$this->autoCreateOwner($company, $entityManager, $passwordEncoder, $userRepository);
$entityManager->persist($company);
$entityManager->flush();
/** @var UploadedFile $kbis */
$kbis = $form->get('kbis')->getData();
if (!empty($kbis)) {
$kbis->company_id = $company->getId();
$fileUploader->upload($kbis, 'kbis');
}
/** @var UploadedFile $exceptionPriceFile */
$exceptionPriceFile = $form->get('exception_price_file')->getData();
if (!empty($exceptionPriceFile)) {
$exceptionPriceFile->company_id = $company->getId();
$fileUploader->upload($exceptionPriceFile, 'exception_price_file');
}
\App\Entity\Log::addLogFromController(
"Create Company : ".$company->getName(),
$company->getId(),
$this->getUser(),
null,
$company,
null,
$entityManager
);
return $this->redirectToRoute('company_show', ['id' => $company->getId()]);
}
return $this->render('company/new.html.twig', [
'company' => $company,
'form' => $form->createView(),
'action' => 'new'
]);
}
/**
* @Route("/{id}", name="company_show", methods={"GET"})
*
* @param Company $company
*
* @return Response
*/
public function show(Company $company): Response
{
if (null !== $this->check($company)) {
return $this->redirectToRoute('app_logout');
}
$errors = [];
$errors['missing_contact'] = count($company->getContacts()) == 0 ? true : false;
$errors['missing_delivery_address'] = count($company->getDeliveryAddresses()) == 0 ? true : false;
$errors['missing_billing_address'] = null == $company->getBillingAddress() ? true : false;
return $this->render('company/show.html.twig', [
'entitites_needed_to_be_filled' => $this->checkData($company),
'is_company_completed' => (in_array(true, $errors) === true) ? false : true,
'missing_contact' => $errors['missing_contact'],
'missing_delivery_address' => $errors['missing_delivery_address'],
'missing_billing_address' => $errors['missing_billing_address'],
'company' => $company,
'files' => $company->getFiles() ?: [],
'action' => 'new'
]);
}
/**
* Check if required fields are empty returns true if need to be filled
*
* @param Company $company
*
* @return array
*/
public function checkData(Company $company): array
{
$errors = [
'company' => [],
'contacts' => [],
'billing_addresses' => [],
'delivery_addresses' => []
];
foreach ($company->getRequiredFields() as $field_required) {
if (empty($company->{"$field_required"}())) {
$errors['company'] = $company->getId();
}
}
if (!$company->hasFile('kbis')) {
$errors['company'] = $company->getId();
}
foreach ($company->getContacts() as $contact) {
if (!$this->checkContact($contact)) {
$errors['contacts'][] = $contact->getId();
};
}
foreach ($company->getDeliveryAddresses() as $delivery_address) {
if (!$this->checkDeliveryAddress($delivery_address)) {
$errors['delivery_addresses'][] = $delivery_address->getId();
}
}
if (null !== $company->getBillingAddress()) {
if (!$this->checkBillingAddress($company->getBillingAddress())) {
$errors['billing_addresses'][] = $company->getBillingAddress()->getId();
};
}
return $errors;
}
/**
* Check if required fields are empty
*
* @param Contact $contact
*
* @return bool
*/
public function checkContact(Contact $contact): bool
{
foreach ($contact->getRequiredFields() as $field_required) {
if (empty($contact->{"$field_required"}())) {
return false;
}
}
return true;
}
/**
* Check if required fields are empty returns true if need to be filled
*
* @param DeliveryAddress $delivery_address
*
* @return bool
*/
public function checkDeliveryAddress(DeliveryAddress $delivery_address): bool
{
foreach ($delivery_address->getRequiredFields() as $field_required) {
if (empty($delivery_address->{"$field_required"}())) {
return false;
}
}
return true;
}
/**
* Check if required fields are empty returns true if need to be filled
*
* @param BillingAddress $billing_address
*
* @return bool
*/
public function checkBillingAddress(BillingAddress $billing_address): bool
{
foreach ($billing_address->getRequiredFields()['global'] as $global) {
if (empty($billing_address->{"$global"}())) {
return false;
}
}
foreach ($billing_address->getRequiredFields()['invoice_mail_required'] as $value) {
if ($billing_address->getSendInvoiceMail()) {
if (empty($billing_address->{"$value"}())) {
return false;
}
}
}
foreach ($billing_address->getRequiredFields()['prelevement_required'] as $prelevement_required) {
if ($billing_address->getPaymentMethod() == 'PRELEVEMENT') {
if (empty($billing_address->{"$prelevement_required"}())) {
return false;
}
}
}
return true;
}
/**
* @Route("/{id}/edit", name="company_edit", methods={"GET","POST"})
*
* @param Request $request
* @param Company $company
* @param FileUploader $fileUploader
*
* @return Response
*/
public function edit(Request $request, Company $company, FileUploader $fileUploader): Response
{
if (null !== $this->check($company)) {
return $this->redirectToRoute('app_logout');
}
$current_status = $company->getStatus()->getId();
$form = $this->createForm(CompanyType::class, $company);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if ($company->getLocked()) {
$this->addFlash('warning', 'Société verrouillé, vous ne pouvez pas la modifier');
return $this->redirectToRoute('company_show', ['id' => $company->getId()]);
}
$this->getDoctrine()->getManager()->flush();
/** @var UploadedFile $kbis */
$kbis = $form->get('kbis')->getData();
if (!empty($kbis)) {
$kbis->company_id = $company->getId();
$fileUploader->upload($kbis, 'kbis');
}
/** @var UploadedFile $exceptionPriceFile */
$exceptionPriceFile = $form->get('exception_price_file')->getData();
if (!empty($exceptionPriceFile)) {
$exceptionPriceFile->company_id = $company->getId();
$fileUploader->upload($exceptionPriceFile, 'exception_price_file');
}
if ($current_status != $company->getStatus()->getId()) {
switch ($company->getStatus()->getId()) {
case 3:
try {
MailerController::sendMailToAccountant($this->mailerInterface, $company, $this->getDoctrine()->getManager());
$this->addFlash('success', 'Email envoyé');
} catch (TransportExceptionInterface $e) {
$this->addFlash('warning', $e->getMessage());
}
break;
case 4:
try {
MailerController::sendMailCompanyImported($this->mailerInterface, $company, $this->getDoctrine()->getManager());
$this->addFlash('success', 'Email envoyé');
} catch (TransportExceptionInterface $e) {
$this->addFlash('warning', $e->getMessage());
}
break;
}
}
\App\Entity\Log::addLogFromController(
"Edit Company",
$company->getId(),
$this->getUser(),
$company,
null,
null,
$this->getDoctrine()->getManager()
);
if (
$this->isGranted('ROLE_ACCOUNTANT')
|| $this->isGranted('ROLE_COMMERCIAL')
|| count($company->getDeliveryAddresses()) >= 1
) {
return $this->redirectToRoute('company_show', ['id' => $company->getId()]);
}
/** Redirection to Contact form creation to continue process inscription */
return $this->redirectToRoute('contact_new', ['id_company' => $company->getId()]);
}
return $this->render('company/edit.html.twig', [
'company' => $company,
'files' => $company->getFiles(),
'form' => $form->createView(),
'action' => 'edit'
]);
}
/**
* @Route("/{id}", name="company_delete", methods={"DELETE"})
* @Security("is_granted('ROLE_ADMIN')")
*
* @param Request $request
* @param Company $company
*
* @return Response
*/
public function delete(Request $request, Company $company): Response
{
if (null !== $this->check($company)) {
return $this->redirectToRoute('app_logout');
}
if ($this->isCsrfTokenValid('delete' . $company->getId(), $request->request->get('_token'))) {
$entityManager = $this->getDoctrine()->getManager();
\App\Entity\Log::addLogFromController(
"Delete Company ".$company->getName(),
$company->getId(),
$this->getUser(),
null,
null,
null,
$entityManager
);
$entityManager->remove($company);
$entityManager->flush();
foreach ($company->getFiles() as $file) {
unlink($file->getRealPath());
}
}
return $this->redirectToRoute('company_index');
}
/**
* @Route("/company_file_delete/{controller}/{id}/{timestamp}/{inode}", name="company_file_delete", methods={"GET","POST"})
*
* @param Company $company
* @param string $timestamp
* @param string $inode
*
* @return Response
*/
public function deleteFile(string $controller, Company $company, string $timestamp, string $inode): Response
{
if ($file = $company->getFile($timestamp, $inode)) {
unlink($file->getRealPath());
}
if ($controller === 'company') {
return $this->redirectToRoute('company_edit', ['id' => $company->getId()]);
}
return $this->redirectToRoute('billing_address_edit', ['id' => $company->getBillingAddress()->getId()]);
}
/**
* @Route("/send_message/{id}", name="company_send_message", methods={"POST", "GET"})
*
* @param Request $request
* @param Company $company
*
* @return Response
*/
public function sendMessage(Request $request, Company $company): Response
{
if (null !== $this->check($company)) {
return $this->redirectToRoute('app_logout');
}
$form = $this->createForm(CompanyType::class, $company);
$form->handleRequest($request);
MailerController::sendEmail(
$this->mailerInterface,
$company,
[
'subject' => $request->request->get('subject'),
'message' => $request->request->get('message'),
'token_link' => $request->getSchemeAndHttpHost() . $this->generateUrl('app_api', ['token' => $company->getOwner()->getApiToken(), 'id' => $company->getId()]),
]
);
$this->addFlash('success', 'Email envoyé');
return $this->redirectToRoute('company_show', ['id' => $company->getId()]);
}
/**
* @param Company $company
* @param ObjectManager $entityManager
* @param UserPasswordEncoderInterface $passwordEncoder
*
* @return bool|void
*/
protected function autoCreateOwner(Company $company, $entityManager, UserPasswordEncoderInterface $passwordEncoder, UserRepository $userRepository)
{
if ($user = $userRepository->findOneBy(['email' => $company->getEmail()])) {
$company->setOwner($user);
return false;
}
$user = new User();
$user->setFirstname($company->getName());
$user->setLastname($company->getName());
$user->setEmail($company->getEmail());
$user->setRoles(['ROLE_CLIENT']);
$user->setPassword($passwordEncoder->encodePassword(
$user,
$company->getName() . mt_rand(10, 10000)
));
$entityManager->persist($user);
$company->setOwner($user);
}
/**
* @param Company $company
*
* @return bool|null
*/
protected function check(Company $company): ?bool
{
if ($this->checkAccess() == 'denied') {
return false;
}
if ($this->checkAccess() == 'commercial') {
if ($company->getCommercial()->getId() != $this->getUser()->getId()) {
return false;
}
} elseif ($this->checkAccess() == 'client') {
if ($company->getOwner()->getId() != $this->getUser()->getId()) {
return false;
}
}
return null;
}
/**
* @Route("/send_to_accountant/{id}", name="company_to_accountant", methods={"POST", "GET"})
*
* @param Company $company
*
* @return Response
*/
public function sendToAcountant(Company $company): Response
{
if (null !== $this->check($company)) {
return $this->redirectToRoute('app_logout');
}
$entityManager = $this->getDoctrine()->getManager();
$company->setStatus($entityManager->find(Status::class, 3));
$entityManager->persist($company);
$entityManager->flush();
try {
MailerController::sendMailToAccountant($this->mailerInterface, $company, $entityManager);
$this->addFlash('success', 'Email envoyé');
\App\Entity\Log::addLogFromController(
"Send Information to Accountant",
$company->getId(),
$this->getUser(),
null,
null,
null,
$entityManager
);
} catch (TransportExceptionInterface $e) {
$this->addFlash('warning', $e->getMessage());
}
return $this->redirectToRoute('company_show', ['id' => $company->getId()]);
}
/**
* @Route("/send_validate_importation/{id}", name="send_validate_importation", methods={"POST", "GET"})
*
* @param Company $company
*
* @return Response
*/
public function sendValidateImportation(Company $company): Response
{
if (null !== $this->check($company)) {
return $this->redirectToRoute('app_logout');
}
$entityManager = $this->getDoctrine()->getManager();
$company->setStatus($entityManager->find(Status::class, 4));
$company->setLocked(true);
$entityManager->persist($company);
$entityManager->flush();
try {
MailerController::sendMailCompanyImported($this->mailerInterface, $company, $entityManager);
$this->addFlash('success', 'Email envoyé');
} catch (TransportExceptionInterface $e) {
$this->addFlash('warning', $e->getMessage());
}
return $this->redirectToRoute('company_show', ['id' => $company->getId()]);
}
/**
* @Route("/{id}/lock", name="company_lock", methods={"GET","POST"})
* @Security("is_granted('ROLE_ADMIN')")
*
* @param Company $company
*
* @return Response
*/
public function toggleLock(Company $company): Response
{
$entityManager = $this->getDoctrine()->getManager();
$company->setLocked(!$company->getLocked());
$entityManager->persist($company);
$entityManager->flush();
\App\Entity\Log::addLogFromController(
$company->getLocked() ?
"Lock Company ".$company->getName() :
"Unlock Company ".$company->getName(),
$company->getId(),
$this->getUser(),
$company,
null,
null,
$this->getDoctrine()->getManager()
);
$this->addFlash('success', $company->getLocked() ? 'Société verrouillé' : 'Société déverrouillé');
return $this->redirectToRoute('company_index');
}
}