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

129 lines
5.9 KiB
Java

package com.imprimelibros.erp.presupuesto;
import com.imprimelibros.erp.datatables.*;
import com.imprimelibros.erp.presupuesto.dto.Presupuesto;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.JoinType;
import org.springframework.context.MessageSource;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import jakarta.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.text.NumberFormat;
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) {
return commonDataTable(dt, locale, "publico", true);
}
@Transactional(readOnly = true)
public DataTablesResponse<Map<String, Object>> datatablePrivados(DataTablesRequest dt, Locale locale) {
return commonDataTable(dt, locale, "privado", false);
}
private DataTablesResponse<Map<String, Object>> commonDataTable(DataTablesRequest dt, Locale locale, String origen,
boolean publico) {
Long count = repo.findAllByOrigen(Presupuesto.Origen.valueOf(origen)).stream().count();
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 -> 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)
.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 formatCurrency(BigDecimal value, Locale locale) {
if (value == null)
return "";
return NumberFormat.getCurrencyInstance(locale).format(value);
}
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) ? "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>";
}
}