mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-02-08 11:59:13 +00:00
454 lines
19 KiB
Java
454 lines
19 KiB
Java
package com.imprimelibros.erp.pedidos;
|
|
|
|
import org.springframework.web.bind.annotation.GetMapping;
|
|
import org.springframework.web.bind.annotation.PathVariable;
|
|
import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
|
import org.springframework.core.io.Resource;
|
|
import org.springframework.http.HttpHeaders;
|
|
import java.security.Principal;
|
|
import java.util.Comparator;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.Map;
|
|
|
|
import org.springframework.context.MessageSource;
|
|
import org.springframework.core.io.ByteArrayResource;
|
|
import org.springframework.data.jpa.domain.Specification;
|
|
import org.springframework.http.MediaType;
|
|
import org.springframework.http.ResponseEntity;
|
|
import org.springframework.stereotype.Controller;
|
|
import org.springframework.ui.Model;
|
|
|
|
import com.imprimelibros.erp.common.Utils;
|
|
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.facturacion.service.FacturacionService;
|
|
import com.imprimelibros.erp.i18n.TranslationService;
|
|
import com.imprimelibros.erp.paises.PaisesService;
|
|
import com.imprimelibros.erp.presupuesto.service.PresupuestoService;
|
|
import com.imprimelibros.erp.users.UserDao;
|
|
|
|
import jakarta.persistence.criteria.Join;
|
|
import jakarta.persistence.criteria.JoinType;
|
|
import jakarta.servlet.http.HttpServletRequest;
|
|
|
|
import org.springframework.web.bind.annotation.ResponseBody;
|
|
import org.springframework.web.bind.annotation.PostMapping;
|
|
import org.springframework.web.bind.annotation.RequestBody;
|
|
|
|
@Controller
|
|
@RequestMapping("/pedidos")
|
|
public class PedidosController {
|
|
|
|
private final PresupuestoService presupuestoService;
|
|
|
|
private final PedidoRepository repoPedido;
|
|
private final PedidoService pedidoService;
|
|
private final UserDao repoUser;
|
|
private final MessageSource messageSource;
|
|
private final PedidoLineaRepository repoPedidoLinea;
|
|
private final PaisesService paisesService;
|
|
private final TranslationService translationService;
|
|
private final FacturacionService facturacionService;
|
|
|
|
public PedidosController(PedidoRepository repoPedido, PedidoService pedidoService, UserDao repoUser,
|
|
MessageSource messageSource, TranslationService translationService,
|
|
PedidoLineaRepository repoPedidoLinea, PaisesService paisesService,
|
|
FacturacionService facturacionService, PresupuestoService presupuestoService) {
|
|
this.repoPedido = repoPedido;
|
|
this.pedidoService = pedidoService;
|
|
this.repoUser = repoUser;
|
|
this.messageSource = messageSource;
|
|
this.translationService = translationService;
|
|
this.repoPedidoLinea = repoPedidoLinea;
|
|
this.paisesService = paisesService;
|
|
this.facturacionService = facturacionService;
|
|
this.presupuestoService = presupuestoService;
|
|
}
|
|
|
|
@GetMapping
|
|
public String listarPedidos(Model model, Locale locale) {
|
|
|
|
List<String> keys = List.of(
|
|
"app.cancelar",
|
|
"app.seleccionar",
|
|
"app.yes",
|
|
"checkout.payment.card",
|
|
"checkout.payment.bizum",
|
|
"checkout.payment.bank-transfer",
|
|
"checkout.error.select-method");
|
|
|
|
Map<String, String> translations = translationService.getTranslations(locale, keys);
|
|
model.addAttribute("languageBundle", translations);
|
|
|
|
if (Utils.isCurrentUserAdmin()) {
|
|
return "imprimelibros/pedidos/pedidos-list";
|
|
}
|
|
return "imprimelibros/pedidos/pedidos-list-cliente";
|
|
}
|
|
|
|
@GetMapping(value = "datatable", produces = "application/json")
|
|
@ResponseBody
|
|
public DataTablesResponse<Map<String, Object>> getDatatable(
|
|
HttpServletRequest request,
|
|
Principal principal,
|
|
Locale locale) {
|
|
|
|
DataTablesRequest dt = DataTablesParser.from(request);
|
|
|
|
Boolean isAdmin = Utils.isCurrentUserAdmin();
|
|
Long currentUserId = Utils.currentUserId(principal);
|
|
|
|
List<String> searchable = List.of(
|
|
"id");
|
|
|
|
// Campos ordenables
|
|
List<String> orderable = List.of(
|
|
"id",
|
|
"createdBy.fullName",
|
|
"createdAt",
|
|
"total",
|
|
"estado");
|
|
|
|
Specification<Pedido> base = (root, query, cb) -> cb.conjunction();
|
|
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");
|
|
|
|
// 2) Si hay filtro, traducirlo a userIds y añadirlo al Specification
|
|
if (clientSearch != null) {
|
|
List<Long> userIds = repoUser.findIdsByFullNameLike(clientSearch.trim());
|
|
|
|
if (userIds.isEmpty()) {
|
|
// Ningún usuario coincide → forzamos 0 resultados
|
|
base = base.and((root, query, cb) -> cb.disjunction());
|
|
} else {
|
|
base = base.and((root, query, cb) -> root.get("createdBy").in(userIds));
|
|
}
|
|
}
|
|
if (estadoSearch != null && !estadoSearch.isBlank()) {
|
|
try {
|
|
PedidoLinea.Estado estadoEnum = PedidoLinea.Estado.valueOf(estadoSearch.trim());
|
|
|
|
base = base.and((root, query, cb) -> {
|
|
// Evitar duplicados de pedidos si el provider usa joins
|
|
if (Pedido.class.equals(query.getResultType())) {
|
|
query.distinct(true);
|
|
}
|
|
|
|
Join<Pedido, PedidoLinea> lineas = root.join("lineas", JoinType.INNER);
|
|
return cb.equal(lineas.get("estado"), estadoEnum);
|
|
});
|
|
|
|
} catch (IllegalArgumentException ex) {
|
|
// Valor de estado no válido → forzamos 0 resultados
|
|
base = base.and((root, query, cb) -> cb.disjunction());
|
|
}
|
|
}
|
|
Long total = repoPedido.count(base);
|
|
|
|
return DataTable
|
|
.of(repoPedido, Pedido.class, dt, searchable)
|
|
.orderable(orderable)
|
|
.add("id", Pedido::getId)
|
|
.add("created_at", pedido -> Utils.formatInstant(pedido.getCreatedAt(), locale))
|
|
.add("cliente", pedido -> {
|
|
if (pedido.getCreatedBy() != null) {
|
|
return pedido.getCreatedBy().getFullName();
|
|
}
|
|
return "";
|
|
})
|
|
.add("total", pedido -> {
|
|
if (pedido.getTotal() != null) {
|
|
return Utils.formatCurrency(pedido.getTotal(), locale);
|
|
} else {
|
|
return "";
|
|
}
|
|
})
|
|
.add("estado", pedido -> {
|
|
List<PedidoLinea> lineas = repoPedidoLinea.findByPedidoId(pedido.getId());
|
|
if (lineas.isEmpty()) {
|
|
return "";
|
|
}
|
|
// concatenar los estados de las líneas, ordenados por prioridad
|
|
StringBuilder sb = new StringBuilder();
|
|
lineas.stream()
|
|
.map(PedidoLinea::getEstado)
|
|
.distinct()
|
|
.sorted(Comparator.comparingInt(PedidoLinea.Estado::getPriority))
|
|
.forEach(estado -> {
|
|
if (sb.length() > 0) {
|
|
sb.append(", ");
|
|
}
|
|
sb.append(messageSource.getMessage(estado.getMessageKey(), null, locale));
|
|
});
|
|
String text = sb.toString();
|
|
return text;
|
|
})
|
|
.add("actions", pedido -> {
|
|
String data = "<span class=\'badge bg-success btn-view \' data-id=\'" + pedido.getId()
|
|
+ "\' style=\'cursor: pointer;\'>"
|
|
+ messageSource.getMessage("app.view", null, locale) + "</span>";
|
|
List<PedidoLinea> lineas = repoPedidoLinea.findByPedidoId(pedido.getId());
|
|
boolean hasDenegadoPago = lineas.stream()
|
|
.anyMatch(linea -> PedidoLinea.Estado.denegado_pago.equals(linea.getEstado()));
|
|
if (hasDenegadoPago) {
|
|
data += " <span class='badge bg-danger btn-pay' data-amount='" + (int) (pedido.getTotal() * 100)
|
|
+ "' data-id='" + pedido.getId() + "' style='cursor: pointer;'>"
|
|
+ messageSource.getMessage("app.pay", null, locale) + "</span>";
|
|
}
|
|
return data;
|
|
})
|
|
.where(base)
|
|
.toJson(total);
|
|
|
|
}
|
|
|
|
@GetMapping("/view/{id}")
|
|
public String verPedido(
|
|
@PathVariable(name = "id", required = true) Long id,
|
|
Model model, Locale locale) {
|
|
|
|
List<String> keys = List.of(
|
|
"app.cancelar",
|
|
"app.yes",
|
|
"pedido.view.cancel-title",
|
|
"pedido.view.cancel-text");
|
|
|
|
Map<String, String> translations = translationService.getTranslations(locale, keys);
|
|
model.addAttribute("languageBundle", translations);
|
|
|
|
Boolean isAdmin = Utils.isCurrentUserAdmin();
|
|
if (isAdmin) {
|
|
model.addAttribute("isAdmin", true);
|
|
} else {
|
|
model.addAttribute("isAdmin", false);
|
|
}
|
|
|
|
PedidoDireccion direccionFacturacion = pedidoService.getDireccionFacturacionPedido(id);
|
|
if (direccionFacturacion != null) {
|
|
String paisNombre = paisesService.getPaisNombrePorCode3(direccionFacturacion.getPaisCode3(), locale);
|
|
direccionFacturacion.setPaisNombre(paisNombre);
|
|
}
|
|
|
|
model.addAttribute("direccionFacturacion", direccionFacturacion);
|
|
|
|
Boolean showCancel = false;
|
|
Boolean showDownloadFactura = true;
|
|
List<Map<String, Object>> lineas = pedidoService.getLineas(id, locale);
|
|
for (Map<String, Object> linea : lineas) {
|
|
|
|
PedidoLinea pedidoLinea = repoPedidoLinea.findById(
|
|
((Number) linea.get("lineaId")).longValue()).orElse(null);
|
|
if (pedidoLinea != null) {
|
|
Map<String, Boolean> buttons = new HashMap<>();
|
|
if (pedidoLinea.getEstado() != PedidoLinea.Estado.enviado) {
|
|
showDownloadFactura = false;
|
|
}
|
|
if (pedidoLinea.getEstado().getPriority() >= PedidoLinea.Estado.esperando_aceptacion_ferro.getPriority()
|
|
&& pedidoLinea.getEstado().getPriority() <= PedidoLinea.Estado.produccion.getPriority()) {
|
|
|
|
if (pedidoLinea.getEstado() == PedidoLinea.Estado.esperando_aceptacion_ferro) {
|
|
buttons.put("aceptar_ferro", true);
|
|
} else {
|
|
buttons.put("aceptar_ferro", false);
|
|
}
|
|
|
|
Map<String, Object> filesType = pedidoService.getFilesType(pedidoLinea.getId(), locale);
|
|
if (filesType == null || filesType.get("error") != null) {
|
|
throw new RuntimeException(
|
|
messageSource.getMessage("pedido.errors.update-server-error", null, locale));
|
|
}
|
|
for (String key : filesType.keySet()) {
|
|
buttons.put(key, (Integer) filesType.get(key) == 1 ? true : false);
|
|
}
|
|
linea.put("buttons", buttons);
|
|
}
|
|
|
|
if (pedidoLinea.getEstado() != PedidoLinea.Estado.cancelado
|
|
&& pedidoLinea.getEstado() != PedidoLinea.Estado.terminado
|
|
&& pedidoLinea.getEstado() != PedidoLinea.Estado.enviado) {
|
|
showCancel = true;
|
|
}
|
|
}
|
|
|
|
List<PedidoDireccion> dirEntrega = pedidoService.getDireccionesEntregaPedidoLinea(
|
|
((Number) linea.get("lineaId")).longValue());
|
|
|
|
if (dirEntrega != null && !dirEntrega.isEmpty()) {
|
|
for (PedidoDireccion direccion : dirEntrega) {
|
|
String paisNombre = paisesService.getPaisNombrePorCode3(direccion.getPaisCode3(), locale);
|
|
direccion.setPaisNombre(paisNombre);
|
|
}
|
|
}
|
|
linea.put("direccionesEntrega", dirEntrega);
|
|
|
|
}
|
|
Long facturaId = null;
|
|
if (showDownloadFactura) {
|
|
facturaId = facturacionService.getFacturaIdFromPedidoId(id);
|
|
}
|
|
model.addAttribute("lineas", lineas);
|
|
model.addAttribute("showCancel", showCancel);
|
|
if (showDownloadFactura && facturaId != null) {
|
|
model.addAttribute("facturaId", facturaId);
|
|
model.addAttribute("showDownloadFactura", showDownloadFactura);
|
|
}
|
|
model.addAttribute("id", id);
|
|
return "imprimelibros/pedidos/pedidos-view";
|
|
}
|
|
|
|
@PostMapping("/cancel/{id}")
|
|
@ResponseBody
|
|
public Map<String, Object> cancelPedido(
|
|
@PathVariable(name = "id", required = true) Long id,
|
|
Locale locale) {
|
|
Boolean result = pedidoService.cancelarPedido(id);
|
|
if (result) {
|
|
String successMsg = messageSource.getMessage("pedido.success.pedido-cancelado", null, locale);
|
|
return Map.of(
|
|
"success", true,
|
|
"message", successMsg);
|
|
} else {
|
|
String errorMsg = messageSource.getMessage("pedido.errors.cancel-pedido", null, locale);
|
|
return Map.of(
|
|
"success", false,
|
|
"message", errorMsg);
|
|
}
|
|
}
|
|
|
|
// -------------------------------------
|
|
// Acciones sobre las lineas de pedido
|
|
// -------------------------------------
|
|
@PostMapping("/linea/{id}/update-status")
|
|
@ResponseBody
|
|
public Map<String, Object> updateStatus(
|
|
@PathVariable(name = "id", required = true) Long id, Locale locale) {
|
|
|
|
Map<String, Object> result = pedidoService.actualizarEstado(id, locale);
|
|
|
|
return result;
|
|
}
|
|
|
|
@PostMapping("/linea/{id}/update-maquetacion")
|
|
@ResponseBody
|
|
public Map<String, Object> updateMaquetacion(
|
|
@PathVariable(name = "id", required = true) Long id,
|
|
Locale locale) {
|
|
|
|
PedidoLinea entity = repoPedidoLinea.findById(id).orElse(null);
|
|
if (entity == null) {
|
|
String errorMsg = messageSource.getMessage("pedido.errors.linea-not-found", null, locale);
|
|
return Map.of(
|
|
"success", false,
|
|
"message", errorMsg);
|
|
}
|
|
|
|
if (entity.getEstado() != PedidoLinea.Estado.maquetacion) {
|
|
String errorMsg = messageSource.getMessage("pedido.errors.state-error", null, locale);
|
|
return Map.of(
|
|
"success", false,
|
|
"message", errorMsg);
|
|
}
|
|
|
|
entity.setEstado(PedidoLinea.Estado.haciendo_ferro);
|
|
repoPedidoLinea.save(entity);
|
|
String successMsg = messageSource.getMessage("pedido.success.estado-actualizado", null, locale);
|
|
return Map.of(
|
|
"success", true,
|
|
"message", successMsg,
|
|
"state", messageSource.getMessage(entity.getEstado().getMessageKey(), null, locale));
|
|
}
|
|
|
|
@GetMapping("/linea/{id}/download-ferro")
|
|
public ResponseEntity<Resource> downloadFerro(@PathVariable(name = "id", required = true) Long id, Locale locale) {
|
|
|
|
byte[] ferroFileContent = pedidoService.getFerroFileContent(id, locale);
|
|
if (ferroFileContent == null) {
|
|
return ResponseEntity.notFound().build();
|
|
}
|
|
|
|
ByteArrayResource resource = new ByteArrayResource(ferroFileContent);
|
|
|
|
return ResponseEntity.ok()
|
|
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=ferro_" + id + ".pdf")
|
|
.contentType(MediaType.APPLICATION_PDF)
|
|
.body(resource);
|
|
}
|
|
|
|
@GetMapping("/linea/{id}/download-cub")
|
|
public ResponseEntity<Resource> downloadCubierta(@PathVariable(name = "id", required = true) Long id,
|
|
Locale locale) {
|
|
|
|
byte[] cubFileContent = pedidoService.getCubiertaFileContent(id, locale);
|
|
if (cubFileContent == null) {
|
|
return ResponseEntity.notFound().build();
|
|
}
|
|
|
|
ByteArrayResource resource = new ByteArrayResource(cubFileContent);
|
|
|
|
return ResponseEntity.ok()
|
|
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=cubierta_" + id + ".pdf")
|
|
.contentType(MediaType.APPLICATION_PDF)
|
|
.body(resource);
|
|
}
|
|
|
|
@GetMapping("/linea/{id}/download-tapa")
|
|
public ResponseEntity<Resource> downloadTapa(@PathVariable(name = "id", required = true) Long id, Locale locale) {
|
|
|
|
byte[] tapaFileContent = pedidoService.getTapaFileContent(id, locale);
|
|
if (tapaFileContent == null) {
|
|
return ResponseEntity.notFound().build();
|
|
}
|
|
|
|
ByteArrayResource resource = new ByteArrayResource(tapaFileContent);
|
|
|
|
return ResponseEntity.ok()
|
|
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=tapa_" + id + ".pdf")
|
|
.contentType(MediaType.APPLICATION_PDF)
|
|
.body(resource);
|
|
}
|
|
|
|
@PostMapping("/linea/{id}/aceptar-ferro")
|
|
@ResponseBody
|
|
public Map<String, Object> aceptarFerro(@PathVariable(name = "id", required = true) Long id,
|
|
Locale locale) {
|
|
|
|
PedidoLinea entity = repoPedidoLinea.findById(id).orElse(null);
|
|
if (entity == null) {
|
|
String errorMsg = messageSource.getMessage("pedido.errors.linea-not-found", null, locale);
|
|
return Map.of(
|
|
"success", false,
|
|
"message", errorMsg);
|
|
}
|
|
|
|
if (entity.getEstado() != PedidoLinea.Estado.esperando_aceptacion_ferro) {
|
|
String errorMsg = messageSource.getMessage("pedido.errors.state-error", null, locale);
|
|
return Map.of(
|
|
"success", false,
|
|
"message", errorMsg);
|
|
}
|
|
|
|
Boolean result = pedidoService.aceptarFerro(id, locale);
|
|
|
|
if (result) {
|
|
String successMsg = messageSource.getMessage("pedido.success.estado-actualizado", null, locale);
|
|
return Map.of(
|
|
"success", true,
|
|
"message", successMsg,
|
|
"state", messageSource.getMessage(entity.getEstado().getMessageKey(), null, locale));
|
|
} else {
|
|
String errorMsg = messageSource.getMessage("pedido.errors.update-server-error", null, locale);
|
|
return Map.of(
|
|
"success", false,
|
|
"message", errorMsg);
|
|
}
|
|
}
|
|
|
|
} |