ya obtengo los datos de los anonimos, falta formatear esos datos y buscar

This commit is contained in:
2025-10-07 10:44:32 +02:00
parent 1e8f9cafb3
commit 389ac22b68
19 changed files with 205 additions and 93 deletions

View File

@ -3,16 +3,22 @@ package com.imprimelibros.erp.presupuesto;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import java.util.Arrays;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.TimeZone;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.validation.BindingResult;
@ -22,24 +28,21 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.http.MediaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.type.TypeReference;
import com.imprimelibros.erp.configuracion.margenes_presupuestos.MargenPresupuesto;
import com.imprimelibros.erp.datatables.DataTable;
import com.imprimelibros.erp.datatables.DataTablesParser;
import com.imprimelibros.erp.datatables.DataTablesRequest;
import com.imprimelibros.erp.datatables.DataTablesResponse;
import com.imprimelibros.erp.datatables.*;
import com.imprimelibros.erp.externalApi.skApiClient;
import com.imprimelibros.erp.i18n.TranslationService;
import com.imprimelibros.erp.presupuesto.Presupuesto.TipoCubierta;
import com.imprimelibros.erp.presupuesto.Presupuesto.TipoEncuadernacion;
import com.imprimelibros.erp.presupuesto.classes.ImagenPresupuesto;
import com.imprimelibros.erp.presupuesto.classes.PresupuestoMaquetacion;
import com.imprimelibros.erp.presupuesto.classes.PresupuestoMarcapaginas;
import com.imprimelibros.erp.presupuesto.dto.Presupuesto;
import com.imprimelibros.erp.presupuesto.dto.PresupuestoDTAnonimo;
import com.imprimelibros.erp.presupuesto.validation.PresupuestoValidationGroups;
import jakarta.servlet.http.HttpServletRequest;
@ -439,54 +442,87 @@ public class PresupuestoController {
return "imprimelibros/presupuestos/presupuesto-list";
}
@GetMapping(value = "/datatable/{tipo}", produces = "application/json")
@GetMapping(value = "/datatable/anonimos", produces = "application/json")
@ResponseBody
public DataTablesResponse<Map<String, Object>> datatable(@RequestParam("tipo") String tipo,
HttpServletRequest request, Authentication authentication,
public DataTablesResponse<Map<String, Object>> datatable(
HttpServletRequest request,
Authentication authentication,
Locale locale) {
DataTablesRequest dt = DataTablesParser.from(request);
List<String> searchable = List.of(
"id",
"titulo",
"cliente",
"tipoEncuadernacion",
"tipoCubierta",
"tipoImpresion",
"tirada",
"paginas",
"estado", "total", "pais", "region", "ciudad", "updatedAt");
// Filtros (opcional): p.ej. estado desde select extra
String fEstado = Optional.ofNullable(dt.raw.get("f_estado")).orElse(""); // '', 'borrador', ...
String term = (dt.search != null && dt.search.value != null) ? dt.search.value.trim() : "";
List<String> orderable = List.of(/*
* "id",
* "tipoEncuadernacion",
* "tipoCubierta",
* "tiradaMin",
* "tiradaMax",
* "margenMin",
* "margenMax"
*/);
// Pageable y Sort desde DataTables (usarás 'name' completos en el front)
int page = dt.length > 0 ? dt.start / dt.length : 0;
List<Sort.Order> orders = new ArrayList<>();
for (var o : dt.order) {
String field = dt.columns.get(o.column).name; // EJ: "cliente.nombre", "tipoImpresion", "pais"
// Whitelist de campos ordenables:
switch (field) {
case "id", "titulo",
"tipoEncuadernacion", "tipoCubierta", "tipoImpresion",
"selectedTirada", "paginas", "estado",
"totalConIva",
"pais", "region", "ciudad",
"updatedAt" ->
orders.add(new Sort.Order(
"desc".equalsIgnoreCase(o.dir) ? Sort.Direction.DESC : Sort.Direction.ASC,
field));
default -> {
/* ignora */ }
}
}
Sort sort = orders.isEmpty() ? Sort.by(Sort.Order.asc("id")) : Sort.by(orders);
Pageable pageable = dt.length > 0 ? PageRequest.of(page, dt.length, sort) : Pageable.unpaged();
Specification<MargenPresupuesto> base = (root, query, cb) -> cb.conjunction();
// Query DTO
Page<PresupuestoDTAnonimo> pageDTO = repo.datatableAnonimos(fEstado, term, pageable);
long total = repo.count();
return DataTable
.of(repo, MargenPresupuesto.class, dt, searchable) // 'searchable' en DataTable.java
// edita columnas "reales":
.orderable(orderable)
.add("actions", (presupuesto) -> {
return "<div class=\"hstack gap-3 flex-wrap\">\n" +
" <a href=\"javascript:void(0);\" data-id=\"" + presupuesto.getId()
+ "\" class=\"link-success btn-edit-" + tipo
+ " fs-15\"><i class=\"ri-edit-2-line\"></i></a>\n"
+ " <a href=\"javascript:void(0);\" data-id=\"" + presupuesto.getId()
+ "\" class=\"link-danger btn-delete-" + tipo
+ " fs-15\"><i class=\"ri-delete-bin-5-line\"></i></a>\n"
+ " </div>";
})
.where(base)
.toJson(total);
// para formatear la fecha
ZoneId zone = null;
if (locale != null && locale.getCountry() != null && !locale.getCountry().isEmpty()) {
zone = TimeZone.getTimeZone(locale.toLanguageTag()).toZoneId();
} else {
zone = ZoneId.systemDefault(); // fallback
}
DateTimeFormatter df = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm").withZone(zone);
// Mapear DTO -> Map para DataTables + acciones
List<Map<String, Object>> rows = pageDTO.getContent().stream().map(r -> {
Map<String, Object> m = new HashMap<>();
m.put("id", r.id());
m.put("titulo", r.titulo());
m.put("tipoEncuadernacion", r.tipoEncuadernacion().name()); // o etiqueta i18n si quieres
m.put("tipoCubierta", r.tipoCubierta().name());
m.put("tipoImpresion", r.tipoImpresion().name());
m.put("tirada", r.selectedTirada());
m.put("paginas", r.paginas());
m.put("estado", r.estado().name());
m.put("totalConIva", r.totalConIva());
m.put("pais", r.pais());
m.put("region", r.region());
m.put("ciudad", r.ciudad());
m.put("updatedAt", r.updatedAt() == null ? "" : df.format(r.updatedAt()));
// Mantén aquí tu “actions” como antes (puedes usar `tipo` en el css)
m.put("actions",
"<div class=\"hstack gap-3 flex-wrap\">" +
" <a href=\"javascript:void(0);\" data-id=\"" + r.id()
+ "\" class=\"link-success btn-edit-anonimo"
+ " fs-15\"><i class=\"ri-edit-2-line\"></i></a>" +
" <a href=\"javascript:void(0);\" data-id=\"" + r.id()
+ "\" class=\"link-danger btn-delete-anonimo"
+ " fs-15\"><i class=\"ri-delete-bin-5-line\"></i></a>" +
"</div>");
return m;
}).toList();
return new DataTablesResponse<>(dt.draw, total, pageDTO.getTotalElements(), rows);
}
}