trabajando2

This commit is contained in:
2026-02-24 20:57:51 +01:00
parent e4c1692ef0
commit 355c5b6019
12 changed files with 217 additions and 23 deletions

View File

@ -0,0 +1,47 @@
package com.imprimelibros.erp.error;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.imprimelibros.erp.common.Utils;
import java.time.ZonedDateTime;
@Controller
public class ErrorPageController implements ErrorController {
@RequestMapping("/error")
public String handleError(HttpServletRequest request, Model model) {
Object statusObj = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
Integer statusCode = statusObj != null ? Integer.valueOf(statusObj.toString()) : 500;
HttpStatus status = HttpStatus.resolve(statusCode);
if (status == null) status = HttpStatus.INTERNAL_SERVER_ERROR;
Object message = request.getAttribute(RequestDispatcher.ERROR_MESSAGE);
Object exception = request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
Object path = request.getAttribute(RequestDispatcher.ERROR_REQUEST_URI);
model.addAttribute("status", status.value());
model.addAttribute("error", status.getReasonPhrase());
model.addAttribute("message", message != null ? message : "");
model.addAttribute("path", path != null ? path : "");
model.addAttribute("timestamp", ZonedDateTime.now());
// Puedes usar esto para cambiar iconos/texto según status
model.addAttribute("is404", status == HttpStatus.NOT_FOUND);
model.addAttribute("is403", status == HttpStatus.FORBIDDEN);
model.addAttribute("is500", status.is5xxServerError());
if(Utils.isCurrentUserAdmin())
// una sola vista para todos los errores
return "imprimelibros/error/error";
else
return "redirect:/"; // redirige a home para usuarios no admin
}
}

View File

