Commit 6e3f6cce27d43274ddb70fddc17ec5b43d8885ab

Authored by Eduardo Santos
Committed by Eduardo Santos
1 parent bee7f236
Exists in master and in 1 other branch 3.1

Novo relatório de faturamento que agrupa os resultados pelo MAC Address, mostran…

…do explicitamente as informações que forem repetidas.
app/config/config.yml
... ... @@ -123,6 +123,9 @@ doctrine:
123 123 orm:
124 124 auto_generate_proxy_classes: "%kernel.debug%"
125 125 auto_mapping: true
  126 + dql:
  127 + string_functions:
  128 + string_agg: Cacic\CommonBundle\Query\PostgreSQL\StringAggFunction
126 129  
127 130 # Swiftmailer Configuration
128 131 swiftmailer:
... ...
src/Cacic/CommonBundle/Entity/LogAcessoRepository.php
... ... @@ -3,6 +3,7 @@
3 3 namespace Cacic\CommonBundle\Entity;
4 4  
5 5 use Doctrine\ORM\EntityRepository;
  6 +use Doctrine\ORM\Query\ResultSetMapping;
6 7  
7 8 /**
8 9 * LogAcessoRepository
... ... @@ -42,7 +43,7 @@ class LogAcessoRepository extends EntityRepository
42 43  
43 44 // Monta a Consulta básica...
44 45 $query = $this->createQueryBuilder('log')
45   - ->select('rede.idRede', 'rede.nmRede', 'rede.teIpRede', 'loc.nmLocal', 'loc.sgLocal', 'COUNT(DISTINCT log.idComputador) as numComp')
  46 + ->select('rede.idRede', 'rede.nmRede', 'rede.teIpRede', 'loc.nmLocal', 'loc.sgLocal', 'COUNT(DISTINCT comp.teNodeAddress) as numComp')
46 47 ->innerJoin('log.idComputador', 'comp')
47 48 ->innerJoin('comp.idRede', 'rede')
48 49 ->innerJoin('rede.idLocal', 'loc')
... ... @@ -63,29 +64,84 @@ class LogAcessoRepository extends EntityRepository
63 64  
64 65 return $query->getQuery()->execute();
65 66 }
66   - public function gerarRelatorioRede( $filtros, $idRede,$dataInicio, $dataFim )
  67 +
  68 +
  69 + public function gerarRelatorioRede( $filtros, $idRede, $dataInicio, $dataFim )
67 70 {
68   - $query = $this->createQueryBuilder('log')
69   - ->select('comp.idComputador', 'comp.nmComputador', 'comp.teNodeAddress','comp.teIpComputador', 'max(log.data) AS data', 'so.idSo', 'so.inMswindows', 'so.sgSo', 'rede.idRede', 'rede.nmRede', 'rede.teIpRede', 'local.nmLocal', 'local.idLocal')
70   - ->innerJoin('log.idComputador','comp')
71   - ->innerJoin('comp.idSo', 'so')
72   - ->innerJoin('comp.idRede','rede')
73   - ->innerJoin('rede.idLocal', 'local')
74   - ->groupBy('comp.idComputador', 'comp.nmComputador', 'comp.teNodeAddress','comp.teIpComputador', 'so.idSo', 'so.inMswindows', 'so.sgSo', 'rede.idRede', 'rede.nmRede', 'rede.teIpRede', 'local.nmLocal', 'local.idLocal');
  71 + $rsm = new ResultSetMapping();
  72 + $rsm->addScalarResult('te_node_address', 'teNodeAddress');
  73 + $rsm->addScalarResult('id_computador', 'idComputador');
  74 + $rsm->addScalarResult('te_ip_computador', 'teIpComputador');
  75 + $rsm->addScalarResult('nm_computador', 'nmComputador');
  76 + $rsm->addScalarResult('id_so', 'idSo');
  77 + $rsm->addScalarResult('sg_so', 'sgSo');
  78 + $rsm->addScalarResult('id_rede', 'idRede');
  79 + $rsm->addScalarResult('nm_rede', 'nmRede');
  80 + $rsm->addScalarResult('te_ip_rede', 'teIpRede');
  81 + $rsm->addScalarResult('max_data', 'data');
  82 + $rsm->addScalarResult('nm_local', 'nmLocal');
  83 + $rsm->addScalarResult('id_local', 'idLocal');
  84 +
  85 + $sql = "
  86 +SELECT c0_.te_node_address AS te_node_address,
  87 + string_agg(DISTINCT CAST(c0_.id_computador AS text), ', ') as id_computador,
  88 + string_agg(DISTINCT c0_.te_ip_computador, ', ') as te_ip_computador,
  89 + string_agg(DISTINCT c0_.nm_computador, ', ') AS nm_computador,
  90 + string_agg(DISTINCT CAST(s2_.id_so AS text), ', ') AS id_so,
  91 + string_agg(DISTINCT s2_.sg_so, ', ') AS sg_so,
  92 + string_agg(DISTINCT CAST(r3_.id_rede AS text), ', ') AS id_rede,
  93 + string_agg(DISTINCT r3_.nm_rede, ', ') AS nm_rede,
  94 + string_agg(DISTINCT r3_.te_ip_rede, ', ') AS te_ip_rede,
  95 + max(l1_.data) AS max_data,
  96 + l4_.nm_local AS nm_local,
  97 + l4_.id_local AS id_local
  98 +FROM log_acesso l1_
  99 +INNER JOIN computador c0_ ON l1_.id_computador = c0_.id_computador
  100 +INNER JOIN so s2_ ON c0_.id_so = s2_.id_so
  101 +INNER JOIN rede r3_ ON c0_.id_rede = r3_.id_rede
  102 +INNER JOIN local l4_ ON r3_.id_local = l4_.id_local
  103 +WHERE 1 = 1
  104 +";
75 105  
76 106 /**
77 107 * Verifica os filtros que foram parametrizados
78 108 */
79   - if ( $dataInicio )
80   - $query->andWhere( 'log.data >= :dtInicio' )->setParameter('dtInicio', ( $dataInicio.' 00:00:00' ));
  109 + if ( $dataInicio ) {
  110 + $sql .= " AND l1_.data >= ? ";
  111 + }
  112 +
  113 + if ( $dataFim ) {
  114 + $sql .= " AND l1_.data <= ?";
  115 + }
  116 +
  117 + if ( $idRede ) {
  118 + $sql .= " AND c0_.id_rede IN (?)";
  119 + }
  120 +
  121 + $sql .= "
  122 +GROUP BY c0_.te_node_address,
  123 + l4_.nm_local,
  124 + l4_.id_local
  125 + ";
  126 +
  127 + $query = $this->getEntityManager()->createNativeQuery($sql, $rsm);
  128 +
  129 + /**
  130 + * Verifica os filtros que foram parametrizados
  131 + */
  132 + if ( $dataInicio ) {
  133 + $query->setParameter(1, ( $dataInicio.' 00:00:00' ));
  134 + }
  135 +
