Compare commits

..

1 Commits

27 changed files with 115 additions and 248 deletions

View File

@ -80,7 +80,7 @@ public class CartController {
else if (direcciones != null && direcciones.containsKey("direcciones"))
model.addAttribute("direcciones", direcciones.get("direcciones"));
var summary = service.getCartSummary(cart, locale, true);
var summary = service.getCartSummary(cart, locale);
model.addAttribute("cartSummary", summary);
if (summary.get("errorShipmentCost") != null && (Boolean) summary.get("errorShipmentCost"))
model.addAttribute("errorEnvio", true);
@ -165,7 +165,7 @@ public class CartController {
try {
service.updateCart(id, updateRequest);
var cartSummary = service.getCartSummary(service.getCartById(id), locale, true);
var cartSummary = service.getCartSummary(service.getCartById(id), locale);
model.addAttribute("cartSummary", cartSummary);
return "imprimelibros/cart/_cartSummary :: cartSummary(summary=${cartSummary})";

View File

@ -163,7 +163,7 @@ public class CartService {
return itemRepo.findByCartId(cart.getId()).size();
}
public Map<String, Object> getCartSummaryRaw(Cart cart, Locale locale, Boolean hasTaxes) {
public Map<String, Object> getCartSummaryRaw(Cart cart, Locale locale) {
double base = 0.0;
double iva4 = 0.0;
@ -269,11 +269,6 @@ public class CartService {
}
}
if(!hasTaxes) {
iva4 = 0.0;
iva21 = 0.0;
}
double totalBeforeDiscount = base + iva4 + iva21 + shipment;
int fidelizacion = this.getDescuentoFidelizacion(cart.getUserId());
double descuento = totalBeforeDiscount * fidelizacion / 100.0;
@ -323,8 +318,8 @@ public class CartService {
return 0;
}
public Map<String, Object> getCartSummary(Cart cart, Locale locale, Boolean hasTaxes) {
Map<String, Object> raw = getCartSummaryRaw(cart, locale, hasTaxes);
public Map<String, Object> getCartSummary(Cart cart, Locale locale) {
Map<String, Object> raw = getCartSummaryRaw(cart, locale);
double base = (Double) raw.get("base");
double iva4 = (Double) raw.get("iva4");

View File

@ -22,7 +22,6 @@ import com.imprimelibros.erp.direcciones.DireccionService;
import com.imprimelibros.erp.cart.Cart;
import com.imprimelibros.erp.cart.CartService;
@Controller
@RequestMapping("/checkout")
public class CheckoutController {
@ -59,25 +58,10 @@ public class CheckoutController {
Long userId = Utils.currentUserId(principal);
Cart cart = cartService.getOrCreateActiveCart(userId);
model.addAttribute("summary", cartService.getCartSummary(cart, locale, true));
model.addAttribute("summary", cartService.getCartSummary(cart, locale));
return "imprimelibros/checkout/checkout"; // crea esta vista si quieres (tabla simple)
}
@GetMapping({"/get-summary", "/get-summary/{direccionId}"})
public String getCheckoutSummary(@PathVariable(required = false) Long direccionId, Principal principal, Model model, Locale locale) {
Long userId = Utils.currentUserId(principal);
Cart cart = cartService.getOrCreateActiveCart(userId);
Boolean hasTaxes = true;
if(direccionId != null) {
hasTaxes = direccionService.hasTaxes(direccionId);
}
Map<String, Object> summary = cartService.getCartSummary(cart, locale, hasTaxes);
model.addAttribute("summary", summary);
return "imprimelibros/checkout/_summary :: checkoutSummary(summary=${summary})";
}
@GetMapping("/get-address/{id}")
public String getDireccionCard(@PathVariable Long id, Model model, Locale locale) {
Direccion dir = direccionService.findById(id)

View File

@ -153,26 +153,4 @@ public class DireccionService {
return false;
}
public Boolean hasTaxes(Long direccionId) {
if(direccionId == null) {
return true; // Si no hay dirección, asumimos que sí tiene impuestos
}
Optional<Direccion> dir = repo.findById(direccionId);
if (dir == null || dir.isEmpty()) {
throw new RuntimeException("Dirección no encontrada");
}
if(dir.get().getPaisCode3().toLowerCase().equals("esp")) {
int provincia = dir.get().getCp() / 1000;
if (provincia == 35 || provincia == 38 ) {
return false; // Canarias (sin IVA)lñ.
}
return true; // España (todas las provincias)
}
else{
// Fuera de España, asumimos que no tiene impuestos (puedes ajustar esto según tus necesidades)
return false;
}
}
}

View File

@ -8,6 +8,7 @@ import com.imprimelibros.erp.facturacion.dto.FacturaDireccionMapper;
import com.imprimelibros.erp.facturacion.dto.FacturaGuardarDto;
import com.imprimelibros.erp.facturacion.dto.FacturaLineaUpsertDto;
import com.imprimelibros.erp.facturacion.dto.FacturaPagoUpsertDto;
import com.imprimelibros.erp.facturacion.repo.FacturaDireccionRepository;
import com.imprimelibros.erp.facturacion.repo.FacturaLineaRepository;
import com.imprimelibros.erp.facturacion.repo.FacturaPagoRepository;
import com.imprimelibros.erp.facturacion.repo.FacturaRepository;

View File

@ -13,7 +13,7 @@ public interface PedidoDireccionRepository extends JpaRepository<PedidoDireccion
// Si en tu código sueles trabajar con el objeto:
List<PedidoDireccion> findByPedidoLinea(PedidoLinea pedidoLinea);
PedidoDireccion findFirstByPedidoIdAndFacturacionTrue(Long pedidoId);
PedidoDireccion findByPedidoIdAndFacturacionTrue(Long pedidoId);
@Query("""
select distinct d

View File

@ -1,6 +1,5 @@
package com.imprimelibros.erp.pedidos;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.ArrayList;
@ -69,7 +68,7 @@ public class PedidoService {
}
public PedidoDireccion getPedidoDireccionFacturacionByPedidoId(Long pedidoId) {
return pedidoDireccionRepository.findFirstByPedidoIdAndFacturacionTrue(pedidoId);
return pedidoDireccionRepository.findByPedidoIdAndFacturacionTrue(pedidoId);
}
@Transactional
@ -82,8 +81,7 @@ public class PedidoService {
Pedido pedido = new Pedido();
Cart cart = cartService.getCartById(cartId);
Boolean hasTaxes = direccionService.hasTaxes(direccionFacturacionId);
Map<String, Object> cartSummaryRaw = cartService.getCartSummaryRaw(cart, Locale.getDefault(), hasTaxes);
Map<String, Object> cartSummaryRaw = cartService.getCartSummaryRaw(cart, Locale.getDefault());
// Datos económicos (ojo con las claves, son las del summaryRaw)
pedido.setBase((Double) cartSummaryRaw.getOrDefault("base", 0.0d));
@ -139,11 +137,6 @@ public class PedidoService {
Presupuesto p = presupuestoRepository.findById(pCart.getId())
.orElseThrow(() -> new IllegalStateException("Presupuesto no encontrado: " + pCart.getId()));
p.setEstado(Presupuesto.Estado.aceptado);
if(!hasTaxes){
p.setIvaImporte21(BigDecimal.ZERO);
p.setIvaImporte4(BigDecimal.ZERO);
p.setTotalConIva(p.getBaseImponible());
}
presupuestoRepository.save(p);
PedidoLinea linea = new PedidoLinea();
@ -157,12 +150,9 @@ public class PedidoService {
// Guardar las direcciones asociadas a la línea del pedido
Map<String, Object> direcciones_presupuesto = this.getDireccionesPresupuesto(cart, p);
saveDireccionesPedidoLinea(direcciones_presupuesto, pedidoGuardado, linea);
saveDireccionesPedidoLinea(direcciones_presupuesto, pedidoGuardado, linea, direccionFacturacionId);
}
if(direccionFacturacionId != null && pedidoGuardado != null && pedidoGuardado.getId() != null){
saveDireccionFacturacionPedido(pedidoGuardado, direccionFacturacionId);
}
return pedidoGuardado;
}
@ -206,7 +196,7 @@ public class PedidoService {
Pedido pedido = pedidoRepository.findById(pedidoId).orElse(null);
if (pedido != null) {
PedidoDireccion direccionPedido = pedidoDireccionRepository.findFirstByPedidoIdAndFacturacionTrue(pedidoId);
PedidoDireccion direccionPedido = pedidoDireccionRepository.findByPedidoIdAndFacturacionTrue(pedidoId);
if (direccionPedido == null) {
// crear
@ -253,7 +243,7 @@ public class PedidoService {
}
public PedidoDireccion getDireccionFacturacionPedido(Long pedidoId) {
return pedidoDireccionRepository.findFirstByPedidoIdAndFacturacionTrue(pedidoId);
return pedidoDireccionRepository.findByPedidoIdAndFacturacionTrue(pedidoId);
}
public List<PedidoDireccion> getDireccionesEntregaPedidoLinea(Long pedidoLineaId) {
@ -655,7 +645,7 @@ public class PedidoService {
private void saveDireccionesPedidoLinea(
Map<String, Object> direcciones,
Pedido pedido,
PedidoLinea linea) {
PedidoLinea linea, Long direccionFacturacionId) {
String email = pedido.getCreatedBy().getUserName();
@ -702,12 +692,7 @@ public class PedidoService {
pedidoDireccionRepository.save(direccion);
}
}
}
private void saveDireccionFacturacionPedido(Pedido pedido, Long direccionFacturacionId) {
if (direccionFacturacionId != null) {
String email = pedido.getCreatedBy().getUserName();
Direccion dirFact = direccionService.findById(direccionFacturacionId).orElse(null);
if (dirFact != null) {
HashMap<String, Object> dirFactMap = new HashMap<>();
@ -728,7 +713,7 @@ public class PedidoService {
false,
dirFactMap,
pedido,
null,
linea,
false,
true);
pedidoDireccionRepository.save(direccion);

View File

@ -12,7 +12,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.context.MessageSource;
import org.springframework.core.io.ByteArrayResource;
@ -30,22 +29,23 @@ 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.persistence.criteria.Subquery;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.PostMapping;
import com.imprimelibros.erp.presupuesto.dto.Presupuesto;
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;
@ -58,7 +58,7 @@ public class PedidosController {
public PedidosController(PedidoRepository repoPedido, PedidoService pedidoService, UserDao repoUser,
MessageSource messageSource, TranslationService translationService,
PedidoLineaRepository repoPedidoLinea, PaisesService paisesService,
FacturacionService facturacionService) {
FacturacionService facturacionService, PresupuestoService presupuestoService) {
this.repoPedido = repoPedido;
this.pedidoService = pedidoService;
this.repoUser = repoUser;
@ -67,6 +67,7 @@ public class PedidosController {
this.repoPedidoLinea = repoPedidoLinea;
this.paisesService = paisesService;
this.facturacionService = facturacionService;
this.presupuestoService = presupuestoService;
}
@GetMapping
@ -110,7 +111,6 @@ public class PedidosController {
"id",
"createdBy.fullName",
"createdAt",
"titulos",
"total",
"estado");
@ -118,10 +118,8 @@ public class PedidosController {
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");
String titulosSearch = dt.getColumnSearch("titulos");
// 2) Si hay filtro, traducirlo a userIds y añadirlo al Specification
if (clientSearch != null) {
@ -153,45 +151,11 @@ public class PedidosController {
base = base.and((root, query, cb) -> cb.disjunction());
}
}
if (titulosSearch != null && !titulosSearch.isBlank()) {
String like = "%" + titulosSearch.trim().toLowerCase() + "%";
base = base.and((root, query, cb) -> {
Subquery<Long> minLineaIdSq = query.subquery(Long.class);
var plMin = minLineaIdSq.from(PedidoLinea.class);
minLineaIdSq.select(cb.min(plMin.get("id")));
minLineaIdSq.where(cb.equal(plMin.get("pedido"), root));
Subquery<String> firstTitleSq = query.subquery(String.class);
var plFirst = firstTitleSq.from(PedidoLinea.class);
var prFirst = plFirst.join("presupuesto", JoinType.LEFT);
firstTitleSq.select(cb.lower(cb.coalesce(prFirst.get("titulo"), "")));
firstTitleSq.where(
cb.equal(plFirst.get("pedido"), root),
cb.equal(plFirst.get("id"), minLineaIdSq));
return cb.like(firstTitleSq, like);
});
}
Long total = repoPedido.count(base);
return DataTable
.of(repoPedido, Pedido.class, dt, searchable)
.orderable(orderable)
.orderable("titulos", (root, query, cb) -> {
Subquery<Long> minLineaIdSq = query.subquery(Long.class);
var plMin = minLineaIdSq.from(PedidoLinea.class);
minLineaIdSq.select(cb.min(plMin.get("id")));
minLineaIdSq.where(cb.equal(plMin.get("pedido"), root));
Subquery<String> firstTitleSq = query.subquery(String.class);
var plFirst = firstTitleSq.from(PedidoLinea.class);
var prFirst = plFirst.join("presupuesto", JoinType.LEFT);
firstTitleSq.select(cb.lower(cb.coalesce(prFirst.get("titulo"), "")));
firstTitleSq.where(
cb.equal(plFirst.get("pedido"), root),
cb.equal(plFirst.get("id"), minLineaIdSq));
return firstTitleSq;
})
.add("id", Pedido::getId)
.add("created_at", pedido -> Utils.formatInstant(pedido.getCreatedAt(), locale))
.add("cliente", pedido -> {
@ -207,38 +171,6 @@ public class PedidosController {
return "";
}
})
.add("titulos", pedido -> {
List<PedidoLinea> lineas = repoPedidoLinea.findByPedidoIdOrderByIdAsc(pedido.getId());
if (lineas.isEmpty()) {
return "";
}
List<Presupuesto> presupuestos = lineas.stream()
.map(PedidoLinea::getPresupuesto)
.filter(presupuesto -> presupuesto != null)
.collect(Collectors.toList());
if (presupuestos.isEmpty()) {
return "";
}
String primerTitulo = presupuestos.get(0).getTitulo();
if (primerTitulo == null) {
primerTitulo = "";
} else {
primerTitulo = primerTitulo.trim();
}
int extras = presupuestos.size() - 1;
if (extras <= 0) {
return primerTitulo;
}
String suffix = messageSource.getMessage(
"pedido.table.titulos.and-more",
new Object[] { extras },
locale);
return primerTitulo + " " + suffix;
})
.add("estado", pedido -> {
List<PedidoLinea> lineas = repoPedidoLinea.findByPedidoId(pedido.getId());
if (lineas.isEmpty()) {

View File

@ -109,6 +109,21 @@ public class Presupuesto extends AbstractAuditedEntity implements Cloneable {
}
}
public enum Entrega {
peninsula("presupuesto.entrega.peninsula"),
canarias("presupuesto.entrega.canarias"),
paises_ue("presupuesto.entrega.paises-ue");
private final String messageKey;
Entrega(String messageKey) {
this.messageKey = messageKey;
}
public String getMessageKey() {
return messageKey;
}
}
@Override
public Presupuesto clone() {
@ -173,6 +188,10 @@ public class Presupuesto extends AbstractAuditedEntity implements Cloneable {
@Column(name = "iva_reducido")
private Boolean ivaReducido;
@Column(name = "entrega_tipo")
@Enumerated(EnumType.STRING)
private Entrega entregaTipo;
@Column(name = "iva_importe_4", precision = 12, scale = 2)
private BigDecimal ivaImporte4;
@ -512,6 +531,14 @@ public class Presupuesto extends AbstractAuditedEntity implements Cloneable {
this.ivaReducido = ivaReducido;
}
public Entrega getEntregaTipo() {
return entregaTipo;
}
public void setEntregaTipo(Entrega entregaTipo) {
this.entregaTipo = entregaTipo;
}
public BigDecimal getIvaImporte4() {
return ivaImporte4;
}

View File

@ -37,6 +37,7 @@ public class PresupuestoFormDataMapper {
public String paginasColor = "";
public String posicionPaginasColor = "";
public String tipoEncuadernacion = "fresado"; // enum name
public String entregaTipo = "peninsula"; // enum name
public boolean ivaReducido = true;
}
@ -156,6 +157,7 @@ public class PresupuestoFormDataMapper {
vm.datosGenerales.tipoEncuadernacion = enumName(p.getTipoEncuadernacion(), "fresado");
vm.datosGenerales.entregaTipo = enumName(p.getEntregaTipo(), "peninsula");
vm.datosGenerales.ivaReducido = Boolean.TRUE.equals(p.getIvaReducido());
// ===== Interior

View File

@ -329,7 +329,7 @@ public class PresupuestoService {
.filter(Objects::nonNull)
.map(tirada -> tirada + 4)
.collect(Collectors.toList()));
if (presupuesto.getSelectedTirada() != null) {
if(presupuesto.getSelectedTirada() != null) {
presupuesto.setSelectedTirada(presupuesto.getSelectedTirada());
}
} else {
@ -352,7 +352,7 @@ public class PresupuestoService {
body.put("cubierta", cubierta);
body.put("guardas", null);
// Para las reimpresiones
if (presupuesto.getIsReimpresion() != null && presupuesto.getIsReimpresion()) {
if(presupuesto.getIsReimpresion() != null && presupuesto.getIsReimpresion()) {
body.put("reimpresion", 1);
body.put("iskn", presupuesto.getProveedorRef1());
}
@ -1126,7 +1126,7 @@ public class PresupuestoService {
if (s.get("id").equals("retractilado")) {
String p = obtenerPrecioRetractilado(cantidad);
if (p != null) {
if(p != null){
double precio_retractilado = Double.parseDouble(p);
s.put("price", precio_retractilado);
} else {
@ -1149,7 +1149,7 @@ public class PresupuestoService {
}
}
try {
if (presupuesto.getSelectedTirada() != null && presupuesto.getSelectedTirada().equals(tirada))
if(presupuesto.getSelectedTirada() != null && presupuesto.getSelectedTirada().equals(tirada))
presupuesto.setServiciosJson(new ObjectMapper().writeValueAsString(servicios));
} catch (Exception ignore) {
System.out.println("Error guardando servicios JSON: " + ignore.getMessage());
@ -1162,6 +1162,7 @@ public class PresupuestoService {
// Si la entrega es en peninsula, se mira el valor del iva
// Canarias y paises UE no llevan IVA
if (presupuesto.getEntregaTipo() == Presupuesto.Entrega.peninsula) {
// Si el iva es reducido, el precio de la tirada y el del prototipo llevan IVA
// 4%
if (presupuesto.getIvaReducido()) {
@ -1176,6 +1177,7 @@ public class PresupuestoService {
BigDecimal.valueOf(100), 2,
RoundingMode.HALF_UP);
}
}
baseImponible = baseImponible.add(serviciosTotal);
BigDecimal totalConIva = baseImponible.add(ivaImporte21).add(ivaImporte4);
@ -1333,7 +1335,7 @@ public class PresupuestoService {
public Boolean hasMaquetacion(Presupuesto presupuesto) {
if (presupuesto.getServiciosJson() != null && !presupuesto.getServiciosJson().isEmpty()) {
if (presupuesto.getServiciosJson().contains("maquetacion")) {
if(presupuesto.getServiciosJson().contains("maquetacion")) {
return true;
}
}
@ -1472,6 +1474,7 @@ public class PresupuestoService {
target.setServiciosTotal(src.getServiciosTotal());
target.setBaseImponible(src.getBaseImponible());
target.setIvaReducido(src.getIvaReducido());
target.setEntregaTipo(src.getEntregaTipo());
target.setIvaImporte4(src.getIvaImporte4());
target.setIvaImporte21(src.getIvaImporte21());
target.setTotalConIva(src.getTotalConIva());

View File

@ -29,7 +29,6 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import com.imprimelibros.erp.datatables.DataTablesRequest;
import com.imprimelibros.erp.datatables.DataTablesParser;
@ -378,7 +377,7 @@ public class UserController {
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size) {
Pageable pageable = PageRequest.of(Math.max(0, page - 1), size, Sort.by(Sort.Direction.ASC, "fullName"));
Pageable pageable = PageRequest.of(Math.max(0, page - 1), size);
Page<User> users = userService.findByRoleAndSearch(role, q, pageable);

View File

@ -1,20 +0,0 @@
databaseChangeLog:
- changeSet:
id: 0026-drop-entrega-tipo-from-presupuesto
author: jjo
changes:
- dropColumn:
tableName: presupuesto
columnName: entrega_tipo
rollback:
- addColumn:
tableName: presupuesto
columns:
- column:
name: entrega_tipo
type: ENUM('peninsula', 'canarias', 'paises_ue')
defaultValue: peninsula
afterColumn: base_imponible
constraints:
nullable: false

View File

@ -49,5 +49,3 @@ databaseChangeLog:
file: db/changelog/changesets/0024-series-facturacion-seeder.yml
- include:
file: db/changelog/changesets/0025-create-facturas-direcciones.yml
- include:
file: db/changelog/changesets/0026-drop-entrega-tipo-from-presupuesto.yml

View File

@ -47,8 +47,6 @@ pedido.prueba=Prueba
pedido.table.id=Num. Pedido
pedido.table.cliente=Cliente
pedido.table.fecha=Fecha
pedido.table.titulos=Títulos
pedido.table.titulos.and-more=y {0} más
pedido.table.importe=Importe
pedido.table.estado=Estado
pedido.table.acciones=Acciones

View File

@ -18,8 +18,8 @@ $(() => {
$('#addBillingAddressBtn').on('click', seleccionarDireccionEnvio);
$(document).on('change', '#authorization-required', function () {
if ($(this).is(':checked')) {
$('#authorization-required').on('change', function () {
if($(this).is(':checked')) {
if ($('#direccion-div .direccion-card').length > 0) {
$('#btn-checkout').prop('disabled', false);
}
@ -148,23 +148,6 @@ $(() => {
$('#btn-checkout').prop('disabled', false);
}
hideLoader();
if (direccionId) {
$.ajax({
url: `/checkout/get-summary/${direccionId}`,
type: 'GET',
success: function (response) {
const parent = $('.cart-summary-container').parent();
$('.cart-summary-container').remove();
parent.append(response);
$('#dirFactId').val(direccionId);
},
error: function () {
console.error('Error al actualizar el resumen del carrito.');
}
});
}
return true;
}
hideLoader();
@ -181,18 +164,6 @@ $(() => {
$card.remove();
$('#addBillingAddressBtn').removeClass('d-none');
$('#btn-checkout').prop('disabled', true);
$.ajax({
url: `/checkout/get-summary`,
type: 'GET',
success: function (response) {
const parent = $('.cart-summary-container').parent();
$('.cart-summary-container').remove();
parent.append(response);
},
error: function () {
console.error('Error al actualizar el resumen del carrito.');
}
});
});
@ -223,7 +194,7 @@ $(() => {
type: 'POST', // PUT simulado via _method
data: $form.serialize(),
dataType: 'html',
success: async function (html) {
success: function (html) {
// Si por cualquier motivo llega 200 con fragmento, lo insertamos igual
if (typeof html === 'string' && html.indexOf('id="direccionForm"') !== -1 && html.indexOf('<html') === -1) {
$('#direccionFormModalBody').html(html);
@ -234,8 +205,7 @@ $(() => {
}
// Éxito real: cerrar y recargar tabla
$('#direccionFormModal').modal('hide');
await seleccionarDireccionEnvio();
seleccionarDireccionEnvio();
},
error: function (xhr) {
// Con 422 devolvemos el fragmento con errores aquí

View File

@ -71,7 +71,7 @@ $(() => {
// -----------------------------
$table.on('click', '.btn-view-factura', function () {
const row = dt.row($(this).closest('tr')).data();
window.open('/facturas/' + row.id, '_blank', 'noopener,noreferrer');
window.location.href = `/facturas/${row.id}`;
});
// -----------------------------

View File

@ -48,7 +48,6 @@ $(() => {
{ data: 'id', name: 'id', orderable: true },
{ data: 'cliente', name: 'createdBy.fullName', orderable: true },
{ data: 'created_at', name: 'createdAt', orderable: true },
{ data: 'titulos', name: 'titulos', orderable: true },
{ data: 'total', name: 'total', orderable: true },
{ data: 'estado', name: 'estado', orderable: true },
{ data: 'actions', name: 'actions', orderable: false, searchable: false }

View File

@ -1,8 +1,8 @@
$(() => {
$(document).on('click', '.btn-view', function () {
let pedidoId = $(this).data('id');
if(!pedidoId) return;
window.open('/pedidos/view/' + pedidoId, '_blank', 'noopener,noreferrer');
let url = `/pedidos/view/${pedidoId}`;
window.location.href = url;
});
$(document).on('click', '.btn-pay', async function () {

View File

@ -47,7 +47,6 @@ $(() => {
columns: [
{ data: 'id', name: 'id', orderable: true },
{ data: 'created_at', name: 'createdAt', orderable: true },
{ data: 'titulos', name: 'titulos', orderable: true },
{ data: 'total', name: 'total', orderable: true },
{ data: 'estado', name: 'estado', orderable: true },
{ data: 'actions', name: 'actions', orderable: false, searchable: false }

View File

@ -34,6 +34,7 @@ export default class PresupuestoWizard {
paginasColor: 0,
posicionPaginasColor: '',
tipoEncuadernacion: 'fresado',
entregaTipo: 'peninsula',
ivaReducido: true,
},
interior: {
@ -129,6 +130,7 @@ export default class PresupuestoWizard {
this.divPosicionPaginasColor = $('#div-posicion-paginas-color');
this.posicionPaginasColor = $('#posicionPaginasColor');
this.paginas = $('#paginas');
this.entregaTipo = $('#entregaTipo');
this.ivaReducido = $('#iva-reducido');
this.btnIvaReducidoDetail = $('#btn-iva-reducido-detail');
this.datos_generales_alert = $('#datos-generales-alert');
@ -664,6 +666,7 @@ export default class PresupuestoWizard {
paginasColor: this.paginasColor.val(),
posicionPaginasColor: this.posicionPaginasColor.val(),
tipoEncuadernacion: $('.tipo-libro input:checked').val() || 'fresado',
entregaTipo: this.entregaTipo.val(),
ivaReducido: this.ivaReducido.is(':checked'),
};
}
@ -685,6 +688,7 @@ export default class PresupuestoWizard {
paginasColor: data.paginasColor,
posicionPaginasColor: data.posicionPaginasColor,
tipoEncuadernacion: data.tipoEncuadernacion,
entregaTipo: data.entregaTipo,
ivaReducido: data.ivaReducido,
};
}
@ -732,6 +736,7 @@ export default class PresupuestoWizard {
}
}
this.entregaTipo.val(this.formData.datosGenerales.entregaTipo);
this.ivaReducido.prop('checked', this.formData.datosGenerales.ivaReducido);
}
@ -1892,6 +1897,15 @@ export default class PresupuestoWizard {
...result,
};
if (!this.formData.servicios.servicios.some(s => s.id === "marcapaginas") && result.precio > 0) {
this.formData.servicios.servicios.push({
id: "marcapaginas",
label: $(`label[for="marcapaginas"] .service-title`).text().trim(),
units: 1,
price: result.precio,
});
}
this.#cacheFormData();
});

View File

@ -72,7 +72,7 @@ import { preguntarTipoPresupuesto, duplicar, reimprimir } from './presupuesto-ut
e.preventDefault();
const id = $(this).data('id');
if (id) {
window.open('/presupuesto/view/' + id, '_blank', 'noopener,noreferrer');
window.location.href = '/presupuesto/view/' + id;
}
});
@ -196,7 +196,7 @@ import { preguntarTipoPresupuesto, duplicar, reimprimir } from './presupuesto-ut
e.preventDefault();
const id = $(this).data('id');
if (id) {
window.open('/presupuesto/edit/' + id, '_blank', 'noopener,noreferrer');
window.location.href = '/presupuesto/edit/' + id;
}
});

View File

@ -55,11 +55,7 @@ export async function preguntarTipoPresupuesto() {
url: 'users/api/get-users', // ajusta a tu endpoint
dataType: 'json',
delay: 250,
data: (params) => ({
q: params.term || '',
page: params.page || 1,
size: 10,
}),
data: (params) => ({ q: params.term }),
processResults: data => ({
results: data.results,
pagination: data.pagination

View File

@ -56,8 +56,6 @@
<h5 class="fs-14 text-truncate mb-1">
<span th:text="#{cart.item.presupuesto-numero}">Presupuesto #</span>
<span th:text="${item.presupuestoId != null ? item.presupuestoId : ''}">#</span>
<a th:href="@{|/presupuesto/edit/${item.presupuestoId}|}"
th:text="#{pedido.view.view-presupuesto}" class="badge bg-secondary">Ver presupuesto</a>
</h5>
<ul class="list-unstyled text-muted mb-1 ps-0">

View File

@ -37,7 +37,6 @@
<tr>
<th class="text-start" scope="col" th:text="#{pedido.table.id}">Num. Pedido</th>
<th class="text-start" scope="col" th:text="#{pedido.table.fecha}">Fecha</th>
<th class="text-start" scope="col" th:text="#{pedido.table.titulos}">Títulos</th>
<th class="text-start" scope="col" th:text="#{pedido.table.importe}">Importe</th>
<th class="text-start" scope="col" th:text="#{pedido.table.estado}">Estado</th>
<th class="text-start" scope="col" th:text="#{pedido.table.acciones}">Acciones</th>
@ -45,7 +44,6 @@
<tr>
<th><input type="text" class="form-control form-control-sm input-filter" data-col="id" /></th>
<th></th>
<th><input type="text" class="form-control form-control-sm input-filter" data-col="titulos" /></th>
<th></th>
<th>
<select class="form-select form-select-sm input-filter" data-col="estado">

View File

@ -38,7 +38,6 @@
<th class="text-start" scope="col" th:text="#{pedido.table.id}">Num. Pedido</th>
<th class="text-start" scope="col" th:text="#{pedido.table.cliente}">Cliente</th>
<th class="text-start" scope="col" th:text="#{pedido.table.fecha}">Fecha</th>
<th class="text-start" scope="col" th:text="#{pedido.table.titulos}">Títulos</th>
<th class="text-start" scope="col" th:text="#{pedido.table.importe}">Importe</th>
<th class="text-start" scope="col" th:text="#{pedido.table.estado}">Estado</th>
<th class="text-start" scope="col" th:text="#{pedido.table.acciones}">Acciones</th>
@ -47,7 +46,6 @@
<th><input type="text" class="form-control form-control-sm input-filter" data-col="id" /></th>
<th><input type="text" class="form-control form-control-sm input-filter" data-col="createdBy.fullName" /></th>
<th></th>
<th><input type="text" class="form-control form-control-sm input-filter" data-col="titulos" /></th>
<th></th>
<th>
<select class="form-select form-select-sm input-filter" data-col="estado">

View File

@ -302,6 +302,19 @@
</label>
</div>
</div>
<div class="row justify-content-center mb-2">
<div class="col-sm-3 justify-content-center">
<label for="entregaTipo" class="form-label mt-2"
th:text="#{presupuesto.entrega}">Entrega</label>
<select class="form-select select2 datos-generales-data" id="entregaTipo" name="entregaTipo">
<option selected value="peninsula" th:text="#{presupuesto.entrega.peninsula}">Península
y
Baleares</option>
<option value="canarias" th:text="#{presupuesto.entrega.canarias}">Canarias</option>
<option value="paises_ue" th:text="#{presupuesto.entrega.paises-ue}">Países UE</option>
</select>
</div>
</div>
</div>
</div>
</div>