@ -14,14 +14,16 @@ public class PedidoLinea {
procesando_pago("pedido.estado.procesando_pago", 2),
denegado_pago("pedido.estado.denegado_pago", 3),
aprobado("pedido.estado.aprobado", 4),
maquetacion("pedido.estado.maquetacion", 5),
haciendo_ferro("pedido.estado.haciendo_ferro", 6),
esperando_aceptacion_ferro("pedido.estado.esperando_aceptacion_ferro", 7),
ferro_cliente("pedido.estado.ferro_cliente", 8),
produccion("pedido.estado.produccion", 9),
terminado("pedido.estado.terminado", 10),
enviado("pedido.estado.enviado", 11),
cancelado("pedido.estado.cancelado", 12);
procesando_pedido("pedido.estado.procesando_pedido", 5),
maquetacion("pedido.estado.maquetacion", 6),
haciendo_ferro_digital("pedido.estado.haciendo_ferro_digital", 7),
esperando_aceptacion_ferro_digital("pedido.estado.esperando_aceptacion_ferro_digital", 8),
haciendo_ferro("pedido.estado.haciendo_ferro", 9),
esperando_aceptacion_ferro("pedido.estado.esperando_aceptacion_ferro", 10),
produccion("pedido.estado.produccion", 11),
terminado("pedido.estado.terminado", 12),
enviado("pedido.estado.enviado", 13),
cancelado("pedido.estado.cancelado", 14);
private final String messageKey;
private final int priority;

View File

@ -271,7 +271,7 @@ public class PedidoService {
Integer counter = 1;
for (PedidoLinea linea : lineas) {
if (linea.getEstado() == Estado.pendiente_pago
|| linea.getEstado() == Estado.denegado_pago) {
|| linea.getEstado() == Estado.denegado_pago || linea.getEstado() == Estado.procesando_pago) {
Presupuesto presupuesto = linea.getPresupuesto();
linea.setEstado(getEstadoInicial(presupuesto));
@ -311,6 +311,7 @@ public class PedidoService {
return true;
}
@Transactional
public Map<String, Object> actualizarEstado(Long pedidoLineaId, Locale locale) {
PedidoLinea pedidoLinea = pedidoLineaRepository.findById(pedidoLineaId).orElse(null);
@ -327,8 +328,8 @@ public class PedidoService {
"message", messageSource.getMessage("pedido.errors.cannot-update", null, locale));
}
// Rango: >= haciendo_ferro y < enviado
if (estadoOld.getPriority() < PedidoLinea.Estado.haciendo_ferro.getPriority()
// Rango: >= procesando_pedido y < enviado
if (estadoOld.getPriority() < PedidoLinea.Estado.procesando_pedido.getPriority()
|| estadoOld.getPriority() >= PedidoLinea.Estado.enviado.getPriority()) {
return Map.of(
"success", false,
@ -788,7 +789,7 @@ public class PedidoService {
if (presupuestoService.hasMaquetacion(p)) {
return Estado.maquetacion;
} else {
return Estado.haciendo_ferro;
return Estado.procesando_pedido;
}
}

View File

@ -48,12 +48,12 @@ 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.PresupuestoFormDataMapper;
import com.imprimelibros.erp.presupuesto.dto.PresupuestoFormDataMapper.PresupuestoFormDataDto;
import com.imprimelibros.erp.presupuesto.service.PresupuestoService;
import com.imprimelibros.erp.presupuesto.validation.PresupuestoValidationGroups;
import com.imprimelibros.erp.users.UserDao;
import com.imprimelibros.erp.users.UserDetailsImpl;
import com.imprimelibros.erp.presupuesto.service.PresupuestoFormDataMapper;
import com.imprimelibros.erp.presupuesto.service.PresupuestoFormDataMapper.PresupuestoFormDataDto;
import com.imprimelibros.erp.common.Utils;
import com.imprimelibros.erp.common.web.IpUtils;

View File

@ -284,6 +284,9 @@ public class Presupuesto extends AbstractAuditedEntity implements Cloneable {
@Column(name = "lomo")
private Double lomo;
@Column(name = "lomo_cubierta")
private Double lomoCubierta;
@NotNull(message = "{presupuesto.errores.gramaje-interior}", groups = PresupuestoValidationGroups.Interior.class)
@Column(name = "gramaje_interior")
private Integer gramajeInterior;
@ -731,6 +734,14 @@ public class Presupuesto extends AbstractAuditedEntity implements Cloneable {
this.lomo = lomo;
}
public Double getLomoCubierta() {
return lomoCubierta;
}
public void setLomoCubierta(Double lomoCubierta) {
this.lomoCubierta = lomoCubierta;
}
public Integer getGramajeInterior() {
return gramajeInterior;
}

View File

@ -1,9 +1,7 @@
package com.imprimelibros.erp.presupuesto.service;
package com.imprimelibros.erp.presupuesto.dto;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.imprimelibros.erp.presupuesto.dto.Presupuesto;
import org.springframework.stereotype.Service;
@ -21,6 +19,7 @@ public class PresupuestoFormDataMapper {
public Servicios servicios = new Servicios();
public Integer selectedTirada;
public Double lomo;
public Double lomoCubierta;
// ===== Datos Generales =====
public static class DatosGenerales {
@ -194,7 +193,10 @@ public class PresupuestoFormDataMapper {
// ===== Selected tirada
vm.selectedTirada = p.getSelectedTirada();
// ===== Lomos
vm.lomo = p.getLomo();
vm.lomoCubierta = p.getLomoCubierta();
// ===== Servicios desde JSONs
vm.servicios.servicios = parse(p.getServiciosJson(),

View File

@ -0,0 +1,18 @@
databaseChangeLog:
- changeSet:
id: 0028-add-lomo-cubierta-to-presupuesto
author: jjo
changes:
- addColumn:
tableName: presupuesto
columns:
- column:
name: lomo_cubierta
type: DECIMAL(12, 2)
defaultValueNumeric: 0
afterColumn: lomo
rollback:
- dropColumn:
tableName: presupuesto
columnName: lomo_cubierta

View File

@ -0,0 +1,43 @@
databaseChangeLog:
- changeSet:
id: 0029-update-estados-pedidos-lineas
author: jjo
changes:
- modifyDataType:
tableName: pedidos_lineas
columnName: estado
newDataType: >
enum(
'pendiente_pago',
'procesando_pago',
'denegado_pago',
'aprobado',
'procesando_pedido',
'maquetacion',
'haciendo_ferro_digital',
'esperando_aceptacion_ferro_digital',
'haciendo_ferro',
'esperando_aceptacion_ferro',
'produccion',
'terminado',
'enviado',
'cancelado'
)
rollback:
- modifyDataType:
tableName: pedidos_lineas
columnName: estado
newDataType: >
enum(
'pendiente_pago',
'procesando_pago',
'denegado_pago',
'aprobado',
'maquetacion',
'haciendo_ferro',
'esperando_aceptacion_ferro',
'produccion',
'terminado',
'enviado',
'cancelado'
)

View File

@ -1,4 +1,4 @@
databaseChangeLog:
databaseChangeLog:
- include:
file: db/changelog/changesets/0001-baseline.yml
- include:
@ -53,3 +53,8 @@ databaseChangeLog:
file: db/changelog/changesets/0026-drop-entrega-tipo-from-presupuesto.yml
- include:
file: db/changelog/changesets/0027-add-lomo-to-presupuesto.yml
- include:
file: db/changelog/changesets/0028-add-lomo-cubierta-to-presupuesto.yml
- include:
file: db/changelog/changesets/0029-update-estados-pedidos-lineas.yml

View File

@ -22,10 +22,12 @@ pedido.estado.pendiente_pago=Pendiente de pago
pedido.estado.procesando_pago=Procesando pago
pedido.estado.denegado_pago=Pago denegado
pedido.estado.aprobado=Aprobado
pedido.estado.procesando_pedido=Procesando pedido
pedido.estado.maquetacion=Maquetación
pedido.estado.haciendo_ferro=Haciendo ferro
pedido.estado.esperando_aceptacion_ferro=Esperando aceptación de ferro
pedido.estado.ferro_cliente=Esperando aprobación de ferro
pedido.estado.haciendo_ferro_digital=Haciendo ferro digital
pedido.estado.esperando_aceptacion_ferro_digital=Esperando aceptación de ferro digital
pedido.estado.haciendo_ferro=Haciendo ejemplar de prueba
pedido.estado.esperando_aceptacion_ferro=Esperando aceptación de ejemplar de prueba
pedido.estado.produccion=Producción
pedido.estado.terminado=Terminado
pedido.estado.enviado=Enviado

View File

@ -107,7 +107,8 @@ export default class PresupuestoWizard {
}
},
selectedTirada: 10,
lomo: 0
lomo: 0,
lomoCubierta: 0
}
// pestaña datos generales
@ -445,7 +446,8 @@ export default class PresupuestoWizard {
...this.#getInteriorData(),
...this.#getCubiertaData(),
selectedTirada: this.formData.selectedTirada,
lomo: this.formData.lomo
lomo: this.formData.lomo,
lomoCubierta: this.formData.lomoCubierta
};
const sobrecubierta = data.sobrecubierta;

View File

@ -0,0 +1,61 @@
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{imprimelibros/layout}">
<head>
<th:block layout:fragment="pagetitle" />
<th:block th:replace="~{imprimelibros/partials/head-css :: head-css}" />
<th:block layout:fragment="pagecss">
<link th:href="@{/assets/libs/datatables/dataTables.bootstrap5.min.css}" rel="stylesheet" />
</th:block>
</head>
<body>
<div th:replace="~{imprimelibros/partials/topbar :: topbar}" />
<div th:replace="~{imprimelibros/partials/sidebar :: sidebar}"
sec:authorize="isAuthenticated() and hasAnyRole('SUPERADMIN','ADMIN')">
<th:block layout:fragment="content">
<!-- CONTENIDO -->
<div class="row justify-content-center">
<div class="col-lg-7">
<div class="card shadow-sm">
<div class="card-body p-4 p-md-5 text-center">
<h1 class="display-4 mb-2" th:text="${status}">404</h1>
<h4 class="mb-3" th:text="${error}">Not Found</h4>
<p class="text-muted mb-4"
th:text="${message != null and !#strings.isEmpty(message)} ? ${message} : 'Ha ocurrido un error inesperado.'">
Ha ocurrido un error inesperado.
</p>
<div class="small text-muted mb-4">
<div><strong>Ruta:</strong> <span th:text="${path}">/logout</span></div>
<div><strong>Fecha:</strong> <span
th:text="${#temporals.format(timestamp, 'dd/MM/yyyy HH:mm:ss')}">--</span></div>
</div>
<div class="d-flex gap-2 justify-content-center">
<a class="btn btn-primary" th:href="@{/}">Volver al inicio</a>
<a class="btn btn-outline-secondary" href="javascript:history.back()">Atrás</a>
</div>
<!-- Opcional: bloque extra sólo para 404 -->
<div class="mt-4" th:if="${is404}">
<div class="alert alert-warning mb-0">
No se ha encontrado el recurso solicitado.
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- /CONTENIDO -->
</div>
</body>
</html>