diff --git a/src/main/java/com/imprimelibros/erp/pedidos/PedidoDireccionRepository.java b/src/main/java/com/imprimelibros/erp/pedidos/PedidoDireccionRepository.java index fc67cff..8033dc0 100644 --- a/src/main/java/com/imprimelibros/erp/pedidos/PedidoDireccionRepository.java +++ b/src/main/java/com/imprimelibros/erp/pedidos/PedidoDireccionRepository.java @@ -13,7 +13,7 @@ public interface PedidoDireccionRepository extends JpaRepository findByPedidoLinea(PedidoLinea pedidoLinea); - PedidoDireccion findByPedidoIdAndFacturacionTrue(Long pedidoId); + PedidoDireccion findFirstByPedidoIdAndFacturacionTrue(Long pedidoId); @Query(""" select distinct d diff --git a/src/main/java/com/imprimelibros/erp/pedidos/PedidoService.java b/src/main/java/com/imprimelibros/erp/pedidos/PedidoService.java index d99218e..1a59055 100644 --- a/src/main/java/com/imprimelibros/erp/pedidos/PedidoService.java +++ b/src/main/java/com/imprimelibros/erp/pedidos/PedidoService.java @@ -69,7 +69,7 @@ public class PedidoService { } public PedidoDireccion getPedidoDireccionFacturacionByPedidoId(Long pedidoId) { - return pedidoDireccionRepository.findByPedidoIdAndFacturacionTrue(pedidoId); + return pedidoDireccionRepository.findFirstByPedidoIdAndFacturacionTrue(pedidoId); } @Transactional @@ -206,7 +206,7 @@ public class PedidoService { Pedido pedido = pedidoRepository.findById(pedidoId).orElse(null); if (pedido != null) { - PedidoDireccion direccionPedido = pedidoDireccionRepository.findByPedidoIdAndFacturacionTrue(pedidoId); + PedidoDireccion direccionPedido = pedidoDireccionRepository.findFirstByPedidoIdAndFacturacionTrue(pedidoId); if (direccionPedido == null) { // crear @@ -253,7 +253,7 @@ public class PedidoService { } public PedidoDireccion getDireccionFacturacionPedido(Long pedidoId) { - return pedidoDireccionRepository.findByPedidoIdAndFacturacionTrue(pedidoId); + return pedidoDireccionRepository.findFirstByPedidoIdAndFacturacionTrue(pedidoId); } public List getDireccionesEntregaPedidoLinea(Long pedidoLineaId) { diff --git a/src/main/java/com/imprimelibros/erp/pedidos/PedidosController.java b/src/main/java/com/imprimelibros/erp/pedidos/PedidosController.java index 442cf50..03c5d65 100644 --- a/src/main/java/com/imprimelibros/erp/pedidos/PedidosController.java +++ b/src/main/java/com/imprimelibros/erp/pedidos/PedidosController.java @@ -12,6 +12,7 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.stream.Collectors; import org.springframework.context.MessageSource; import org.springframework.core.io.ByteArrayResource; @@ -33,11 +34,14 @@ import com.imprimelibros.erp.users.UserDao; import jakarta.persistence.criteria.Join; import jakarta.persistence.criteria.JoinType; +import jakarta.persistence.criteria.Subquery; import jakarta.servlet.http.HttpServletRequest; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.PostMapping; +import com.imprimelibros.erp.presupuesto.dto.Presupuesto; + @Controller @RequestMapping("/pedidos") public class PedidosController { @@ -106,6 +110,7 @@ public class PedidosController { "id", "createdBy.fullName", "createdAt", + "titulos", "total", "estado"); @@ -113,8 +118,10 @@ public class PedidosController { if (!isAdmin) { base = base.and((root, query, cb) -> cb.equal(root.get("createdBy").get("id"), currentUserId)); } + String clientSearch = dt.getColumnSearch("cliente"); String estadoSearch = dt.getColumnSearch("estado"); + String titulosSearch = dt.getColumnSearch("titulos"); // 2) Si hay filtro, traducirlo a userIds y añadirlo al Specification if (clientSearch != null) { @@ -146,11 +153,45 @@ public class PedidosController { base = base.and((root, query, cb) -> cb.disjunction()); } } + if (titulosSearch != null && !titulosSearch.isBlank()) { + String like = "%" + titulosSearch.trim().toLowerCase() + "%"; + base = base.and((root, query, cb) -> { + Subquery minLineaIdSq = query.subquery(Long.class); + var plMin = minLineaIdSq.from(PedidoLinea.class); + minLineaIdSq.select(cb.min(plMin.get("id"))); + minLineaIdSq.where(cb.equal(plMin.get("pedido"), root)); + + Subquery firstTitleSq = query.subquery(String.class); + var plFirst = firstTitleSq.from(PedidoLinea.class); + var prFirst = plFirst.join("presupuesto", JoinType.LEFT); + firstTitleSq.select(cb.lower(cb.coalesce(prFirst.get("titulo"), ""))); + firstTitleSq.where( + cb.equal(plFirst.get("pedido"), root), + cb.equal(plFirst.get("id"), minLineaIdSq)); + + return cb.like(firstTitleSq, like); + }); + } Long total = repoPedido.count(base); return DataTable .of(repoPedido, Pedido.class, dt, searchable) .orderable(orderable) + .orderable("titulos", (root, query, cb) -> { + Subquery minLineaIdSq = query.subquery(Long.class); + var plMin = minLineaIdSq.from(PedidoLinea.class); + minLineaIdSq.select(cb.min(plMin.get("id"))); + minLineaIdSq.where(cb.equal(plMin.get("pedido"), root)); + + Subquery firstTitleSq = query.subquery(String.class); + var plFirst = firstTitleSq.from(PedidoLinea.class); + var prFirst = plFirst.join("presupuesto", JoinType.LEFT); + firstTitleSq.select(cb.lower(cb.coalesce(prFirst.get("titulo"), ""))); + firstTitleSq.where( + cb.equal(plFirst.get("pedido"), root), + cb.equal(plFirst.get("id"), minLineaIdSq)); + return firstTitleSq; + }) .add("id", Pedido::getId) .add("created_at", pedido -> Utils.formatInstant(pedido.getCreatedAt(), locale)) .add("cliente", pedido -> { @@ -166,6 +207,38 @@ public class PedidosController { return ""; } }) + .add("titulos", pedido -> { + List lineas = repoPedidoLinea.findByPedidoIdOrderByIdAsc(pedido.getId()); + if (lineas.isEmpty()) { + return ""; + } + + List presupuestos = lineas.stream() + .map(PedidoLinea::getPresupuesto) + .filter(presupuesto -> presupuesto != null) + .collect(Collectors.toList()); + if (presupuestos.isEmpty()) { + return ""; + } + + String primerTitulo = presupuestos.get(0).getTitulo(); + if (primerTitulo == null) { + primerTitulo = ""; + } else { + primerTitulo = primerTitulo.trim(); + } + + int extras = presupuestos.size() - 1; + if (extras <= 0) { + return primerTitulo; + } + + String suffix = messageSource.getMessage( + "pedido.table.titulos.and-more", + new Object[] { extras }, + locale); + return primerTitulo + " " + suffix; + }) .add("estado", pedido -> { List lineas = repoPedidoLinea.findByPedidoId(pedido.getId()); if (lineas.isEmpty()) { @@ -446,4 +519,4 @@ public class PedidosController { } } -} \ No newline at end of file +} diff --git a/src/main/resources/i18n/pedidos_es.properties b/src/main/resources/i18n/pedidos_es.properties index 21648e1..d097a9f 100644 --- a/src/main/resources/i18n/pedidos_es.properties +++ b/src/main/resources/i18n/pedidos_es.properties @@ -47,6 +47,8 @@ pedido.prueba=Prueba pedido.table.id=Num. Pedido pedido.table.cliente=Cliente pedido.table.fecha=Fecha +pedido.table.titulos=Títulos +pedido.table.titulos.and-more=y {0} m\u00E1s pedido.table.importe=Importe pedido.table.estado=Estado pedido.table.acciones=Acciones @@ -73,4 +75,4 @@ pedido.errors.connecting-server-error=Error al conectar con el servidor externo. pedido.errors.cannot-update=No se puede actualizar el estado de una línea con ese estado inicial. pedido.success.estado-actualizado=Estado del pedido actualizado correctamente. pedido.success.same-estado=Sin cambios en el estado. -pedido.success.pedido-cancelado=Pedido cancelado correctamente. \ No newline at end of file +pedido.success.pedido-cancelado=Pedido cancelado correctamente. diff --git a/src/main/resources/static/assets/js/pages/imprimelibros/pedidos/pedidos-admin.js b/src/main/resources/static/assets/js/pages/imprimelibros/pedidos/pedidos-admin.js index 48616ef..c48288d 100644 --- a/src/main/resources/static/assets/js/pages/imprimelibros/pedidos/pedidos-admin.js +++ b/src/main/resources/static/assets/js/pages/imprimelibros/pedidos/pedidos-admin.js @@ -48,6 +48,7 @@ $(() => { { data: 'id', name: 'id', orderable: true }, { data: 'cliente', name: 'createdBy.fullName', orderable: true }, { data: 'created_at', name: 'createdAt', orderable: true }, + { data: 'titulos', name: 'titulos', orderable: true }, { data: 'total', name: 'total', orderable: true }, { data: 'estado', name: 'estado', orderable: true }, { data: 'actions', name: 'actions', orderable: false, searchable: false } diff --git a/src/main/resources/static/assets/js/pages/imprimelibros/pedidos/pedidos.js b/src/main/resources/static/assets/js/pages/imprimelibros/pedidos/pedidos.js index 714e19d..277e27f 100644 --- a/src/main/resources/static/assets/js/pages/imprimelibros/pedidos/pedidos.js +++ b/src/main/resources/static/assets/js/pages/imprimelibros/pedidos/pedidos.js @@ -47,6 +47,7 @@ $(() => { columns: [ { data: 'id', name: 'id', orderable: true }, { data: 'created_at', name: 'createdAt', orderable: true }, + { data: 'titulos', name: 'titulos', orderable: true }, { data: 'total', name: 'total', orderable: true }, { data: 'estado', name: 'estado', orderable: true }, { data: 'actions', name: 'actions', orderable: false, searchable: false } diff --git a/src/main/resources/templates/imprimelibros/pedidos/pedidos-list-cliente.html b/src/main/resources/templates/imprimelibros/pedidos/pedidos-list-cliente.html index d988e73..377e71f 100644 --- a/src/main/resources/templates/imprimelibros/pedidos/pedidos-list-cliente.html +++ b/src/main/resources/templates/imprimelibros/pedidos/pedidos-list-cliente.html @@ -37,6 +37,7 @@ Num. Pedido Fecha + Títulos Importe Estado Acciones @@ -44,6 +45,7 @@ + +