81 136  
82 137 if ( $dataFim )
83   - $query->andWhere( 'log.data <= :dtFim' )->setParameter('dtFim', ( $dataFim.' 23:59:59' ));
  138 + $query->setParameter(2, ( $dataFim.' 23:59:59' ));
84 139  
85   - if ( ($idRede) )
86   - $query->andWhere( 'comp.idRede IN (:rede)' )->setParameter('rede', $idRede);
  140 + if ( $idRede )
  141 + $query->setParameter(3, $idRede);
87 142  
88   - return $query->getQuery()->execute();
  143 +
  144 + return $query->execute();
89 145 }
90 146  
91 147 /**
... ... @@ -97,7 +153,7 @@ class LogAcessoRepository extends EntityRepository
97 153 public function countPorComputador() {
98 154  
99 155 $query = $this->createQueryBuilder('log')
100   - ->select('COUNT(DISTINCT comp.idComputador)')
  156 + ->select('COUNT(DISTINCT comp.teNodeAddress)')
101 157 ->innerJoin('CacicCommonBundle:Computador','comp', 'WITH', 'log.idComputador = comp.idComputador')
102 158 ->andWhere( 'log.data >= (current_date() - 30)' );
103 159  
... ... @@ -107,12 +163,13 @@ class LogAcessoRepository extends EntityRepository
107 163  
108 164 return $query->execute();
109 165 }
  166 +
110 167 public function faturamentoCsv( $dataInicio, $dataFim, $locais )
111 168 {
112 169  
113 170 // Monta a Consulta básica...
114 171 $query = $this->createQueryBuilder('log')
115   - ->select( 'loc.nmLocal', 'rede.nmRede', 'rede.teIpRede', 'COUNT(DISTINCT log.idComputador) as numComp')
  172 + ->select( 'loc.nmLocal', 'rede.nmRede', 'rede.teIpRede', 'COUNT(DISTINCT comp.teNodeAddress) as numComp')
116 173 ->innerJoin('log.idComputador', 'comp')
117 174 ->innerJoin('comp.idRede', 'rede')
118 175 ->innerJoin('rede.idLocal', 'loc')
... ... @@ -133,29 +190,74 @@ class LogAcessoRepository extends EntityRepository
133 190  
134 191 return $query->getQuery()->execute();
135 192 }
  193 +
136 194 public function listarCsv( $filtros, $idRede, $dataInicio, $dataFim )
137 195 {
138   - $query = $this->createQueryBuilder('log')
139   - ->select('comp.nmComputador', 'comp.teNodeAddress','comp.teIpComputador', 'so.sgSo', 'local.nmLocal', 'rede.nmRede','max(log.data) AS data')
140   - ->innerJoin('log.idComputador','comp')
141   - ->innerJoin('comp.idSo', 'so')
142   - ->innerJoin('comp.idRede','rede')
143   - ->innerJoin('rede.idLocal', 'local')
144   - ->groupBy( 'comp.idComputador', 'comp.nmComputador', 'comp.teNodeAddress','comp.teIpComputador', 'so.idSo', 'so.inMswindows', 'so.sgSo', 'rede.idRede', 'rede.nmRede', 'rede.teIpRede', 'local.nmLocal', 'local.idLocal');
  196 +
  197 + $rsm = new ResultSetMapping();
  198 + $rsm->addScalarResult('nm_computador', 'nmComputador');
  199 + $rsm->addScalarResult('te_node_address', 'teNodeAddress');
  200 + $rsm->addScalarResult('te_ip_computador', 'teIpComputador');
  201 + $rsm->addScalarResult('sg_so', 'sgSo');
  202 + $rsm->addScalarResult('nm_local', 'nmLocal');
  203 + $rsm->addScalarResult('nm_rede', 'nmRede');
  204 + $rsm->addScalarResult('max_data', 'data');
  205 +
  206 + $sql = "
  207 +SELECT c0_.te_node_address AS te_node_address,
  208 + string_agg(DISTINCT c0_.te_ip_computador, ', ') as te_ip_computador,
  209 + string_agg(DISTINCT c0_.nm_computador, ', ') AS nm_computador,
  210 + string_agg(DISTINCT s2_.sg_so, ', ') AS sg_so,
  211 + string_agg(DISTINCT r3_.nm_rede, ', ') AS nm_rede,
  212 + max(l1_.data) AS max_data,
  213 + l4_.nm_local AS nm_local
  214 +FROM log_acesso l1_
  215 +INNER JOIN computador c0_ ON l1_.id_computador = c0_.id_computador
  216 +INNER JOIN so s2_ ON c0_.id_so = s2_.id_so
  217 +INNER JOIN rede r3_ ON c0_.id_rede = r3_.id_rede
  218 +INNER JOIN local l4_ ON r3_.id_local = l4_.id_local
  219 +WHERE 1 = 1
  220 +";
145 221  
146 222 /**
147 223 * Verifica os filtros que foram parametrizados
148 224 */
149   - if ( $dataInicio )
150   - $query->andWhere( 'log.data >= :dtInicio' )->setParameter('dtInicio', ( $dataInicio.' 00:00:00' ));
  225 + if ( $dataInicio ) {
  226 + $sql .= " AND l1_.data >= ? ";
  227 + }
  228 +
  229 + if ( $dataFim ) {
  230 + $sql .= " AND l1_.data <= ?";
  231 + }
  232 +
  233 + if ( $idRede ) {
  234 + $sql .= " AND c0_.id_rede IN (?)";
  235 + }
  236 +
  237 + $sql .= "
  238 +GROUP BY c0_.te_node_address,
  239 + l4_.nm_local,
  240 + l4_.id_local
  241 + ";
  242 +
  243 + $query = $this->getEntityManager()->createNativeQuery($sql, $rsm);
  244 +
  245 + /**
  246 + * Verifica os filtros que foram parametrizados
  247 + */
  248 + if ( $dataInicio ) {
  249 + $query->setParameter(1, ( $dataInicio.' 00:00:00' ));
  250 + }
  251 +
