<?php
namespace App\Application\Internit\LeadBundle\Controller;
// Include PhpSpreadsheet required namespaces
use App\Application\Internit\RealEstateBundle\Entity\RealEstate;
use App\Application\Sonata\UserBundle\Entity\User;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Writer\Csv;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use App\Application\Internit\ContentBundle\Controller\CRUD;
use App\Application\Internit\LeadBundle\DTO\ProductUserDTO;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use App\Application\Internit\LeadBundle\Entity\ProductUser;
use App\Application\Internit\LeadBundle\Entity\realStatePercent;
use App\Application\Internit\LeadBundle\Entity\Product;
use App\Application\Internit\LeadBundle\Entity\ProductLog;
/**
* Client Admin controller.
*
* @Route("/admin/internit/lead/product")
*/
class ProductAdminController extends CRUD
{
public $base = "@ApplicationInternit/LeadBundle/Resources/views/Product/";
public $bundle = "ApplicationInternitLeadBundle:Product";
private $listActionRoles = array('ROLE_CONSTRUTORA', 'ROLE_DIRETORIA', 'ROLE_IMOBILIARIA');
private $createActionRoles = array('ROLE_CONSTRUTORA');
private $editActionRoles = array('ROLE_CONSTRUTORA');
private $showActionRoles = array('ROLE_CONSTRUTORA', 'ROLE_DIRETORIA', 'ROLE_IMOBILIARIA');
private $exportFilteredActionRoles = array('ROLE_CONSTRUTORA', 'ROLE_DIRETORIA', 'ROLE_IMOBILIARIA');
public function listAction($order = array('id' => 'DESC'))
{
if (!$this->get('security.token_storage')->getToken()->getUser()->hasRole($this->listActionRoles))
{
return $this->renderWithExtraParams("@ApplicationInternit/ContentBundle/Resources/views/permission.html.twig");
}
return parent::listAction($order);
}
public function createAction()
{
if (!$this->get('security.token_storage')->getToken()->getUser()->hasRole($this->createActionRoles))
{
return $this->renderWithExtraParams("@ApplicationInternit/ContentBundle/Resources/views/permission.html.twig");
}
$request = $this->getRequest();
// the key used to lookup the template
$templateKey = 'edit';
$this->admin->checkAccess('create');
$class = new \ReflectionClass($this->admin->hasActiveSubClass() ? $this->admin->getActiveSubClass() : $this->admin->getClass());
$newObject = $this->admin->getNewInstance();
$preResponse = $this->preCreate($request, $newObject);
if (null !== $preResponse) {
return $preResponse;
}
$this->admin->setSubject($newObject);
$form = $this->admin->getForm();
$form->setData($newObject);
$form->handleRequest($request);
if ($form->isSubmitted()) {
$isFormValid = $form->isValid();
// persist if the form was valid and if in preview mode the preview was approved
if ($isFormValid && (!$this->isInPreviewMode() || $this->isPreviewApproved())) {
$this->persistImageApresentation($form);
$submittedObject = $form->getData();
$this->admin->setSubject($submittedObject);
$this->admin->checkAccess('create', $submittedObject);
try {
$token = md5(random_bytes(10).date('dmYHis'));
$realStatePercentList = $submittedObject->getRealStatePercents();
$productUserList = $submittedObject->getProductUsers();
$newObject->setProductUsers(null);
$newObject->setToken($token);
if($realStatePercentList)
{
//Checa percent = 100%
$totalPercent = 0;
foreach ($realStatePercentList as $rsPercent) {
$totalPercent += $rsPercent->getPercent();
}
if($totalPercent != 100)
{
$this->get('session')->getFlashBag()->set('flash_create_error', 'As porcentagens das imobiliárias devem somar 100%');
return $this->redirectToRoute('admin_internit_lead_product_create');
}
foreach ($realStatePercentList as $imob => $rsPercent) {
$imobComEspaco = str_replace(
array('_'),
' ',
$imob
);
$realEstate = $this->getDoctrine()->getRepository('ApplicationInternitRealEstateBundle:RealEstate')->findOneByName($imobComEspaco);
if($realEstate){
$rsPercent->setProduct($newObject);
$rsPercent->setRealEstate($realEstate);
$newRealStatePercent = $this->admin->create($rsPercent);
$newObject->addRealStatePercents($newRealStatePercent);
}
}
}
if($productUserList)
{
$i=0;
foreach ($productUserList as $user) {
$userImob = explode(':',$user);
$corretor = $this->getDoctrine()->getRepository('ApplicationSonataUserBundle:User')->findOneById($userImob[1]);
$realEstate = $this->getDoctrine()->getRepository('ApplicationInternitRealEstateBundle:RealEstate')->findOneById($userImob[0]);
if($corretor && $realEstate){
$productUser = new ProductUser();
$productUser->setUser($corretor);
$productUser->setRealEstate($realEstate);
$productUser->setProduct($newObject);
$productUser->setPosition($i);
$newProductUser = $this->admin->create($productUser);
$newObject->addProductUsers($newProductUser);
$i++;
}
}
}
$newObject = $this->admin->create($newObject);
$this->get('session')->getFlashBag()->set('flash_create_success', 'Mensagem enviada com sucesso');
// redirect to edit mode
return $this->redirectTo($newObject);
} catch (ModelManagerException $e) {
$this->handleModelManagerException($e);
$isFormValid = false;
}
}
// show an error message if the form failed validation
if (!$isFormValid) {
if (!$this->isXmlHttpRequest())
{
$errors = array();
foreach ($form->getErrors(true) as $error) {
$errors[] = $error->getMessage();
}
$this->get('session')->getFlashBag()->set('flash_create_error', implode('<br>', $errors));
}
}
}
$formView = $form->createView();
return $this->renderWithExtraParams($this->base."create.html.twig", [
'form' => $formView
], null);
}
public function saveExtraLeadsAction(Request $request)
{
$realEstate = $request->get('realStateId');
$extraLeads = $request->get('extraLeads');
$productId = $request->get('product');
$product = $this->getDoctrine()->getRepository('ApplicationInternitLeadBundle:realStatePercent')->findOneBy(['product' => $productId, 'realEstate' => $realEstate]);
if($product){
$product->setExtraLeads($extraLeads);
$em = $this->getDoctrine()->getManager();
$em->persist($product);
$em->flush();
}
$route = $request->headers->get('referer');
return $this->redirect($route);
}
public function saveLogs($productId, Request $request)
{
$formData = $request->request->all();
$formKey = array_key_first($formData);
$users = $formData[$formKey]['productUsers'];
$percents = $formData[$formKey]['realStatePercents'];
$product = $formData[$formKey]['name'];
$data = [];
foreach($users as $user){
$user = explode(':',$user);
$realEstate = $this->getDoctrine()->getRepository('ApplicationInternitRealEstateBundle:RealEstate')->findOneById($user[0]);
$corretor = $this->getDoctrine()->getRepository('ApplicationSonataUserBundle:User')->findOneById($user[1]);
$index = str_replace(" ", "_", $this->removeAcentos($realEstate->getName()));
$data[$index]["corretores"][] = $corretor->getFirstname();
}
foreach($percents as $key=>$percent){
if($percent['percent'] > 0 && !is_numeric($key) )
{
$data[$key]['percent'] = $percent['percent'];
// dump($key);
}
}
// dump($percents);
// dump($data); exit;;/
// $finalData["product"] = $product;
$finalData["LogData"] = date('d/m/Y H:i:s');
$finalData["Imobiliarias"] = [];
foreach($data as $key => $val){
$percent = isset($val["percent"]) ? $val["percent"] : 0;
unset($val["percent"]); // Remove o campo interno
$finalData["Imobiliarias"][$key . " " . $percent . "%"] = $val;
}
$productObject = $this->getDoctrine()->getRepository('ApplicationInternitLeadBundle:Product')->findOneById($productId);
//dump($productObject); exit;
$dataJson = json_encode($finalData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
$log = new ProductLog();
$log->setProduct($productObject);
$log->setLog($dataJson);
$log->setType("CAMPANHA");
$log->setCreatedAt(new \DateTime());
$em = $this->getDoctrine()->getManager();
$em->persist($log);
}
function removeAcentos($string) {
$acentos = [
'á','à','ã','â','ä','é','è','ê','ë','í','ì','î','ï','ó','ò','õ','ô','ö','ú','ù','û','ü','ç',
'Á','À','Ã','Â','Ä','É','È','Ê','Ë','Í','Ì','Î','Ï','Ó','Ò','Õ','Ô','Ö','Ú','Ù','Û','Ü','Ç'
];
$semAcentos = [
'a','a','a','a','a','e','e','e','e','i','i','i','i','o','o','o','o','o','u','u','u','u','c',
'A','A','A','A','A','E','E','E','E','I','I','I','I','O','O','O','O','O','U','U','U','U','C'
];
return str_replace($acentos, $semAcentos, $string);
}
public function editAction($id = null)
{
if (!$this->get('security.token_storage')->getToken()->getUser()->hasRole($this->editActionRoles))
{
return $this->renderWithExtraParams("@ApplicationInternit/ContentBundle/Resources/views/permission.html.twig");
}
// return parent::editAction($id = null);
$request = $this->getRequest();
$templateKey = 'edit';
$id = $request->get($this->admin->getIdParameter());
$existingObject = $this->admin->getObject($id);
if (!$existingObject) {
throw $this->createNotFoundException(sprintf('unable to find the object with id: %s', $id));
}
$form = $this->admin->getForm();
$form->setData($existingObject);
$form->handleRequest($request);
if ($form->isSubmitted()) {
$isFormValid = $form->isValid();
$submittedObject = $form->getData();
$this->admin->setSubject($submittedObject);
try {
$this->saveLogs($id, $request);
$realStatePercentList = $submittedObject->getRealStatePercents();
//Checa percent = 100%
$totalPercent = 0;
foreach ($realStatePercentList as $imob => $rsPercent) {
if (is_string($imob)) {
$totalPercent += $rsPercent->getPercent();
}
}
if($totalPercent != 100)
{
$this->get('session')->getFlashBag()->set('flash_create_error', 'As porcentagens das imobiliárias devem somar 100%');
$isFormValid = false;
// redirect to edit mode
return $this->redirectTo($existingObject);
}
$realStatePercent = $this->getDoctrine()->getRepository('ApplicationInternitLeadBundle:realStatePercent')->findBy(['product' => $submittedObject]);
$rpLastExtraLeads = [];
/** @var $rp realStatePercent */
foreach ($realStatePercent as $rp) {
$rpLastExtraLeads[$rp->getRealEstate()->getId()] = $rp->getExtraLeads();
}
//Clean corretores selecionados para atualizar
$this->getDoctrine()->getRepository('ApplicationInternitLeadBundle:Product')->cleanProductUser($submittedObject->getId());
$productUserList = $submittedObject->getProductUsers();
//Atualizar corretores selecionados
$submittedObject->setProductUsers(null);
if($productUserList){
$i=0;
foreach ($productUserList as $user) {
$userImob = explode(':',$user);
$corretor = $this->getDoctrine()->getRepository('ApplicationSonataUserBundle:User')->findOneById($userImob[1]);
$realEstate = $this->getDoctrine()->getRepository('ApplicationInternitRealEstateBundle:RealEstate')->findOneById($userImob[0]);
if($corretor && $realEstate){
$productUser = new ProductUser();
$productUser->setUser($corretor);
$productUser->setRealEstate($realEstate);
$productUser->setProduct($submittedObject);
$productUser->setPosition($i);
$newProductUser = $this->admin->create($productUser);
$submittedObject->addProductUsers($newProductUser);
$i++;
}
}
}
$lastRealStatePercent = $this->getDoctrine()->getRepository(realStatePercent::class)->findBy(['product' => $id]);
$this->getDoctrine()->getRepository('ApplicationInternitLeadBundle:Product')->cleanRealEstatePercent($submittedObject->getId());
// Salvar historico das turnos das imobiliarias do produto atual
// Quando for criar as novas realState_percent manter o campo turn
//Atualizar porcentagem das imobiliarias nas campanhas
if($realStatePercentList)
{
foreach ($realStatePercentList as $imob => $rsPercent) {
$imobComEspaco = str_replace(
array('_'),
' ',
$imob
);
$realEstate = $this->getDoctrine()->getRepository('ApplicationInternitRealEstateBundle:RealEstate')->findOneByName($imobComEspaco);
if($realEstate){
/**
* @var $lastRP realStatePercent
*/
foreach ($lastRealStatePercent as $lastRP){
if($lastRP->getRealEstate() === $realEstate){
$rsPercent->setTurn($lastRP->getTurn());
}
}
$rsPercent->setProduct($submittedObject);
$rsPercent->setRealEstate($realEstate);
$rsPercent->setExtraLeads($rpLastExtraLeads[$realEstate->getId()]?? 0);
$newRealStatePercent = $this->admin->create($rsPercent);
$submittedObject->addRealStatePercents($newRealStatePercent);
}
}
}
$existingObject = $this->admin->update($submittedObject);
$this->get('session')->getFlashBag()->set('flash_create_success', 'Mensagem enviada com sucesso');
// redirect to edit mode
return $this->redirectTo($existingObject);
} catch (ModelManagerException $e) {
$this->handleModelManagerException($e);
$isFormValid = false;
} catch (LockException $e) {
$this->get('session')->getFlashBag()->set('flash_create_error', 'Mensagem enviada com sucesso');
}
//}
// show an error message if the form failed validation
if (!$isFormValid) {
if (!$this->isXmlHttpRequest()) {
$this->addFlash(
'sonata_flash_error',
$this->trans(
'flash_edit_error',
['%name%' => $this->escapeHtml($this->admin->toString($existingObject))],
'SonataAdminBundle'
)
);
}
} elseif ($this->isPreviewRequested()) {
// enable the preview template if the form was valid and preview was requested
$templateKey = 'preview';
$this->admin->getShow();
}
}
$formView = $form->createView();
return $this->renderWithExtraParams($this->base."edit.html.twig", [
'action' => 'edit',
'form' => $formView,
'obj' => $existingObject,
'next' => $this->get('tupi.caster.service')->next($existingObject, null),
], null);
}
public function showAction($id = null)
{
if (!$this->get('security.token_storage')->getToken()->getUser()->hasRole($this->showActionRoles))
{
return $this->renderWithExtraParams("@ApplicationInternit/ContentBundle/Resources/views/permission.html.twig");
}
$request = $this->getRequest();
$id = $request->get($this->admin->getIdParameter());
$filter=[
'from' => '',
'to' => '',
'imob' => '',
'group' => '',
'user' => '',
];
if(isset($_POST['filter']))
{
$filter = $_POST['filter'];
}
$data = $this->getDoctrine()->getRepository($this->bundle)->find($id);
$template = $this->base.'show.html.twig';
//$imobFilter = $this->getDoctrine()->getRepository('ApplicationInternitLeadBundle:Lead')->findAllImobs($id);
$imobs = $this->getDoctrine()->getRepository(RealEstate::class)->findAll();
foreach ($imobs as $imob){
$imobFilter[] = [ 'name' => $imob->getName() ];
}
$users = $this->getDoctrine()->getRepository(User::class)->findAll();
foreach ($users as $user){
$userFilter[] = [ 'name' => $user->getFirstname() ];
}
// dd($imobFilter);
$userGroup = $this->get('security.token_storage')->getToken()->getUser()->getGroups()[0]->getName();
return $this->renderWithExtraParams($template, [
'action' => 'show',
'data' => $data,
'imobFilter' => $imobFilter,
'userFilter' => $userFilter,
'filter' => $filter,
'userGroup' => $userGroup,
], null);
return parent::showAction($id = null);
}
function exportLogSendedAction()
{
$request = $this->getRequest();
$id = $request->get($this->admin->getIdParameter());
return $this->exportLogs($id, "DISTRIBUICAO");
}
public function exportLogAction()
{
$request = $this->getRequest();
$id = $request->get($this->admin->getIdParameter());
return $this->exportLogs($id, "CAMPANHA");
}
public function exportLogs($id = null, $type = null)
{
$request = $this->getRequest();
$id = $request->get($this->admin->getIdParameter());
$logEntities = $this->getDoctrine()->getRepository("ApplicationInternitLeadBundle:ProductLog")->findBy(['product' => $id, 'type' => $type]);
// dump($logEntities); exit;
if (!$logEntities) {
return $response = new Response("Log com ID {$id} não encontrado.");
//throw $this->createNotFoundException("Log com ID {$id} não encontrado.");
}
$allLogs = [];
$allLogs = [
'id' => $logEntities[0]->getId(),
'createdAt' => $logEntities[0]->getCreatedAt()->format('Y-m-d H:i:s'),
'product' => $logEntities[0]->getProduct() ? $logEntities[0]->getProduct()->getName() : null,
];
$realEstateArray = [];
foreach ($logEntities as $logEntity) {
$logData = json_decode($logEntity->getLog(), true);
$realEstateArray[] = $logData;
// Adiciona metadados opcionais, como ID ou data
}
$allLogs['data'] = $realEstateArray;
$jsonContent = json_encode($allLogs, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
$fileName = 'logs_' . date('Y-m-d_H-i-s') . '.json';
$response = new Response($jsonContent);
$response->headers->set('Content-Type', 'application/json');
$response->headers->set('Content-Disposition', $response->headers->makeDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
$fileName
));
return $response;
}
/**
* Trata a requisição para exportar os leads filtrados em um arquivo csv.
* @param int $id - ID da campanha cujos leads serão exportados.
*/
public function exportFilteredAction($id = null)
{
if (!$this->get('security.token_storage')->getToken()->getUser()->hasRole($this->exportFilteredActionRoles))
{
return $this->renderWithExtraParams("@ApplicationInternit/ContentBundle/Resources/views/permission.html.twig");
}
$request = $this->getRequest();
$id = $request->get($this->admin->getIdParameter());
$product = $this->getDoctrine()->getRepository($this->bundle)->find($id);
$productName = is_null($product) ? '' : $product->getName();
$filter = $_POST['filter'];
$leads = $this->getDoctrine()->getRepository('ApplicationInternitLeadBundle:Lead')
->findLeadByGroup($id, $filter['group'], $filter);
$data = [];
if($filter['user'])
{
$user = $this->getDoctrine()->getRepository(User::class)->findOneBy(['firstname' => $filter['user']]);
$data = [];
foreach ($leads as $lead)
if($lead['brokerEmail'] == $user->getEmail())
$data[] = $lead;
$leads = $data;
}
$spreadsheet = new Spreadsheet();
/* @var $sheet \PhpOffice\PhpSpreadsheet\Writer\Xlsx\Worksheet */
$sheet = $spreadsheet->getActiveSheet();
$date = date('d/m/Y H:i:s');
$dateFileName = date('d-m-y__H-i-s');
$this->generateFileContent($sheet, $leads);
$writer = new Csv($spreadsheet);
$group = empty($filter['group']) ? '' : $filter['group'];
$fileName = "leads_{$productName}_{$group}_$dateFileName.csv";
$contentType = 'text/csv';
return $this->generateFileResponse($fileName, $contentType, $writer);
}
/**
* Escreve os leads em um arquivo de spreadsheet.
*
* @param \PhpOffice\PhpSpreadsheet\Writer\Xlsx\Worksheet $sheet - planilha de trabalho atual
* @param array $leads - array dos leads filtrados para escrita.
*/
private function generateFileContent($sheet, $leads)
{
$columns = [
'A' => ['label' => 'Nome', 'field' => 'name'],
'B' => ['label' => 'E-mail', 'field' => 'email'],
'C' => ['label' => 'Telefone', 'field' => 'phone'],
'D' => ['label' => 'Imobiliaria', 'field' => 'brokerRealState'],
'E' => ['label' => 'E-mail corretor', 'field' => 'brokerEmail'],
'F' => ['label' => 'Fidelidade', 'field' => 'loyalty'],
'G' => ['label' => 'Origem', 'field' => 'origem'],
'H' => ['label' => 'Grupo', 'field' => 'group'],
'I' => ['label' => 'Data de envio', 'field' => 'createdAt'],
'J' => ['label' => 'Enviado', 'field' => 'send_status'],
'K' => ['label' => 'Utm Source', 'field' => 'utm_source'],
'L' => ['label' => 'Utm Medium', 'field' => 'utm_medium'],
'M' => ['label' => 'Utm Campaign', 'field' => 'utm_campaign'],
];
$indRow = 1;
foreach($columns as $col => $content) {
$sheet->setCellValue($col . $indRow, $content['label']);
}
$indRow = 2;
foreach($leads as $lead) {
foreach ($columns as $col => $content) {
$field = $content['field'];
$sheet->setCellValue($col . $indRow, $lead[$field]);
}
$indRow++;
}
}
/**
* Gera o arquivo csv exportado como uma resposta para o cliente.
*
* @param string $fileName - nome do arquivo
* @param string $contentType - tipo mime do arquivo
* @param use PhpOffice\PhpSpreadsheet\Writer\Csv $writer - objeto que vai exportar o arquivo csv
* @return StreamedResponse
*/
private function generateFileResponse($fileName, $contentType, $writer)
{
$response = new StreamedResponse();
$response->headers->set('Content-Type', $contentType);
$response->headers->set('Content-Disposition', 'attachment;filename="'.$fileName.'"');
$response->setPrivate();
$response->headers->addCacheControlDirective('no-cache', true);
$response->headers->addCacheControlDirective('must-revalidate', true);
$response->setCallback(function() use ($writer) {
$writer->save('php://output');
});
return $response;
}
public function getBundleName()
{
return 'ApplicationInternitLeadBundle';
}
public function getEntityName()
{
return 'Product';
}
public function getFormType()
{
return 'App\Application\Internit\LeadBundle\Form\ProductType';
}
}