terminado a falta de pruebas en servidor

This commit is contained in:
2025-11-13 17:30:19 +01:00
parent 32416d10f3
commit 51ea3b4120
12 changed files with 2936 additions and 41 deletions

3
.gitignore vendored
View File

@ -31,3 +31,6 @@ build/
### VS Code ###
.vscode/
### Logs ###
erp-*.log

View File

@ -31,6 +31,8 @@ services:
SPRING_DATASOURCE_PASSWORD: om91irrDctd
ports:
- "8080:8080"
volumes:
- ./logs:/var/log/imprimelibros
restart: always
networks:
- imprimelibros-network

2799
logs/erp.log Normal file

File diff suppressed because it is too large Load Diff

View File

@ -445,6 +445,7 @@ public class CartService {
cartDireccionRepo.deleteByDireccionIdAndCartStatus(direccionId, Cart.Status.ACTIVE);
}
@Transactional
public Long crearPedido(Long cartId, Locale locale) {
@ -456,21 +457,25 @@ public class CartService {
for (Integer i = 0; i < items.size(); i++) {
CartItem item = items.get(i);
Presupuesto p = item.getPresupuesto();
Presupuesto pCart = item.getPresupuesto();
// Asegurarnos de trabajar con la entidad gestionada por JPA
Presupuesto p = presupuestoRepo.findById(pCart.getId())
.orElseThrow(() -> new IllegalStateException("Presupuesto no encontrado: " + pCart.getId()));
Map<String, Object> data_to_send = presupuestoService.toSkApiRequest(p, true);
data_to_send.put("createPedido", 0);
if (items.size() > 1) {
// Recuperar el mapa anidado datosCabecera
@SuppressWarnings("unchecked")
Map<String, Object> datosCabecera = (Map<String, Object>) data_to_send.get("datosCabecera");
if (datosCabecera != null) {
Object tituloOriginal = datosCabecera.get("titulo");
datosCabecera.put(
"titulo",
"[" + (i + 1) + "/" + items.size() + "] " + (tituloOriginal != null ? tituloOriginal : ""));
}
// Recuperar el mapa anidado datosCabecera
@SuppressWarnings("unchecked")
Map<String, Object> datosCabecera = (Map<String, Object>) data_to_send.get("datosCabecera");
if (datosCabecera != null) {
Object tituloOriginal = datosCabecera.get("titulo");
datosCabecera.put(
"titulo",
"[" + (i + 1) + "/" + items.size() + "] " + (tituloOriginal != null ? tituloOriginal : ""));
}
Map<String, Object> direcciones_presupuesto = this.getDireccionesPresupuesto(cart, p);
data_to_send.put("direcciones", direcciones_presupuesto.get("direcciones"));
data_to_send.put("direccionesFP1", direcciones_presupuesto.get("direccionesFP1"));
@ -530,11 +535,8 @@ public class CartService {
List<Map<String, Object>> direccionesPresupuesto = new ArrayList<>();
List<Map<String, Object>> direccionesPrueba = new ArrayList<>();
List<CartDireccion> direcciones = cart.getDirecciones().stream()
.filter(d -> d.getPresupuesto() != null && d.getPresupuesto().getId().equals(presupuesto.getId()))
.toList();
if (cart.getOnlyOneShipment()) {
direcciones = direcciones.stream().limit(1).toList();
List<CartDireccion> direcciones = cart.getDirecciones().stream().limit(1).toList();
if (!direcciones.isEmpty()) {
direccionesPresupuesto.add(direcciones.get(0).toSkMap(
presupuesto.getSelectedTirada(),
@ -555,11 +557,19 @@ public class CartService {
}
Map<String, Object> direccionesRet = new HashMap<>();
direccionesRet.put("direcciones", direccionesPresupuesto);
direccionesRet.put("direccionesFP1", direccionesPrueba.get(0));
if (!direccionesPrueba.isEmpty())
direccionesRet.put("direccionesFP1", direccionesPrueba.get(0));
else {
direccionesRet.put("direccionesFP1", new ArrayList<>());
}
return direccionesRet;
}
} else {
for (CartDireccion cd : cart.getDirecciones()) {
List<CartDireccion> direcciones = cart.getDirecciones().stream()
.filter(d -> d.getPresupuesto() != null && d.getPresupuesto().getId().equals(presupuesto.getId()))
.toList();
for (CartDireccion cd : direcciones) {
// direccion de ejemplar de prueba
if (cd.getPresupuesto() == null || !cd.getPresupuesto().getId().equals(presupuesto.getId())) {

View File

@ -457,6 +457,7 @@ public class PaymentService {
* - crea el pedido a partir del carrito
*
*/
@Transactional
private Boolean processOrder(Long cartId, Locale locale) {
Cart cart = this.cartService.findById(cartId);

View File

@ -315,16 +315,28 @@ public class PresupuestoService {
Map<String, Object> body = new HashMap<>();
body.put("tipo_impresion_id", this.getTipoImpresionId(presupuesto));
if (toSave) {
Boolean hasDepositoLegal = false;
if (presupuesto.getServiciosJson() != null
&& presupuesto.getServiciosJson().contains("deposito-legal")) {
hasDepositoLegal = true;
}
if (toSave && hasDepositoLegal) {
body.put("tirada", Arrays.stream(presupuesto.getTiradas())
.filter(Objects::nonNull)
.map(tirada -> tirada + 4)
.collect(Collectors.toList()));
if(presupuesto.getSelectedTirada() != null) {
presupuesto.setSelectedTirada(presupuesto.getSelectedTirada());
}
} else {
body.put("tirada", Arrays.stream(presupuesto.getTiradas())
.filter(Objects::nonNull)
.collect(Collectors.toList()));
}
body.put("selectedTirada",
presupuesto.getSelectedTirada() != null ? presupuesto.getSelectedTirada() : presupuesto.getTirada1());
body.put("tamanio", tamanio);
body.put("tipo", presupuesto.getTipoEncuadernacion());
body.put("clienteId", SK_CLIENTE_ID);
@ -356,6 +368,7 @@ public class PresupuestoService {
}
if (toSave) {
Map<String, Object> servicios = new HashMap<>();
Map<String, Object> data = new HashMap<>();
data.put("input_data", body);
data.put("ferroDigital", 1);
@ -365,11 +378,13 @@ public class PresupuestoService {
if (presupuesto.getServiciosJson() != null
&& presupuesto.getServiciosJson().indexOf("ejemplar-prueba") > 0) {
data.put("prototipo", 1);
servicios.put("prototipo", "1");
} else {
data.put("prototipo", 0);
}
if (presupuesto.getServiciosJson() != null && presupuesto.getServiciosJson().indexOf("retractilado") > 0) {
data.put("retractilado", 1);
servicios.put("retractilado", "1");
} else {
data.put("retractilado", 0);
}
@ -382,6 +397,7 @@ public class PresupuestoService {
datosCabecera.put("coleccion", "");
datosCabecera.put("referenciaCliente", presupuesto.getId());
data.put("datosCabecera", datosCabecera);
body.put("servicios", servicios);
return data;
}
@ -1099,10 +1115,14 @@ public class PresupuestoService {
try {
// retractilado: recalcular precio
if (s.get("id").equals("retractilado")) {
double precio_retractilado = obtenerPrecioRetractilado(cantidad) != null
? Double.parseDouble(obtenerPrecioRetractilado(cantidad))
: 0.0;
s.put("price", precio_retractilado);
String p = obtenerPrecioRetractilado(cantidad);
if(p != null){
double precio_retractilado = Double.parseDouble(p);
s.put("price", precio_retractilado);
} else {
s.put("price", 0.0);
}
}
// si tiene protitipo, guardamos el valor para el IVA al 4%
else if (s.get("id").equals("ejemplar-prueba")) {
@ -1120,7 +1140,8 @@ public class PresupuestoService {
}
}
try {
presupuesto.setServiciosJson(new ObjectMapper().writeValueAsString(servicios));
if(presupuesto.getSelectedTirada() != null && presupuesto.getSelectedTirada().equals(tirada))
presupuesto.setServiciosJson(new ObjectMapper().writeValueAsString(servicios));
} catch (Exception ignore) {
}
}

View File

@ -3,16 +3,35 @@
#
# Logging
#
logging.level.root=INFO
logging.level.org.springframework.security=ERROR
logging.level.root=ERROR
logging.level.org.springframework=ERROR
logging.level.org.springframework.web=ERROR
logging.level.org.thymeleaf=ERROR
logging.level.org.apache.catalina.core=ERROR
# Debug JPA / Hibernate
#logging.level.org.hibernate.SQL=DEBUG
#logging.level.org.hibernate.orm.jdbc.bind=TRACE
#spring.jpa.properties.hibernate.format_sql=true
server.error.include-message=always
server.error.include-stacktrace=on_param
server.error.include-binding-errors=on_param
# Archivo relativo a tu proyecto (asegúrate de que exista el directorio ./logs)
logging.file.name=logs/erp.log
# Rotación tiempo+tamaño (mismo patrón, pero en ./logs)
logging.logback.rollingpolicy.file-name-pattern=logs/erp-%d{yyyy-MM-dd}.%i.log
logging.logback.rollingpolicy.max-file-size=10MB
logging.logback.rollingpolicy.max-history=10
logging.logback.rollingpolicy.total-size-cap=1GB
# Formatos con timestamp
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{36} - %msg%n
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{36} - %msg%n
# Datos de la API de Safekat
safekat.api.url=http://localhost:8000/
safekat.api.email=imnavajas@coit.es

View File

@ -3,14 +3,34 @@
#
# Logging
#
logging.level.org.springframework.security=ERROR
# Niveles
logging.level.root=ERROR
logging.level.org.springframework=ERROR
# Debug JPA / Hibernate
#logging.level.org.hibernate.SQL=DEBUG
#logging.level.org.hibernate.orm.jdbc.bind=TRACE
#spring.jpa.properties.hibernate.format_sql=true
logging.level.org.springframework.security=ERROR
logging.level.org.springframework.web=ERROR
logging.level.org.thymeleaf=ERROR
logging.level.org.apache.catalina.core=ERROR
server.error.include-message=never
server.error.include-stacktrace=never
server.error.include-binding-errors=never
# Opcional: desactivar Whitelabel y servir tu propia página de error
server.error.whitelabel.enabled=false
# Archivo principal dentro del contenedor (monta /var/log/imprimelibros como volumen)
logging.file.name=/var/log/imprimelibros/erp.log
# Rotación tiempo+tamaño -> requiere %d y %i
logging.logback.rollingpolicy.file-name-pattern=/var/log/imprimelibros/erp-%d{yyyy-MM-dd}.%i.log
logging.logback.rollingpolicy.max-file-size=10MB
logging.logback.rollingpolicy.max-history=10
logging.logback.rollingpolicy.total-size-cap=1GB
# Formatos con timestamp
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{36} - %msg%n
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{36} - %msg%n
# Datos de la API de Safekat

View File

@ -19,15 +19,6 @@ spring.jpa.show-sql=false
# Hibernate Timezone
spring.jpa.properties.hibernate.jdbc.time_zone=UTC
# Mensajes de error mas cortos
# Oculta el stack trace en los errores del servidor
server.error.include-stacktrace=never
# No mostrar el mensaje completo de excepción en la respuesta
server.error.include-message=always
#
# Resource chain
# Activa el resource chain y versionado por contenido
@ -106,5 +97,3 @@ redsys.currency=978
redsys.transaction-type=0
redsys.secret-key=sq7HjrUOBfKmC576ILgskD5srU870gJ7

View File

@ -0,0 +1,28 @@
databaseChangeLog:
- changeSet:
id: 0012-drop-unique-tx-gateway
author: JJO
# ✅ Solo ejecuta el changeSet si existe la UNIQUE constraint
preConditions:
- onFail: MARK_RAN
- uniqueConstraintExists:
tableName: payment_transactions
constraintName: idx_payment_tx_gateway_txid
changes:
# 1⃣ Eliminar la UNIQUE constraint si existe
- dropIndex:
tableName: payment_transactions
indexName: idx_payment_tx_gateway_txid
rollback:
# 🔙 1) Eliminar el índice normal creado en este changeSet
- createIndex:
tableName: payment_transactions
indexName: idx_payment_tx_gateway_txid
columns:
- column:
name: gateway_transaction_id

View File

@ -31,6 +31,9 @@ pagos.transferencia.finalizar.error.general=Error al finalizar la transferencia
pagos.transferencia.ok.title=Pago por transferencia bancaria
pagos.transferencia.ok.text=Ha realizado su pedido correctamente. Para completar el pago, realice una transferencia bancaria con los siguientes datos:<br>Titular de la cuenta: Impresión Imprime Libros SL<br>IBAN: ES00 1234 5678 9012 3456 7890<br>Importe: {0}<br>Concepto: {1}<br>Le rogamos que nos envíe el justificante de la transferencia respondiendo al correo de confirmación de pedido que le acabamos de enviar.<br>Si no encuentra el mensaje, por favor revise la carpeta de correo no deseado y añada <a href="mailto:contacto@imprimelibros.com">contacto@imprimelibros.com</a>
pagos.tarjeta-bizum.ok.title=Pago realizado correctamente
pagos.tarjeta-bizum.ok.text=Gracias por confiar en nosotros.<br> Su pago se ha procesado correctamente. En breve recibirá un correo electrónico con los detalles de su pedido.
pagos.refund.title=Devolución
pagos.refund.text=Introduce la cantidad a devolver (en euros):
pagos.refund.success=Devolución solicitada con éxito. Si no se refleja inmediatamente, espere unos minutos y actualiza la página.

View File

@ -36,7 +36,7 @@
<div class="card-body">
<h3 th:text="#{pagos.tarjeta-bizum.ok.title}"></h3>
<span th:utext="#{pagos.tarjeta-bizum.ok.text}"></span>
<div class="col-md-12 d-flex justify-content-center">
<div class="col-md-12 d-flex justify-content-center mt-4">
<div class="progress-container">
<div class="progress-bar-custom"></div>
</div>