151 252  
152 253 if ( $dataFim )
153   - $query->andWhere( 'log.data <= :dtFim' )->setParameter('dtFim', ( $dataFim.' 23:59:59' ));
  254 + $query->setParameter(2, ( $dataFim.' 23:59:59' ));
154 255  
155   - if ( count($idRede) )
156   - $query->andWhere( 'comp.idRede IN (:rede)' )->setParameter('rede', $idRede);
  256 + if ( $idRede )
  257 + $query->setParameter(3, $idRede);
157 258  
158   - return $query->getQuery()->execute();
  259 +
  260 + return $query->execute();
159 261 }
160 262  
161 263 }
... ...
src/Cacic/CommonBundle/Query/PostgreSQL/StringAggFunction.php 0 → 100644
... ... @@ -0,0 +1,40 @@
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: eduardo
  5 + * Date: 26/06/14
  6 + * Time: 00:08
  7 + */
  8 +
  9 +namespace Cacic\CommonBundle\Query\PostgreSQL;
  10 +
  11 +use Doctrine\ORM\Query\AST\Functions\FunctionNode;
  12 +use Doctrine\ORM\Query\Lexer;
  13 +use Doctrine\ORM\Query\Parser;
  14 +use Doctrine\ORM\Query\SqlWalker;
  15 +
  16 +/**
  17 + * Class StringAggFunction
  18 + * @package Cacic\CommonBundle\Query\PostgreSQL
  19 + *
  20 + * Extracted from http://pierrickcaen.fr/blog/symfony-sql-functions.html
  21 + */
  22 +
  23 +class StringAggFunction extends FunctionNode
  24 +{
  25 + public function getSql(SqlWalker $sqlWalker)
  26 + {
  27 + return 'string_agg(' . $this->expression->dispatch($sqlWalker) . ',' . $this->delimiter->dispatch($sqlWalker) .')';
  28 + }
  29 +
  30 + public function parse(Parser $parser)
  31 + {
  32 + $parser->match(Lexer::T_IDENTIFIER);
  33 + $parser->match(Lexer::T_OPEN_PARENTHESIS);
  34 + $parser->match(Lexer::T_DISTINCT);
  35 + $this->expression = $parser->ArithmeticPrimary();
  36 + $parser->match(Lexer::T_COMMA);
  37 + $this->delimiter = $parser->ArithmeticPrimary();
  38 + $parser->match(Lexer::T_CLOSE_PARENTHESIS);
  39 + }
  40 +}
