<?php
namespace App\Controller\Componentes;
use App\Controller\Customs\Custom2IMController;
use App\Helper\DateHelper;
use App\Repository\Cliente\Periodo\PeriodoRepository;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* @Route("/periodo")
*/
class PeriodoController extends Custom2IMController
{
/**
* @var PeriodoRepository
*/
public $periodo;
/**
* @var array
*/
public $periodosExtenso = [
'Mensal' => [
'01' => 'Jan', '02' => 'Fev', '03' => 'Mar'
,'04' => 'Abr', '05' => 'Mai', '06' => 'Jun'
,'07' => 'Jul', '08' => 'Ago', '09' => 'Set'
,'10' => 'Out', '11' => 'Nov', '12' => 'Dez'
],
'Ciclos' => ['01' => '1º ciclo', '02' => '2º ciclo'],
'Marco' => []
];
/**
* @var array
*/
public $periodos = [
'Marco' => 'marco'
,'Anual' => 'ano'
,'Mensal' => 'mes'
,'Trimestral' => 'trimestre'
,'Bimestral' => 'bimestre'
,'Ciclos' => 'semestre'
];
/**
* @param PeriodoRepository $periodoRepository
*/
public function __construct(PeriodoRepository $periodoRepository)
{
$this->periodo = $periodoRepository;
}
/**
* @Route("/", name="periodo_componente")
*
* @param boolean $select_multiple
* @param boolean $modelagem
* @param string $request_referer
* @param string $modelo
* @return Response
*/
public function index(bool $select_multiple = FALSE, bool $modelagem = TRUE, string $request_referer = '') :Response
{
$modelo = $this->getModelagem()->getPrograma()->getEvs() ? 'evs' : 'gps';
// comportamento padrao
$periodoAtual = $this->getSession()->get('periodo');
$atual = $periodoAtual['from']['titulo'] ?? '';
$lastMesVisaoGestor = FALSE;
// quando solicita visualizacao do dashboard do avaliado pelo gestor
if ( FALSE === $select_multiple AND $this->hasAvaliado() AND array_key_exists('http_referer', $this->getAvaliado()) ) {
$periodoAtual['from']['periodo'] = $periodoAtual['to']['periodo'];
$atual = $periodoAtual['to']['titulo'];
$lastMesVisaoGestor = TRUE;
$select_multiple = false;
}
if ($request_referer == 'homologacao' || $request_referer == 'dados') {
$periodos = $this->periodo->listaPeriodosSemModelagem('', true, 'variavel');
} else {
$periodos = ( $this->hasModelagem() && $modelagem && $this->getSession()->get('visao') != 'gps_visao_gestor_rede_dashboard')
? $this->periodo->listaPeriodos($this->getModelagem()->getWhere(), $this->verificaAvaliado($modelagem), ($request_referer === 'gestor'), $modelo)
: $this->periodo->listaPeriodosSemModelagem($this->verificaAvaliado($modelagem), ($request_referer === 'gestor'), $modelo);
}
if ( isset($periodoAtual['to']) AND ($periodoAtual['from']['periodo'] != $periodoAtual['to']['periodo']) ) {
$atual = $atual.' à '.$periodoAtual['to']['titulo'];
}
$periodosReturn = [];
foreach ( $periodos as $periodo ) {
$periodosReturn[$periodo['tipo']][] = $periodo;
}
return $this->render('componentes/periodo/componente.html.twig', [
'multiplo' => $select_multiple,
'periodos' => $periodosReturn,
'atual' => $atual,
'lastMesVisaoGestor' => $lastMesVisaoGestor
,'referer' => $request_referer
]);
}
/**
* @Route("/processa", name="periodo_processa")
*
* @param null|mixed $periodoBruto
* @return JsonResponse
*/
public function processa(Request $request, $periodoBruto = null)
{
$periodoBruto = $periodoBruto ?? $request->query->all();
$referer = ( isset($periodoBruto['referer']) ) ? $periodoBruto['referer'] : NULL;
$periodoBruto = array_intersect_key($periodoBruto,['from' => NULL,'to' => NULL]);
foreach ( $periodoBruto as $key => $query ) {
$explode = explode('|', $query);
$selectedPeriodo = 'Anual' == $explode[0] ? $explode[2] : substr($explode[2], -2);
$periodo[$key] = [
'tipo' => $explode[0],
'tipo_alias' => $this->__getTipo($explode[0]),
'ano' => $explode[1],
'periodo' => $selectedPeriodo,
'titulo' => array_key_exists($selectedPeriodo, $this->periodosExtenso[$explode[0]]) ? $this->periodosExtenso[$explode[0]][$selectedPeriodo].' de '.$explode[1] : $selectedPeriodo.' de '.$explode[1],
];
}
$periodo['select'] = $this->__processaSelect($periodo);
$periodo['where'] = $this->__processaWhere($periodo);
$periodo['whereAnterior'] = $this->__processaWhereAnterior($periodo);
$periodo['whereSemRange'] = $this->__processaWhereSemRange($periodo);
$periodo['selectPeriodo'] = $this->__processaSelectPeriodo($periodo);
$periodo['tipoFiltro'] = $this->__getTipo($periodo['to']['tipo']);
$periodo['selectAnterior'] = $this->__getSelectAnterior($periodo);
$periodo['whereAvaliacao'] = $this->__processaWhereAvaliacao($periodo);
$this->getSession()->set('periodo', $periodo);
// quando avaliado
// refaz o a chave de periodo
if ( $this->hasAvaliado() AND count($this->getAvaliado()) > 0 AND ('avaliado' === $referer) ) {
$ano = $periodo['to']['ano'];
$mes = $periodo['to']['periodo'];
$sessAvaliado = $this->getAvaliado();
$sessAvaliado['periodo'] = ($ano * 100) + $mes;
$this->getSession()->set('avaliado', $sessAvaliado);
$this->getSession()->set('periodo_multiplo', FALSE);
unset($sessAvaliado);
} elseif ( 'gestor' === $referer ) {
$this->getSession()->set('visao_gestor_periodo', $periodo);
$this->getSession()->set('periodo_multiplo', TRUE);
} elseif ('gestor_rede' === $referer) {
$this->getSession()->set('visao_gestor_rede_periodo', $periodo);
$this->getSession()->set('periodo_multiplo', TRUE);
}
unset($periodo);
return new JsonResponse(['sucesso' => true, 'mensagem' => 'Período Configurado!']);
}
/**
* @param string $tipo
* @return string
*/
private function __getTipo($tipo)
{
return $this->periodos[$tipo];
}
/**
* @param array $periodos
* @return string
*/
private function __processaSelect(array $periodos): string
{
if ( 'Anual' === $periodos['from']['tipo'] ) {
return " (periodo->>'ano')::int AS periodo ";
}
if ( 'Marco' === $periodos['from']['tipo'] ){
return " (periodo->>'ano')::int AS periodo ";
}
return " CONCAT(periodo->>'ano', LPAD(periodo->>'periodo', 2, '0'))::int AS periodo ";
}
/**
* @param array $periodos
* @return string
*/
private function __processaWhere($periodos)
{
$whereReturn = " AND periodo->>'tipo' = '".$this->__getTipo($periodos['from']['tipo'])."'";
$whereData = '';
if ( 'Anual' === $periodos['from']['tipo'] ) {
$whereData .= $this->_whereAnual($periodos);
} elseif ( 'Marco' === $periodos['from']['tipo'] ) {
//@todo adicionar o periodo do marco
$whereData .= " AND (periodo->>'periodo')::text = '{$periodos['from']['periodo']}'";
} else {//quando for periodo com mes(es) e ano(s)
if ( $periodos['from']['ano'] == $periodos['to']['ano'] ) {//mesmo ano
$whereData .= " AND (periodo->>'ano')::int = {$periodos['from']['ano']}";
if ( $periodos['from']['periodo'] == $periodos['to']['periodo'] ) {
$whereData .= " AND (periodo->>'periodo')::int = {$periodos['from']['periodo']}";
} else {
$whereData .= " AND (periodo->>'periodo')::int BETWEEN {$periodos['from']['periodo']} AND {$periodos['to']['periodo']}";
}
} else {//anos diferentes
$a = strlen($periodos['from']['periodo']);
$b = strlen($periodos['to']['periodo']);
$perFrom = $a <= 1 ? '0'.$periodos['from']['periodo'] : $periodos['from']['periodo'];
$perTo = $b <= 1 ? '0'.$periodos['to']['periodo'] : $periodos['to']['periodo'];
$periodoFrom = $periodos['from']['ano'].$perFrom;
$periodoTo = $periodos['to']['ano'].$perTo;
$whereData .= " AND ((periodo->>'ano') || (periodo->>'periodo'))::int BETWEEN {$periodoFrom} AND {$periodoTo}";
}
}
return $whereReturn.$whereData;
}
/**
* @param array $periodos
* @return string
*/
private function __processaWhereAnterior($periodos)
{
$whereReturn = " AND periodo->>'tipo' = '".$this->__getTipo($periodos['from']['tipo'])."'";
$whereData = '';
if ( 'Anual' === $periodos['from']['tipo'] ) {
$whereData .= $this->_whereAnual($periodos);
} elseif ( 'Marco' === $periodos['from']['tipo'] ) {
//@todo adicionar o periodo do marco
" AND (periodo->>'ano')::int = {$periodos['from']['ano']}";
} else {//quando for periodo com mes(es) e ano(s)
if ($periodos['from']['ano'] == $periodos['to']['ano']) {//mesmo ano
//$whereData .= " AND (periodo->>'ano')::int = {$periodos['from']['ano']}";
if ( $periodos['from']['periodo'] == $periodos['to']['periodo'] ) {
//HELPER DATA
$p_atual = $periodos['from']['ano'].$periodos['from']['periodo'];
$p = DateHelper::geraSequenciaPeriodo(DateHelper::anterior($p_atual), $p_atual);
$whereData .= " AND ((periodo->>'ano') || (periodo->>'periodo'))::int IN({$p})";
} else {
$whereData .= " AND (periodo->>'periodo')::int BETWEEN {$periodos['from']['periodo']} AND {$periodos['to']['periodo']}";
}
} else {//anos diferentes
$a = strlen($periodos['from']['periodo']);
$b = strlen($periodos['to']['periodo']);
$perFrom = $a <= 1 ? '0'.$periodos['from']['periodo'] : $periodos['from']['periodo'];
$perTo = $b <= 1 ? '0'.$periodos['to']['periodo'] : $periodos['to']['periodo'];
$periodoFrom = $periodos['from']['ano'].$perFrom;
$periodoTo = $periodos['to']['ano'].$perTo;
$whereData .= " AND ((periodo->>'ano') || (periodo->>'periodo'))::int BETWEEN {$periodoFrom} AND {$periodoTo}";
}
}
return $whereReturn.$whereData;
}
/**
* @param array $periodos
* @return string
*/
private function __processaWhereSemRange($periodos)
{
return " AND periodo->>'tipo' = '".$this->__getTipo($periodos['from']['tipo'])."'";
}
/**
* @param array $periodos
* @return string
*/
private function __processaSelectPeriodo($periodos)
{
$tipo = $periodos['to']['tipo'];
switch ($tipo) {
case 'Anual':
$periodo = $periodos['to']['periodo'].'-01-01'; // formatação do periodo selecionado
$subitrair = '11 year'; // unidade a subtrair da data selecionada
$intervalo = '1 year'; // unidade a subtrair da data selecionada
$exibir = 'YYYY'; // forma a ser exibido o retorno
return sprintf("
To_Char(Generate_Series(
To_Char((('%s')::date - interval '%s'), 'YYYY-MM-DD')::timestamp
,timestamp '%s'
,interval '%s')::date
, '%s')::integer AS periodo",
$periodo,$subitrair,$periodo,$intervalo,$exibir
);
break;
case 'Mensal':
$periodo = $periodos['to']['ano'].'-'.substr($periodos['to']['periodo'], -2).'-01'; // formatação do periodo selecionado
$subitrair = '11 month'; // unidade a subtrair da data selecionada
$intervalo = '1 month'; // unidade a subtrair da data selecionada
$exibir = 'YYYYMM'; // forma a ser exibido o retorno
return sprintf("
To_Char(Generate_series(
To_Char((('%s')::date - interval '%s')
,'YYYY-MM-DD')::timestamp
,timestamp '%s'
, interval '%s')::date
,'%s')::integer AS periodo",
$periodo,
$subitrair,
$periodo,
$intervalo,
$exibir
);
break;
case 'Ciclos':
$periodo = $periodos['to']['ano'].'-'.('01' == substr($periodos['to']['periodo'], -2) ? '06' : '12').'-01'; // formatação do periodo selecionado
$subitrair = '71 month'; // unidade a subtrair da data selecionada
$intervalo = '6 month'; // unidade a subtrair da data selecionada
return sprintf(
"(CONCAT(ano, case when periodo between 1 and 6 then '01' else '02' end))::int as periodo FROM (
SELECT
To_Char(Generate_Series(
To_Char((('%s')::date - interval '%s'), 'YYYY-MM-DD')::timestamp
, timestamp '%s'
, interval '%s')::date, 'YYYY')::integer AS ano,
To_Char(Generate_Series(
To_Char((('%s')::date - interval '%s'), 'YYYY-MM-DD')::timestamp
, timestamp '%s'
, interval '%s')::date, 'MM')::integer AS periodo
) a",
$periodo,
$subitrair,
$periodo,
$intervalo,
$periodo,
$subitrair,
$periodo,
$intervalo
);
break;
case 'Marco':
$periodo = $periodos['to']['ano'].'-01-01'; // formatação do periodo selecionado
$subitrair = '11 year'; // unidade a subtrair da data selecionada
$intervalo = '1 year'; // unidade a subtrair da data selecionada
$exibir = 'YYYYMM'; // forma a ser exibido o retorno
return sprintf(
"to_char(Generate_Series(
to_char((('%s')::date - interval '%s'), 'YYYY-MM-DD')::timestamp
, timestamp '%s'
, interval '%s')::date, '%s')::integer AS periodo",
$periodo,
$subitrair,
$periodo,
$intervalo,
$exibir
);
break;
default:
// code...
break;
}
}
/**
* @param array $periodos
* @return string
*/
private function __getSelectAnterior($periodos)
{
$tipo = $periodos['to']['tipo'];
switch ($tipo) {
case 'Anual':
$periodo = date_create($periodos['to']['periodo'].'-01-01'); // formatação do periodo selecionado
$subitrair = '1 year'; // unidade a subtrair da data selecionada
$exibir = 'Y'; // forma a ser exibido o retorno
break;
case 'Mensal':
$periodo = date_create($periodos['to']['ano'].'-'.substr($periodos['to']['periodo'], -2).'-01'); // formatação do periodo selecionado
$subitrair = '1 month'; // unidade a subtrair da data selecionada
$exibir = 'm'; // forma a ser exibido o retorno
break;
case 'Ciclos':
$periodo = date_create($periodos['to']['ano'].'-'.('01' == substr($periodos['to']['periodo'], -2) ? '06' : '12').'-01'); // formatação do periodo selecionado
$subitrair = '11 month'; // unidade a subtrair da data selecionada
$exibir = 'm'; // forma a ser exibido o retorno
break;
case 'Marco':
$periodo = date_create($periodos['to']['ano'].'-01-01'); // formatação do periodo selecionado
$subitrair = '1 year'; // unidade a subtrair da data selecionada
$exibir = 'Y'; // forma a ser exibido o retorno
break;
default:
// code...
break;
}
return sprintf(
"AND (periodo->>'%s')::numeric IN (%s, %s)",
$periodos['tipoFiltro'],
$periodos['to']['periodo'],
date_format(date_sub($periodo, date_interval_create_from_date_string($subitrair)), $exibir)
);
}
/**
* @param bool $modelagem
* @return string
*/
public function verificaAvaliado($modelagem)
{
if ( $this->hasAvaliado() ) {
if ( $this->hasModelagem() AND $modelagem ) {
return sprintf(' AND id_avaliado = %d ', $this->getIdAvaliado());
}
return sprintf(' WHERE id_avaliado = %d', $this->getIdAvaliado());
}
return '';
}
/**
* @param array $periodos
* @return void
*/
private function _whereAnual(array $periodos)
{
if ( $periodos['from']['periodo'] == $periodos['to']['periodo'] ) {
return " AND (periodo->>'ano')::int = {$periodos['from']['periodo']}";
}
return " AND (periodo->>'ano')::int BETWEEN {$periodos['from']['periodo']} AND {$periodos['to']['periodo']}";
}
/**
* @param array $periodos
* @return string
*/
private function __processaWhereAvaliacao($periodos)
{
$whereReturn =
" AND avaliacao_inicio <= " . $periodos['from']['ano'].$periodos['from']['periodo'] . " AND avaliacao_fim >= " . $periodos['to']['ano'].$periodos['to']['periodo']
. " AND scorecard_inicio <= " . $periodos['from']['ano'].$periodos['from']['periodo'] . " AND scorecard_fim >= " . $periodos['to']['ano'].$periodos['to']['periodo']
;
return $whereReturn;
}
}