Files
erp-imprimelibros/src/main/java/com/imprimelibros/erp/presupuesto/PresupuestoDatatableService.java

133 lines
6.1 KiB
Java

package com.imprimelibros.erp.presupuesto;
import com.imprimelibros.erp.common.Utils;
import com.imprimelibros.erp.datatables.*;
import com.imprimelibros.erp.presupuesto.dto.Presupuesto;
import jakarta.persistence.criteria.Expression;
import org.springframework.context.MessageSource;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.security.Principal;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
@Service
public class PresupuestoDatatableService {
private final MessageSource messageSource;
private final PresupuestoRepository repo;
public PresupuestoDatatableService(MessageSource messageSource, PresupuestoRepository repo) {
this.messageSource = messageSource;
this.repo = repo;
}
@Transactional(readOnly = true)
public DataTablesResponse<Map<String, Object>> datatablePublicos(DataTablesRequest dt, Locale locale,
Principal principal) {
return commonDataTable(dt, locale, "publico", true, principal);
}
@Transactional(readOnly = true)
public DataTablesResponse<Map<String, Object>> datatablePrivados(DataTablesRequest dt, Locale locale,
Principal principal) {
return commonDataTable(dt, locale, "privado", false, principal);
}
private DataTablesResponse<Map<String, Object>> commonDataTable(DataTablesRequest dt, Locale locale, String origen,
boolean publico, Principal principal) {
Specification<Presupuesto> base = Specification.allOf(
(root, query, cb) -> cb.equal(root.get("origen"), Presupuesto.Origen.valueOf(origen)));
Boolean isAdmin = Utils.isCurrentUserAdmin();
if (!isAdmin) {
base = base.and((root, query, cb) -> cb.equal(root.get("user").get("id"), Utils.currentUserId(principal)));
}
Long count = repo.count(base);
List<String> orderable = List.of(
"id", "titulo", "user.fullName", "tipoEncuadernacion", "tipoCubierta", "tipoImpresion",
"selectedTirada", "estado", "totalConIva", "paginas", "pais", "region", "ciudad", "updatedAt");
return DataTable.of(repo, Presupuesto.class, dt,
List.of("")) // búsqueda global solo por campos simples
.orderable(orderable)
.where((root, query, cb) -> cb.equal(root.get("origen"), Presupuesto.Origen.valueOf(origen)))
.onlyAddedColumns()
.add("id", Presupuesto::getId)
.add("titulo", Presupuesto::getTitulo)
.add("tipoEncuadernacion", p -> msg(p.getTipoEncuadernacion().getMessageKey(), locale))
.add("tipoCubierta", p -> msg(p.getTipoCubierta().getMessageKey(), locale))
.add("tipoImpresion", p -> msg(p.getTipoImpresion().getMessageKey(), locale))
.add("selectedTirada", Presupuesto::getSelectedTirada)
.add("paginas", p -> n(p.getPaginasColor()) + n(p.getPaginasNegro()))
.filter("paginas", (root, q, cb, value) -> {
Expression<Integer> sum = cb.sum(
cb.coalesce(root.get("paginasColor"), cb.literal(0)),
cb.coalesce(root.get("paginasNegro"), cb.literal(0)));
Expression<String> asStr = cb.function("CONCAT", String.class, cb.literal(""), sum);
return cb.like(asStr, "%" + value.trim() + "%");
})
.orderable("paginas", (root, q, cb) -> cb.sum(
cb.coalesce(root.get("paginasColor"), cb.literal(0)),
cb.coalesce(root.get("paginasNegro"), cb.literal(0))))
.add("estado", p -> msg(p.getEstado().getMessageKey(), locale))
.add("totalConIva", p -> Utils.formatCurrency(p.getTotalConIva(), locale))
.addIf(publico, "pais", Presupuesto::getPais)
.addIf(publico, "region", Presupuesto::getRegion)
.addIf(publico, "ciudad", Presupuesto::getCiudad)
.add("updatedAt", p -> formatDate(p.getUpdatedAt(), locale))
.addIf(!publico, "user", p -> p.getUser() != null ? p.getUser().getFullName() : "")
.add("actions", this::generarBotones)
.where(base)
.toJson(count);
}
/* ---------- helpers ---------- */
private String msg(String key, Locale locale) {
try {
return messageSource.getMessage(key, null, locale);
} catch (Exception e) {
return key;
}
}
private int n(Integer v) {
return v == null ? 0 : v;
}
private String formatDate(Instant instant, Locale locale) {
if (instant == null)
return "";
ZoneId zone = (locale != null && locale.getCountry() != null && !locale.getCountry().isEmpty())
? TimeZone.getTimeZone(locale.toLanguageTag()).toZoneId()
: ZoneId.systemDefault();
var df = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm").withZone(zone);
return df.format(instant);
}
private String generarBotones(Presupuesto p) {
boolean borrador = p.getEstado() == Presupuesto.Estado.borrador;
String id = String.valueOf(p.getId());
String editBtn = "<a href=\"javascript:void(0);\" data-id=\"" + id + "\" class=\"link-success btn-edit-" +
(p.getOrigen().equals(Presupuesto.Origen.publico) ? "anonimo" : "privado") + " fs-15\"><i class=\"ri-" +
(p.getOrigen().equals(Presupuesto.Origen.publico) || p.getEstado() == Presupuesto.Estado.aceptado ? "eye" : "pencil") + "-line\"></i></a>";
String deleteBtn = borrador ? "<a href=\"javascript:void(0);\" data-id=\"" + id
+ "\" class=\"link-danger btn-delete-"
+ (p.getOrigen().equals(Presupuesto.Origen.publico) ? "anonimo" : "privado")
+ " fs-15\"><i class=\"ri-delete-bin-5-line\"></i></a>" : "";
return "<div class=\"hstack gap-3 flex-wrap\">" + editBtn + deleteBtn + "</div>";
}
}