mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-01-13 00:48:49 +00:00
Merge branch 'mod/presupuesto_cliente_and_cancel_pedido' into 'main'
Mod/presupuesto cliente and cancel pedido See merge request jjimenez/erp-imprimelibros!26
This commit is contained in:
7944
logs/erp.log
7944
logs/erp.log
File diff suppressed because one or more lines are too long
6
pom.xml
6
pom.xml
@ -32,6 +32,12 @@
|
|||||||
<liquibase.version>4.29.2</liquibase.version>
|
<liquibase.version>4.29.2</liquibase.version>
|
||||||
</properties>
|
</properties>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-security</artifactId>
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import java.util.Objects;
|
|||||||
import com.imprimelibros.erp.presupuesto.classes.PresupuestoFormatter;
|
import com.imprimelibros.erp.presupuesto.classes.PresupuestoFormatter;
|
||||||
import com.imprimelibros.erp.presupuesto.dto.Presupuesto;
|
import com.imprimelibros.erp.presupuesto.dto.Presupuesto;
|
||||||
import com.imprimelibros.erp.presupuesto.service.PresupuestoService;
|
import com.imprimelibros.erp.presupuesto.service.PresupuestoService;
|
||||||
|
import com.imprimelibros.erp.users.UserService;
|
||||||
import com.imprimelibros.erp.cart.dto.CartDireccionRepository;
|
import com.imprimelibros.erp.cart.dto.CartDireccionRepository;
|
||||||
import com.imprimelibros.erp.cart.dto.DireccionCardDTO;
|
import com.imprimelibros.erp.cart.dto.DireccionCardDTO;
|
||||||
import com.imprimelibros.erp.cart.dto.DireccionShipment;
|
import com.imprimelibros.erp.cart.dto.DireccionShipment;
|
||||||
@ -41,11 +42,12 @@ public class CartService {
|
|||||||
private final skApiClient skApiClient;
|
private final skApiClient skApiClient;
|
||||||
private final PresupuestoService presupuestoService;
|
private final PresupuestoService presupuestoService;
|
||||||
private final PedidoRepository pedidoRepository;
|
private final PedidoRepository pedidoRepository;
|
||||||
|
private final UserService userService;
|
||||||
|
|
||||||
public CartService(CartRepository cartRepo, CartItemRepository itemRepo,
|
public CartService(CartRepository cartRepo, CartItemRepository itemRepo,
|
||||||
CartDireccionRepository cartDireccionRepo, MessageSource messageSource,
|
CartDireccionRepository cartDireccionRepo, MessageSource messageSource,
|
||||||
PresupuestoFormatter presupuestoFormatter, PresupuestoRepository presupuestoRepo, PedidoRepository pedidoRepository,
|
PresupuestoFormatter presupuestoFormatter, PresupuestoRepository presupuestoRepo, PedidoRepository pedidoRepository,
|
||||||
DireccionService direccionService, skApiClient skApiClient,PresupuestoService presupuestoService, EmailService emailService) {
|
DireccionService direccionService, skApiClient skApiClient,PresupuestoService presupuestoService, EmailService emailService, UserService userService) {
|
||||||
this.cartRepo = cartRepo;
|
this.cartRepo = cartRepo;
|
||||||
this.itemRepo = itemRepo;
|
this.itemRepo = itemRepo;
|
||||||
this.cartDireccionRepo = cartDireccionRepo;
|
this.cartDireccionRepo = cartDireccionRepo;
|
||||||
@ -56,6 +58,7 @@ public class CartService {
|
|||||||
this.presupuestoService = presupuestoService;
|
this.presupuestoService = presupuestoService;
|
||||||
this.emailService = emailService;
|
this.emailService = emailService;
|
||||||
this.pedidoRepository = pedidoRepository;
|
this.pedidoRepository = pedidoRepository;
|
||||||
|
this.userService = userService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cart findById(Long cartId) {
|
public Cart findById(Long cartId) {
|
||||||
@ -420,6 +423,13 @@ public class CartService {
|
|||||||
|
|
||||||
cart.setUserId(customerId);
|
cart.setUserId(customerId);
|
||||||
cartRepo.save(cart);
|
cartRepo.save(cart);
|
||||||
|
// Se mueven los presupuestos de cartitems a ese usuario
|
||||||
|
List<CartItem> items = itemRepo.findByCartId(cart.getId());
|
||||||
|
for (CartItem item : items) {
|
||||||
|
Presupuesto p = item.getPresupuesto();
|
||||||
|
p.setUser(userService.findById(customerId));
|
||||||
|
presupuestoRepo.save(p);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@ -576,6 +576,42 @@ public class skApiClient {
|
|||||||
return Boolean.parseBoolean(result);
|
return Boolean.parseBoolean(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Boolean cancelarPedido(Long pedidoId) {
|
||||||
|
|
||||||
|
String result = performWithRetry(() -> {
|
||||||
|
String url = this.skApiUrl + "api/cancelar-pedido/" + pedidoId;
|
||||||
|
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
headers.setBearerAuth(authService.getToken());
|
||||||
|
|
||||||
|
HttpEntity<Void> entity = new HttpEntity<>(headers);
|
||||||
|
|
||||||
|
ResponseEntity<String> response = restTemplate.exchange(
|
||||||
|
url,
|
||||||
|
HttpMethod.POST,
|
||||||
|
entity,
|
||||||
|
String.class);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Map<String, Object> responseBody = new ObjectMapper().readValue(
|
||||||
|
response.getBody(),
|
||||||
|
new TypeReference<Map<String, Object>>() {
|
||||||
|
});
|
||||||
|
|
||||||
|
Boolean success = (Boolean) (responseBody.get("success") != null ? responseBody.get("success") : false);
|
||||||
|
|
||||||
|
return success.toString();
|
||||||
|
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return "false"; // Fallback en caso de error
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return Boolean.parseBoolean(result);
|
||||||
|
}
|
||||||
|
|
||||||
/******************
|
/******************
|
||||||
* PRIVATE METHODS
|
* PRIVATE METHODS
|
||||||
******************/
|
******************/
|
||||||
|
|||||||
@ -86,15 +86,34 @@ public class PedidoService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Auditoría mínima
|
// Auditoría mínima
|
||||||
Long userId = cart.getUserId();
|
/*Long userId = cart.getUserId();
|
||||||
pedido.setCreatedBy(userService.findById(userId));
|
pedido.setCreatedBy(userService.findById(userId));
|
||||||
|
pedido.setUpdatedBy(userService.findById(userId));
|
||||||
|
*/
|
||||||
|
// Se obtiene el usuario del primer presupuesto del carrito
|
||||||
|
Long userId = null;
|
||||||
|
List<CartItem> cartItems = cart.getItems();
|
||||||
|
if (!cartItems.isEmpty()) {
|
||||||
|
Presupuesto firstPresupuesto = cartItems.get(0).getPresupuesto();
|
||||||
|
if (firstPresupuesto != null) {
|
||||||
|
userId = firstPresupuesto.getUser().getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(userId == null){
|
||||||
|
userId = cart.getUserId();
|
||||||
|
}
|
||||||
|
pedido.setCreatedBy(userService.findById(userId));
|
||||||
|
pedido.setUpdatedBy(userService.findById(userId));
|
||||||
pedido.setCreatedAt(Instant.now());
|
pedido.setCreatedAt(Instant.now());
|
||||||
pedido.setDeleted(false);
|
pedido.setDeleted(false);
|
||||||
pedido.setUpdatedAt(Instant.now());
|
pedido.setUpdatedAt(Instant.now());
|
||||||
pedido.setUpdatedBy(userService.findById(userId));
|
|
||||||
|
|
||||||
// Guardamos el pedido
|
// Guardamos el pedido
|
||||||
Pedido pedidoGuardado = pedidoRepository.save(pedido);
|
Pedido pedidoGuardado = pedidoRepository.save(pedido);
|
||||||
|
pedidoGuardado.setCreatedBy(userService.findById(userId));
|
||||||
|
pedidoGuardado.setUpdatedBy(userService.findById(userId));
|
||||||
|
pedidoRepository.save(pedidoGuardado);
|
||||||
|
|
||||||
List<CartItem> items = cart.getItems();
|
List<CartItem> items = cart.getItems();
|
||||||
|
|
||||||
@ -336,9 +355,35 @@ public class PedidoService {
|
|||||||
pedidoLineaRepository.save(pedidoLinea);
|
pedidoLineaRepository.save(pedidoLinea);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Boolean cancelarPedido(Long pedidoId) {
|
||||||
|
|
||||||
|
Pedido pedido = pedidoRepository.findById(pedidoId).orElse(null);
|
||||||
|
if (pedido == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Boolean result = skApiClient.cancelarPedido(Long.valueOf(pedido.getProveedorRef()));
|
||||||
|
if (!result) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
List<PedidoLinea> lineas = pedidoLineaRepository.findByPedidoId(pedidoId);
|
||||||
|
for (PedidoLinea linea : lineas) {
|
||||||
|
if (linea.getEstado() != PedidoLinea.Estado.terminado) {
|
||||||
|
linea.setEstado(PedidoLinea.Estado.cancelado);
|
||||||
|
pedidoLineaRepository.save(linea);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************
|
/***************************
|
||||||
* MÉTODOS PRIVADOS
|
* MÉTODOS PRIVADOS
|
||||||
***************************/
|
***************************/
|
||||||
|
|
||||||
private byte[] downloadFile(Long pedidoLineaId, String fileType, Locale locale) {
|
private byte[] downloadFile(Long pedidoLineaId, String fileType, Locale locale) {
|
||||||
PedidoLinea pedidoLinea = pedidoLineaRepository.findById(pedidoLineaId).orElse(null);
|
PedidoLinea pedidoLinea = pedidoLineaRepository.findById(pedidoLineaId).orElse(null);
|
||||||
if (pedidoLinea == null) {
|
if (pedidoLinea == null) {
|
||||||
|
|||||||
@ -211,6 +211,15 @@ public class PedidosController {
|
|||||||
@PathVariable(name = "id", required = true) Long id,
|
@PathVariable(name = "id", required = true) Long id,
|
||||||
Model model, Locale locale) {
|
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();
|
Boolean isAdmin = Utils.isCurrentUserAdmin();
|
||||||
if (isAdmin) {
|
if (isAdmin) {
|
||||||
model.addAttribute("isAdmin", true);
|
model.addAttribute("isAdmin", true);
|
||||||
@ -226,6 +235,7 @@ public class PedidosController {
|
|||||||
|
|
||||||
model.addAttribute("direccionFacturacion", direccionFacturacion);
|
model.addAttribute("direccionFacturacion", direccionFacturacion);
|
||||||
|
|
||||||
|
Boolean showCancel = false;
|
||||||
List<Map<String, Object>> lineas = pedidoService.getLineas(id, locale);
|
List<Map<String, Object>> lineas = pedidoService.getLineas(id, locale);
|
||||||
for (Map<String, Object> linea : lineas) {
|
for (Map<String, Object> linea : lineas) {
|
||||||
|
|
||||||
@ -252,6 +262,10 @@ public class PedidosController {
|
|||||||
}
|
}
|
||||||
linea.put("buttons", buttons);
|
linea.put("buttons", buttons);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(pedidoLinea.getEstado() != PedidoLinea.Estado.cancelado && pedidoLinea.getEstado() != PedidoLinea.Estado.terminado) {
|
||||||
|
showCancel = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<PedidoDireccion> dirEntrega = pedidoService.getDireccionesEntregaPedidoLinea(
|
List<PedidoDireccion> dirEntrega = pedidoService.getDireccionesEntregaPedidoLinea(
|
||||||
@ -267,10 +281,30 @@ public class PedidosController {
|
|||||||
|
|
||||||
}
|
}
|
||||||
model.addAttribute("lineas", lineas);
|
model.addAttribute("lineas", lineas);
|
||||||
|
model.addAttribute("showCancel", showCancel);
|
||||||
model.addAttribute("id", id);
|
model.addAttribute("id", id);
|
||||||
return "imprimelibros/pedidos/pedidos-view";
|
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
|
// Acciones sobre las lineas de pedido
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
|
|||||||
@ -359,6 +359,7 @@ public class UserController {
|
|||||||
@GetMapping(value = "api/get-users", produces = MediaType.APPLICATION_JSON_VALUE)
|
@GetMapping(value = "api/get-users", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
public Map<String, Object> getUsers(
|
public Map<String, Object> getUsers(
|
||||||
@RequestParam(required = false) String role, // puede venir ausente
|
@RequestParam(required = false) String role, // puede venir ausente
|
||||||
|
@RequestParam(required = false) Boolean showUsername,
|
||||||
@RequestParam(required = false) String q,
|
@RequestParam(required = false) String q,
|
||||||
@RequestParam(defaultValue = "1") int page,
|
@RequestParam(defaultValue = "1") int page,
|
||||||
@RequestParam(defaultValue = "10") int size) {
|
@RequestParam(defaultValue = "10") int size) {
|
||||||
@ -373,9 +374,15 @@ public class UserController {
|
|||||||
.map(u -> {
|
.map(u -> {
|
||||||
Map<String, Object> m = new HashMap<>();
|
Map<String, Object> m = new HashMap<>();
|
||||||
m.put("id", u.getId());
|
m.put("id", u.getId());
|
||||||
m.put("text", (u.getFullName() != null && !u.getFullName().isBlank())
|
if (showUsername != null && Boolean.TRUE.equals(showUsername)) {
|
||||||
? u.getFullName()
|
m.put("text", (u.getFullName() != null && !u.getFullName().isBlank())
|
||||||
: u.getUserName());
|
? u.getFullName() + " (" + u.getUserName() + ")"
|
||||||
|
: u.getUserName());
|
||||||
|
} else {
|
||||||
|
m.put("text", (u.getFullName() != null && !u.getFullName().isBlank())
|
||||||
|
? u.getFullName()
|
||||||
|
: u.getUserName());
|
||||||
|
}
|
||||||
return m;
|
return m;
|
||||||
})
|
})
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
@ -385,4 +392,20 @@ public class UserController {
|
|||||||
"pagination", Map.of("more", more));
|
"pagination", Map.of("more", more));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ResponseBody
|
||||||
|
@GetMapping(value = "api/get-user/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
public Map<String, Object> getUser(@PathVariable Long id) {
|
||||||
|
User u = userService.findById(id);
|
||||||
|
if (u == null) {
|
||||||
|
return Map.of();
|
||||||
|
}
|
||||||
|
Map<String, Object> m = new HashMap<>();
|
||||||
|
m.put("id", u.getId());
|
||||||
|
m.put("userName", u.getUserName());
|
||||||
|
m.put("fullName", u.getFullName());
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,11 +56,16 @@ pedido.view.aceptar-ferro=Aceptar ferro
|
|||||||
pedido.view.ferro-download=Descargar ferro
|
pedido.view.ferro-download=Descargar ferro
|
||||||
pedido.view.cub-download=Descargar cubierta
|
pedido.view.cub-download=Descargar cubierta
|
||||||
pedido.view.tapa-download=Descargar tapa
|
pedido.view.tapa-download=Descargar tapa
|
||||||
|
pedido.view.admin-actions=Acciones de administrador
|
||||||
|
pedido.view.cancel-title=¿Estás seguro de que deseas cancelar este pedido?
|
||||||
|
pedido.view.cancel-text=Esta acción no se puede deshacer.
|
||||||
|
|
||||||
pedido.errors.linea-not-found=No se ha encontrado la línea de pedido.
|
pedido.errors.linea-not-found=No se ha encontrado la línea de pedido.
|
||||||
|
pedido.errors.cancel-pedido=Error al cancelar el pedido
|
||||||
pedido.errors.state-error=Estado de línea no válido.
|
pedido.errors.state-error=Estado de línea no válido.
|
||||||
pedido.errors.update-server-error=Error al actualizar el estado desde el servidor externo.
|
pedido.errors.update-server-error=Error al actualizar el estado desde el servidor externo.
|
||||||
pedido.errors.connecting-server-error=Error al conectar con el servidor externo.
|
pedido.errors.connecting-server-error=Error al conectar con el servidor externo.
|
||||||
pedido.errors.cannot-update=No se puede actualizar el estado de una línea con ese estado inicial.
|
pedido.errors.cannot-update=No se puede actualizar el estado de una línea con ese estado inicial.
|
||||||
pedido.success.estado-actualizado=Estado del pedido actualizado correctamente.
|
pedido.success.estado-actualizado=Estado del pedido actualizado correctamente.
|
||||||
pedido.success.same-estado=Sin cambios en el estado.
|
pedido.success.same-estado=Sin cambios en el estado.
|
||||||
|
pedido.success.pedido-cancelado=Pedido cancelado correctamente.
|
||||||
@ -49,6 +49,7 @@ presupuesto.comentario-administrador=Comentarios
|
|||||||
presupuesto.informacion-libro=Información del libro
|
presupuesto.informacion-libro=Información del libro
|
||||||
presupuesto.datos-generales-descripcion=Datos generales del presupuesto
|
presupuesto.datos-generales-descripcion=Datos generales del presupuesto
|
||||||
presupuesto.titulo=Título*
|
presupuesto.titulo=Título*
|
||||||
|
presupuesto.cliente=Cliente*
|
||||||
presupuesto.autor=Autor
|
presupuesto.autor=Autor
|
||||||
presupuesto.isbn=ISBN
|
presupuesto.isbn=ISBN
|
||||||
presupuesto.tirada=Tirada
|
presupuesto.tirada=Tirada
|
||||||
|
|||||||
@ -141,6 +141,79 @@ $(() => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('click', '.btn-cancel-pedido', function () {
|
||||||
|
const pedidoId = $(this).data('pedido-id');
|
||||||
|
if (!pedidoId) {
|
||||||
|
console.error('No se ha encontrado el ID del pedido.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Swal.fire({
|
||||||
|
title: window.languageBundle['pedido.view.cancel-title'] || '¿Estás seguro de que deseas cancelar este pedido?',
|
||||||
|
text: window.languageBundle['pedido.view.cancel-text'] || "Esta acción no se puede deshacer.",
|
||||||
|
icon: 'warning',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: window.languageBundle['app.yes'] || 'Sí, cancelar pedido',
|
||||||
|
cancelButtonText: window.languageBundle['app.cancel'] || 'No, mantener pedido',
|
||||||
|
buttonsStyling: false,
|
||||||
|
customClass: {
|
||||||
|
confirmButton: 'btn btn-danger me-2',
|
||||||
|
cancelButton: 'btn btn-light'
|
||||||
|
}
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
// Llamada AJAX para cancelar el pedido
|
||||||
|
$.ajax({
|
||||||
|
url: `/pedidos/cancel/${pedidoId}`,
|
||||||
|
type: 'POST',
|
||||||
|
success: function (response) {
|
||||||
|
if (!response || !response.success) {
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'error',
|
||||||
|
title: response.message || "Error",
|
||||||
|
timer: 1800,
|
||||||
|
buttonsStyling: false,
|
||||||
|
customClass: {
|
||||||
|
confirmButton: 'btn btn-secondary me-2',
|
||||||
|
cancelButton: 'btn btn-light'
|
||||||
|
},
|
||||||
|
showConfirmButton: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: response.message || "Éxito",
|
||||||
|
timer: 1800,
|
||||||
|
buttonsStyling: false,
|
||||||
|
customClass: {
|
||||||
|
confirmButton: 'btn btn-secondary me-2',
|
||||||
|
cancelButton: 'btn btn-light'
|
||||||
|
},
|
||||||
|
showConfirmButton: false
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.dismiss === Swal.DismissReason.timer) {
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function (xhr, status, error) {
|
||||||
|
console.error('Error al cancelar el pedido:', error);
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'error',
|
||||||
|
title: xhr.responseJSON?.message || 'Error',
|
||||||
|
buttonsStyling: false,
|
||||||
|
customClass: {
|
||||||
|
confirmButton: 'btn btn-secondary me-2', // clases para el botón confirmar
|
||||||
|
cancelButton: 'btn btn-light' // clases para cancelar
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@ -332,7 +332,7 @@ export default class PresupuestoWizard {
|
|||||||
servicios: this.formData.servicios.servicios,
|
servicios: this.formData.servicios.servicios,
|
||||||
datosMaquetacion: this.formData.servicios.datosMaquetacion,
|
datosMaquetacion: this.formData.servicios.datosMaquetacion,
|
||||||
datosMarcapaginas: this.formData.servicios.datosMarcapaginas,
|
datosMarcapaginas: this.formData.servicios.datosMarcapaginas,
|
||||||
cliente_id: $('#cliente_id').val() || null,
|
cliente_id: $('#user_id').val() || null,
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -1696,7 +1696,7 @@ export default class PresupuestoWizard {
|
|||||||
|
|
||||||
const body = {
|
const body = {
|
||||||
presupuesto: this.#getPresupuestoData(),
|
presupuesto: this.#getPresupuestoData(),
|
||||||
save: this.opts.canSave,
|
save: this.opts.mode == 'public' ? true : this.opts.canSave,
|
||||||
mode: this.opts.mode,
|
mode: this.opts.mode,
|
||||||
servicios: servicios,
|
servicios: servicios,
|
||||||
datosMaquetacion: this.formData.servicios.datosMaquetacion,
|
datosMaquetacion: this.formData.servicios.datosMaquetacion,
|
||||||
|
|||||||
@ -0,0 +1,43 @@
|
|||||||
|
$(() => {
|
||||||
|
|
||||||
|
// Inicializar select2 para el campo de cliente en el formulario de presupuesto
|
||||||
|
if ($('#user_id').length) {
|
||||||
|
$('#user_id').select2({
|
||||||
|
allowClear: false,
|
||||||
|
width: '100%',
|
||||||
|
ajax: {
|
||||||
|
url: '/users/api/get-users',
|
||||||
|
dataType: 'json',
|
||||||
|
data: function (params) {
|
||||||
|
return {
|
||||||
|
q: params.term, // término de búsqueda
|
||||||
|
page: params.page || 1,
|
||||||
|
size: 10,
|
||||||
|
showUsername: true
|
||||||
|
};
|
||||||
|
},
|
||||||
|
delay: 250,
|
||||||
|
processResults: function (data) {
|
||||||
|
return {
|
||||||
|
results: data.results || [],
|
||||||
|
pagination: data.pagination || { more: false }
|
||||||
|
};
|
||||||
|
},
|
||||||
|
cache: true
|
||||||
|
},
|
||||||
|
minimumInputLength: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
// Si hay un valor inicial, cargar y establecer el usuario seleccionado
|
||||||
|
const initialUserId = $('#user_id').val();
|
||||||
|
if (initialUserId) {
|
||||||
|
$.ajax({
|
||||||
|
url: `/users/api/get-user/${initialUserId}`,
|
||||||
|
dataType: 'json'
|
||||||
|
}).then(function (data) {
|
||||||
|
const option = new Option(`${data.fullName} (${data.userName})`, data.id, true, true);
|
||||||
|
$('#user_id').append(option).trigger('change');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -46,7 +46,7 @@
|
|||||||
url: '/presupuesto/datatable/clientes',
|
url: '/presupuesto/datatable/clientes',
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
},
|
},
|
||||||
order: [[0, 'asc']],
|
order: [[0, 'desc']],
|
||||||
columns: [
|
columns: [
|
||||||
{ data: 'id', name: 'id', orderable: true },
|
{ data: 'id', name: 'id', orderable: true },
|
||||||
{ data: 'titulo', name: 'titulo', orderable: true },
|
{ data: 'titulo', name: 'titulo', orderable: true },
|
||||||
|
|||||||
@ -48,7 +48,7 @@ import { preguntarTipoPresupuesto, duplicar, reimprimir } from './presupuesto-ut
|
|||||||
url: '/presupuesto/datatable/anonimos',
|
url: '/presupuesto/datatable/anonimos',
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
},
|
},
|
||||||
order: [[0, 'asc']],
|
order: [[0, 'desc']],
|
||||||
columns: [
|
columns: [
|
||||||
{ data: 'id', name: 'id', orderable: true },
|
{ data: 'id', name: 'id', orderable: true },
|
||||||
{ data: 'titulo', name: 'titulo', orderable: true },
|
{ data: 'titulo', name: 'titulo', orderable: true },
|
||||||
@ -174,7 +174,7 @@ import { preguntarTipoPresupuesto, duplicar, reimprimir } from './presupuesto-ut
|
|||||||
url: '/presupuesto/datatable/clientes',
|
url: '/presupuesto/datatable/clientes',
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
},
|
},
|
||||||
order: [[0, 'asc']],
|
order: [[0, 'desc']],
|
||||||
columns: [
|
columns: [
|
||||||
{ data: 'id', name: 'id', orderable: true },
|
{ data: 'id', name: 'id', orderable: true },
|
||||||
{ data: 'user', name: 'user.fullName', orderable: true },
|
{ data: 'user', name: 'user.fullName', orderable: true },
|
||||||
|
|||||||
@ -134,14 +134,6 @@
|
|||||||
<div class="row align-items-center gy-3">
|
<div class="row align-items-center gy-3">
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<div class="d-flex flex-wrap my-n1">
|
<div class="d-flex flex-wrap my-n1">
|
||||||
<!-- Botón cancelar -->
|
|
||||||
<div th:if="${item.estado.name != 'cancelado' && item.estado.name != 'terminado'}">
|
|
||||||
<a href="javascript:void(0);" class="d-block text-body p-1 px-2 cancel-item"
|
|
||||||
th:attr="data-linea-id=${item.lineaId}">
|
|
||||||
<i class="ri-delete-bin-fill text-muted align-bottom me-1"><span
|
|
||||||
th:text="#{pedido.cancelar}">Cancelar Pedido</span></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<!-- Actualizar estado-->
|
<!-- Actualizar estado-->
|
||||||
<div class="update-estado-button"
|
<div class="update-estado-button"
|
||||||
th:if="${item.estado.name != 'cancelado' && item.estado.name != 'maquetacion' && item.estado.name != 'terminado'}">
|
th:if="${item.estado.name != 'cancelado' && item.estado.name != 'maquetacion' && item.estado.name != 'terminado'}">
|
||||||
|
|||||||
@ -38,15 +38,33 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 col-md-auto">
|
<div class="col-12 col-md-auto">
|
||||||
<div th:insert="~{imprimelibros/direcciones/direccionFacturacionCard ::
|
<div th:insert="~{imprimelibros/direcciones/direccionFacturacionCard ::
|
||||||
direccionFacturacionCard(
|
direccionFacturacionCard(
|
||||||
direccion=${direccionFacturacion},
|
direccion=${direccionFacturacion},
|
||||||
pais=${direccionFacturacion != null ? direccionFacturacion.paisNombre : ''}
|
pais=${direccionFacturacion != null ? direccionFacturacion.paisNombre : ''}
|
||||||
)}">
|
)}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<th:block th:if="${isAdmin and showCancel}">
|
||||||
|
<div sec:authorize="isAuthenticated() and hasAnyRole('SUPERADMIN','ADMIN')"
|
||||||
|
class="col-12 col-md-auto">
|
||||||
|
<div class="card card border mb-3 admin-actions">
|
||||||
|
<div class="card-header bg-light">
|
||||||
|
<span class="fs-16" th:text="#{'pedido.view.admin-actions'}"></span>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<button type="button" class="btn btn-danger w-100 btn-cancel-pedido"
|
||||||
|
th:text="#{pedido.cancelar}" th:attr="data-pedido-id=${id}">
|
||||||
|
Cancelar pedido
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</th:block>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th:block th:each="linea: ${lineas}">
|
<th:block th:each="linea: ${lineas}">
|
||||||
<div
|
<div
|
||||||
th:insert="~{imprimelibros/pedidos/pedidos-linea :: pedido-linea (item=${linea}, isAdmin=${isAdmin})}">
|
th:insert="~{imprimelibros/pedidos/pedidos-linea :: pedido-linea (item=${linea}, isAdmin=${isAdmin})}">
|
||||||
@ -76,7 +94,8 @@
|
|||||||
<script th:src="@{/assets/libs/datatables/buttons.colVis.min.js}"></script>
|
<script th:src="@{/assets/libs/datatables/buttons.colVis.min.js}"></script>
|
||||||
|
|
||||||
<script type="module" th:src="@{/assets/js/pages/imprimelibros/pedidos/pedidos-view.js}"></script>
|
<script type="module" th:src="@{/assets/js/pages/imprimelibros/pedidos/pedidos-view.js}"></script>
|
||||||
<script th:if="${isAdmin}" type="module" th:src="@{/assets/js/pages/imprimelibros/pedidos/pedidos-view-admin.js}"></script>
|
<script th:if="${isAdmin}" type="module"
|
||||||
|
th:src="@{/assets/js/pages/imprimelibros/pedidos/pedidos-view-admin.js}"></script>
|
||||||
</th:block>
|
</th:block>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,28 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="px-2">
|
<div class="px-2">
|
||||||
|
<th:block th:if="${presupuesto?.user != null}">
|
||||||
|
<div sec:authorize="isAuthenticated() and hasAnyRole('SUPERADMIN','ADMIN')" class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="user_id" class="form-label" th:text="#{presupuesto.cliente}">
|
||||||
|
>Cliente*</label>
|
||||||
|
<select class="form-select select2 datos-generales-data" id="user_id">
|
||||||
|
<option
|
||||||
|
th:value="${presupuesto?.user.id} ?: ''"
|
||||||
|
th:text="${presupuesto.user != null ? presupuesto.user.fullName + ' (' + presupuesto.user.userName + ')' : ''}"
|
||||||
|
selected>
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div sec:authorize="isAuthenticated() and !hasAnyRole('SUPERADMIN','ADMIN')">
|
||||||
|
<input type="hidden" class="datos-generales-data" id="user_id"
|
||||||
|
th:value="${presupuesto?.user.id} ?: ''">
|
||||||
|
</div>
|
||||||
|
</th:block>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
|
|||||||
@ -89,6 +89,8 @@
|
|||||||
th:src="@{/assets/libs/quill/quill.min.js}"></script>
|
th:src="@{/assets/libs/quill/quill.min.js}"></script>
|
||||||
<script sec:authorize="isAuthenticated() and hasAnyRole('SUPERADMIN','ADMIN')"
|
<script sec:authorize="isAuthenticated() and hasAnyRole('SUPERADMIN','ADMIN')"
|
||||||
th:src="@{/assets/js/pages/imprimelibros/presupuestador/text-editor.js}"></script>
|
th:src="@{/assets/js/pages/imprimelibros/presupuestador/text-editor.js}"></script>
|
||||||
|
<script sec:authorize="isAuthenticated() and hasAnyRole('SUPERADMIN','ADMIN')"
|
||||||
|
th:src="@{/assets/js/pages/imprimelibros/presupuestos/admin-utils.js}"></script>
|
||||||
|
|
||||||
<script type="module" th:src="@{/assets/js/pages/imprimelibros/presupuestos/duplicate-reprint.js}"></script>
|
<script type="module" th:src="@{/assets/js/pages/imprimelibros/presupuestos/duplicate-reprint.js}"></script>
|
||||||
</th:block>
|
</th:block>
|
||||||
|
|||||||
Reference in New Issue
Block a user