0 41 \ No newline at end of file
... ...
src/Cacic/RelatorioBundle/Controller/FaturamentoController.php
... ... @@ -12,6 +12,7 @@
12 12 use Ddeboer\DataImport\Writer\CsvWriter;
13 13 use Ddeboer\DataImport\ValueConverter\CallbackValueConverter;
14 14 use Symfony\Component\HttpFoundation\BinaryFileResponse;
  15 + use Cacic\CommonBundle\Form\Type\ComputadorConsultaType;
15 16  
16 17  
17 18 class FaturamentoController extends Controller {
... ... @@ -323,4 +324,30 @@
323 324 $response->headers->set('Content-Disposition', 'attachment; filename="Não Coletadas.csv"');
324 325 $response->headers->set('Content-Transfer-Encoding', 'binary');
325 326 }
  327 +
  328 + /**
  329 + * Search computer with params
  330 + *
  331 + * @param Request $request
  332 + * @return \Symfony\Component\HttpFoundation\Response
  333 + */
  334 + public function computadorAction( Request $request )
  335 + {
  336 + $locale = $request->getLocale();
  337 + $data = $request->query->all();
  338 +
  339 + $form = $this->createForm( new ComputadorConsultaType() );
  340 +
  341 + $computadores = $this->getDoctrine()->getRepository( 'CacicCommonBundle:Computador')
  342 + ->selectIp($data['teIpComputador'],$data['nmComputador'] ,$data['teNodeAddress'] );
  343 +
  344 +
  345 + return $this->render( 'CacicCommonBundle:Computador:buscar.html.twig',
  346 + array(
  347 + 'local'=>$locale ,
  348 + 'form' => $form->createView(),
  349 + 'computadores' => ( $computadores )
  350 + )
  351 + );
  352 + }
