package com.algaworks.pedidovenda.repository; import java.io.Serializable; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Map; import java.util.TreeMap; import javax.inject.Inject; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.From; import javax.persistence.criteria.Join; import javax.persistence.criteria.JoinType; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateUtils; import com.algaworks.pedidovenda.model.Cliente; import com.algaworks.pedidovenda.model.Pedido; import com.algaworks.pedidovenda.model.Usuario; import com.algaworks.pedidovenda.model.vo.DataValor; import com.algaworks.pedidovenda.repository.filter.PedidoFilter; public class Pedidos implements Serializable { private static final long serialVersionUID = 1L; @Inject private EntityManager manager; public Map<Date, BigDecimal> valoresTotaisPorData(Integer numeroDeDias, Usuario criadoPor) { numeroDeDias -= 1; Calendar dataInicial = Calendar.getInstance(); dataInicial = DateUtils.truncate(dataInicial, Calendar.DAY_OF_MONTH); dataInicial.add(Calendar.DAY_OF_MONTH, numeroDeDias * -1); Map<Date, BigDecimal> resultado = criarMapaVazio(numeroDeDias, dataInicial); String jpql = "select new com.algaworks.pedidovenda.model.vo.DataValor(date(p.dataCriacao), sum(p.valorTotal)) " + "from Pedido p where p.dataCriacao >= :dataInicial "; if (criadoPor != null) { jpql += "and p.vendedor = :vendedor "; } jpql += "group by date(dataCriacao)"; TypedQuery<DataValor> query = manager.createQuery(jpql, DataValor.class); query.setParameter("dataInicial", dataInicial.getTime()); if (criadoPor != null) { query.setParameter("vendedor", criadoPor); } List<DataValor> valoresPorData = query.getResultList(); for (DataValor dataValor : valoresPorData) { resultado.put(dataValor.getData(), dataValor.getValor()); } return resultado; } private Map<Date, BigDecimal> criarMapaVazio(Integer numeroDeDias, Calendar dataInicial) { dataInicial = (Calendar) dataInicial.clone(); Map<Date, BigDecimal> mapaInicial = new TreeMap<>(); for (int i = 0; i <= numeroDeDias; i++) { mapaInicial.put(dataInicial.getTime(), BigDecimal.ZERO); dataInicial.add(Calendar.DAY_OF_MONTH, 1); } return mapaInicial; } private List<Predicate> criarPredicatesParaFiltro(PedidoFilter filtro, Root<Pedido> pedidoRoot, From<?, ?> clienteJoin, From<?, ?> vendedorJoin) { CriteriaBuilder builder = manager.getCriteriaBuilder(); List<Predicate> predicates = new ArrayList<>(); if (filtro.getNumeroDe() != null) { predicates.add(builder.greaterThanOrEqualTo(pedidoRoot.get("id"), filtro.getNumeroDe())); } if (filtro.getNumeroAte() != null) { predicates.add(builder.lessThanOrEqualTo(pedidoRoot.get("id"), filtro.getNumeroAte())); } if (filtro.getDataCriacaoDe() != null) { predicates.add(builder.greaterThanOrEqualTo(pedidoRoot.get("dataCriacao"), filtro.getDataCriacaoDe())); } if (filtro.getDataCriacaoAte() != null) { predicates.add(builder.lessThanOrEqualTo(pedidoRoot.get("dataCriacao"), filtro.getDataCriacaoAte())); } if (StringUtils.isNotBlank(filtro.getNomeCliente())) { predicates.add(builder.like(clienteJoin.get("nome"), "%" + filtro.getNomeCliente() + "%")); } if (StringUtils.isNotBlank(filtro.getNomeVendedor())) { predicates.add(builder.like(vendedorJoin.get("nome"), "%" + filtro.getNomeVendedor() + "%")); } if (filtro.getStatuses() != null && filtro.getStatuses().length > 0) { predicates.add(pedidoRoot.get("status").in(Arrays.asList(filtro.getStatuses()))); } return predicates; } public List<Pedido> filtrados(PedidoFilter filtro) { From<?, ?> orderByFromEntity = null; CriteriaBuilder builder = manager.getCriteriaBuilder(); CriteriaQuery<Pedido> criteriaQuery = builder.createQuery(Pedido.class); Root<Pedido> pedidoRoot = criteriaQuery.from(Pedido.class); From<?, ?> clienteJoin = (From<?, ?>) pedidoRoot.fetch("cliente", JoinType.INNER); From<?, ?> vendedorJoin = (From<?, ?>) pedidoRoot.fetch("vendedor", JoinType.INNER); List<Predicate> predicates = criarPredicatesParaFiltro(filtro, pedidoRoot, clienteJoin, vendedorJoin); criteriaQuery.select(pedidoRoot); criteriaQuery.where(predicates.toArray(new Predicate[0])); if (filtro.getPropriedadeOrdenacao() != null) { String nomePropriedadeOrdenacao = filtro.getPropriedadeOrdenacao(); orderByFromEntity = pedidoRoot; if (filtro.getPropriedadeOrdenacao().contains(".")) { nomePropriedadeOrdenacao = nomePropriedadeOrdenacao.substring( filtro.getPropriedadeOrdenacao().indexOf(".") + 1); } if (filtro.getPropriedadeOrdenacao().startsWith("cliente.")) { orderByFromEntity = clienteJoin; } if (filtro.isAscendente() && filtro.getPropriedadeOrdenacao() != null) { criteriaQuery.orderBy(builder.asc(orderByFromEntity.get(nomePropriedadeOrdenacao))); } else if (filtro.getPropriedadeOrdenacao() != null) { criteriaQuery.orderBy(builder.desc(orderByFromEntity.get(nomePropriedadeOrdenacao))); } } TypedQuery<Pedido> query = manager.createQuery(criteriaQuery); query.setFirstResult(filtro.getPrimeiroRegistro()); query.setMaxResults(filtro.getQuantidadeRegistros()); return query.getResultList(); } public int quantidadeFiltrados(PedidoFilter filtro) { CriteriaBuilder builder = manager.getCriteriaBuilder(); CriteriaQuery<Long> criteriaQuery = builder.createQuery(Long.class); Root<Pedido> pedidoRoot = criteriaQuery.from(Pedido.class); Join<Pedido, Cliente> clienteJoin = pedidoRoot.join("cliente", JoinType.INNER); Join<Pedido, Cliente> vendedorJoin = pedidoRoot.join("vendedor", JoinType.INNER); List<Predicate> predicates = criarPredicatesParaFiltro(filtro, pedidoRoot, clienteJoin, vendedorJoin); criteriaQuery.select(builder.count(pedidoRoot)); criteriaQuery.where(predicates.toArray(new Predicate[0])); TypedQuery<Long> query = manager.createQuery(criteriaQuery); return query.getSingleResult().intValue(); } public Pedido guardar(Pedido pedido) { return this.manager.merge(pedido); } public Pedido porId(Long id) { return this.manager.find(Pedido.class, id); } }