326 353 }
... ...
src/Cacic/RelatorioBundle/Resources/config/routing.yml
... ... @@ -175,4 +175,8 @@ cacic_relatorio_csv_hardware_wmi:
175 175  
176 176 cacic_relatorio_csv_hardware_wmi_detalhe:
177 177 pattern: /csv/hardware/{classe}/{propriedade}
178   - defaults: { _controller: CacicRelatorioBundle:Hardware:csvWMIRelatorioDetalhe }
179 178 \ No newline at end of file
  179 + defaults: { _controller: CacicRelatorioBundle:Hardware:csvWMIRelatorioDetalhe }
  180 +
  181 +cacic_faturamento_computador:
  182 + pattern: /faturamento/computador
  183 + defaults: { _controller: CacicRelatorioBundle:Faturamento:computador }
180 184 \ No newline at end of file
... ...
src/Cacic/RelatorioBundle/Resources/views/Faturamento/listar.html.twig
... ... @@ -10,7 +10,6 @@
10 10 <table class="display datatable" id="datatable">
11 11 <thead>
12 12 <tr>
13   - <th width="5%" style="text-align: center"></th>
14 13 <th width="15%">{{ "Computador"|trans }}</th>
15 14 <th width="10%">{{ "MAC Address"|trans }}</th>
16 15 <th width="10%">{{ "Endereço IP"|trans }}</th>
... ... @@ -23,14 +22,26 @@
23 22  
24 23 <tbody>
25 24 {% for reg in dados %}
  25 + {% set computadores = reg.idComputador|split(',') %}
  26 + {% set nomes = reg.nmComputador|split(',') %}
  27 + {% set ips = reg.teIpComputador|split(',') %}
26 28 <tr>
27   - <td style="text-align: center">{{ loop.index }}</td>
28 29 <td>
29   - <b><a href="{{ path('cacic_computador_detalhar') }}/{{ reg.idComputador }}" title="{{ "Todas as informações do computador"|trans }}" target="_blank">{{ reg.nmComputador }}</a></b>
  30 + {% for comp in nomes %}
  31 + <b><a href="{{ path('cacic_faturamento_computador', {'nmComputador' : comp|trim }) }}" title="{{ 'Detalhar computador'|trans }}" target="_blank">{{ comp }}</a></b>
  32 + {% else %}
  33 + <b>{{ reg.nmComputador }}</b>
  34 + {% endfor %}
30 35 </td>
31   - <td><a href="{{ path('cacic_computador_detalhar') }}/{{ reg.idComputador }}" title="{{ "Todas as informações do computador"|trans }}" target="_blank">{{ reg.teNodeAddress }}</a></td>
32   - <td><a href="{{ path('cacic_computador_detalhar') }}/{{ reg.idComputador }}" title="{{ "Todas as informações do computador"|trans }}" target="_blank">{{ reg.teIpComputador }}</a></td>
33   - <td><span class="{% if reg.inMswindows == 'S' %}red{% else %}blue{% endif %}">{{ reg.sgSo }}</span></td>
  36 + <td><a href="{{ path('cacic_faturamento_computador', {'teNodeAddress' : reg.teNodeAddress|trim }) }}" title="{{ 'Detalhar computador'|trans }}" target="_blank">{{ reg.teNodeAddress }}</a></td>
  37 + <td>
  38 + {% for comp in ips %}
  39 + <b><a href="{{ path('cacic_faturamento_computador', {'teIpComputador' : comp|trim }) }}" title="{{ 'Detalhar computador'|trans }}" target="_blank">{{ comp }}</a></b>
  40 + {% else %}
  41 + <b>{{ reg.teIpComputador }}</b>
  42 + {% endfor %}
  43 + </td>
  44 + <td>{{ reg.sgSo }}</td>
34 45 <td>{{ reg.nmLocal }}</td>
35 46 <td>{{ reg.nmRede }} / {{ reg.teIpRede }}</td>
36 47 <td>{{ reg.data|date(' d, M, Y H:m:s') }}</td>
... ...