mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-02-02 09:08:49 +00:00
Compare commits
10 Commits
29dbd21693
...
f6a2b196e1
| Author | SHA1 | Date | |
|---|---|---|---|
| f6a2b196e1 | |||
| 3d9444c3d6 | |||
| ea1c485c80 | |||
| 6b883ffab2 | |||
| baf4cb6ae5 | |||
| 185088f487 | |||
| a1b8fb01fc | |||
| a593a1af78 | |||
| 3f89f323cf | |||
| e7589de194 |
@ -4,14 +4,13 @@ services:
|
|||||||
imprimelibros-db:
|
imprimelibros-db:
|
||||||
image: mysql:8.0
|
image: mysql:8.0
|
||||||
container_name: imprimelibros-db
|
container_name: imprimelibros-db
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
environment:
|
||||||
MYSQL_ROOT_PASSWORD: NrXz6DK6UoN
|
MYSQL_ROOT_PASSWORD: NrXz6DK6UoN
|
||||||
MYSQL_DATABASE: imprimelibros
|
MYSQL_DATABASE: imprimelibros
|
||||||
MYSQL_USER: imprimelibros_user
|
MYSQL_USER: imprimelibros_user
|
||||||
MYSQL_PASSWORD: om91irrDctd
|
MYSQL_PASSWORD: om91irrDctd
|
||||||
ports:
|
ports:
|
||||||
- "3306:3306"
|
- "3309:3306"
|
||||||
volumes:
|
volumes:
|
||||||
- db_data:/var/lib/mysql
|
- db_data:/var/lib/mysql
|
||||||
networks:
|
networks:
|
||||||
|
|||||||
2
pom.xml
2
pom.xml
@ -85,11 +85,13 @@
|
|||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-test</artifactId>
|
<artifactId>spring-security-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package com.imprimelibros.erp.entity;
|
package com.imprimelibros.erp.configurationERP;
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
@ -1,6 +1,5 @@
|
|||||||
package com.imprimelibros.erp.repository;
|
package com.imprimelibros.erp.configurationERP;
|
||||||
|
|
||||||
import com.imprimelibros.erp.entity.Variable;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@ -1,6 +1,5 @@
|
|||||||
package com.imprimelibros.erp.service;
|
package com.imprimelibros.erp.configurationERP;
|
||||||
|
|
||||||
import com.imprimelibros.erp.repository.VariableRepository;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@ -1,108 +0,0 @@
|
|||||||
package com.imprimelibros.erp.controller;
|
|
||||||
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import com.imprimelibros.erp.service.PresupuestoService;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.validation.BindingResult;
|
|
||||||
import org.springframework.validation.annotation.Validated;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import com.imprimelibros.erp.config.validation.PresupuestoValidationGroups;
|
|
||||||
import com.imprimelibros.erp.entity.Presupuesto;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/presupuesto")
|
|
||||||
public class PresupuestoController {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected PresupuestoService presupuestoService;
|
|
||||||
|
|
||||||
@PostMapping("/public/validar/datos-generales")
|
|
||||||
public ResponseEntity<?> validarDatosGenerales(
|
|
||||||
@Validated(PresupuestoValidationGroups.DatosGenerales.class) Presupuesto presupuesto,
|
|
||||||
BindingResult result, Locale locale) {
|
|
||||||
|
|
||||||
Map<String, String> errores = new HashMap<>();
|
|
||||||
|
|
||||||
// errores de campos individuales
|
|
||||||
result.getFieldErrors().forEach(error -> errores.put(error.getField(), error.getDefaultMessage()));
|
|
||||||
|
|
||||||
// errores globales (@ConsistentTiradas...)
|
|
||||||
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
|
||||||
|
|
||||||
if (!errores.isEmpty()) {
|
|
||||||
return ResponseEntity.badRequest().body(errores);
|
|
||||||
}
|
|
||||||
|
|
||||||
// opciones color
|
|
||||||
Map<String, Object> resultado = presupuestoService.obtenerOpcionesColor(presupuesto, locale);
|
|
||||||
|
|
||||||
// opciones papel interior
|
|
||||||
resultado.putAll(presupuestoService.obtenerOpcionesPapelInterior(presupuesto, locale));
|
|
||||||
|
|
||||||
// opciones gramaje interior
|
|
||||||
resultado.putAll(presupuestoService.obtenerOpcionesGramajeInterior(presupuesto));
|
|
||||||
return ResponseEntity.ok(resultado);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@PostMapping("/public/validar/interior")
|
|
||||||
public ResponseEntity<?> validarInterior(
|
|
||||||
@Validated(PresupuestoValidationGroups.Interior.class) Presupuesto presupuesto,
|
|
||||||
BindingResult result, Locale locale) {
|
|
||||||
|
|
||||||
Map<String, String> errores = new HashMap<>();
|
|
||||||
|
|
||||||
// errores de campos individuales
|
|
||||||
result.getFieldErrors().forEach(error -> errores.put(error.getField(), error.getDefaultMessage()));
|
|
||||||
|
|
||||||
// errores globales (@ConsistentTiradas...)
|
|
||||||
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
|
||||||
|
|
||||||
if (!errores.isEmpty()) {
|
|
||||||
return ResponseEntity.badRequest().body(errores);
|
|
||||||
}
|
|
||||||
return ResponseEntity.ok(Collections.singletonMap("success", true));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@PostMapping("/public/get-gramaje-interior")
|
|
||||||
public ResponseEntity<?> getGramajeInterior(
|
|
||||||
@Validated(PresupuestoValidationGroups.Interior.class) Presupuesto presupuesto,
|
|
||||||
BindingResult result) {
|
|
||||||
|
|
||||||
Map<String, String> errores = new HashMap<>();
|
|
||||||
|
|
||||||
// errores de campos individuales
|
|
||||||
result.getFieldErrors().forEach(error -> errores.put(error.getField(), error.getDefaultMessage()));
|
|
||||||
|
|
||||||
if (!errores.isEmpty()) {
|
|
||||||
return ResponseEntity.badRequest().body(errores);
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Object> resultado = presupuestoService.obtenerOpcionesGramajeInterior(presupuesto);
|
|
||||||
return ResponseEntity.ok(resultado);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/public/get-papel-cubierta")
|
|
||||||
public ResponseEntity<?> getPapelCubierta(
|
|
||||||
Presupuesto presupuesto,
|
|
||||||
BindingResult result, Locale locale) {
|
|
||||||
|
|
||||||
Map<String, Object> resultado = presupuestoService.obtenerOpcionesPapelCubierta(presupuesto, locale);
|
|
||||||
return ResponseEntity.ok(resultado);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
package com.imprimelibros.erp.externalApi;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.http.*;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class AuthService {
|
||||||
|
|
||||||
|
@Value("${safekat.api.url}")
|
||||||
|
private String skApiUrl;
|
||||||
|
@Value("${safekat.api.email}")
|
||||||
|
private String skApiEmail;
|
||||||
|
@Value("${safekat.api.password}")
|
||||||
|
private String skApiPassword;
|
||||||
|
|
||||||
|
private final RestTemplate restTemplate = new RestTemplate();
|
||||||
|
private String currentToken;
|
||||||
|
|
||||||
|
public synchronized String getToken() {
|
||||||
|
if (currentToken == null) {
|
||||||
|
currentToken = fetchNewToken();
|
||||||
|
}
|
||||||
|
return currentToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void invalidateToken() {
|
||||||
|
currentToken = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String fetchNewToken() {
|
||||||
|
Map<String, String> credentials = Map.of(
|
||||||
|
"email", this.skApiEmail,
|
||||||
|
"password", this.skApiPassword);
|
||||||
|
ResponseEntity<Map> response = restTemplate.postForEntity(this.skApiUrl + "auth/jwt", credentials, Map.class);
|
||||||
|
return (String) response.getBody().get("access_token");
|
||||||
|
}
|
||||||
|
}
|
||||||
165
src/main/java/com/imprimelibros/erp/externalApi/skApiClient.java
Normal file
165
src/main/java/com/imprimelibros/erp/externalApi/skApiClient.java
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
package com.imprimelibros.erp.externalApi;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.http.*;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.client.HttpClientErrorException;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class skApiClient {
|
||||||
|
|
||||||
|
@Value("${safekat.api.url}")
|
||||||
|
private String skApiUrl;
|
||||||
|
|
||||||
|
private final AuthService authService;
|
||||||
|
private final RestTemplate restTemplate;
|
||||||
|
|
||||||
|
public skApiClient(AuthService authService) {
|
||||||
|
this.authService = authService;
|
||||||
|
this.restTemplate = new RestTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrice(Map<String, Object> requestBody) {
|
||||||
|
return performWithRetry(() -> {
|
||||||
|
String url = this.skApiUrl + "api/calcular";
|
||||||
|
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
headers.setBearerAuth(authService.getToken());
|
||||||
|
|
||||||
|
HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestBody, headers);
|
||||||
|
|
||||||
|
ResponseEntity<String> response = restTemplate.exchange(
|
||||||
|
url,
|
||||||
|
HttpMethod.POST,
|
||||||
|
entity,
|
||||||
|
String.class);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Map<String, Object> responseBody = new ObjectMapper().readValue(response.getBody(), Map.class);
|
||||||
|
|
||||||
|
if (responseBody.get("error") == null) {
|
||||||
|
return new ObjectMapper().writeValueAsString(
|
||||||
|
Map.of("data", responseBody.get("data")));
|
||||||
|
} else {
|
||||||
|
return "{\"error\": 1}";
|
||||||
|
}
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return "{\"error\": 1}";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getMaxSolapas(Map<String, Object> requestBody) {
|
||||||
|
try {
|
||||||
|
String jsonResponse = performWithRetry(() -> {
|
||||||
|
String url = this.skApiUrl + "api/calcular-solapas";
|
||||||
|
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
headers.setBearerAuth(authService.getToken()); // token actualizado
|
||||||
|
|
||||||
|
Map<String, Object> data = new HashMap<>();
|
||||||
|
data.put("clienteId", requestBody.get("clienteId"));
|
||||||
|
data.put("tamanio", requestBody.get("tamanio"));
|
||||||
|
data.put("tirada", requestBody.get("tirada"));
|
||||||
|
data.put("paginas", requestBody.get("paginas"));
|
||||||
|
data.put("paginasColor", requestBody.get("paginasColor"));
|
||||||
|
data.put("papelInteriorDiferente", 0);
|
||||||
|
data.put("paginasCuadernillo", requestBody.get("paginasCuadernillo"));
|
||||||
|
data.put("tipo", requestBody.get("tipo"));
|
||||||
|
data.put("isColor", requestBody.get("isColor"));
|
||||||
|
data.put("isHq", requestBody.get("isHq"));
|
||||||
|
data.put("interior", requestBody.get("interior"));
|
||||||
|
|
||||||
|
HttpEntity<Map<String, Object>> entity = new HttpEntity<>(data, headers);
|
||||||
|
|
||||||
|
ResponseEntity<String> response = restTemplate.exchange(
|
||||||
|
url,
|
||||||
|
HttpMethod.POST,
|
||||||
|
entity,
|
||||||
|
String.class);
|
||||||
|
|
||||||
|
return response.getBody();
|
||||||
|
});
|
||||||
|
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
JsonNode root = mapper.readTree(jsonResponse);
|
||||||
|
|
||||||
|
if (root.get("data") == null || !root.get("data").isInt()) {
|
||||||
|
throw new RuntimeException("Respuesta inesperada de calcular-solapas: " + jsonResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
return root.get("data").asInt();
|
||||||
|
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
// Fallback al 80% del ancho
|
||||||
|
Map<String, Object> tamanio = (Map<String, Object>) requestBody.get("tamanio");
|
||||||
|
if (tamanio == null || tamanio.get("ancho") == null)
|
||||||
|
throw new RuntimeException("Tamaño no válido en la solicitud: " + requestBody);
|
||||||
|
else {
|
||||||
|
int ancho = (int) tamanio.get("ancho");
|
||||||
|
return (int) Math.floor(ancho * 0.8); // 80% del ancho
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getRetractilado(Map<String, Object> requestBody) {
|
||||||
|
|
||||||
|
String value = performWithRetry(() -> {
|
||||||
|
String url = this.skApiUrl + "api/calcular-retractilado";
|
||||||
|
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
headers.setBearerAuth(authService.getToken());
|
||||||
|
|
||||||
|
HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestBody, headers);
|
||||||
|
|
||||||
|
ResponseEntity<String> response = restTemplate.exchange(
|
||||||
|
url,
|
||||||
|
HttpMethod.POST,
|
||||||
|
entity,
|
||||||
|
String.class);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Map<String, Object> responseBody = new ObjectMapper().readValue(response.getBody(), Map.class);
|
||||||
|
return responseBody.get("data").toString();
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return "0.0"; // Fallback en caso de error
|
||||||
|
}
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
return Double.parseDouble(value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new RuntimeException("Error al parsear el valor de retractilado: " + value, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************
|
||||||
|
* PRIVATE METHODS
|
||||||
|
******************/
|
||||||
|
private String performWithRetry(Supplier<String> request) {
|
||||||
|
try {
|
||||||
|
return request.get();
|
||||||
|
} catch (HttpClientErrorException.Unauthorized e) {
|
||||||
|
// Token expirado, renovar y reintentar
|
||||||
|
authService.invalidateToken();
|
||||||
|
try {
|
||||||
|
return request.get(); // segundo intento
|
||||||
|
} catch (HttpClientErrorException ex) {
|
||||||
|
throw new RuntimeException("La autenticación ha fallado tras renovar el token.", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,12 +1,12 @@
|
|||||||
package com.imprimelibros.erp.controller;
|
package com.imprimelibros.erp.home;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
|
||||||
|
import com.imprimelibros.erp.configurationERP.VariableService;
|
||||||
import com.imprimelibros.erp.i18n.TranslationService;
|
import com.imprimelibros.erp.i18n.TranslationService;
|
||||||
import com.imprimelibros.erp.service.VariableService;
|
|
||||||
|
|
||||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.imprimelibros.erp.controller;
|
package com.imprimelibros.erp.login;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
@ -1,21 +1,20 @@
|
|||||||
package com.imprimelibros.erp.entity;
|
package com.imprimelibros.erp.presupuesto;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
import com.imprimelibros.erp.presupuesto.validation.ConsistentTiradas;
|
||||||
|
import com.imprimelibros.erp.presupuesto.validation.Par;
|
||||||
|
import com.imprimelibros.erp.presupuesto.validation.PresupuestoValidationGroups;
|
||||||
|
import com.imprimelibros.erp.presupuesto.validation.Tamanio;
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
import com.imprimelibros.erp.config.validation.PresupuestoValidationGroups;
|
|
||||||
import com.imprimelibros.erp.config.validation.Tamanio;
|
|
||||||
|
|
||||||
import com.imprimelibros.erp.config.validation.ConsistentTiradas;
|
|
||||||
import com.imprimelibros.erp.config.validation.Par;
|
|
||||||
|
|
||||||
|
|
||||||
@ConsistentTiradas(groups = PresupuestoValidationGroups.DatosGenerales.class)
|
@ConsistentTiradas(groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||||
@Tamanio(groups = PresupuestoValidationGroups.DatosGenerales.class)
|
@Tamanio(groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "presupuesto")
|
@Table(name = "presupuesto")
|
||||||
public class Presupuesto {
|
public class Presupuesto implements Cloneable{
|
||||||
|
|
||||||
public enum TipoEncuadernacion {
|
public enum TipoEncuadernacion {
|
||||||
fresado, cosido, grapado, espiral, wireo
|
fresado, cosido, grapado, espiral, wireo
|
||||||
@ -25,8 +24,17 @@ public class Presupuesto {
|
|||||||
negro, negrohq, color, colorhq
|
negro, negrohq, color, colorhq
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum TipoCubierta{
|
public enum TipoCubierta {
|
||||||
tapaBlanda, tapaDuraLomoRecto, tapaDuraLomoRedondo
|
tapaBlanda, tapaDura, tapaDuraLomoRedondo
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Presupuesto clone() {
|
||||||
|
try {
|
||||||
|
return (Presupuesto) super.clone();
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@ -60,6 +68,9 @@ public class Presupuesto {
|
|||||||
@Column(name = "tirada4")
|
@Column(name = "tirada4")
|
||||||
private Integer tirada4;
|
private Integer tirada4;
|
||||||
|
|
||||||
|
@Column(name = "selected_tirada")
|
||||||
|
private Integer selectedTirada;
|
||||||
|
|
||||||
@NotNull(message = "{presupuesto.errores.ancho}", groups = PresupuestoValidationGroups.DatosGenerales.class)
|
@NotNull(message = "{presupuesto.errores.ancho}", groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||||
@Column(name = "ancho")
|
@Column(name = "ancho")
|
||||||
private Integer ancho;
|
private Integer ancho;
|
||||||
@ -97,7 +108,7 @@ public class Presupuesto {
|
|||||||
|
|
||||||
@NotNull(message = "{presupuesto.errores.gramaje-interior}", groups = PresupuestoValidationGroups.Interior.class)
|
@NotNull(message = "{presupuesto.errores.gramaje-interior}", groups = PresupuestoValidationGroups.Interior.class)
|
||||||
@Column(name = "gramaje_interior")
|
@Column(name = "gramaje_interior")
|
||||||
private Integer gramejeInterior;
|
private Integer gramajeInterior;
|
||||||
|
|
||||||
@NotNull(message = "{presupuesto.errores.tipo-cubierta}", groups = PresupuestoValidationGroups.Cubierta.class)
|
@NotNull(message = "{presupuesto.errores.tipo-cubierta}", groups = PresupuestoValidationGroups.Cubierta.class)
|
||||||
@Column(name = "tipo_cubierta")
|
@Column(name = "tipo_cubierta")
|
||||||
@ -119,7 +130,7 @@ public class Presupuesto {
|
|||||||
private Integer gramajeGuardas;
|
private Integer gramajeGuardas;
|
||||||
|
|
||||||
@Column(name = "guardas_impresas")
|
@Column(name = "guardas_impresas")
|
||||||
private Boolean guardasImpresas;
|
private Integer guardasImpresas;
|
||||||
|
|
||||||
@Column(name = "cabezada")
|
@Column(name = "cabezada")
|
||||||
private String cabezada;
|
private String cabezada;
|
||||||
@ -132,8 +143,35 @@ public class Presupuesto {
|
|||||||
@Column(name = "gramaje_cubierta")
|
@Column(name = "gramaje_cubierta")
|
||||||
private Integer gramajeCubierta = 240;
|
private Integer gramajeCubierta = 240;
|
||||||
|
|
||||||
// Getters y Setters
|
@NotNull(message = "{presupuesto.errores.acabado-cubierta}", groups = PresupuestoValidationGroups.Cubierta.class)
|
||||||
|
@Column(name = "acabado")
|
||||||
|
private Integer acabado = 1;
|
||||||
|
|
||||||
|
@Column(name = "sobrecubierta")
|
||||||
|
private Boolean sobrecubierta = false;
|
||||||
|
@Column(name = "papel_sobrecubierta_id")
|
||||||
|
private Integer papelSobrecubiertaId = 2;
|
||||||
|
@Column(name = "gramaje_sobrecubierta")
|
||||||
|
private Integer gramajeSobrecubierta = 170;
|
||||||
|
@Column(name = "tamanio_solapas_sobrecubierta")
|
||||||
|
private Integer tamanioSolapasSobrecubierta = 80;
|
||||||
|
@Column(name = "acabado_sobrecubierta")
|
||||||
|
private Integer acabadoSobrecubierta = 0; // 0: sin acabado,
|
||||||
|
|
||||||
|
@Column(name = "faja")
|
||||||
|
private Boolean faja = false;
|
||||||
|
@Column(name = "papel_faja_id")
|
||||||
|
private Integer papelFajaId = 2;
|
||||||
|
@Column(name = "gramaje_faja")
|
||||||
|
private Integer gramajeFaja = 170;
|
||||||
|
@Column(name = "tamanio_solapas_faja")
|
||||||
|
private Integer tamanioSolapasFaja = 80;
|
||||||
|
@Column(name = "acabado_faja")
|
||||||
|
private Integer acabadoFaja = 0; // 0: sin acabado
|
||||||
|
@Column(name = "alto_faja")
|
||||||
|
private Integer altoFaja = 0;
|
||||||
|
|
||||||
|
// Getters y Setters
|
||||||
public String getAutor() {
|
public String getAutor() {
|
||||||
return autor;
|
return autor;
|
||||||
}
|
}
|
||||||
@ -179,7 +217,7 @@ public class Presupuesto {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Integer[] getTiradas() {
|
public Integer[] getTiradas() {
|
||||||
return new Integer[]{tirada1, tirada2, tirada3, tirada4};
|
return new Integer[] { tirada1, tirada2, tirada3, tirada4 };
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTirada4(Integer tirada4) {
|
public void setTirada4(Integer tirada4) {
|
||||||
@ -282,12 +320,12 @@ public class Presupuesto {
|
|||||||
this.papelInteriorId = papelInteriorId;
|
this.papelInteriorId = papelInteriorId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getGramejeInterior() {
|
public Integer getGramajeInterior() {
|
||||||
return gramejeInterior;
|
return gramajeInterior;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGramejeInterior(Integer gramejeInterior) {
|
public void setGramajeInterior(Integer gramajeInterior) {
|
||||||
this.gramejeInterior = gramejeInterior;
|
this.gramajeInterior = gramajeInterior;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TipoCubierta getTipoCubierta() {
|
public TipoCubierta getTipoCubierta() {
|
||||||
@ -338,11 +376,11 @@ public class Presupuesto {
|
|||||||
this.gramajeGuardas = gramajeGuardas;
|
this.gramajeGuardas = gramajeGuardas;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getGuardasImpresas() {
|
public Integer getGuardasImpresas() {
|
||||||
return guardasImpresas;
|
return guardasImpresas;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGuardasImpresas(Boolean guardasImpresas) {
|
public void setGuardasImpresas(Integer guardasImpresas) {
|
||||||
this.guardasImpresas = guardasImpresas;
|
this.guardasImpresas = guardasImpresas;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,6 +408,109 @@ public class Presupuesto {
|
|||||||
this.gramajeCubierta = gramajeCubierta;
|
this.gramajeCubierta = gramajeCubierta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getAcabado() {
|
||||||
|
return acabado;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAcabado(Integer acabado) {
|
||||||
|
this.acabado = acabado;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getSobrecubierta() {
|
||||||
|
return sobrecubierta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSobrecubierta(Boolean sobrecubierta) {
|
||||||
|
this.sobrecubierta = sobrecubierta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPapelSobrecubiertaId() {
|
||||||
|
return papelSobrecubiertaId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPapelSobrecubiertaId(Integer papelSobrecubiertaId) {
|
||||||
|
this.papelSobrecubiertaId = papelSobrecubiertaId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getGramajeSobrecubierta() {
|
||||||
|
return gramajeSobrecubierta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGramajeSobrecubierta(Integer gramajeSobrecubierta) {
|
||||||
|
this.gramajeSobrecubierta = gramajeSobrecubierta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getTamanioSolapasSobrecubierta() {
|
||||||
|
return tamanioSolapasSobrecubierta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTamanioSolapasSobrecubierta(Integer tamanioSolapasSobrecubierta) {
|
||||||
|
this.tamanioSolapasSobrecubierta = tamanioSolapasSobrecubierta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getAcabadoSobrecubierta() {
|
||||||
|
return acabadoSobrecubierta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAcabadoSobrecubierta(Integer acabadoSobrecubierta) {
|
||||||
|
this.acabadoSobrecubierta = acabadoSobrecubierta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getFaja() {
|
||||||
|
return faja;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFaja(Boolean faja) {
|
||||||
|
this.faja = faja;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPapelFajaId() {
|
||||||
|
return papelFajaId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPapelFajaId(Integer papelFajaId) {
|
||||||
|
this.papelFajaId = papelFajaId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getGramajeFaja() {
|
||||||
|
return gramajeFaja;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGramajeFaja(Integer gramajeFaja) {
|
||||||
|
this.gramajeFaja = gramajeFaja;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getTamanioSolapasFaja() {
|
||||||
|
return tamanioSolapasFaja;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTamanioSolapasFaja(Integer tamanioSolapasFaja) {
|
||||||
|
this.tamanioSolapasFaja = tamanioSolapasFaja;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getAcabadoFaja() {
|
||||||
|
return acabadoFaja;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAcabadoFaja(Integer acabadoFaja) {
|
||||||
|
this.acabadoFaja = acabadoFaja;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getAltoFaja() {
|
||||||
|
return altoFaja;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAltoFaja(Integer altoFaja) {
|
||||||
|
this.altoFaja = altoFaja;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getSelectedTirada() {
|
||||||
|
return selectedTirada;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectedTirada(Integer selectedTirada) {
|
||||||
|
this.selectedTirada = selectedTirada;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,304 @@
|
|||||||
|
package com.imprimelibros.erp.presupuesto;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.validation.BindingResult;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.imprimelibros.erp.externalApi.skApiClient;
|
||||||
|
import com.imprimelibros.erp.presupuesto.classes.ImagenPresupuesto;
|
||||||
|
import com.imprimelibros.erp.presupuesto.validation.PresupuestoValidationGroups;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/presupuesto")
|
||||||
|
public class PresupuestoController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected PresupuestoService presupuestoService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected skApiClient apiClient;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected MessageSource messageSource;
|
||||||
|
|
||||||
|
@PostMapping("/public/validar/datos-generales")
|
||||||
|
public ResponseEntity<?> validarDatosGenerales(
|
||||||
|
@Validated(PresupuestoValidationGroups.DatosGenerales.class) Presupuesto presupuesto,
|
||||||
|
BindingResult result, Locale locale) {
|
||||||
|
|
||||||
|
Map<String, String> errores = new HashMap<>();
|
||||||
|
|
||||||
|
// errores de campos individuales
|
||||||
|
result.getFieldErrors().forEach(error -> errores.put(error.getField(), error.getDefaultMessage()));
|
||||||
|
|
||||||
|
// errores globales (@ConsistentTiradas...)
|
||||||
|
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
||||||
|
|
||||||
|
if (!errores.isEmpty()) {
|
||||||
|
return ResponseEntity.badRequest().body(errores);
|
||||||
|
}
|
||||||
|
|
||||||
|
// opciones color
|
||||||
|
Map<String, Object> resultado = presupuestoService.obtenerOpcionesColor(presupuesto, locale);
|
||||||
|
|
||||||
|
// opciones papel interior
|
||||||
|
resultado.putAll(presupuestoService.obtenerOpcionesPapelInterior(presupuesto, locale));
|
||||||
|
|
||||||
|
// opciones gramaje interior
|
||||||
|
resultado.putAll(presupuestoService.obtenerOpcionesGramajeInterior(presupuesto));
|
||||||
|
return ResponseEntity.ok(resultado);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/public/validar/interior")
|
||||||
|
public ResponseEntity<?> validarInterior(
|
||||||
|
@Validated(PresupuestoValidationGroups.Interior.class) Presupuesto presupuesto,
|
||||||
|
BindingResult result, Locale locale) {
|
||||||
|
|
||||||
|
Map<String, String> errores = new HashMap<>();
|
||||||
|
|
||||||
|
// errores de campos individuales
|
||||||
|
result.getFieldErrors().forEach(error -> errores.put(error.getField(), error.getDefaultMessage()));
|
||||||
|
|
||||||
|
// errores globales (@ConsistentTiradas...)
|
||||||
|
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
||||||
|
|
||||||
|
if (!errores.isEmpty()) {
|
||||||
|
return ResponseEntity.badRequest().body(errores);
|
||||||
|
}
|
||||||
|
Map<String, Object> resultado = new HashMap<>();
|
||||||
|
resultado.put("solapas", apiClient.getMaxSolapas(presupuestoService.toSkApiRequest(presupuesto)));
|
||||||
|
resultado.putAll(presupuestoService.obtenerOpcionesAcabadosCubierta(presupuesto, locale));
|
||||||
|
return ResponseEntity.ok(resultado);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/public/validar/cubierta")
|
||||||
|
public ResponseEntity<?> validarCubierta(
|
||||||
|
@Validated(PresupuestoValidationGroups.Cubierta.class) Presupuesto presupuesto,
|
||||||
|
@RequestParam(name = "calcular", defaultValue = "true") boolean calcular,
|
||||||
|
BindingResult result, Locale locale) {
|
||||||
|
|
||||||
|
Map<String, String> errores = new HashMap<>();
|
||||||
|
|
||||||
|
// errores de campos individuales
|
||||||
|
result.getFieldErrors().forEach(error -> errores.put(error.getField(), error.getDefaultMessage()));
|
||||||
|
|
||||||
|
// errores globales (@ConsistentTiradas...)
|
||||||
|
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
||||||
|
|
||||||
|
if (!errores.isEmpty()) {
|
||||||
|
return ResponseEntity.badRequest().body(errores);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (calcular) {
|
||||||
|
|
||||||
|
HashMap<String, Object> price = new HashMap<>();
|
||||||
|
String priceStr = apiClient.getPrice(presupuestoService.toSkApiRequest(presupuesto));
|
||||||
|
|
||||||
|
try {
|
||||||
|
price = new ObjectMapper().readValue(priceStr, new TypeReference<>() {
|
||||||
|
});
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
price = new HashMap<>();
|
||||||
|
price.put("error", messageSource.getMessage("presupuesto.error-obtener-precio", null, locale));
|
||||||
|
}
|
||||||
|
if (!price.containsKey("data")) {
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body(messageSource.getMessage("presupuesto.error-obtener-precio", null, locale));
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(price.get("data"));
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/public/validar/seleccion-tirada")
|
||||||
|
public ResponseEntity<?> validarSeleccionTirada(
|
||||||
|
Presupuesto presupuesto,
|
||||||
|
BindingResult result, Locale locale) {
|
||||||
|
|
||||||
|
Map<String, String> errores = new HashMap<>();
|
||||||
|
|
||||||
|
// errores de campos individuales
|
||||||
|
result.getFieldErrors().forEach(error -> errores.put(error.getField(), error.getDefaultMessage()));
|
||||||
|
|
||||||
|
// errores globales (@ConsistentTiradas...)
|
||||||
|
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
||||||
|
|
||||||
|
if (!errores.isEmpty()) {
|
||||||
|
return ResponseEntity.badRequest().body(errores);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> resultado = new HashMap<>();
|
||||||
|
// servicios extra
|
||||||
|
resultado.putAll(presupuestoService.obtenerServiciosExtras(presupuesto, locale, apiClient));
|
||||||
|
|
||||||
|
return ResponseEntity.ok(resultado);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/public/get-papel-interior")
|
||||||
|
public ResponseEntity<?> getPapelInterior(
|
||||||
|
@Validated(PresupuestoValidationGroups.Interior.class) Presupuesto presupuesto,
|
||||||
|
BindingResult result, Locale locale) {
|
||||||
|
|
||||||
|
Map<String, String> errores = new HashMap<>();
|
||||||
|
|
||||||
|
// errores de campos individuales
|
||||||
|
result.getFieldErrors().forEach(error -> errores.put(error.getField(), error.getDefaultMessage()));
|
||||||
|
|
||||||
|
if (!errores.isEmpty()) {
|
||||||
|
return ResponseEntity.badRequest().body(errores);
|
||||||
|
}
|
||||||
|
|
||||||
|
// opciones color
|
||||||
|
Map<String, Object> resultado = presupuestoService.obtenerOpcionesPapelInterior(presupuesto, locale);
|
||||||
|
|
||||||
|
// opciones gramaje interior
|
||||||
|
resultado.putAll(presupuestoService.obtenerOpcionesGramajeInterior(presupuesto));
|
||||||
|
List<String> opciones = (List<String>) resultado.get("opciones_gramaje_interior");
|
||||||
|
|
||||||
|
if (opciones != null && !opciones.isEmpty()) {
|
||||||
|
String gramajeActual = presupuesto.getGramajeInterior().toString();
|
||||||
|
if (!opciones.contains(gramajeActual)) {
|
||||||
|
presupuesto.setGramajeInterior(Integer.parseInt(opciones.get(0))); // Asignar primera opción
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resultado.put("solapas", apiClient.getMaxSolapas(presupuestoService.toSkApiRequest(presupuesto)));
|
||||||
|
return ResponseEntity.ok(resultado);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/public/get-gramaje-interior")
|
||||||
|
public ResponseEntity<?> getGramajeInterior(
|
||||||
|
@Validated(PresupuestoValidationGroups.Interior.class) Presupuesto presupuesto,
|
||||||
|
BindingResult result) {
|
||||||
|
|
||||||
|
Map<String, String> errores = new HashMap<>();
|
||||||
|
|
||||||
|
// errores de campos individuales
|
||||||
|
result.getFieldErrors().forEach(error -> errores.put(error.getField(), error.getDefaultMessage()));
|
||||||
|
|
||||||
|
if (!errores.isEmpty()) {
|
||||||
|
return ResponseEntity.badRequest().body(errores);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> resultado = presupuestoService.obtenerOpcionesGramajeInterior(presupuesto);
|
||||||
|
List<String> opciones = (List<String>) resultado.get("opciones_gramaje_interior");
|
||||||
|
|
||||||
|
if (opciones != null && !opciones.isEmpty()) {
|
||||||
|
String gramajeActual = presupuesto.getGramajeInterior().toString();
|
||||||
|
if (!opciones.contains(gramajeActual)) {
|
||||||
|
presupuesto.setGramajeInterior(Integer.parseInt(opciones.get(0))); // Asignar primera opción
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultado.put("solapas", apiClient.getMaxSolapas(presupuestoService.toSkApiRequest(presupuesto)));
|
||||||
|
return ResponseEntity.ok(resultado);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/public/get-max-solapas")
|
||||||
|
public ResponseEntity<?> getMaxSolapas(
|
||||||
|
@Validated(PresupuestoValidationGroups.Interior.class) Presupuesto presupuesto,
|
||||||
|
BindingResult result) {
|
||||||
|
|
||||||
|
Map<String, String> errores = new HashMap<>();
|
||||||
|
|
||||||
|
// errores de campos individuales
|
||||||
|
result.getFieldErrors().forEach(error -> errores.put(error.getField(), error.getDefaultMessage()));
|
||||||
|
|
||||||
|
if (!errores.isEmpty()) {
|
||||||
|
return ResponseEntity.badRequest().body(errores);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> resultado = new HashMap<>();
|
||||||
|
resultado.put("solapas", apiClient.getMaxSolapas(presupuestoService.toSkApiRequest(presupuesto)));
|
||||||
|
return ResponseEntity.ok(resultado);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/public/get-papel-cubierta")
|
||||||
|
public ResponseEntity<?> getPapelCubierta(
|
||||||
|
Presupuesto presupuesto,
|
||||||
|
BindingResult result, Locale locale) {
|
||||||
|
|
||||||
|
Map<String, Object> resultado = new HashMap<>();
|
||||||
|
Map<String, Object> papelesCubierta = presupuestoService.obtenerOpcionesPapelCubierta(presupuesto, locale);
|
||||||
|
List<ImagenPresupuesto> opciones = (List<ImagenPresupuesto>) presupuestoService
|
||||||
|
.obtenerOpcionesPapelCubierta(presupuesto, locale)
|
||||||
|
.get("opciones_papel_cubierta");
|
||||||
|
|
||||||
|
if (opciones != null && opciones.stream().noneMatch(
|
||||||
|
o -> o.getExtra_data().get("sk-id").equals(String.valueOf(presupuesto.getPapelCubiertaId())))) {
|
||||||
|
presupuesto.setPapelCubiertaId(Integer.valueOf(opciones.get(0).getExtra_data().get("sk-id")));
|
||||||
|
}
|
||||||
|
resultado.putAll(papelesCubierta);
|
||||||
|
|
||||||
|
resultado.putAll(presupuestoService.obtenerOpcionesGramajeCubierta(presupuesto));
|
||||||
|
List<String> gramajesCubierta = (List<String>) resultado.get("opciones_gramaje_cubierta");
|
||||||
|
if (gramajesCubierta != null && !gramajesCubierta.isEmpty()) {
|
||||||
|
String gramajeActual = presupuesto.getGramajeCubierta().toString();
|
||||||
|
if (!gramajesCubierta.contains(gramajeActual)) {
|
||||||
|
presupuesto.setGramajeCubierta(Integer.parseInt(gramajesCubierta.get(0))); // Asignar primera opción
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(resultado);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/public/get-gramaje-cubierta")
|
||||||
|
public ResponseEntity<?> getGramajeCubierta(
|
||||||
|
Presupuesto presupuesto,
|
||||||
|
BindingResult result) {
|
||||||
|
|
||||||
|
Map<String, Object> resultado = presupuestoService.obtenerOpcionesGramajeCubierta(presupuesto);
|
||||||
|
List<String> gramajesCubierta = (List<String>) resultado.get("opciones_gramaje_cubierta");
|
||||||
|
if (gramajesCubierta != null && !gramajesCubierta.isEmpty()) {
|
||||||
|
String gramajeActual = presupuesto.getGramajeCubierta().toString();
|
||||||
|
if (!gramajesCubierta.contains(gramajeActual)) {
|
||||||
|
presupuesto.setGramajeCubierta(Integer.parseInt(gramajesCubierta.get(0))); // Asignar primera opción
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(resultado);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/public/get-acabados-cubierta")
|
||||||
|
public ResponseEntity<?> getAcabadosCubierta(
|
||||||
|
Presupuesto presupuesto,
|
||||||
|
BindingResult result, Locale locale) {
|
||||||
|
|
||||||
|
Map<String, Object> resultado = presupuestoService.obtenerOpcionesAcabadosCubierta(presupuesto, locale);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(resultado);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/public/get-price")
|
||||||
|
public ResponseEntity<?> getPrice(
|
||||||
|
Presupuesto presupuesto,
|
||||||
|
BindingResult result, Locale locale) {
|
||||||
|
|
||||||
|
Map<String, String> errores = new HashMap<>();
|
||||||
|
// errores de campos individuales
|
||||||
|
result.getFieldErrors().forEach(error -> errores.put(error.getField(), error.getDefaultMessage()));
|
||||||
|
// errores globales (@ConsistentTiradas...)
|
||||||
|
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
||||||
|
if (!errores.isEmpty()) {
|
||||||
|
return ResponseEntity.badRequest().body(errores);
|
||||||
|
}
|
||||||
|
String price = apiClient.getPrice(presupuestoService.toSkApiRequest(presupuesto));
|
||||||
|
if (price == null || price.isEmpty()) {
|
||||||
|
return ResponseEntity.badRequest().body("No se pudo obtener el precio. Intente nuevamente.");
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(price);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,581 @@
|
|||||||
|
package com.imprimelibros.erp.presupuesto;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.imprimelibros.erp.configurationERP.VariableService;
|
||||||
|
import com.imprimelibros.erp.presupuesto.Presupuesto.TipoCubierta;
|
||||||
|
import com.imprimelibros.erp.presupuesto.classes.ImagenPresupuesto;
|
||||||
|
import com.imprimelibros.erp.presupuesto.classes.PresupuestadorItems;
|
||||||
|
import com.imprimelibros.erp.externalApi.skApiClient;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class PresupuestoService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected VariableService variableService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected MessageSource messageSource;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected skApiClient skApiClient;
|
||||||
|
|
||||||
|
private final PresupuestadorItems presupuestadorItems;
|
||||||
|
|
||||||
|
public PresupuestoService(PresupuestadorItems presupuestadorItems) {
|
||||||
|
this.presupuestadorItems = presupuestadorItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean validateDatosGenerales(int[] tiradas) {
|
||||||
|
|
||||||
|
for (int tirada : tiradas) {
|
||||||
|
if (tirada <= 0) {
|
||||||
|
return false; // Invalid tirada found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean isPOD(Presupuesto presupuesto) {
|
||||||
|
|
||||||
|
int pod_value = variableService.getValorEntero("POD");
|
||||||
|
return (presupuesto.getTirada1() != null && presupuesto.getTirada1() <= pod_value) ||
|
||||||
|
(presupuesto.getTirada2() != null && presupuesto.getTirada2() <= pod_value) ||
|
||||||
|
(presupuesto.getTirada3() != null && presupuesto.getTirada3() <= pod_value) ||
|
||||||
|
(presupuesto.getTirada4() != null && presupuesto.getTirada4() <= pod_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> obtenerOpcionesColor(Presupuesto presupuesto, Locale locale) {
|
||||||
|
|
||||||
|
List<ImagenPresupuesto> opciones = new ArrayList<>();
|
||||||
|
|
||||||
|
if (presupuesto.getPaginasColor() > 0) {
|
||||||
|
if (!this.isPOD(presupuesto)) {
|
||||||
|
// POD solo color foto
|
||||||
|
ImagenPresupuesto opcionColor = this.presupuestadorItems.getImpresionColor(locale);
|
||||||
|
opcionColor.setSelected(Presupuesto.TipoImpresion.color.equals(presupuesto.getTipoImpresion()));
|
||||||
|
opciones.add(opcionColor);
|
||||||
|
}
|
||||||
|
ImagenPresupuesto opcionColorHq = this.presupuestadorItems.getImpresionColorPremium(locale);
|
||||||
|
if (Presupuesto.TipoImpresion.colorhq.equals(presupuesto.getTipoImpresion()))
|
||||||
|
opcionColorHq.setSelected(true);
|
||||||
|
opciones.add(opcionColorHq);
|
||||||
|
} else {
|
||||||
|
ImagenPresupuesto opcionNegro = this.presupuestadorItems.getImpresionNegro(locale);
|
||||||
|
if (Presupuesto.TipoImpresion.negro.equals(presupuesto.getTipoImpresion()))
|
||||||
|
opcionNegro.setSelected(true);
|
||||||
|
opciones.add(opcionNegro);
|
||||||
|
ImagenPresupuesto opcionNegroHq = this.presupuestadorItems.getImpresionNegroPremium(locale);
|
||||||
|
if (Presupuesto.TipoImpresion.negrohq.equals(presupuesto.getTipoImpresion()))
|
||||||
|
opcionNegroHq.setSelected(true);
|
||||||
|
opciones.add(opcionNegroHq);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean opcionSeleccionada = opciones.stream().anyMatch(ImagenPresupuesto::isSelected);
|
||||||
|
if (!opcionSeleccionada) {
|
||||||
|
opciones.get(0).setSelected(true);
|
||||||
|
presupuesto.setTipoImpresion(Presupuesto.TipoImpresion.valueOf(opciones.get(0).getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> response = new HashMap<>();
|
||||||
|
response.put("opciones_color", opciones);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> obtenerOpcionesPapelInterior(Presupuesto presupuesto, Locale locale) {
|
||||||
|
|
||||||
|
List<ImagenPresupuesto> opciones = new ArrayList<>();
|
||||||
|
|
||||||
|
opciones.add(this.presupuestadorItems.getPapelOffsetBlanco(locale));
|
||||||
|
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negro ||
|
||||||
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
||||||
|
opciones.add(this.presupuestadorItems.getPapelOffsetBlancoVolumen(locale));
|
||||||
|
}
|
||||||
|
opciones.add(this.presupuestadorItems.getPapelOffsetAhuesado(locale));
|
||||||
|
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negro ||
|
||||||
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
||||||
|
opciones.add(this.presupuestadorItems.getPapelOffsetAhuesadoVolumen(locale));
|
||||||
|
}
|
||||||
|
opciones.add(this.presupuestadorItems.getPapelEstucadoMate(locale));
|
||||||
|
|
||||||
|
for (ImagenPresupuesto imagenPresupuesto : opciones) {
|
||||||
|
imagenPresupuesto.setSelected(
|
||||||
|
presupuesto.getPapelInteriorId() != null
|
||||||
|
&& imagenPresupuesto.getExtra_data().get("sk-id").equals(
|
||||||
|
String.valueOf(presupuesto.getPapelInteriorId())));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean yaSeleccionado = opciones.stream().anyMatch(ImagenPresupuesto::isSelected);
|
||||||
|
|
||||||
|
if (!yaSeleccionado && !opciones.isEmpty()) {
|
||||||
|
ImagenPresupuesto primeraOpcion = opciones.get(0);
|
||||||
|
primeraOpcion.setSelected(true);
|
||||||
|
presupuesto.setPapelInteriorId(Integer.parseInt(primeraOpcion.getExtra_data().get("sk-id")));
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> response = new HashMap<>();
|
||||||
|
response.put("opciones_papel_interior", opciones);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> obtenerOpcionesGramajeInterior(Presupuesto presupuesto) {
|
||||||
|
|
||||||
|
List<String> gramajes = new ArrayList<>();
|
||||||
|
|
||||||
|
final int BLANCO_OFFSET_ID = 3;
|
||||||
|
final int BLANCO_OFFSET_VOLUMEN_ID = 7;
|
||||||
|
final int AHUESADO_OFFSET_ID = 4;
|
||||||
|
final int AHUESADO_OFFSET_VOLUMEN_ID = 6;
|
||||||
|
final int ESTUCADO_MATE_ID = 2;
|
||||||
|
|
||||||
|
if (presupuesto.getPapelInteriorId() != null && presupuesto.getPapelInteriorId() == BLANCO_OFFSET_ID) {
|
||||||
|
|
||||||
|
gramajes.add("80");
|
||||||
|
gramajes.add("90");
|
||||||
|
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negrohq ||
|
||||||
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.colorhq) {
|
||||||
|
gramajes.add("100");
|
||||||
|
gramajes.add("120");
|
||||||
|
gramajes.add("150");
|
||||||
|
gramajes.add("170");
|
||||||
|
}
|
||||||
|
} else if (presupuesto.getPapelInteriorId() != null
|
||||||
|
&& presupuesto.getPapelInteriorId() == BLANCO_OFFSET_VOLUMEN_ID) {
|
||||||
|
|
||||||
|
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negro ||
|
||||||
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
||||||
|
gramajes.add("80");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (presupuesto.getPapelInteriorId() != null && presupuesto.getPapelInteriorId() == AHUESADO_OFFSET_ID) {
|
||||||
|
|
||||||
|
gramajes.add("80");
|
||||||
|
gramajes.add("90");
|
||||||
|
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negrohq ||
|
||||||
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.colorhq) {
|
||||||
|
gramajes.add("100");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (presupuesto.getPapelInteriorId() != null
|
||||||
|
&& presupuesto.getPapelInteriorId() == AHUESADO_OFFSET_VOLUMEN_ID) {
|
||||||
|
|
||||||
|
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negro ||
|
||||||
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
||||||
|
gramajes.add("70");
|
||||||
|
gramajes.add("80");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (presupuesto.getPapelInteriorId() != null && presupuesto.getPapelInteriorId() == ESTUCADO_MATE_ID) {
|
||||||
|
|
||||||
|
if (presupuesto.getTipoImpresion() != Presupuesto.TipoImpresion.color) {
|
||||||
|
gramajes.add("90");
|
||||||
|
}
|
||||||
|
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negrohq ||
|
||||||
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.colorhq) {
|
||||||
|
gramajes.add("100");
|
||||||
|
gramajes.add("115");
|
||||||
|
}
|
||||||
|
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negro ||
|
||||||
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
||||||
|
gramajes.add("120");
|
||||||
|
}
|
||||||
|
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negrohq ||
|
||||||
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.colorhq) {
|
||||||
|
gramajes.add("125");
|
||||||
|
gramajes.add("135");
|
||||||
|
gramajes.add("150");
|
||||||
|
gramajes.add("170");
|
||||||
|
gramajes.add("200");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> response = new HashMap<>();
|
||||||
|
response.put("opciones_gramaje_interior", gramajes);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> obtenerOpcionesPapelCubierta(Presupuesto presupuesto, Locale locale) {
|
||||||
|
|
||||||
|
List<ImagenPresupuesto> opciones = new ArrayList<>();
|
||||||
|
|
||||||
|
if (presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaBlanda) {
|
||||||
|
opciones.add(this.presupuestadorItems.getCartulinaGraficaCubierta(locale));
|
||||||
|
}
|
||||||
|
opciones.add(this.presupuestadorItems.getEstucadoMateCubierta(locale));
|
||||||
|
|
||||||
|
for (ImagenPresupuesto imagenPresupuesto : opciones) {
|
||||||
|
imagenPresupuesto.setSelected(
|
||||||
|
presupuesto.getPapelCubiertaId() != null
|
||||||
|
&& imagenPresupuesto.getExtra_data().get("sk-id").equals(
|
||||||
|
String.valueOf(presupuesto.getPapelCubiertaId())));
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> response = new HashMap<>();
|
||||||
|
response.put("opciones_papel_cubierta", opciones);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> obtenerOpcionesGramajeCubierta(Presupuesto presupuesto) {
|
||||||
|
|
||||||
|
List<String> gramajes = new ArrayList<>();
|
||||||
|
|
||||||
|
final int CARTULINA_GRAFICA_ID = 5;
|
||||||
|
final int ESTUCADO_MATE_ID = 2;
|
||||||
|
|
||||||
|
if (presupuesto.getPapelCubiertaId() != null && presupuesto.getPapelCubiertaId() == CARTULINA_GRAFICA_ID) {
|
||||||
|
gramajes.add("240");
|
||||||
|
gramajes.add("270");
|
||||||
|
gramajes.add("300");
|
||||||
|
gramajes.add("350");
|
||||||
|
} else if (presupuesto.getPapelCubiertaId() != null && presupuesto.getPapelCubiertaId() == ESTUCADO_MATE_ID) {
|
||||||
|
if (presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaBlanda) {
|
||||||
|
|
||||||
|
gramajes.add("250");
|
||||||
|
gramajes.add("300");
|
||||||
|
gramajes.add("350");
|
||||||
|
} else {
|
||||||
|
gramajes.add("170");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> response = new HashMap<>();
|
||||||
|
response.put("opciones_gramaje_cubierta", gramajes);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> toSkApiRequest(Presupuesto presupuesto) {
|
||||||
|
|
||||||
|
final int SK_CLIENTE_ID = 1284;
|
||||||
|
final int SK_PAGINAS_CUADERNILLO = 32;
|
||||||
|
|
||||||
|
Map<String, Object> tamanio = Map.of(
|
||||||
|
"ancho", presupuesto.getAncho(),
|
||||||
|
"alto", presupuesto.getAlto());
|
||||||
|
Map<String, Object> interior = Map.of(
|
||||||
|
"papelInterior", presupuesto.getPapelInteriorId(),
|
||||||
|
"gramajeInterior", presupuesto.getGramajeInterior());
|
||||||
|
Map<String, Object> cubierta = Map.of(
|
||||||
|
"tipoCubierta", presupuesto.getTipoCubierta().name(),
|
||||||
|
"papelCubierta", presupuesto.getPapelCubiertaId(),
|
||||||
|
"gramajeCubierta", presupuesto.getGramajeCubierta(),
|
||||||
|
"carasImpresion", presupuesto.getCubiertaCaras(),
|
||||||
|
"solapas", presupuesto.getSolapasCubierta() ? presupuesto.getTamanioSolapasCubierta() : 0,
|
||||||
|
"acabado", presupuesto.getAcabado(),
|
||||||
|
"cabezada", presupuesto.getCabezada(),
|
||||||
|
"lomoRedondo", presupuesto.getTipoCubierta() == TipoCubierta.tapaDuraLomoRedondo ? 1 : 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Map<String, Object> servicios = Map.of(
|
||||||
|
* "retractilado", 0,
|
||||||
|
* "retractilado5", 0,
|
||||||
|
* "ferro", 0,
|
||||||
|
* "ferroDigital", 0,
|
||||||
|
* "marcapaginas", 0,
|
||||||
|
* "prototipo", 0);
|
||||||
|
*/
|
||||||
|
Map<String, Object> body = new HashMap<>();
|
||||||
|
body.put("tipo_impresion_id", this.getTipoImpresionId(presupuesto));
|
||||||
|
body.put("tirada", Arrays.stream(presupuesto.getTiradas())
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
body.put("tamanio", tamanio);
|
||||||
|
body.put("tipo", presupuesto.getTipoEncuadernacion());
|
||||||
|
body.put("clienteId", SK_CLIENTE_ID);
|
||||||
|
body.put("isColor", presupuesto.getTipoImpresion().name().contains("color") ? 1 : 0);
|
||||||
|
body.put("isHq", presupuesto.getTipoImpresion().name().contains("hq") ? 1 : 0);
|
||||||
|
body.put("paginas", presupuesto.getPaginasNegro() + presupuesto.getPaginasColor());
|
||||||
|
body.put("paginasColor", presupuesto.getPaginasColor());
|
||||||
|
body.put("paginasCuadernillo", SK_PAGINAS_CUADERNILLO);
|
||||||
|
body.put("interior", interior);
|
||||||
|
body.put("cubierta", cubierta);
|
||||||
|
body.put("guardas", null);
|
||||||
|
if (presupuesto.getSobrecubierta()) {
|
||||||
|
Map<String, Object> sobrecubierta = new HashMap<>();
|
||||||
|
sobrecubierta.put("papel", presupuesto.getPapelSobrecubiertaId());
|
||||||
|
sobrecubierta.put("gramaje", presupuesto.getGramajeSobrecubierta());
|
||||||
|
sobrecubierta.put("solapas", presupuesto.getTamanioSolapasSobrecubierta());
|
||||||
|
sobrecubierta.put("acabado", presupuesto.getAcabadoSobrecubierta());
|
||||||
|
body.put("sobrecubierta", sobrecubierta);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (presupuesto.getFaja()) {
|
||||||
|
Map<String, Object> faja = new HashMap<>();
|
||||||
|
faja.put("papel", presupuesto.getPapelFajaId());
|
||||||
|
faja.put("gramaje", presupuesto.getGramajeFaja());
|
||||||
|
faja.put("solapas", presupuesto.getTamanioSolapasFaja());
|
||||||
|
faja.put("acabado", presupuesto.getAcabadoFaja());
|
||||||
|
faja.put("alto", presupuesto.getAltoFaja());
|
||||||
|
body.put("faja", faja);
|
||||||
|
}
|
||||||
|
// body.put("servicios", servicios);
|
||||||
|
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getTipoImpresionId(Presupuesto presupuesto) {
|
||||||
|
|
||||||
|
if (presupuesto.getTipoEncuadernacion() == Presupuesto.TipoEncuadernacion.fresado) {
|
||||||
|
if (presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaDura ||
|
||||||
|
presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaDuraLomoRedondo) {
|
||||||
|
return 1; // Fresado tapa dura
|
||||||
|
} else {
|
||||||
|
return 2; // Fresado tapa blanda
|
||||||
|
}
|
||||||
|
} else if (presupuesto.getTipoEncuadernacion() == Presupuesto.TipoEncuadernacion.cosido) {
|
||||||
|
if (presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaDura ||
|
||||||
|
presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaDuraLomoRedondo) {
|
||||||
|
return 3; // Cosido tapa dura
|
||||||
|
} else {
|
||||||
|
return 4; // Cosido tapa blanda
|
||||||
|
}
|
||||||
|
} else if (presupuesto.getTipoEncuadernacion() == Presupuesto.TipoEncuadernacion.espiral) {
|
||||||
|
if (presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaDura ||
|
||||||
|
presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaDuraLomoRedondo) {
|
||||||
|
return 5; // Espiral tapa dura
|
||||||
|
} else {
|
||||||
|
return 6; // Espiral tapa blanda
|
||||||
|
}
|
||||||
|
} else if (presupuesto.getTipoEncuadernacion() == Presupuesto.TipoEncuadernacion.wireo) {
|
||||||
|
if (presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaDura ||
|
||||||
|
presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaDuraLomoRedondo) {
|
||||||
|
return 7; // Wireo tapa dura
|
||||||
|
} else {
|
||||||
|
return 8; // Wireo tapa blanda
|
||||||
|
}
|
||||||
|
} else if (presupuesto.getTipoEncuadernacion() == Presupuesto.TipoEncuadernacion.grapado) {
|
||||||
|
return 21; // Grapado
|
||||||
|
} else {
|
||||||
|
return 0; // Default case, no valid type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> obtenerOpcionesAcabadosCubierta(Presupuesto presupuesto, Locale locale) {
|
||||||
|
Map<String, Object> resultado = new HashMap<>();
|
||||||
|
List<Object> opciones = new ArrayList<>();
|
||||||
|
|
||||||
|
opciones.add(new HashMap<>() {
|
||||||
|
{
|
||||||
|
put("name", messageSource.getMessage("presupuesto.acabado-ninguno", null, locale));
|
||||||
|
put("sk-id", 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
opciones.add(new HashMap<>() {
|
||||||
|
{
|
||||||
|
put("name", messageSource.getMessage("presupuesto.acabado-plastificado-brillo-1c", null, locale));
|
||||||
|
put("sk-id", 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
opciones.add(new HashMap<>() {
|
||||||
|
{
|
||||||
|
put("name", messageSource.getMessage("presupuesto.acabado-plastificado-mate-1c", null, locale));
|
||||||
|
put("sk-id", 5);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
opciones.add(new HashMap<>() {
|
||||||
|
{
|
||||||
|
put("name",
|
||||||
|
messageSource.getMessage("presupuesto.acabado-plastificado-mate-1c-antirrayado", null, locale));
|
||||||
|
put("sk-id", 8);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
opciones.add(new HashMap<>() {
|
||||||
|
{
|
||||||
|
put("name", messageSource.getMessage("presupuesto.acabado-plastificado-mate-uvi", null, locale));
|
||||||
|
put("sk-id", 2);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
opciones.add(new HashMap<>() {
|
||||||
|
{
|
||||||
|
put("name", messageSource.getMessage("presupuesto.acabado-plastificado-mate-uvi3d", null, locale));
|
||||||
|
put("sk-id", 3);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
opciones.add(new HashMap<>() {
|
||||||
|
{
|
||||||
|
put("name", messageSource.getMessage("presupuesto.acabado-plastificado-mate-uvi-braile", null, locale));
|
||||||
|
put("sk-id", 4);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
opciones.add(new HashMap<>() {
|
||||||
|
{
|
||||||
|
put("name", messageSource.getMessage("presupuesto.acabado-plastificado-sandy-1c", null, locale));
|
||||||
|
put("sk-id", 9);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
resultado.put("opciones_acabados_cubierta", opciones);
|
||||||
|
return resultado;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> aplicarMargenTiradas(Map<String, Object> data) {
|
||||||
|
|
||||||
|
// implementar margenes
|
||||||
|
return (Map<String, Object>) data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String obtenerPrecioRetractilado(Presupuesto presupuesto, Locale locale) {
|
||||||
|
Integer[] tiradas = presupuesto.getTiradas();
|
||||||
|
Integer tirada_min = Arrays.stream(tiradas)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.min(Integer::compareTo)
|
||||||
|
.orElse(0);
|
||||||
|
Map<String, Object> requestBody = new HashMap<>();
|
||||||
|
requestBody.put("tirada",
|
||||||
|
presupuesto.getSelectedTirada() != null ? presupuesto.getSelectedTirada() : tirada_min);
|
||||||
|
Double precio_retractilado = skApiClient.getRetractilado(requestBody);
|
||||||
|
return precio_retractilado != null
|
||||||
|
? NumberFormat.getNumberInstance(locale)
|
||||||
|
.format(Math.round(precio_retractilado * 100.0) / 100.0)
|
||||||
|
: "0,00";
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> obtenerServiciosExtras(Presupuesto presupuesto, Locale locale, skApiClient apiClient) {
|
||||||
|
|
||||||
|
List<Object> opciones = new ArrayList<>();
|
||||||
|
|
||||||
|
Double price_prototipo = this.obtenerPrototipo(presupuesto, apiClient);
|
||||||
|
|
||||||
|
opciones.add(new HashMap<String, String>() {
|
||||||
|
{
|
||||||
|
put("id", "retractilado");
|
||||||
|
put("title", messageSource.getMessage("presupuesto.extras-retractilado", null, locale));
|
||||||
|
put("description", "");
|
||||||
|
put("price", obtenerPrecioRetractilado(presupuesto, locale));
|
||||||
|
put("priceUnit", messageSource.getMessage("app.currency-symbol", null, locale));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
opciones.add(new HashMap<String, String>() {
|
||||||
|
{
|
||||||
|
put("id", "service-isbn");
|
||||||
|
put("title", messageSource.getMessage("presupuesto.extras-isbn", null, locale));
|
||||||
|
put("description", "");
|
||||||
|
put("price", "30");
|
||||||
|
put("priceUnit", messageSource.getMessage("app.currency-symbol", null, locale));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
opciones.add(new HashMap<String, String>() {
|
||||||
|
{
|
||||||
|
put("id", "deposito-legal");
|
||||||
|
put("title", messageSource.getMessage("presupuesto.extras-deposito-legal", null, locale));
|
||||||
|
put("description",
|
||||||
|
messageSource.getMessage("presupuesto.extras-deposito-legal-descripcion", null, locale));
|
||||||
|
put("price", "30");
|
||||||
|
put("priceUnit", messageSource.getMessage("app.currency-symbol", null, locale));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
opciones.add(new HashMap<String, String>() {
|
||||||
|
{
|
||||||
|
put("id", "revision-archivos");
|
||||||
|
put("title", messageSource.getMessage("presupuesto.extras-revision-archivos", null, locale));
|
||||||
|
put("description", "");
|
||||||
|
put("price", "50");
|
||||||
|
put("priceUnit", messageSource.getMessage("app.currency-symbol", null, locale));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
opciones.add(new HashMap<String, String>() {
|
||||||
|
{
|
||||||
|
put("id", "maquetacion-cubierta");
|
||||||
|
put("title", messageSource.getMessage("presupuesto.extras-maquetacion-cubierta", null, locale));
|
||||||
|
put("description", "");
|
||||||
|
put("price", "50");
|
||||||
|
put("priceUnit", messageSource.getMessage("app.currency-symbol", null, locale));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
opciones.add(new HashMap<String, String>() {
|
||||||
|
{
|
||||||
|
put("id", "ferro-digital");
|
||||||
|
put("title", messageSource.getMessage("presupuesto.extras-ferro-digital", null, locale));
|
||||||
|
put("description", "");
|
||||||
|
put("price", "0");
|
||||||
|
put("priceUnit", messageSource.getMessage("app.currency-symbol", null, locale));
|
||||||
|
put("checked", "true");
|
||||||
|
put("allowChange", "false");
|
||||||
|
put("ribbonText", messageSource.getMessage("presupuesto.extras-ferro-digital-ribbon", null, locale));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
opciones.add(new HashMap<String, String>() {
|
||||||
|
{
|
||||||
|
put("id", "ejemplar-prueba");
|
||||||
|
put("title", messageSource.getMessage("presupuesto.extras-ejemplar-prueba", null, locale));
|
||||||
|
put("description", "");
|
||||||
|
if(price_prototipo == 0.0) {
|
||||||
|
put("price", messageSource.getMessage("presupuesto.consultar-soporte", null, locale));
|
||||||
|
put("priceUnit", "");
|
||||||
|
} else {
|
||||||
|
put("price", NumberFormat.getNumberInstance(locale)
|
||||||
|
.format(Math.round(price_prototipo * 100.0) / 100.0));
|
||||||
|
put("priceUnit", messageSource.getMessage("app.currency-symbol", null, locale));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
opciones.add(new HashMap<String, String>() {
|
||||||
|
{
|
||||||
|
put("id", "marcapaginas");
|
||||||
|
put("title", messageSource.getMessage("presupuesto.extras-marcapaginas", null, locale));
|
||||||
|
put("description", "");
|
||||||
|
put("price", messageSource.getMessage("presupuesto.extras-calcular", null, locale));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
opciones.add(new HashMap<String, String>() {
|
||||||
|
{
|
||||||
|
put("id", "maquetacion");
|
||||||
|
put("title", messageSource.getMessage("presupuesto.extras-maquetacion", null, locale));
|
||||||
|
put("description", "");
|
||||||
|
put("price", messageSource.getMessage("presupuesto.extras-calcular", null, locale));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, Object> response = new HashMap<>();
|
||||||
|
response.put("servicios_extra", opciones);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Double obtenerPrototipo(Presupuesto presupuesto, skApiClient apiClient) {
|
||||||
|
|
||||||
|
// Obtenemos el precio de 1 unidad para el ejemplar de prueba
|
||||||
|
HashMap<String, Object> price = new HashMap<>();
|
||||||
|
// make a copy of "presupuesto" to avoid modifying the original object
|
||||||
|
Presupuesto presupuestoTemp = presupuesto.clone();
|
||||||
|
presupuestoTemp.setTirada1(1);
|
||||||
|
presupuestoTemp.setTirada2(null);
|
||||||
|
presupuestoTemp.setTirada3(null);
|
||||||
|
presupuestoTemp.setTirada4(null);
|
||||||
|
if (presupuestoTemp.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
||||||
|
presupuestoTemp.setTipoImpresion(Presupuesto.TipoImpresion.colorhq);
|
||||||
|
} else if (presupuestoTemp.getTipoImpresion() == Presupuesto.TipoImpresion.negro) {
|
||||||
|
presupuestoTemp.setTipoImpresion(Presupuesto.TipoImpresion.negrohq);
|
||||||
|
}
|
||||||
|
String priceStr = apiClient.getPrice(this.toSkApiRequest(presupuestoTemp));
|
||||||
|
Double price_prototipo = 0.0;
|
||||||
|
try {
|
||||||
|
price = new ObjectMapper().readValue(priceStr, new TypeReference<>() {
|
||||||
|
});
|
||||||
|
price_prototipo = ((List<Double>) ((Map<String, Object>) price.get("data")).get("precios")).get(0);
|
||||||
|
if (price_prototipo < 25) {
|
||||||
|
price_prototipo = 25.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
} catch (Exception exception) {
|
||||||
|
}
|
||||||
|
return price_prototipo;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.imprimelibros.erp.config.Presupuestador;
|
package com.imprimelibros.erp.presupuesto.classes;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -8,7 +8,7 @@ public class ImagenPresupuesto {
|
|||||||
private String imagen;
|
private String imagen;
|
||||||
private String alt;
|
private String alt;
|
||||||
private String texto;
|
private String texto;
|
||||||
private boolean selected;
|
private boolean selected = false;
|
||||||
private Map<String, String> extra_data;
|
private Map<String, String> extra_data;
|
||||||
|
|
||||||
// Constructores
|
// Constructores
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.imprimelibros.erp.config.Presupuestador;
|
package com.imprimelibros.erp.presupuesto.classes;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.MessageSource;
|
import org.springframework.context.MessageSource;
|
||||||
@ -33,9 +33,6 @@ public class PresupuestadorItems {
|
|||||||
|
|
||||||
public ImagenPresupuesto getImpresionColor(Locale locale) {
|
public ImagenPresupuesto getImpresionColor(Locale locale) {
|
||||||
|
|
||||||
String clave = "presupuesto.color"; // ✅
|
|
||||||
String texto = messageSource.getMessage(clave, null, locale);
|
|
||||||
System.out.println("Clave: " + clave + " => Texto: " + texto);
|
|
||||||
return new ImagenPresupuesto(
|
return new ImagenPresupuesto(
|
||||||
"color",
|
"color",
|
||||||
"/assets/images/imprimelibros/presupuestador/color.png",
|
"/assets/images/imprimelibros/presupuestador/color.png",
|
||||||
@ -64,6 +61,17 @@ public class PresupuestadorItems {
|
|||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ImagenPresupuesto getPapelOffsetBlancoVolumen(Locale locale) {
|
||||||
|
|
||||||
|
return new ImagenPresupuesto(
|
||||||
|
"offset-blanco-volumen",
|
||||||
|
"/assets/images/imprimelibros/presupuestador/offset-blanco.png",
|
||||||
|
"",
|
||||||
|
messageSource.getMessage("presupuesto.offset-blanco-volumen", null, locale),
|
||||||
|
Map.of("sk-id", "7"),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
public ImagenPresupuesto getPapelOffsetAhuesado(Locale locale) {
|
public ImagenPresupuesto getPapelOffsetAhuesado(Locale locale) {
|
||||||
|
|
||||||
return new ImagenPresupuesto(
|
return new ImagenPresupuesto(
|
||||||
@ -104,7 +112,7 @@ public class PresupuestadorItems {
|
|||||||
"/assets/images/imprimelibros/presupuestador/cartulina-grafica.png",
|
"/assets/images/imprimelibros/presupuestador/cartulina-grafica.png",
|
||||||
"",
|
"",
|
||||||
messageSource.getMessage("presupuesto.cartulina-grafica-cubierta", null, locale),
|
messageSource.getMessage("presupuesto.cartulina-grafica-cubierta", null, locale),
|
||||||
Map.of("sk-id", "3"),
|
Map.of("sk-id", "5"),
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.imprimelibros.erp.config.validation;
|
package com.imprimelibros.erp.presupuesto.validation;
|
||||||
|
|
||||||
import jakarta.validation.Constraint;
|
import jakarta.validation.Constraint;
|
||||||
import jakarta.validation.Payload;
|
import jakarta.validation.Payload;
|
||||||
@ -1,7 +1,8 @@
|
|||||||
package com.imprimelibros.erp.config.validation;
|
package com.imprimelibros.erp.presupuesto.validation;
|
||||||
|
|
||||||
|
import com.imprimelibros.erp.configurationERP.VariableService;
|
||||||
|
import com.imprimelibros.erp.presupuesto.Presupuesto;
|
||||||
|
|
||||||
import com.imprimelibros.erp.entity.Presupuesto;
|
|
||||||
import com.imprimelibros.erp.service.VariableService;
|
|
||||||
import jakarta.validation.ConstraintValidator;
|
import jakarta.validation.ConstraintValidator;
|
||||||
import jakarta.validation.ConstraintValidatorContext;
|
import jakarta.validation.ConstraintValidatorContext;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.imprimelibros.erp.config.validation;
|
package com.imprimelibros.erp.presupuesto.validation;
|
||||||
|
|
||||||
import jakarta.validation.Constraint;
|
import jakarta.validation.Constraint;
|
||||||
import jakarta.validation.Payload;
|
import jakarta.validation.Payload;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.imprimelibros.erp.config.validation;
|
package com.imprimelibros.erp.presupuesto.validation;
|
||||||
|
|
||||||
import jakarta.validation.ConstraintValidator;
|
import jakarta.validation.ConstraintValidator;
|
||||||
import jakarta.validation.ConstraintValidatorContext;
|
import jakarta.validation.ConstraintValidatorContext;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.imprimelibros.erp.config.validation;
|
package com.imprimelibros.erp.presupuesto.validation;
|
||||||
|
|
||||||
public class PresupuestoValidationGroups {
|
public class PresupuestoValidationGroups {
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.imprimelibros.erp.config.validation;
|
package com.imprimelibros.erp.presupuesto.validation;
|
||||||
|
|
||||||
import jakarta.validation.Constraint;
|
import jakarta.validation.Constraint;
|
||||||
import jakarta.validation.Payload;
|
import jakarta.validation.Payload;
|
||||||
@ -1,7 +1,8 @@
|
|||||||
package com.imprimelibros.erp.config.validation;
|
package com.imprimelibros.erp.presupuesto.validation;
|
||||||
|
|
||||||
|
import com.imprimelibros.erp.configurationERP.VariableService;
|
||||||
|
import com.imprimelibros.erp.presupuesto.Presupuesto;
|
||||||
|
|
||||||
import com.imprimelibros.erp.entity.Presupuesto;
|
|
||||||
import com.imprimelibros.erp.service.VariableService;
|
|
||||||
import jakarta.validation.ConstraintValidator;
|
import jakarta.validation.ConstraintValidator;
|
||||||
import jakarta.validation.ConstraintValidatorContext;
|
import jakarta.validation.ConstraintValidatorContext;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -1,210 +0,0 @@
|
|||||||
package com.imprimelibros.erp.service;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import com.imprimelibros.erp.config.Presupuestador.ImagenPresupuesto;
|
|
||||||
import com.imprimelibros.erp.config.Presupuestador.PresupuestadorItems;
|
|
||||||
import com.imprimelibros.erp.entity.Presupuesto;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class PresupuestoService {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected VariableService variableService;
|
|
||||||
|
|
||||||
private final PresupuestadorItems presupuestadorItems;
|
|
||||||
|
|
||||||
public PresupuestoService(PresupuestadorItems presupuestadorItems) {
|
|
||||||
this.presupuestadorItems = presupuestadorItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean validateDatosGenerales(int[] tiradas) {
|
|
||||||
|
|
||||||
for (int tirada : tiradas) {
|
|
||||||
if (tirada <= 0) {
|
|
||||||
return false; // Invalid tirada found
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean isPOD(Presupuesto presupuesto) {
|
|
||||||
|
|
||||||
int pod_value = variableService.getValorEntero("POD");
|
|
||||||
return (presupuesto.getTirada1() != null && presupuesto.getTirada1() <= pod_value) ||
|
|
||||||
(presupuesto.getTirada2() != null && presupuesto.getTirada2() <= pod_value) ||
|
|
||||||
(presupuesto.getTirada3() != null && presupuesto.getTirada3() <= pod_value) ||
|
|
||||||
(presupuesto.getTirada4() != null && presupuesto.getTirada4() <= pod_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Object> obtenerOpcionesColor(Presupuesto presupuesto, Locale locale) {
|
|
||||||
|
|
||||||
List<ImagenPresupuesto> opciones = new ArrayList<>();
|
|
||||||
|
|
||||||
ImagenPresupuesto opcion;
|
|
||||||
|
|
||||||
if (presupuesto.getPaginasColor() > 0) {
|
|
||||||
if (!this.isPOD(presupuesto)) {
|
|
||||||
// POD solo color foto
|
|
||||||
opcion = this.presupuestadorItems.getImpresionColor(locale);
|
|
||||||
opcion.setSelected(presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color);
|
|
||||||
opciones.add(opcion);
|
|
||||||
}
|
|
||||||
opcion = this.presupuestadorItems.getImpresionColorPremium(locale);
|
|
||||||
opcion.setSelected(presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.colorhq);
|
|
||||||
opciones.add(opcion);
|
|
||||||
} else {
|
|
||||||
opcion = this.presupuestadorItems.getImpresionNegro(locale);
|
|
||||||
opcion.setSelected(presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negro);
|
|
||||||
opciones.add(opcion);
|
|
||||||
opcion = this.presupuestadorItems.getImpresionNegroPremium(locale);
|
|
||||||
opcion.setSelected(presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negrohq);
|
|
||||||
opciones.add(opcion);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean opcionSeleccionada = opciones.stream()
|
|
||||||
.findFirst()
|
|
||||||
.map(op -> {
|
|
||||||
op.setSelected(true);
|
|
||||||
return true;
|
|
||||||
})
|
|
||||||
.orElse(false);
|
|
||||||
if (!opcionSeleccionada) {
|
|
||||||
opciones.get(0).setSelected(true);
|
|
||||||
presupuesto.setPapelInteriorId(Integer.parseInt(opciones.get(0).getExtra_data().get("sk-id")));
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Object> response = new HashMap<>();
|
|
||||||
response.put("opciones_color", opciones);
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Object> obtenerOpcionesPapelInterior(Presupuesto presupuesto, Locale locale) {
|
|
||||||
|
|
||||||
List<ImagenPresupuesto> opciones = new ArrayList<>();
|
|
||||||
|
|
||||||
opciones.add(this.presupuestadorItems.getPapelOffsetBlanco(locale));
|
|
||||||
opciones.add(this.presupuestadorItems.getPapelOffsetAhuesado(locale));
|
|
||||||
opciones.add(this.presupuestadorItems.getPapelOffsetAhuesadoVolumen(locale));
|
|
||||||
opciones.add(this.presupuestadorItems.getPapelEstucadoMate(locale));
|
|
||||||
|
|
||||||
for (ImagenPresupuesto imagenPresupuesto : opciones) {
|
|
||||||
imagenPresupuesto.setSelected(
|
|
||||||
presupuesto.getPapelInteriorId() != null
|
|
||||||
&& imagenPresupuesto.getExtra_data().get("sk-id").equals(
|
|
||||||
String.valueOf(presupuesto.getPapelInteriorId())));
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean opcionSeleccionada = opciones.stream()
|
|
||||||
.findFirst()
|
|
||||||
.map(opcion -> {
|
|
||||||
opcion.setSelected(true);
|
|
||||||
return true;
|
|
||||||
})
|
|
||||||
.orElse(false);
|
|
||||||
if (!opcionSeleccionada) {
|
|
||||||
opciones.get(0).setSelected(true);
|
|
||||||
presupuesto.setPapelInteriorId(Integer.parseInt(opciones.get(0).getExtra_data().get("sk-id")));
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Object> response = new HashMap<>();
|
|
||||||
response.put("opciones_papel_interior", opciones);
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Object> obtenerOpcionesGramajeInterior(Presupuesto presupuesto) {
|
|
||||||
|
|
||||||
List<String> gramajes = new ArrayList<>();
|
|
||||||
|
|
||||||
final int BLANCO_OFFSET_ID = 3;
|
|
||||||
final int AHUESADO_OFFSET_ID = 4;
|
|
||||||
final int AHUESADO_OFFSET_VOLUMEN_ID = 6;
|
|
||||||
final int ESTUCADO_MATE_ID = 2;
|
|
||||||
|
|
||||||
if (presupuesto.getPapelInteriorId() != null && presupuesto.getPapelInteriorId() == BLANCO_OFFSET_ID) {
|
|
||||||
|
|
||||||
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negro ||
|
|
||||||
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
|
||||||
gramajes.add("80");
|
|
||||||
}
|
|
||||||
gramajes.add("90");
|
|
||||||
} else if (presupuesto.getPapelInteriorId() != null && presupuesto.getPapelInteriorId() == AHUESADO_OFFSET_ID) {
|
|
||||||
|
|
||||||
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negro ||
|
|
||||||
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
|
||||||
gramajes.add("80");
|
|
||||||
}
|
|
||||||
gramajes.add("150");
|
|
||||||
gramajes.add("170");
|
|
||||||
|
|
||||||
} else if (presupuesto.getPapelInteriorId() != null
|
|
||||||
&& presupuesto.getPapelInteriorId() == AHUESADO_OFFSET_VOLUMEN_ID) {
|
|
||||||
|
|
||||||
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negro ||
|
|
||||||
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
|
||||||
gramajes.add("70");
|
|
||||||
}
|
|
||||||
gramajes.add("90");
|
|
||||||
gramajes.add("100");
|
|
||||||
gramajes.add("150");
|
|
||||||
gramajes.add("170");
|
|
||||||
|
|
||||||
} else if (presupuesto.getPapelInteriorId() != null && presupuesto.getPapelInteriorId() == ESTUCADO_MATE_ID) {
|
|
||||||
|
|
||||||
gramajes.add("90");
|
|
||||||
gramajes.add("100");
|
|
||||||
gramajes.add("115");
|
|
||||||
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
|
||||||
gramajes.add("120");
|
|
||||||
}
|
|
||||||
gramajes.add("135");
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Object> response = new HashMap<>();
|
|
||||||
response.put("opciones_gramaje_interior", gramajes);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Object> obtenerOpcionesPapelCubierta(Presupuesto presupuesto, Locale locale) {
|
|
||||||
|
|
||||||
List<ImagenPresupuesto> opciones = new ArrayList<>();
|
|
||||||
|
|
||||||
if (presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaBlanda) {
|
|
||||||
opciones.add(this.presupuestadorItems.getCartulinaGraficaCubierta(locale));
|
|
||||||
}
|
|
||||||
opciones.add(this.presupuestadorItems.getEstucadoMateCubierta(locale));
|
|
||||||
|
|
||||||
for (ImagenPresupuesto imagenPresupuesto : opciones) {
|
|
||||||
imagenPresupuesto.setSelected(
|
|
||||||
presupuesto.getPapelCubiertaId() != null
|
|
||||||
&& imagenPresupuesto.getExtra_data().get("sk-id").equals(
|
|
||||||
String.valueOf(presupuesto.getPapelCubiertaId())));
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean opcionSeleccionada = opciones.stream()
|
|
||||||
.findFirst()
|
|
||||||
.map(opcion -> {
|
|
||||||
opcion.setSelected(true);
|
|
||||||
return true;
|
|
||||||
})
|
|
||||||
.orElse(false);
|
|
||||||
if (!opcionSeleccionada) {
|
|
||||||
opciones.get(0).setSelected(true);
|
|
||||||
presupuesto.setPapelInteriorId(Integer.parseInt(opciones.get(0).getExtra_data().get("sk-id")));
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Object> response = new HashMap<>();
|
|
||||||
response.put("opciones_papel_cubierta", opciones);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -4,10 +4,14 @@ logging.level.org.springframework.security=DEBUG
|
|||||||
logging.level.root=WARN
|
logging.level.root=WARN
|
||||||
logging.level.org.springframework=ERROR
|
logging.level.org.springframework=ERROR
|
||||||
|
|
||||||
spring.datasource.url=jdbc:mysql://localhost:3306/imprimelibros
|
spring.datasource.url=jdbc:mysql://localhost:3309/imprimelibros
|
||||||
spring.datasource.username=imprimelibros_user
|
spring.datasource.username=imprimelibros_user
|
||||||
spring.datasource.password=om91irrDctd
|
spring.datasource.password=om91irrDctd
|
||||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||||
|
|
||||||
|
safekat.api.url=http://localhost:8000/
|
||||||
|
safekat.api.email=imnavajas@coit.es
|
||||||
|
safekat.api.password"=Safekat2024
|
||||||
|
|
||||||
spring.jpa.hibernate.ddl-auto=update
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
spring.jpa.show-sql=true
|
spring.jpa.show-sql=true
|
||||||
1
src/main/resources/i18n/app_en.properties
Normal file
1
src/main/resources/i18n/app_en.properties
Normal file
@ -0,0 +1 @@
|
|||||||
|
app.currency-symbol=€
|
||||||
3
src/main/resources/i18n/app_es.properties
Normal file
3
src/main/resources/i18n/app_es.properties
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
app.currency-symbol=€
|
||||||
|
app.yes=Sí
|
||||||
|
app.no=No
|
||||||
@ -1,6 +1,7 @@
|
|||||||
presupuesto.datos-generales=Datos Generales
|
presupuesto.datos-generales=Datos Generales
|
||||||
presupuesto.interior=Interior
|
presupuesto.interior=Interior
|
||||||
presupuesto.cubierta=Cubierta
|
presupuesto.cubierta=Cubierta
|
||||||
|
presupuesto.seleccion-tirada=Seleccion de tirada
|
||||||
presupuesto.extras=Extras
|
presupuesto.extras=Extras
|
||||||
|
|
||||||
# Pestaña datos generales de presupuesto
|
# Pestaña datos generales de presupuesto
|
||||||
@ -28,17 +29,22 @@ presupuesto.paginas-posicion=Posición páginas color
|
|||||||
presupuesto.paginas-posicion-descripcion=Intruzca la posición separada por comas. Ej: 3,5,7 ó 4-10,20,155
|
presupuesto.paginas-posicion-descripcion=Intruzca la posición separada por comas. Ej: 3,5,7 ó 4-10,20,155
|
||||||
presupuesto.siempre-pares=Siempre deben ser pares
|
presupuesto.siempre-pares=Siempre deben ser pares
|
||||||
presupuesto.encuadernacion=Encuadernación
|
presupuesto.encuadernacion=Encuadernación
|
||||||
|
presupuesto.fresado=Fresado
|
||||||
presupuesto.fresado-descripcion=Fresado (a partir de 32 páginas)
|
presupuesto.fresado-descripcion=Fresado (a partir de 32 páginas)
|
||||||
|
presupuesto.cosido=Cosido
|
||||||
presupuesto.cosido-descripcion=Cosido (a partir de 32 páginas)
|
presupuesto.cosido-descripcion=Cosido (a partir de 32 páginas)
|
||||||
|
presupuesto.grapado=Grapado
|
||||||
presupuesto.grapado-descripcion=Grapado (entre 12 y 40 páginas)
|
presupuesto.grapado-descripcion=Grapado (entre 12 y 40 páginas)
|
||||||
|
presupuesto.espiral=Espiral
|
||||||
presupuesto.espiral-descripcion=Espiral (a partir de 20 páginas)
|
presupuesto.espiral-descripcion=Espiral (a partir de 20 páginas)
|
||||||
|
presupuesto.wire-o=Wire-O
|
||||||
presupuesto.wire-o-descripcion=Wire-O (a partir de 20 páginas)
|
presupuesto.wire-o-descripcion=Wire-O (a partir de 20 páginas)
|
||||||
presupuesto.encuadernacion-descripcion=Seleccione la encuadernación del libro
|
presupuesto.encuadernacion-descripcion=Seleccione la encuadernación del libro
|
||||||
presupuesto.continuar-interior=Continuar a diseño interior
|
presupuesto.continuar-interior=Continuar a diseño interior
|
||||||
|
|
||||||
# Pestaña interior de presupuesto
|
# Pestaña interior de presupuesto
|
||||||
presupuesto.tipo-encuadernacion=Tipo de impresión
|
presupuesto.tipo-interior=Tipo de impresión
|
||||||
presupuesto.tipo-encuadernacion-descripcion=Seleccione entre calidad estándar o premium
|
presupuesto.tipo-interior-descripcion=Seleccione entre calidad estándar o premium
|
||||||
presupuesto.papel-interior=Papel interior
|
presupuesto.papel-interior=Papel interior
|
||||||
presupuesto.papel-interior-descripcion=Seleccione el papel para el interior
|
presupuesto.papel-interior-descripcion=Seleccione el papel para el interior
|
||||||
presupuesto.gramaje-interior=Gramaje interior
|
presupuesto.gramaje-interior=Gramaje interior
|
||||||
@ -48,6 +54,7 @@ presupuesto.blanco-negro-premium= Blanco y negro Premium
|
|||||||
presupuesto.color=Color
|
presupuesto.color=Color
|
||||||
presupuesto.color-premium=Color Premium
|
presupuesto.color-premium=Color Premium
|
||||||
presupuesto.offset-blanco=Offset Blanco
|
presupuesto.offset-blanco=Offset Blanco
|
||||||
|
presupuesto.offset-blanco-volumen=Offset Blanco Volumen
|
||||||
presupuesto.offset-ahuesado=Offset Ahuesado
|
presupuesto.offset-ahuesado=Offset Ahuesado
|
||||||
presupuesto.offset-ahuesado-volumen=Offset Ahuesado Volumen
|
presupuesto.offset-ahuesado-volumen=Offset Ahuesado Volumen
|
||||||
presupuesto.estucado-mate=Estucado Mate
|
presupuesto.estucado-mate=Estucado Mate
|
||||||
@ -68,7 +75,7 @@ presupuesto.impresion-cubierta=Impresión de cubierta
|
|||||||
presupuesto.impresion-cubierta-help=La cubierta se puede imprimir por anverso y reverso, como en el caso de las revistas, pero para un libro normal con portada y contraportada, la impresión de cubierta es a una cara.
|
presupuesto.impresion-cubierta-help=La cubierta se puede imprimir por anverso y reverso, como en el caso de las revistas, pero para un libro normal con portada y contraportada, la impresión de cubierta es a una cara.
|
||||||
presupuesto.una-cara=Una cara
|
presupuesto.una-cara=Una cara
|
||||||
presupuesto.dos-caras=Dos caras
|
presupuesto.dos-caras=Dos caras
|
||||||
presupuesto.tamanio-solapa=Tamaño solapa
|
presupuesto.tamanio-solapa=Tamaño solapas
|
||||||
presupuesto.papel-guardas=Papel de guardas
|
presupuesto.papel-guardas=Papel de guardas
|
||||||
presupuesto.guardas-impresas=Guardas impresas
|
presupuesto.guardas-impresas=Guardas impresas
|
||||||
presupuesto.no=No
|
presupuesto.no=No
|
||||||
@ -84,8 +91,74 @@ presupuesto.estucado-mate-cubierta=Estucado mate
|
|||||||
presupuesto.gramaje-cubierta=Gramaje cubierta
|
presupuesto.gramaje-cubierta=Gramaje cubierta
|
||||||
presupuesto.gramaje-cubierta-descripcion=Seleccione el gramaje para la cubierta
|
presupuesto.gramaje-cubierta-descripcion=Seleccione el gramaje para la cubierta
|
||||||
presupuesto.volver-interior=Volver a diseño interior
|
presupuesto.volver-interior=Volver a diseño interior
|
||||||
presupuesto.continuar-extras-libro=Continuar a extras del libro
|
presupuesto.continuar-seleccion-tirada=Continuar a selección de tirada
|
||||||
|
presupuesto.offset=Offset
|
||||||
|
presupuesto.estucado=Estucado
|
||||||
|
presupuesto.verjurado=Verjurado
|
||||||
|
presupuesto.verjurado-blanco-natural=Verjurado blanco natural
|
||||||
|
presupuesto.verjurado-ahuesado=Verjurado ahuesado
|
||||||
|
presupuesto.acabado=Acabado
|
||||||
|
presupuesto.acabado-cubierta-descripcion=Seleccione el acabado para la cubierta
|
||||||
|
presupuesto.acabado-cubierta-aviso=La falta de plastificado en la cubierta puede comprometer su calidad, ya que aumenta el riesgo de agrietamiento en los pliegues o hendidos, afectando su apariencia y resistencia.
|
||||||
|
presupuesto.acabado-ninguno=Sin acabado
|
||||||
|
presupuesto.acabado-plastificado-brillo-1c=Plastificado Brillo 1/C
|
||||||
|
presupuesto.acabado-plastificado-mate-1c=Plastificado Mate 1/C
|
||||||
|
presupuesto.acabado-plastificado-mate-1c-antirrayado=Plastificado Mate 1/C Antirrayado
|
||||||
|
presupuesto.acabado-plastificado-mate-uvi=Plastificado Mate 1/C + Reserva UVI
|
||||||
|
presupuesto.acabado-plastificado-mate-uvi3d=Plastificado Mate 1/C + Reserva UVI 3D
|
||||||
|
presupuesto.acabado-plastificado-mate-uvi-braile=Plastificado Mate 1/C + Reserva UVI Braille
|
||||||
|
presupuesto.acabado-plastificado-sandy-1c=Plastificado Sandy 1/C (tacto arena)
|
||||||
|
presupuesto.cubierta-extras=Extras de cubierta
|
||||||
|
presupuesto.cubierta-extras-descripcion=Seleccione las opciones adicionales para la cubierta
|
||||||
|
presupuesto.sobrecubierta=Sobrecubierta
|
||||||
|
presupuesto.sobrecubierta-papel=Papel sobrecubierta
|
||||||
|
presupuesto.sobrecubierta-solapas=Tamaño solapas sobrecubierta
|
||||||
|
presupuesto.faja=Faja
|
||||||
|
presupuesto.faja-papel=Papel faja
|
||||||
|
presupuesto.faja-solapas=Tamaño solapas faja
|
||||||
|
presupuesto.faja-alto=Alto faja
|
||||||
|
|
||||||
|
#pestaña seleccion-tirada
|
||||||
|
presupuesto.seleccion-tirada-descripcion=Seleccione la tirada deseada
|
||||||
|
presupuesto.total=Total
|
||||||
|
presupuesto.precio-unidad=Precio por unidad
|
||||||
|
presupuesto.seleccionar-tirada=Seleccionar tirada
|
||||||
|
presupuesto.tirada-seleccionada=Seleccionada
|
||||||
|
presupuesto.unidades=UNIDADES
|
||||||
|
presupuesto.volver-seleccion-tirada=Volver a selección de tirada
|
||||||
|
presupuesto.continuar-extras-libro=Continuar a extras del libro
|
||||||
|
presupuesto.error-obtener-precio=No se pudo obtener el precio para los datos introducidos. Por favor, contacte con el soporte técnico.
|
||||||
|
|
||||||
|
#pestaña extras del libro
|
||||||
|
presupuesto.extras=Servicios Extras
|
||||||
|
presupuesto.extras-descripcion=Seleccione los servicios adicionales que desea añadir al presupuesto
|
||||||
|
presupuesto.extras-retractilado=Retractilado
|
||||||
|
presupuesto.extras-isbn=ISBN
|
||||||
|
presupuesto.extras-deposito-legal=Depósito Legal
|
||||||
|
presupuesto.extras-deposito-legal-descripcion=Se añadirán 4 ejemplares a la tirada
|
||||||
|
presupuesto.extras-revision-archivos=Revisión de archivos
|
||||||
|
presupuesto.extras-maquetacion-cubierta=Maquetación de cubierta
|
||||||
|
presupuesto.extras-ferro-digital=Ferro Digital
|
||||||
|
presupuesto.extras-ejemplar-prueba=Ejemplar de prueba
|
||||||
|
presupuesto.extras-marcapaginas=Marcapáginas
|
||||||
|
presupuesto.extras-maquetacion=Maquetación
|
||||||
|
presupuesto.extras-ferro-digital-ribbon=Incluido
|
||||||
|
presupuesto.extras-calcular=Calcular
|
||||||
|
presupuesto.volver-cubierta=Volver a diseño cubierta
|
||||||
|
presupuesto.finalizar=Finalizar presupuesto
|
||||||
|
presupuesto.calcular-presupuesto=Calcular presupuesto
|
||||||
|
presupuesto.consultar-soporte=Consultar con soporte
|
||||||
|
|
||||||
|
# Resumen del presupuesto
|
||||||
|
presupuesto.resumen-presupuesto=Resumen presupuesto
|
||||||
|
presupuesto.resumen-libro=Libro
|
||||||
|
presupuesto.resumen-encuadernacion=Encuadernación
|
||||||
|
presupuesto.interior-libro=Interior del libro
|
||||||
|
presupuesto.cubierta-libro=Cubierta del libro
|
||||||
|
presupuesto.extras-libro=Extras del libro
|
||||||
|
presupuesto.paginas=Páginas
|
||||||
|
presupuesto.solapas=Solapas
|
||||||
|
presupuesto.papel-gramaje=Papel y gramaje
|
||||||
|
|
||||||
# Errores
|
# Errores
|
||||||
presupuesto.errores-title=Corrija los siguientes errores:
|
presupuesto.errores-title=Corrija los siguientes errores:
|
||||||
@ -108,3 +181,4 @@ presupuesto.errores.tipo-cubierta=Seleccione el tipo de cubierta
|
|||||||
presupuesto.errores.solapas-cubierta=Seleccione si desea o no solapas en la cubierta
|
presupuesto.errores.solapas-cubierta=Seleccione si desea o no solapas en la cubierta
|
||||||
presupuesto.errores.papel-cubierta=Seleccione el tipo de papel para la cubierta
|
presupuesto.errores.papel-cubierta=Seleccione el tipo de papel para la cubierta
|
||||||
presupuesto.errores.gramaje-cubierta=Seleccione el gramaje del papel para la cubierta
|
presupuesto.errores.gramaje-cubierta=Seleccione el gramaje del papel para la cubierta
|
||||||
|
presupuesto.errores.acabado-cubierta=Seleccione el acabado de la cubierta
|
||||||
@ -44,10 +44,21 @@
|
|||||||
|
|
||||||
/* Keyframes para la animación */
|
/* Keyframes para la animación */
|
||||||
@keyframes zoomPop {
|
@keyframes zoomPop {
|
||||||
0% { transform: scale(1); }
|
0% {
|
||||||
40% { transform: scale(0.85); }
|
transform: scale(1);
|
||||||
80% { transform: scale(1.05); }
|
}
|
||||||
100% { transform: scale(1); }
|
|
||||||
|
40% {
|
||||||
|
transform: scale(0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
80% {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-container:hover {
|
.image-container:hover {
|
||||||
@ -61,15 +72,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.gramaje-radio{
|
.gramaje-radio {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
min-width: 70px; /* Ancho mínimo */
|
min-width: 70px;
|
||||||
min-height: 70px; /* Alto mínimo */
|
/* Ancho mínimo */
|
||||||
max-width: 70px; /* Ancho máximo */
|
min-height: 70px;
|
||||||
max-height: 70px; /* Alto máximo */
|
/* Alto mínimo */
|
||||||
|
max-width: 70px;
|
||||||
|
/* Ancho máximo */
|
||||||
|
max-height: 70px;
|
||||||
|
/* Alto máximo */
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fadeInUpBounce {
|
@keyframes fadeInUpBounce {
|
||||||
@ -77,13 +92,16 @@
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(30px);
|
transform: translateY(30px);
|
||||||
}
|
}
|
||||||
|
|
||||||
60% {
|
60% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(-10px);
|
transform: translateY(-10px);
|
||||||
}
|
}
|
||||||
|
|
||||||
80% {
|
80% {
|
||||||
transform: translateY(5px);
|
transform: translateY(5px);
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
@ -92,4 +110,241 @@
|
|||||||
.animate-fadeInUpBounce {
|
.animate-fadeInUpBounce {
|
||||||
animation: fadeInUpBounce 0.6s ease-out both;
|
animation: fadeInUpBounce 0.6s ease-out both;
|
||||||
animation-delay: 0.1s;
|
animation-delay: 0.1s;
|
||||||
|
will-change: transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-option {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
border: 1px solid #d0d7e5;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-option.checked {
|
||||||
|
border-color: #4b7bec;
|
||||||
|
background-color: #f0f5ff;
|
||||||
|
box-shadow: 0 0 0 2px #4b7bec inset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-option .price {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-desc {
|
||||||
|
min-height: 2.2rem;
|
||||||
|
/* ajusta según el tamaño de fuente que uses */
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-checkbox {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-check-service+.btn {
|
||||||
|
position: relative;
|
||||||
|
/* <-- Esto es lo más importante */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
white-space: normal;
|
||||||
|
line-height: 1.2;
|
||||||
|
min-height: 180px;
|
||||||
|
padding: 1rem 0.75rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
color: #4b7bec;
|
||||||
|
border: 1px solid #4b7bec;
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ESTILO CUANDO ESTÁ MARCADO */
|
||||||
|
.btn-check-service:checked+.btn {
|
||||||
|
background-color: #4b7bec;
|
||||||
|
color: #ffffff !important;
|
||||||
|
border-color: #4b7bec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Forzamos el color blanco en los subelementos */
|
||||||
|
.btn-check-service:checked+.btn .service-title,
|
||||||
|
.btn-check-service:checked+.btn .service-desc,
|
||||||
|
.btn-check-service:checked+.btn .service-price {
|
||||||
|
color: #ffffff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Forzamos el color azul cuando no está marcado */
|
||||||
|
.btn-check-service+.btn .service-title,
|
||||||
|
.btn-check-service+.btn .service-desc,
|
||||||
|
.btn-check-service+.btn .service-price {
|
||||||
|
color: #4b7bec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ribbon-service */
|
||||||
|
.ribbon-service {
|
||||||
|
position: absolute;
|
||||||
|
top: -5px;
|
||||||
|
right: -5px;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 90px;
|
||||||
|
height: 90px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ribbon-service span {
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
width: 120px;
|
||||||
|
padding: 5px 0;
|
||||||
|
background: #f25c5c;
|
||||||
|
color: white;
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
top: 20px;
|
||||||
|
right: -30px;
|
||||||
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ===== Tiradas (pricing cards) ===== */
|
||||||
|
.tirada-card {
|
||||||
|
--il-accent: #4b7bec;
|
||||||
|
--radius: 18px;
|
||||||
|
--sel-scale-y: 1.12;
|
||||||
|
/* cuánto más alta la seleccionada (crece arriba y abajo) */
|
||||||
|
|
||||||
|
/* círculo */
|
||||||
|
--arc-w: 280px;
|
||||||
|
--arc-h: 190px;
|
||||||
|
--arc-y: -23px;
|
||||||
|
/* tu valor */
|
||||||
|
--arc-stop: 74%;
|
||||||
|
|
||||||
|
border: 1px solid #e9ecef;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
background-color: #fff;
|
||||||
|
background-image: radial-gradient(var(--arc-w) var(--arc-h) at 50% var(--arc-y),
|
||||||
|
rgba(75, 126, 236, .24) 0 var(--arc-stop),
|
||||||
|
transparent calc(var(--arc-stop) + 1%));
|
||||||
|
|
||||||
|
padding: 1.25rem 1.25rem 1rem;
|
||||||
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
box-shadow: 0 4px 14px rgba(17, 24, 39, .06);
|
||||||
|
overflow: hidden;
|
||||||
|
/* integra la línea inferior */
|
||||||
|
transform-origin: center center;
|
||||||
|
/* ⟵ crecer hacia arriba y hacia abajo */
|
||||||
|
will-change: transform;
|
||||||
|
transition: transform .22s ease, box-shadow .22s ease, border-color .22s ease, background .22s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sin elevación al hover */
|
||||||
|
.tirada-card:hover {
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tipografías */
|
||||||
|
.tirada-card .title {
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: .04em;
|
||||||
|
font-size: .9rem;
|
||||||
|
color: #4b7bec;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tirada-card .price-big {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: 800;
|
||||||
|
line-height: 1.1;
|
||||||
|
margin: .35rem 0 .15rem;
|
||||||
|
color: #4b7bec;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tirada-card .per {
|
||||||
|
font-size: .85rem;
|
||||||
|
color: #7f8fa9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tirada-card .price-row {
|
||||||
|
margin-top: .75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tirada-card .muted {
|
||||||
|
color: #8e9bb3;
|
||||||
|
font-size: .9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Botón */
|
||||||
|
.tirada-card .btn-select-tirada {
|
||||||
|
margin-top: 1rem;
|
||||||
|
border-radius: 999px;
|
||||||
|
padding: .6rem 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
border: 2px solid var(--il-accent);
|
||||||
|
color: var(--il-accent);
|
||||||
|
background: transparent;
|
||||||
|
width: 100%;
|
||||||
|
transition: background .2s ease, color .2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== Seleccionada (más alta en Y, sin elevar; crece arriba y abajo) ===== */
|
||||||
|
.tirada-card.selected {
|
||||||
|
transform: scaleY(var(--sel-scale-y));
|
||||||
|
/* ⟵ crecimiento simétrico vertical */
|
||||||
|
z-index: 2;
|
||||||
|
box-shadow: 0 18px 48px rgba(75, 126, 236, .32);
|
||||||
|
border-color: var(--il-accent);
|
||||||
|
|
||||||
|
/* círculo sólido */
|
||||||
|
background-image: radial-gradient(var(--arc-w) var(--arc-h) at 50% var(--arc-y),
|
||||||
|
#4b7bec 0 var(--arc-stop),
|
||||||
|
transparent calc(var(--arc-stop) + 1%));
|
||||||
|
}
|
||||||
|
|
||||||
|
.tirada-card.selected:hover {
|
||||||
|
/* evita que :hover base anule la escala */
|
||||||
|
transform: scaleY(var(--sel-scale-y));
|
||||||
|
}
|
||||||
|
|
||||||
|
.tirada-card.selected .btn-select-tirada {
|
||||||
|
background: var(--il-accent);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* texto en blanco dentro del círculo */
|
||||||
|
.tirada-card.selected .title,
|
||||||
|
.tirada-card.selected .price-big,
|
||||||
|
.tirada-card.selected .per {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== Línea inferior integrada (siempre visible en NO seleccionadas) ===== */
|
||||||
|
.tirada-card:not(.selected)::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: 1px;
|
||||||
|
right: 1px;
|
||||||
|
bottom: 1px;
|
||||||
|
/* dentro del borde */
|
||||||
|
height: 8px;
|
||||||
|
background: var(--il-accent);
|
||||||
|
border-bottom-left-radius: calc(var(--radius) - 1px);
|
||||||
|
border-bottom-right-radius: calc(var(--radius) - 1px);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tirada-card.selected::after {
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Oculta el radio */
|
||||||
|
.tirada-card input[type="radio"] {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
@ -20,6 +20,7 @@ class imagen_presupuesto {
|
|||||||
for (const [key, value] of Object.entries(this.extraData)) {
|
for (const [key, value] of Object.entries(this.extraData)) {
|
||||||
contenedor.attr(`data-${key}`, value);
|
contenedor.attr(`data-${key}`, value);
|
||||||
}
|
}
|
||||||
|
contenedor.attr("data-summary-text", this.texto); // Para el resumen
|
||||||
|
|
||||||
const input = $('<input>', {
|
const input = $('<input>', {
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,46 @@
|
|||||||
|
class ServiceOptionCard {
|
||||||
|
|
||||||
|
constructor({ id, title, description = '', price = '', priceUnit = '', checked = false, allowChange = true, ribbonText }) {
|
||||||
|
this.id = id;
|
||||||
|
this.title = title;
|
||||||
|
this.description = description ? description : ' ';
|
||||||
|
this.price = price;
|
||||||
|
this.priceUnit = priceUnit;
|
||||||
|
this.checked = checked;
|
||||||
|
this.allowChange = !(String(allowChange).toLowerCase() === "false");
|
||||||
|
this.ribbonText = ribbonText;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const ribbonHtml = this.ribbonText
|
||||||
|
? `<div class="ribbon-service"><span>${this.ribbonText}</span></div>`
|
||||||
|
: '';
|
||||||
|
const $card = $(`
|
||||||
|
<div class="col-lg-2 col-md-3 col-sm-6 mb-3">
|
||||||
|
<input type="checkbox" class="service-checkbox data-price=${this.price} btn-check-service" id="${this.id}" name="services[]" value="${this.id}" autocomplete="off" ${this.checked ? 'checked' : ''} />
|
||||||
|
<label class="btn btn-outline-primary w-100 text-center py-3 px-2 d-flex flex-column align-items-center justify-content-center h-100" for="${this.id}">
|
||||||
|
${ribbonHtml}
|
||||||
|
<h5 class="service-title mb-1">${this.title}</h5>
|
||||||
|
<p class="service-desc mb-1 small">${this.description}</p>
|
||||||
|
<h4 class="service-price fw-semibold mt-2 h4 mb-0">${this.price} ${this.priceUnit}</h4>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
|
||||||
|
const $checkbox = $card.find('input[type="checkbox"]');
|
||||||
|
|
||||||
|
if (!this.allowChange) {
|
||||||
|
// Deshabilita el cambio de estado visual
|
||||||
|
$checkbox.on('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return $card;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ServiceOptionCard;
|
||||||
@ -0,0 +1,141 @@
|
|||||||
|
export function updateEncuadernacion() {
|
||||||
|
|
||||||
|
const $selected = $('.tipo-libro.selected');
|
||||||
|
if ($selected.length > 0) {
|
||||||
|
const resumen = $selected.data('summary-text') || $selected.attr('id');
|
||||||
|
$('#summary-encuadernacion').text(resumen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateFormato(){
|
||||||
|
|
||||||
|
if($('#formato-personalizado').is(':checked')) {
|
||||||
|
$('#summary-formato').text($('#ancho').val() + 'x' + $('#alto').val() + ' mm');
|
||||||
|
} else {
|
||||||
|
const $selected = $('#formato option:selected');
|
||||||
|
const resumen = $selected.data('summary-text') || $selected.val();
|
||||||
|
$('#summary-formato').text(resumen + ' mm');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updatePaginas() {
|
||||||
|
|
||||||
|
const paginas = $('#paginas').val();
|
||||||
|
$('#summary-paginas').text(paginas );
|
||||||
|
|
||||||
|
const paginasColor = $('#paginas-color').val();
|
||||||
|
$('#summary-paginas-color').text(paginasColor );
|
||||||
|
|
||||||
|
const paginasNegro = $('#paginas-negro').val();
|
||||||
|
$('#summary-paginas-negro').text(paginasNegro );
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateTipoImpresion() {
|
||||||
|
|
||||||
|
const $selected = $('.opcion-color.selected');
|
||||||
|
if ($selected.length > 0) {
|
||||||
|
const resumen = $selected.data('summary-text') || $selected.attr('id');
|
||||||
|
$('#summary-tipo-interior').text(resumen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updatePapelInterior() {
|
||||||
|
|
||||||
|
const $selected = $('.papel-interior.selected');
|
||||||
|
if ($selected.length > 0) {
|
||||||
|
const resumen = $selected.data('summary-text') || $selected.val();
|
||||||
|
$('#summary-papel-interior').text(resumen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateGramajeInterior() {
|
||||||
|
|
||||||
|
const gramaje = $('input[name="gramaje-interior"]:checked');
|
||||||
|
if(gramaje.length > 0) {
|
||||||
|
$('#summary-gramaje-interior').text(gramaje.data('gramaje'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateTapaCubierta(){
|
||||||
|
|
||||||
|
const $selected = $('.tapa-cubierta.selected');
|
||||||
|
if ($selected.length > 0) {
|
||||||
|
const resumen = $selected.data('summary-text') || $selected.attr('id');
|
||||||
|
$('#summary-tapa-cubierta').text(resumen);
|
||||||
|
}
|
||||||
|
if($selected.attr('id') === 'tapaBlanda') {
|
||||||
|
|
||||||
|
$('.tapa-blanda-row').removeClass('d-none');
|
||||||
|
$('.tapa-dura-row').addClass('d-none');
|
||||||
|
$('#summary-cubierta-solapas').text($('#sin-solapas').hasClass('selected') ? $('#sin-solapas').data('summary-text') : $('#con-solapas').data('summary-text'));
|
||||||
|
if($('#con-solapas').hasClass('selected')) {
|
||||||
|
$('#summary-tamanio-solapa-row').removeClass('d-none');
|
||||||
|
$('#summary-tamanio-solapa').text($('#tamanio-solapas-cubierta').val() + ' mm');
|
||||||
|
} else {
|
||||||
|
$('#summary-tamanio-solapa-row').addClass('d-none');
|
||||||
|
$('#summary-tamanio-solapa').text('');
|
||||||
|
}
|
||||||
|
$('#summary-impresion-cubierta-row').removeClass('d-none');
|
||||||
|
$('#summary-impresion-cubierta').text($('#impresion-cubierta option:selected').text());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$('.tapa-blanda-row').addClass('d-none');
|
||||||
|
$('.tapa-dura-row').removeClass('d-none');
|
||||||
|
$('#summary-papel-guardas').text($('#papel-guardas option:selected').text());
|
||||||
|
$('#summary-guardas-impresas').text($('#guardas-impresas option:selected').text());
|
||||||
|
$('#summary-cabezada').text($('#cabezada option:selected').text());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updatePapelCubierta() {
|
||||||
|
const $selected = $('.papel-cubierta.selected');
|
||||||
|
if ($selected.length > 0) {
|
||||||
|
const resumen = $selected.data('summary-text') || $selected.val();
|
||||||
|
$('#summary-papel-cubierta').text(resumen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateGramajeCubierta() {
|
||||||
|
const gramaje = $('input[name="gramaje-cubierta"]:checked');
|
||||||
|
if(gramaje.length > 0) {
|
||||||
|
$('#summary-gramaje-cubierta').text(gramaje.data('gramaje'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateAcabadoCubierta() {
|
||||||
|
const acabado = $('input[name="acabado-cubierta"]:checked');
|
||||||
|
if(acabado.length > 0) {
|
||||||
|
let labelText = '';
|
||||||
|
const id = acabado.attr('id');
|
||||||
|
|
||||||
|
if (id) {
|
||||||
|
labelText = $(`label[for="${id}"]`).text().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Caso 2: input dentro de label
|
||||||
|
if (!labelText) {
|
||||||
|
labelText = acabado.closest('label').text().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#summary-acabado-cubierta').text(labelText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateSobreCubierta() {
|
||||||
|
|
||||||
|
if($('#sobrecubierta').hasClass('active')) {
|
||||||
|
$('#summary-sobrecubierta-papel-gramaje').text($('#papel-sobrecubierta option:selected').text());
|
||||||
|
$('#summary-sobrecubierta-tamanio-solapa').text($('#tamanio-solapas-sobrecubierta').val() + ' mm');
|
||||||
|
$('#summary-sobrecubierta-acabado').text($('#sobrecubierta-acabado option:selected').text());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateFaja() {
|
||||||
|
|
||||||
|
if($('#faja').hasClass('active')) {
|
||||||
|
$('#summary-faja-papel-gramaje').text($('#papel-faja option:selected').text());
|
||||||
|
$('#summary-faja-alto-faja').text($('#alto-faja').val() + ' mm');
|
||||||
|
$('#summary-faja-tamanio-solapa').text($('#tamanio-solapas-faja').val() + ' mm');
|
||||||
|
$('#summary-faja-acabado').text($('#faja-acabado option:selected').text());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,123 @@
|
|||||||
|
// ===== Clase =====
|
||||||
|
class TiradaCard {
|
||||||
|
constructor({ id, titulo, unidades, precioUnidad, precioTotal, selected = false, moneda = '€', name = 'tirada',
|
||||||
|
labels = {}, locale = (document.documentElement.lang || navigator.language || 'es-ES')
|
||||||
|
}) {
|
||||||
|
this.id = id;
|
||||||
|
this.titulo = titulo;
|
||||||
|
this.unidades = unidades;
|
||||||
|
this.precioUnidad = precioUnidad;
|
||||||
|
this.precioTotal = precioTotal;
|
||||||
|
this.selected = selected;
|
||||||
|
this.moneda = moneda;
|
||||||
|
this.name = name;
|
||||||
|
this.locale = locale;
|
||||||
|
this.labels = Object.assign({
|
||||||
|
perUnit: 'Precio por unidad',
|
||||||
|
total: 'Total',
|
||||||
|
select: 'Seleccionar tirada',
|
||||||
|
selected: 'Seleccionada',
|
||||||
|
units: 'UNIDADES'
|
||||||
|
}, labels);
|
||||||
|
this.$container = null; // se establece al renderizar
|
||||||
|
}
|
||||||
|
|
||||||
|
#formatMoneyES(value, decimals = 2) {
|
||||||
|
return new Intl.NumberFormat(this.locale, {
|
||||||
|
minimumFractionDigits: decimals,
|
||||||
|
maximumFractionDigits: decimals
|
||||||
|
}).format(Number(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
#title() {
|
||||||
|
if (this.titulo) return this.titulo;
|
||||||
|
if (this.unidades != null) return `${this.unidades} ${this.labels.units}`;
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// pásale el contenedor donde van todas las tarjetas de este grupo
|
||||||
|
renderCol($container) {
|
||||||
|
this.$container = $container ? $($container) : $(document.body);
|
||||||
|
|
||||||
|
const col = $(`
|
||||||
|
<div class="col d-flex">
|
||||||
|
<label class="tirada-card ${this.selected ? 'selected' : ''} w-100 h-100" for="tirada-${this.id}">
|
||||||
|
<input type="radio" name="${this.name}" id="tirada-${this.id}" value="${this.unidades}" ${this.selected ? 'checked' : ''}>
|
||||||
|
<div class="title">${this.#title()}</div>
|
||||||
|
|
||||||
|
<div class="per muted">${this.labels.perUnit}</div>
|
||||||
|
<div class="price-big">${this.#formatMoneyES(this.precioUnidad, 4)} ${this.moneda}</div>
|
||||||
|
|
||||||
|
<div class="price-row">
|
||||||
|
<div class="muted">${this.labels.total}</div>
|
||||||
|
<div class="fw-bold">${this.#formatMoneyES(this.precioTotal, 2)} ${this.moneda}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-select-tirada">${this.labels.select}</button>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
|
||||||
|
// --- Delegación de eventos en el contenedor (una sola vez por grupo) ---
|
||||||
|
const boundKey = `tirada-bound-${this.name}`;
|
||||||
|
const groupName = this.name;
|
||||||
|
const $group = this.$container;
|
||||||
|
const labels = this.labels;
|
||||||
|
|
||||||
|
if (!$group.data(boundKey)) {
|
||||||
|
$group.on('change', `input[type="radio"][name="${groupName}"]`, function () {
|
||||||
|
// radios del grupo
|
||||||
|
const $groupRadios = $group.find(`input[type="radio"][name="${groupName}"]`);
|
||||||
|
|
||||||
|
// resetear todas las tarjetas del grupo
|
||||||
|
$groupRadios
|
||||||
|
.closest('.tirada-card')
|
||||||
|
.removeClass('selected')
|
||||||
|
.find('.btn-select-tirada')
|
||||||
|
.html(labels.select || 'Seleccionar tirada');
|
||||||
|
|
||||||
|
// marcar la tarjeta seleccionada y su botón
|
||||||
|
const $card = $(this).closest('.tirada-card');
|
||||||
|
$card.find('.btn-select-tirada')
|
||||||
|
.html(labels.selected + ' <i class="mdi mdi-check-circle ms-1"></i>');
|
||||||
|
$card.addClass('selected');
|
||||||
|
|
||||||
|
const $input = $(this);
|
||||||
|
const detail = {
|
||||||
|
id: $input.attr('id'),
|
||||||
|
name: $input.attr('name'),
|
||||||
|
unidades: Number($input.data('unidades') ?? $input.val()),
|
||||||
|
precioUnidad: Number($input.data('precioUnidad')),
|
||||||
|
precioTotal: Number($input.data('precioTotal'))
|
||||||
|
};
|
||||||
|
// jQuery: pasa 'detail' como segundo argumento del handler
|
||||||
|
$group.trigger('tirada:changed', [detail]);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$group.data(boundKey, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const $btnLocal = col.find('.btn-select-tirada');
|
||||||
|
if (this.selected) {
|
||||||
|
$btnLocal.html(labels.selected + ' <i class="mdi mdi-check-circle ms-1"></i>');
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Comportamiento de la tarjeta/botón (local a esta tarjeta) ---
|
||||||
|
const card = col.find('.tirada-card');
|
||||||
|
|
||||||
|
col.find('.btn-select-tirada').on('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
card.find('input[type="radio"]').prop('checked', true).trigger('change');
|
||||||
|
});
|
||||||
|
|
||||||
|
card.on('click', function (e) {
|
||||||
|
if ($(e.target).is('.btn-select-tirada')) return;
|
||||||
|
$(this).find('input[type="radio"]').prop('checked', true).trigger('change');
|
||||||
|
});
|
||||||
|
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TiradaCard;
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
<div class="ribbon-content mt-4">
|
<div class="ribbon-content mt-4">
|
||||||
<div class="row justify-content-center imagen-container-group mt-3">
|
<div class="row justify-content-center imagen-container-group mt-3">
|
||||||
<div id="tapaBlanda" class="tapa-cubierta image-container imagen-selector selected">
|
<div id="tapaBlanda" class="tapa-cubierta image-container imagen-selector selected" th:attr="data-summary-text=#{presupuesto.tapa-blanda}">
|
||||||
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/tapa-blanda.png"
|
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/tapa-blanda.png"
|
||||||
alt="">
|
alt="">
|
||||||
<label for="titulo" class="form-label" th:text="#{presupuesto.tapa-blanda}">
|
<label for="titulo" class="form-label" th:text="#{presupuesto.tapa-blanda}">
|
||||||
@ -29,7 +29,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="tapaDuraLomoRecto" class="tapa-cubierta image-container imagen-selector">
|
<div id="tapaDura" class="tapa-cubierta image-container imagen-selector" th:attr="data-summary-text=#{presupuesto.tapa-dura}">
|
||||||
<img class="image-presupuesto"
|
<img class="image-presupuesto"
|
||||||
src="/assets/images/imprimelibros/presupuestador/tapa-dura-lomo-recto.png" alt="">
|
src="/assets/images/imprimelibros/presupuestador/tapa-dura-lomo-recto.png" alt="">
|
||||||
<label class="form-label" th:text="#{presupuesto.tapa-dura}">
|
<label class="form-label" th:text="#{presupuesto.tapa-dura}">
|
||||||
@ -37,7 +37,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="tapaDuraLomoRedondo" class="tapa-cubierta image-container imagen-selector">
|
<div id="tapaDuraLomoRedondo" class="tapa-cubierta image-container imagen-selector" th:attr="data-summary-text=#{presupuesto.tapa-dura-lomo-redondo}">
|
||||||
<img class="image-presupuesto"
|
<img class="image-presupuesto"
|
||||||
src="/assets/images/imprimelibros/presupuestador/tapa-dura-lomo-redondo.png" alt="">
|
src="/assets/images/imprimelibros/presupuestador/tapa-dura-lomo-redondo.png" alt="">
|
||||||
<label class="form-label" th:text="#{presupuesto.tapa-dura-lomo-redondo}">
|
<label class="form-label" th:text="#{presupuesto.tapa-dura-lomo-redondo}">
|
||||||
@ -46,66 +46,92 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row justify-content-center align-items-center mt-3 imagen-container-group tapa-blanda-options">
|
|
||||||
|
|
||||||
<div id="sin-solapas" class="image-container imagen-selector solapas-cubierta selected">
|
<div class="row justify-content-center mt-4 imagen-container-group tapa-blanda-options">
|
||||||
<img class="image-presupuesto"
|
<div class="col-auto">
|
||||||
src="/assets/images/imprimelibros/presupuestador/sinSolapasCubierta.png" alt="">
|
<div class="d-flex flex-wrap align-items-center gap-4 ">
|
||||||
<label class="form-label" th:text="#{presupuesto.sin-solapas}">
|
|
||||||
Sin solapas
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="con-solapas" class="image-container imagen-selector solapas-cubierta">
|
<!-- Bloque de solapas -->
|
||||||
<img class="image-presupuesto"
|
<div class="d-flex gap-3">
|
||||||
src="/assets/images/imprimelibros/presupuestador/conSolapasCubierta.png" alt="">
|
<div id="sin-solapas" class="image-container imagen-selector solapas-cubierta selected" th:attr="data-summary-text=#{app.no}">
|
||||||
<label class="form-label" th:text="#{presupuesto.con-solapas}">
|
<img class="image-presupuesto"
|
||||||
Con solapas
|
src="/assets/images/imprimelibros/presupuestador/sinSolapasCubierta.png" alt="">
|
||||||
</label>
|
<label class="form-label text-center d-block" th:text="#{presupuesto.sin-solapas}">
|
||||||
</div>
|
Sin solapas
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="con-solapas" class="image-container imagen-selector solapas-cubierta" th:attr="data-summary-text=#{app.yes}">
|
||||||
|
<img class="image-presupuesto"
|
||||||
|
src="/assets/images/imprimelibros/presupuestador/conSolapasCubierta.png" alt="">
|
||||||
|
<label class="form-label text-center d-block" th:text="#{presupuesto.con-solapas}">
|
||||||
|
Con solapas
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Inputs -->
|
||||||
|
<div class="d-flex flex-column flex-md-row align-items-start gap-3">
|
||||||
|
<!-- Impresión cubierta -->
|
||||||
|
<div>
|
||||||
|
<label for="impresion-cubierta" class="form-label"
|
||||||
|
th:text="#{presupuesto.impresion-cubierta}">Impresión de cubierta</label>
|
||||||
|
<div class="input-group input-group-sm">
|
||||||
|
<select class="form-select select2 datos-cubierta tapa-cubierta-summary" id="impresion-cubierta">
|
||||||
|
<option value="2" th:text="#{presupuesto.una-cara}">Una cara</option>
|
||||||
|
<option value="4" th:text="#{presupuesto.dos-caras}">Dos caras</option>
|
||||||
|
</select>
|
||||||
|
<button
|
||||||
|
class="btn btn-outline-primary btn-icon waves-effect waves-light material-shadow-none"
|
||||||
|
type="button" id="impresion-cubierta-help">
|
||||||
|
<i class="ri-questionnaire-line"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tamaño solapa -->
|
||||||
|
<div id="div-solapas-cubierta" class="d-none">
|
||||||
|
<label for="tamanio-solapas-cubierta" class="form-label"
|
||||||
|
th:text="#{presupuesto.tamanio-solapa}">Tamaño solapa</label>
|
||||||
|
<input type="number"
|
||||||
|
class="form-control form-control-sm solapas-presupuesto datos-cubierta tapa-cubierta-summary"
|
||||||
|
id="tamanio-solapas-cubierta" min="60" max="120" value="80" step="1">
|
||||||
|
<div class="form-text">
|
||||||
|
<p class="mb-0">min: 60 mm</p>
|
||||||
|
<p class="max-solapa-text">max: 120 mm</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="col-auto mb-3">
|
|
||||||
<label for="impresion-cubierta" class="form-label"
|
|
||||||
th:text="#{presupuesto.impresion-cubierta}">Impresión de cubierta</label>
|
|
||||||
<div class="input-group">
|
|
||||||
<select class="form-select select2" id="impresion-cubierta">
|
|
||||||
<option value="2" th:text="#{presupuesto.una-cara}">Una cara</option>
|
|
||||||
<option value="4" th:text="#{presupuesto.dos-caras}">Dos cara</option>
|
|
||||||
</select>
|
|
||||||
<button class="btn btn-outline-primary btn-icon waves-effect waves-light material-shadow-none"
|
|
||||||
type="button" id="impresion-cubierta-help">
|
|
||||||
<i class="ri-questionnaire-line"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="div-solapas-cubierta" class="col-auto mb-3 d-none">
|
|
||||||
<label for="tamanio-solapas-cubierta" class="form-label"
|
|
||||||
th:text="#{presupuesto.tamanio-solapa}">Tamaño solapa</label>
|
|
||||||
<input type="number" class="form-control" id="tamanio-solapas-cubierta" value="80" step="1">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row justify-content-center align-items-center mt-3 imagen-container-group tapa-dura-options d-none">
|
|
||||||
|
<div
|
||||||
|
class="row justify-content-center align-items-center mt-3 imagen-container-group tapa-dura-options d-none">
|
||||||
|
|
||||||
<div class="col-auto mb-3">
|
<div class="col-auto mb-3">
|
||||||
<label for="papel-guardas" class="form-label" th:text="#{presupuesto.papel-guardas}">Papel de
|
<label for="papel-guardas" class="form-label" th:text="#{presupuesto.papel-guardas}">Papel de
|
||||||
guardas</label>
|
guardas</label>
|
||||||
<select class="form-select select2" id="papel-guardas">
|
<select class="form-select select2 datos-cubierta tapa-cubierta-summary" id="papel-guardas">
|
||||||
<option value="1" data-papel-id="3" data-gramaje="170"
|
<optgroup th:label="#{presupuesto.offset}">
|
||||||
th:text="#{presupuesto.offset-blanco} + ' 170 gr'" selected>Offset blanco 170 gr</option>
|
<option value="1" data-papel-id="3" data-gramaje="170"
|
||||||
<option value="2" data-papel-id="4" data-gramaje="170"
|
th:text="#{presupuesto.offset-blanco} + ' 170 gr'" selected>Offset blanco 170 gr
|
||||||
th:text="#{presupuesto.offset-ahuesado} + ' 170 gr'">Offset ahuesado 170 gr</option>
|
</option>
|
||||||
<option value="3" data-papel-id="2" data-gramaje="170"
|
<option value="2" data-papel-id="4" data-gramaje="170"
|
||||||
th:text="#{presupuesto.estucado-mate} + ' 170 gr'">Estucado mate 170 gr</option>
|
th:text="#{presupuesto.offset-ahuesado} + ' 170 gr'">Offset ahuesado 170 gr</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup th:label="#{presupuesto.estucado}">
|
||||||
|
<option value="3" data-papel-id="2" data-gramaje="170"
|
||||||
|
th:text="#{presupuesto.estucado-mate} + ' 170 gr'">Estucado mate 170 gr</option>
|
||||||
|
</optgroup>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto mb-3">
|
<div class="col-auto mb-3">
|
||||||
<label for="guardas-impresas" class="form-label" th:text="#{presupuesto.guardas-impresas}">Guardas
|
<label for="guardas-impresas" class="form-label" th:text="#{presupuesto.guardas-impresas}">Guardas
|
||||||
impresas</label>
|
impresas</label>
|
||||||
<select class="form-select select2" id="guardas-impresas">
|
<select class="form-select select2 datos-cubierta tapa-cubierta-summary" id="guardas-impresas">
|
||||||
<option value="0" th:text="#{presupuesto.no}" selected>No</option>
|
<option value="0" th:text="#{presupuesto.no}" selected>No</option>
|
||||||
<option value="4" th:text="#{presupuesto.una-cara}">Una cara</option>
|
<option value="4" th:text="#{presupuesto.una-cara}">Una cara</option>
|
||||||
<option value="8" th:text="#{presupuesto.dos-caras}">Dos caras</option>
|
<option value="8" th:text="#{presupuesto.dos-caras}">Dos caras</option>
|
||||||
@ -113,7 +139,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-auto mb-3">
|
<div class="col-auto mb-3">
|
||||||
<label for="cabezada" class="form-label" th:text="#{presupuesto.cabezada}">Cabezada</label>
|
<label for="cabezada" class="form-label" th:text="#{presupuesto.cabezada}">Cabezada</label>
|
||||||
<select class="form-select select2" id="guardas-impresas">
|
<select class="form-select select2 datos-cubierta tapa-cubierta-summary" id="cabezada">
|
||||||
<option value="WHI" th:text="#{presupuesto.cabezada-blanca}" selected>Blanca</option>
|
<option value="WHI" th:text="#{presupuesto.cabezada-blanca}" selected>Blanca</option>
|
||||||
<option value="GRE" th:text="#{presupuesto.cabezada-verde}">Verde</option>
|
<option value="GRE" th:text="#{presupuesto.cabezada-verde}">Verde</option>
|
||||||
<option value="BLUE" th:text="#{presupuesto.cabezada-azul}">Azul</option>
|
<option value="BLUE" th:text="#{presupuesto.cabezada-azul}">Azul</option>
|
||||||
@ -135,7 +161,7 @@
|
|||||||
|
|
||||||
<div class="ribbon-content mt-4">
|
<div class="ribbon-content mt-4">
|
||||||
|
|
||||||
<div id="div-papel-cubierta" class="row justify-content-center imagen-container-group">a
|
<div id="div-papel-cubierta" class="row justify-content-center imagen-container-group">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -191,13 +217,188 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- End Ribbon Shape -->
|
<!-- End Ribbon Shape -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Ribbon Shape -->
|
||||||
|
<div class="card ribbon-box border shadow-none mb-lg-0 material-shadow mt-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="ribbon ribbon-primary ribbon-shape" th:text="#{presupuesto.acabado}">Acabado
|
||||||
|
</div>
|
||||||
|
<h5 class="fs-14 text-end" th:text="#{presupuesto.acabado-cubierta-descripcion}">
|
||||||
|
Acabado de la cubierta</h5>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ribbon-content mt-4">
|
||||||
|
<div class="hstack gap-2 justify-content-center flex-wrap mx-4">
|
||||||
|
<p th:text="#{presupuesto.acabado-cubierta-aviso}"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="div-acabado-cubierta" class="hstack gap-2 justify-content-center flex-wrap">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- End Ribbon Shape -->
|
||||||
|
|
||||||
|
<!-- Ribbon Shape -->
|
||||||
|
<div class="card ribbon-box border shadow-none mb-lg-0 material-shadow mt-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="ribbon ribbon-primary ribbon-shape" th:text="#{presupuesto.cubierta-extras}">Extras
|
||||||
|
</div>
|
||||||
|
<h5 class="fs-14 text-end" th:text="#{presupuesto.cubierta-extras-descripcion}">
|
||||||
|
Opciones adicionales para la cubierta</h5>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ribbon-content mt-4">
|
||||||
|
|
||||||
|
<div class="row justify-content-center mt-4">
|
||||||
|
<div class="col-auto">
|
||||||
|
<div class="d-flex flex-wrap align-items-center gap-4 ">
|
||||||
|
|
||||||
|
<button id="sobrecubierta" type="button" class="btn btn-outline-primary custom-toggle mb-4"
|
||||||
|
data-bs-toggle="button">
|
||||||
|
<span class="icon-on">
|
||||||
|
<i class="ri-close-line align-bottom me-1"></i>
|
||||||
|
<span th:text="#{presupuesto.sobrecubierta}"></span>
|
||||||
|
</span>
|
||||||
|
<span class="icon-off">
|
||||||
|
<i class="ri-add-line align-bottom me-1"></i>
|
||||||
|
<span th:text="#{presupuesto.sobrecubierta}"></span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div id="div-sobrecubierta" class="d-flex flex-wrap d-none align-items-start gap-3">
|
||||||
|
<div class="d-flex flex-column me-2">
|
||||||
|
<label for="papel-sobrecubierta" class="form-label"
|
||||||
|
th:text="#{presupuesto.sobrecubierta-papel}">Papel</label>
|
||||||
|
<select class="form-select select2 datos-cubierta sobrecubierta-item w-auto" id="papel-sobrecubierta">
|
||||||
|
<optgroup th:label="#{presupuesto.estucado}">
|
||||||
|
<option selected value="2" data-papel-id="2" data-gramaje="170"
|
||||||
|
th:text="#{presupuesto.estucado-mate} + ' 170 gr'">Estucado mate 170 gr
|
||||||
|
</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup th:label="#{presupuesto.verjurado}">
|
||||||
|
<option value="1" data-papel-id="18" data-gramaje="160"
|
||||||
|
th:text="#{presupuesto.verjurado-blanco-natural} + ' 160 gr'">Verjurado blanco natural 160 gr
|
||||||
|
170 gr
|
||||||
|
</option>
|
||||||
|
<option value="2" data-papel-id="9" data-gramaje="160"
|
||||||
|
th:text="#{presupuesto.verjurado-ahuesado} + ' 160 gr'">Verjurado ahuesado 160 gr
|
||||||
|
</option>
|
||||||
|
</optgroup>
|
||||||
|
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex flex-column me-2">
|
||||||
|
<label for="tamanio-solapas-sobrecubierta" class="form-label"
|
||||||
|
th:text="#{presupuesto.sobrecubierta-solapas}">Tamaño solapas sobrecubierta</label>
|
||||||
|
<input type="number" class="form-control datos-cubierta sobrecubierta-item w-auto"
|
||||||
|
id="tamanio-solapas-sobrecubierta" min="60" max="120" value="80" step="1">
|
||||||
|
<div class="form-text">
|
||||||
|
<p class="mb-0">min: 60 mm</p>
|
||||||
|
<p class="max-solapa-text">max: 120 mm</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex flex-column me-2">
|
||||||
|
<label for="sobrecubierta-acabado" class="form-label"
|
||||||
|
th:text="#{presupuesto.acabado}">Acabado</label>
|
||||||
|
<select class="form-select select2 datos-cubierta sobrecubierta-item w-auto" id="sobrecubierta-acabado">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row justify-content-center mt-4">
|
||||||
|
<div class="col-auto">
|
||||||
|
<div class="d-flex flex-wrap align-items-center gap-4 ">
|
||||||
|
|
||||||
|
<button id="faja" type="button" class="btn btn-outline-primary custom-toggle mb-4"
|
||||||
|
data-bs-toggle="button">
|
||||||
|
<span class="icon-on">
|
||||||
|
<i class="ri-close-line align-bottom me-1"></i>
|
||||||
|
<span th:text="#{presupuesto.faja}"></span>
|
||||||
|
</span>
|
||||||
|
<span class="icon-off">
|
||||||
|
<i class="ri-add-line align-bottom me-1"></i>
|
||||||
|
<span th:text="#{presupuesto.faja}"></span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div id="div-faja" class="d-flex flex-wrap d-none align-items-start gap-3">
|
||||||
|
<div class="d-flex flex-column me-2">
|
||||||
|
<label for="papel-faja" class="form-label"
|
||||||
|
th:text="#{presupuesto.faja-papel}">Papel</label>
|
||||||
|
<select class="form-select select2 datos-cubierta faja-item w-auto" id="papel-faja">
|
||||||
|
<optgroup th:label="#{presupuesto.estucado}">
|
||||||
|
<option selected value="2" data-papel-id="2" data-gramaje="170"
|
||||||
|
th:text="#{presupuesto.estucado-mate} + ' 170 gr'">Estucado mate 170 gr
|
||||||
|
</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup th:label="#{presupuesto.verjurado}">
|
||||||
|
<option value="1" data-papel-id="18" data-gramaje="160"
|
||||||
|
th:text="#{presupuesto.verjurado-blanco-natural} + ' 160 gr'">Verjurado blanco natural 160 gr
|
||||||
|
170 gr
|
||||||
|
</option>
|
||||||
|
<option value="2" data-papel-id="9" data-gramaje="160"
|
||||||
|
th:text="#{presupuesto.verjurado-ahuesado} + ' 160 gr'">Verjurado ahuesado 160 gr
|
||||||
|
</option>
|
||||||
|
</optgroup>
|
||||||
|
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex flex-column me-2">
|
||||||
|
<label for="alto-faja" class="form-label"
|
||||||
|
th:text="#{presupuesto.faja-alto}">Alto faja</label>
|
||||||
|
<input type="number" class="form-control datos-cubierta faja-item w-auto"
|
||||||
|
id="alto-faja" min="50" max="120" value="80" step="1">
|
||||||
|
<div class="form-text">
|
||||||
|
<p class="mb-0">min: 50 mm</p>
|
||||||
|
<p class="alto-faja-max">max: 120 mm</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex flex-column me-2">
|
||||||
|
<label for="tamanio-solapas-faja" class="form-label"
|
||||||
|
th:text="#{presupuesto.faja-solapas}">Tamaño solapas faja</label>
|
||||||
|
<input type="number" class="form-control datos-cubierta faja-item w-auto"
|
||||||
|
id="tamanio-solapas-faja" min="60" max="120" value="80" step="1">
|
||||||
|
<div class="form-text">
|
||||||
|
<p class="mb-0">min: 60 mm</p>
|
||||||
|
<p class="max-solapa-text">max: 120 mm</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex flex-column me-2">
|
||||||
|
<label for="faja-acabado" class="form-label"
|
||||||
|
th:text="#{presupuesto.acabado}">Acabado</label>
|
||||||
|
<select class="form-select select2 datos-cubierta faja-item w-auto" id="faja-acabado">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- End Ribbon Shape -->
|
||||||
|
|
||||||
|
|
||||||
<div class="d-flex justify-content-between align-items-center mt-4 w-100">
|
<div class="d-flex justify-content-between align-items-center mt-4 w-100">
|
||||||
<button type="button" class="btn btn-light d-flex align-items-center">
|
<button id="btn-prev-cubierta" type="button"
|
||||||
|
class="btn btn-light d-flex align-items-center btn-change-tab-cubierta">
|
||||||
<i class=" ri-arrow-left-circle-line label-icon align-middle fs-16 me-2"></i>
|
<i class=" ri-arrow-left-circle-line label-icon align-middle fs-16 me-2"></i>
|
||||||
<span th:text="#{presupuesto.volver-interior}">Volver a interior</span>
|
<span th:text="#{presupuesto.volver-interior}">Volver a interior</span>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn btn-primary d-flex align-items-center">
|
<button id="btn-next-cubierta" type="button"
|
||||||
<span th:text="#{presupuesto.continuar-extras-libro}">Continuar a extras del libro</span>
|
class="btn btn-primary d-flex align-items-center btn-change-tab-cubierta">
|
||||||
|
<span th:text="#{presupuesto.continuar-seleccion-tirada}">Continuar a selección de tirada</span>
|
||||||
<i class="ri-arrow-right-circle-line fs-16 ms-2"></i>
|
<i class="ri-arrow-right-circle-line fs-16 ms-2"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -23,7 +23,8 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="titulo" class="form-label" th:text="#{presupuesto.titulo}">
|
<label for="titulo" class="form-label" th:text="#{presupuesto.titulo}">
|
||||||
>Título*</label>
|
>Título*</label>
|
||||||
<input type="text" class="form-control datos-generales-data" id="titulo" placeholder="" value="">
|
<input type="text" class="form-control datos-generales-data" id="titulo" placeholder=""
|
||||||
|
value="">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -47,19 +48,23 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-3 mb-1">
|
<div class="col-sm-3 mb-1">
|
||||||
<label for="tirada1" class="form-label" th:text="#{presupuesto.tirada1}">Tirada 1*</label>
|
<label for="tirada1" class="form-label" th:text="#{presupuesto.tirada1}">Tirada 1*</label>
|
||||||
<input type="number" class="form-control datos-generales-data" id="tirada1" placeholder="" value="10">
|
<input type="number" class="form-control datos-generales-data" id="tirada1" placeholder=""
|
||||||
|
value="10">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3 mb-1">
|
<div class="col-sm-3 mb-1">
|
||||||
<label for="tirada2" class="form-label" th:text="#{presupuesto.tirada2}">Tirada 2</label>
|
<label for="tirada2" class="form-label" th:text="#{presupuesto.tirada2}">Tirada 2</label>
|
||||||
<input type="number" class="form-control datos-generales-data" id="tirada2" placeholder="" value="">
|
<input type="number" class="form-control datos-generales-data" id="tirada2" placeholder=""
|
||||||
|
value="">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3 mb-1">
|
<div class="col-sm-3 mb-1">
|
||||||
<label for="tirada3" class="form-label" th:text="#{presupuesto.tirada3}">Tirada 3</label>
|
<label for="tirada3" class="form-label" th:text="#{presupuesto.tirada3}">Tirada 3</label>
|
||||||
<input type="number" class="form-control datos-generales-data" id="tirada3" placeholder="" value="">
|
<input type="number" class="form-control datos-generales-data" id="tirada3" placeholder=""
|
||||||
|
value="">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3 mb-1">
|
<div class="col-sm-3 mb-1">
|
||||||
<label for="tirada4" class="form-label" th:text="#{presupuesto.tirada4}">Tirada 4</label>
|
<label for="tirada4" class="form-label" th:text="#{presupuesto.tirada4}">Tirada 4</label>
|
||||||
<input type="number" class="form-control datos-generales-data" id="tirada4" placeholder="" value="">
|
<input type="number" class="form-control datos-generales-data" id="tirada4" placeholder=""
|
||||||
|
value="">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-muted" th:text="#{presupuesto.tiradasPODnoPOD(${pod})}">
|
<p class="text-muted" th:text="#{presupuesto.tiradasPODnoPOD(${pod})}">
|
||||||
@ -95,20 +100,21 @@
|
|||||||
<div class="row justify-content-center div-formato-personalizado d-none">
|
<div class="row justify-content-center div-formato-personalizado d-none">
|
||||||
<div class="col-3 col-sm-3 mb-1">
|
<div class="col-3 col-sm-3 mb-1">
|
||||||
<label for="ancho" class="form-label" th:text="#{presupuesto.ancho}">Ancho (mm)</label>
|
<label for="ancho" class="form-label" th:text="#{presupuesto.ancho}">Ancho (mm)</label>
|
||||||
<input type="number" class="form-control datos-generales-data" id="ancho" name="ancho" value="210"
|
<input type="number" class="form-control datos-generales-data" id="ancho" name="ancho"
|
||||||
th:attr="min=${ancho_alto_min}, max=${ancho_alto_max}">
|
value="210" th:attr="min=${ancho_alto_min}, max=${ancho_alto_max}">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-3 col-sm-3 mb-1">
|
<div class="col-3 col-sm-3 mb-1">
|
||||||
<label for="alto" class="form-label" th:text="#{presupuesto.alto}">Alto (mm)</label>
|
<label for="alto" class="form-label" th:text="#{presupuesto.alto}">Alto (mm)</label>
|
||||||
<input type="number" class="form-control datos-generales-data" id="alto" name="alto" value="297"
|
<input type="number" class="form-control datos-generales-data" id="alto" name="alto"
|
||||||
th:attr="min=${ancho_alto_min}, max=${ancho_alto_max}">
|
value="297" th:attr="min=${ancho_alto_min}, max=${ancho_alto_max}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row justify-content-center mb-3">
|
<div class="row justify-content-center mb-3">
|
||||||
<div class="col-sm-4 d-flex justify-content-center">
|
<div class="col-sm-4 d-flex justify-content-center">
|
||||||
<div class="form-check form-switch form-switch-custom form-switch-primary mb-3">
|
<div class="form-check form-switch form-switch-custom form-switch-primary mb-3">
|
||||||
<input type="checkbox" class="form-check-input form-switch-custom-primary datos-generales-data"
|
<input type="checkbox"
|
||||||
|
class="form-check-input form-switch-custom-primary datos-generales-data"
|
||||||
id="formato-personalizado" name="formato-personalizado">
|
id="formato-personalizado" name="formato-personalizado">
|
||||||
<label for="formato-personalizado" class="form-label"
|
<label for="formato-personalizado" class="form-label"
|
||||||
th:text="#{presupuesto.formato-personalizado}">
|
th:text="#{presupuesto.formato-personalizado}">
|
||||||
@ -125,8 +131,8 @@
|
|||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
<label for="paginas-negro" class="form-label" th:text="#{presupuesto.paginas-negro}">Páginas
|
<label for="paginas-negro" class="form-label" th:text="#{presupuesto.paginas-negro}">Páginas
|
||||||
Negro</label>
|
Negro</label>
|
||||||
<input type="number" step="2" class="form-control paginas datos-generales-data" id="paginas-negro"
|
<input type="number" step="2" class="form-control paginas datos-generales-data"
|
||||||
name="paginas-negro" value="0">
|
id="paginas-negro" name="paginas-negro" value="0">
|
||||||
<div class="form-text" th:text="#{presupuesto.siempre-pares}">
|
<div class="form-text" th:text="#{presupuesto.siempre-pares}">
|
||||||
Siempre deben ser pares</div>
|
Siempre deben ser pares</div>
|
||||||
</div>
|
</div>
|
||||||
@ -138,8 +144,8 @@
|
|||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
<label for="paginas-color" class="form-label" th:text="#{presupuesto.paginas-color}">Páginas
|
<label for="paginas-color" class="form-label" th:text="#{presupuesto.paginas-color}">Páginas
|
||||||
Color</label>
|
Color</label>
|
||||||
<input type="number" step="2" class="form-control paginas datos-generales-data" id="paginas-color"
|
<input type="number" step="2" class="form-control paginas datos-generales-data"
|
||||||
name="paginas-color" value="32">
|
id="paginas-color" name="paginas-color" value="32">
|
||||||
<div class="form-text" th:text="#{presupuesto.siempre-pares}">
|
<div class="form-text" th:text="#{presupuesto.siempre-pares}">
|
||||||
Siempre deben ser pares</div>
|
Siempre deben ser pares</div>
|
||||||
</div>
|
</div>
|
||||||
@ -156,7 +162,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="div-posicion-paginas-color" class="row justify-content-center">
|
<div id="div-posicion-paginas-color" class="row justify-content-center">
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-6">
|
||||||
<label for="posicionPaginasColor" class="form-label" th:text="#{presupuesto.paginas-posicion}">
|
<label for="posicionPaginasColor" class="form-label" th:text="#{presupuesto.paginas-posicion}">
|
||||||
Posición páginas color
|
Posición páginas color
|
||||||
</label>
|
</label>
|
||||||
@ -189,7 +195,8 @@
|
|||||||
<div class="d-flex flex-wrap justify-content-center gap-3 imagen-container-group">
|
<div class="d-flex flex-wrap justify-content-center gap-3 imagen-container-group">
|
||||||
|
|
||||||
<!-- Opción: Fresado -->
|
<!-- Opción: Fresado -->
|
||||||
<div class="tipo-libro image-container imagen-selector selected datos-generales-data" id="fresado">
|
<div class="tipo-libro image-container imagen-selector selected datos-generales-data"
|
||||||
|
th:attr="data-summary-text=#{presupuesto.fresado}" id="fresado">
|
||||||
<input type="radio" name="tipoEncuadernacion" value="fresado" hidden>
|
<input type="radio" name="tipoEncuadernacion" value="fresado" hidden>
|
||||||
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/fresado.png"
|
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/fresado.png"
|
||||||
alt="Fresado" />
|
alt="Fresado" />
|
||||||
@ -199,7 +206,8 @@
|
|||||||
|
|
||||||
|
|
||||||
<!-- Opción: Cosido -->
|
<!-- Opción: Cosido -->
|
||||||
<div class="tipo-libro image-container imagen-selector datos-generales-data" id="cosido">
|
<div class="tipo-libro image-container imagen-selector datos-generales-data"
|
||||||
|
th:attr="data-summary-text=#{presupuesto.cosido}" id="cosido">
|
||||||
<input type="radio" name="tipoEncuadernacion" value="cosido" hidden>
|
<input type="radio" name="tipoEncuadernacion" value="cosido" hidden>
|
||||||
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/cosido.png"
|
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/cosido.png"
|
||||||
alt="Cosido" />
|
alt="Cosido" />
|
||||||
@ -209,7 +217,8 @@
|
|||||||
|
|
||||||
|
|
||||||
<!-- Opción: Grapado -->
|
<!-- Opción: Grapado -->
|
||||||
<div class="tipo-libro image-container imagen-selector datos-generales-data" id="grapado">
|
<div class="tipo-libro image-container imagen-selector datos-generales-data"
|
||||||
|
th:attr="data-summary-text=#{presupuesto.grapado}" id="grapado">
|
||||||
<input type="radio" name="tipoEncuadernacion" value="grapado" hidden>
|
<input type="radio" name="tipoEncuadernacion" value="grapado" hidden>
|
||||||
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/grapado.png"
|
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/grapado.png"
|
||||||
alt="Grapado" />
|
alt="Grapado" />
|
||||||
@ -218,7 +227,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Opción: Espiral -->
|
<!-- Opción: Espiral -->
|
||||||
<div class="tipo-libro image-container imagen-selector datos-generales-data" id="espiral">
|
<div class="tipo-libro image-container imagen-selector datos-generales-data"
|
||||||
|
th:attr="data-summary-text=#{presupuesto.espiral}" id="espiral">
|
||||||
<input type="radio" name="tipoEncuadernacion" value="espiral" hidden>
|
<input type="radio" name="tipoEncuadernacion" value="espiral" hidden>
|
||||||
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/espiral.png"
|
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/espiral.png"
|
||||||
alt="Espiral" />
|
alt="Espiral" />
|
||||||
@ -227,7 +237,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Opción: Wire-O -->
|
<!-- Opción: Wire-O -->
|
||||||
<div class="tipo-libro image-container imagen-selector datos-generales-data" id="wireo">
|
<div class="tipo-libro image-container imagen-selector datos-generales-data"
|
||||||
|
th:attr="data-summary-text=#{presupuesto.wire-o}" id="wireo">
|
||||||
<input type="radio" name="tipoEncuadernacion" value="wireo" hidden>
|
<input type="radio" name="tipoEncuadernacion" value="wireo" hidden>
|
||||||
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/wire-o.png"
|
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/wire-o.png"
|
||||||
alt="Wire-O" />
|
alt="Wire-O" />
|
||||||
|
|||||||
@ -0,0 +1,31 @@
|
|||||||
|
<div class="animate-fadeInUpBounce">
|
||||||
|
|
||||||
|
<!-- Ribbon Shape -->
|
||||||
|
<div class="card ribbon-box border shadow-none mb-lg-0 material-shadow">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="ribbon ribbon-primary ribbon-shape" th:text="#{presupuesto.extras}">Extras
|
||||||
|
</div>
|
||||||
|
<h5 class="fs-14 text-end" th:text="#{presupuesto.extras-descripcion}">Seleccione los extras
|
||||||
|
que desea añadir a su presupuesto.</h5>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ribbon-content mt-4">
|
||||||
|
<div id="div-extras" class="hstack gap-2 justify-content-center flex-wrap">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- End Ribbon Shape -->
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-between align-items-center mt-4 w-100">
|
||||||
|
<button id="btn-prev-extras" type="button"
|
||||||
|
class="btn btn-light d-flex align-items-center btn-change-tab-extras">
|
||||||
|
<i class=" ri-arrow-left-circle-line label-icon align-middle fs-16 me-2"></i>
|
||||||
|
<span th:text="#{presupuesto.volver-seleccion-tirada}">Volver a selección de tirada</span>
|
||||||
|
</button>
|
||||||
|
<button id="btn-next-extras" type="button"
|
||||||
|
class="btn btn-primary d-flex align-items-center btn-change-tab-extras">
|
||||||
|
<span><b th:text="#{presupuesto.calcular-presupuesto}">Calcular presupuesto</b></span>
|
||||||
|
<i class="ri-arrow-right-circle-line fs-16 ms-2"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -2,9 +2,9 @@
|
|||||||
<!-- Ribbon Shape -->
|
<!-- Ribbon Shape -->
|
||||||
<div class="card ribbon-box border shadow-none mb-lg-0 material-shadow">
|
<div class="card ribbon-box border shadow-none mb-lg-0 material-shadow">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="ribbon ribbon-primary ribbon-shape" th:text="#{presupuesto.tipo-encuadernacion}">Tipo de impresión
|
<div class="ribbon ribbon-primary ribbon-shape" th:text="#{presupuesto.tipo-interior}">Tipo de impresión
|
||||||
</div>
|
</div>
|
||||||
<h5 class="fs-14 text-end" th:text="#{presupuesto.tipo-encuadernacion-descripcion}">Elija entre calidad estándar
|
<h5 class="fs-14 text-end" th:text="#{presupuesto.tipo-interior-descripcion}">Elija entre calidad estándar
|
||||||
o premium</h5>
|
o premium</h5>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -36,37 +36,6 @@
|
|||||||
|
|
||||||
<div id="div-papel-interior" class="row justify-content-center imagen-container-group">
|
<div id="div-papel-interior" class="row justify-content-center imagen-container-group">
|
||||||
|
|
||||||
<div id="offset-blanco" data-sk-id="3" class="image-container imagen-selector selected">
|
|
||||||
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/offset-blanco.png"
|
|
||||||
alt="">
|
|
||||||
<label for="titulo" class="form-label" th:text="#{presupuesto.offset-blanco}">
|
|
||||||
Offset Blanco
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="offset-ahuesado" data-sk-id="4" class="image-container imagen-selector">
|
|
||||||
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/offset-ahuesado.png"
|
|
||||||
alt="">
|
|
||||||
<label class="form-label" th:text="#{presupuesto.offset-ahuesado}">
|
|
||||||
Offset Ahuesado
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="offset-ahuesado-volumen" data-sk-id="6" class="image-container imagen-selector">
|
|
||||||
<img class="image-presupuesto"
|
|
||||||
src="/assets/images/imprimelibros/presupuestador/offset-ahuesado-volumen.png" alt="">
|
|
||||||
<label class="form-label" th:text="#{presupuesto.offset-ahuesado-volumen}">
|
|
||||||
Offset Ahuesado Volumen
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="estucado-mate" data-sk-id="2" class="image-container imagen-selector">
|
|
||||||
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/estucado-mate.png"
|
|
||||||
alt="">
|
|
||||||
<label class="form-label" th:text="#{presupuesto.estucado-mate}">
|
|
||||||
Estucado Mate
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -83,32 +52,7 @@
|
|||||||
|
|
||||||
<div class="ribbon-content mt-4">
|
<div class="ribbon-content mt-4">
|
||||||
<div id="div-gramaje-interior" class="hstack gap-2 justify-content-center flex-wrap">
|
<div id="div-gramaje-interior" class="hstack gap-2 justify-content-center flex-wrap">
|
||||||
<input type="radio" class="btn-check" data-gramaje="70" id="gramaje-70" name="gramaje-interior">
|
|
||||||
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-70">70</label>
|
|
||||||
|
|
||||||
<input type="radio" class="btn-check" data-gramaje="80" id="gramaje-80" name="gramaje-interior">
|
|
||||||
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-80">80</label>
|
|
||||||
|
|
||||||
<input type="radio" class="btn-check" data-gramaje="90" id="gramaje-90" checked name="gramaje-interior">
|
|
||||||
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-90">90</label>
|
|
||||||
|
|
||||||
<input type="radio" class="btn-check" data-gramaje="100" id="gramaje-100" name="gramaje-interior">
|
|
||||||
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-100">100</label>
|
|
||||||
|
|
||||||
<input type="radio" class="btn-check" data-gramaje="115" id="gramaje-115" name="gramaje-interior">
|
|
||||||
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-115">115</label>
|
|
||||||
|
|
||||||
<input type="radio" class="btn-check" data-gramaje="120" id="gramaje-120" name="gramaje-interior">
|
|
||||||
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-120">120</label>
|
|
||||||
|
|
||||||
<input type="radio" class="btn-check" data-gramaje="135" id="gramaje-135" name="gramaje-interior">
|
|
||||||
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-135">135</label>
|
|
||||||
|
|
||||||
<input type="radio" class="btn-check" data-gramaje="150" id="gramaje-150" name="gramaje-interior">
|
|
||||||
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-150">150</label>
|
|
||||||
|
|
||||||
<input type="radio" class="btn-check" data-gramaje="170" id="gramaje-170" name="gramaje-interior">
|
|
||||||
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-170">170</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -0,0 +1,41 @@
|
|||||||
|
<div class="animate-fadeInUpBounce">
|
||||||
|
|
||||||
|
<!-- Ribbon Shape -->
|
||||||
|
<div class="card ribbon-box border shadow-none mb-lg-0 material-shadow">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="ribbon ribbon-primary ribbon-shape" th:text="#{presupuesto.seleccion-tirada}">Seleccion de
|
||||||
|
tirada
|
||||||
|
</div>
|
||||||
|
<h5 class="fs-14 text-end" th:text="#{presupuesto.seleccion-tirada-descripcion}">Seleccione la tirada
|
||||||
|
deseada</h5>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ribbon-content mt-4">
|
||||||
|
<div id="div-tiradas-error"
|
||||||
|
class="d-flex justify-content-center mt-4 w-100 d-none">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="div-tiradas"
|
||||||
|
class="row row-cols-1 row-cols-sm-2 row-cols-lg-4 g-4 justify-content-center align-items-stretch mx-auto mb-4"
|
||||||
|
style="max-width:1120px" th:data-per-unit="#{presupuesto.precio-unidad}"
|
||||||
|
th:data-total="#{presupuesto.total}" th:data-select="#{presupuesto.seleccionar-tirada}"
|
||||||
|
th:data-selected="#{presupuesto.tirada-seleccionada}" th:data-units="#{presupuesto.unidades}">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- End Ribbon Shape -->
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-between align-items-center mt-4 w-100">
|
||||||
|
<button id="btn-prev-seleccion-tirada" type="button"
|
||||||
|
class="btn btn-light d-flex align-items-center btn-change-tab-seleccion-tirada">
|
||||||
|
<i class=" ri-arrow-left-circle-line label-icon align-middle fs-16 me-2"></i>
|
||||||
|
<span th:text="#{presupuesto.volver-cubierta}">Volver a diseño de cubierta</span>
|
||||||
|
</button>
|
||||||
|
<button id="btn-next-seleccion-tirada" type="button"
|
||||||
|
class="btn btn-primary d-flex align-items-center btn-change-tab-seleccion-tirada">
|
||||||
|
<span><b th:text="#{presupuesto.continuar-extras-libro}">Continuar a extras del libro</b></span>
|
||||||
|
<i class="ri-arrow-right-circle-line fs-16 ms-2"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,214 @@
|
|||||||
|
<div class="col-xl-3">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<div class="d-flex">
|
||||||
|
<div class="flex-grow-1">
|
||||||
|
<h5 th:text="#{presupuesto.resumen-presupuesto}">Resumen presupuesto</h5>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive table-card">
|
||||||
|
<table id="summary-datos-generales" class="table table-responsive align-middle mb-0">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th th:text="#{presupuesto.resumen-libro}" scope="col" colspan="2">Libro</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="align-items-center">
|
||||||
|
<span th:text="#{presupuesto.resumen-encuadernacion}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-encuadernacion" class="text-end">Fresado</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.formato}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-formato" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.paginas}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-paginas" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="ps-3">
|
||||||
|
<span class="ps-3" th:text="#{presupuesto.paginas-negro}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-paginas-negro" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="ps-3">
|
||||||
|
<span class="ps-3" th:text="#{presupuesto.paginas-color}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-paginas-color" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table id="summary-interior" class="table table-responsive align-middle mb-0 d-none">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th th:text="#{presupuesto.interior}" scope="col" colspan="2">Interior</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.tipo-interior}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-tipo-interior" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.papel-interior}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-papel-interior" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.gramaje-interior}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-gramaje-interior" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table id="summary-cubierta" class="table table-responsive align-middle mb-0 d-none">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th th:text="#{presupuesto.cubierta}" scope="col" colspan="2">Cubierta</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.tipo-cubierta}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-tapa-cubierta" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="tapa-blanda-row d-none">
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.solapas}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-cubierta-solapas" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="tapa-blanda-row d-none">
|
||||||
|
<td class="ps-3">
|
||||||
|
<span class="ps-3" th:text="#{presupuesto.tamanio-solapa}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-tamanio-solapa" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="tapa-blanda-row d-none">
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.impresion-cubierta}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-impresion-cubierta" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="tapa-dura-row d-none">
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.papel-guardas}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-papel-guardas" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="tapa-dura-row d-none">
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.guardas-impresas}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-guardas-impresas" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="tapa-dura-row d-none">
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.cabezada}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-cabezada" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.papel-cubierta}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-papel-cubierta" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.gramaje-cubierta}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-gramaje-cubierta" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.acabado}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-acabado-cubierta" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table id="summary-sobrecubierta" class="table table-responsive align-middle mb-0 d-none">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th th:text="#{presupuesto.sobrecubierta}" scope="col" colspan="2">Sobrecubierta</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.papel-gramaje}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-sobrecubierta-papel-gramaje" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.tamanio-solapa}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-sobrecubierta-tamanio-solapa" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.acabado}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-sobrecubierta-acabado" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table id="summary-faja" class="table table-responsive align-middle mb-0 d-none">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th th:text="#{presupuesto.faja}" scope="col" colspan="2">Faja</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.papel-gramaje}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-faja-papel-gramaje" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.faja-alto}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-faja-alto-faja" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.tamanio-solapa}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-faja-tamanio-solapa" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span th:text="#{presupuesto.acabado}"></span>
|
||||||
|
</td>
|
||||||
|
<td id="summary-faja-acabado" class="text-end"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- end card body -->
|
||||||
|
</div>
|
||||||
|
<!-- end card -->
|
||||||
|
</div>
|
||||||
|
<!-- end col -->
|
||||||
@ -1,6 +1,6 @@
|
|||||||
<div th:fragment="presupuestador">
|
<div th:fragment="presupuestador">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xl-8">
|
<div class="col-xl-9">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body checkout-tab">
|
<div class="card-body checkout-tab">
|
||||||
|
|
||||||
@ -10,15 +10,15 @@
|
|||||||
<ul class="nav nav-pills nav-justified custom-nav" role="tablist">
|
<ul class="nav nav-pills nav-justified custom-nav" role="tablist">
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<button class="nav-link fs-15 p-3 active" id="pills-general-data-tab"
|
<button class="nav-link fs-15 p-3 active" id="pills-general-data-tab"
|
||||||
data-bs-toggle="pill" data-bs-target="#pills-general-data" type="button"
|
data-bs-target="#pills-general-data" type="button" role="tab"
|
||||||
role="tab" aria-controls="pills-general-data" aria-selected="true">
|
aria-controls="pills-general-data" aria-selected="true">
|
||||||
<i
|
<i
|
||||||
class="ri-information-line fs-16 p-2 bg-soft-primary text-primary rounded-circle align-middle me-2"></i>
|
class="ri-information-line fs-16 p-2 bg-soft-primary text-primary rounded-circle align-middle me-2"></i>
|
||||||
<label th:text="#{presupuesto.datos-generales}">Datos Generales</label>
|
<label th:text="#{presupuesto.datos-generales}">Datos Generales</label>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<button class="nav-link fs-15 p-3" id="pills-inside-tab" data-bs-toggle="pill"
|
<button class="nav-link fs-15 p-3" id="pills-inside-tab"
|
||||||
data-bs-target="#pills-inside" type="button" role="tab"
|
data-bs-target="#pills-inside" type="button" role="tab"
|
||||||
aria-controls="pills-inside" aria-selected="false">
|
aria-controls="pills-inside" aria-selected="false">
|
||||||
<i
|
<i
|
||||||
@ -27,7 +27,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<button class="nav-link fs-15 p-3" id="pills-cover-tab" data-bs-toggle="pill"
|
<button class="nav-link fs-15 p-3" id="pills-cover-tab"
|
||||||
data-bs-target="#pills-cover" type="button" role="tab"
|
data-bs-target="#pills-cover" type="button" role="tab"
|
||||||
aria-controls="pills-cover" aria-selected="false">
|
aria-controls="pills-cover" aria-selected="false">
|
||||||
<i
|
<i
|
||||||
@ -36,9 +36,18 @@
|
|||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<button class="nav-link fs-15 p-3" id="pills-shipping-tab" data-bs-toggle="pill"
|
<button class="nav-link fs-15 p-3" id="pills-seleccion-tirada-tab"
|
||||||
data-bs-target="#pills-shipping" type="button" role="tab"
|
data-bs-target="#pills-seleccion-tirada" type="button" role="tab"
|
||||||
aria-controls="pills-shipping" aria-selected="false">
|
aria-controls="pills-seleccion-tirada" aria-selected="false">
|
||||||
|
<i
|
||||||
|
class="ri-add-box-line fs-16 p-2 bg-soft-primary text-primary rounded-circle align-middle me-2"></i>
|
||||||
|
<label th:text="#{presupuesto.seleccion-tirada}">Seleccion de tirada</label>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<button class="nav-link fs-15 p-3" id="pills-extras-tab"
|
||||||
|
data-bs-target="#pills-extras" type="button" role="tab"
|
||||||
|
aria-controls="pills-extras" aria-selected="false">
|
||||||
<i
|
<i
|
||||||
class="ri-add-box-line fs-16 p-2 bg-soft-primary text-primary rounded-circle align-middle me-2"></i>
|
class="ri-add-box-line fs-16 p-2 bg-soft-primary text-primary rounded-circle align-middle me-2"></i>
|
||||||
<label th:text="#{presupuesto.extras}">Extras</label>
|
<label th:text="#{presupuesto.extras}">Extras</label>
|
||||||
@ -51,24 +60,43 @@
|
|||||||
<div class="tab-pane fade show active" id="pills-general-data" role="tabpanel"
|
<div class="tab-pane fade show active" id="pills-general-data" role="tabpanel"
|
||||||
aria-labelledby="pills-general-data-tab">
|
aria-labelledby="pills-general-data-tab">
|
||||||
|
|
||||||
<div th:include="~{imprimelibros/presupuestos/presupuestador-items/_datos-generales.html}"></div>
|
<div
|
||||||
|
th:include="~{imprimelibros/presupuestos/presupuestador-items/_datos-generales.html}">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- end tab pane -->
|
<!-- end tab pane -->
|
||||||
|
|
||||||
<div class="tab-pane fade" id="pills-inside" role="tabpanel"
|
<div class="tab-pane fade" id="pills-inside" role="tabpanel"
|
||||||
aria-labelledby="pills-inside-tab">
|
aria-labelledby="pills-inside-tab">
|
||||||
|
|
||||||
<div th:include="~{imprimelibros/presupuestos/presupuestador-items/_interior.html}"></div>
|
<div th:include="~{imprimelibros/presupuestos/presupuestador-items/_interior.html}">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- end tab pane -->
|
<!-- end tab pane -->
|
||||||
|
|
||||||
<div class="tab-pane fade" id="pills-cover" role="tabpanel"
|
<div class="tab-pane fade" id="pills-cover" role="tabpanel"
|
||||||
aria-labelledby="pills-cover-tab">
|
aria-labelledby="pills-cover-tab">
|
||||||
|
|
||||||
<div th:include="~{imprimelibros/presupuestos/presupuestador-items/_cubierta.html}"></div>
|
<div th:include="~{imprimelibros/presupuestos/presupuestador-items/_cubierta.html}">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- end tab pane -->
|
<!-- end tab pane -->
|
||||||
|
|
||||||
|
<div class="tab-pane fade" id="pills-seleccion-tirada" role="tabpanel"
|
||||||
|
aria-labelledby="pills-seleccion-tirada-tab">
|
||||||
|
|
||||||
|
<div
|
||||||
|
th:include="~{imprimelibros/presupuestos/presupuestador-items/_seleccion-tirada.html}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- end tab pane -->
|
||||||
|
|
||||||
|
<div class="tab-pane fade" id="pills-extras" role="tabpanel"
|
||||||
|
aria-labelledby="pills-extras-tab">
|
||||||
|
|
||||||
|
<div th:include="~{imprimelibros/presupuestos/presupuestador-items/_extras.html}"></div>
|
||||||
|
</div>
|
||||||
|
<!-- end tab pane -->
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- end tab content -->
|
<!-- end tab content -->
|
||||||
@ -80,103 +108,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- end col -->
|
<!-- end col -->
|
||||||
|
|
||||||
<!-- Order Summary -->
|
<!-- Summary -->
|
||||||
<div class="col-xl-4">
|
<div th:replace="~{imprimelibros/presupuestos/presupuestador-items/_summary.html}"></div>
|
||||||
<div class="card">
|
|
||||||
<div class="card-header">
|
|
||||||
<div class="d-flex">
|
|
||||||
<div class="flex-grow-1">
|
|
||||||
<h5 class="card-title mb-0">Order Summary</h5>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="table-responsive table-card">
|
|
||||||
<table class="table table-borderless align-middle mb-0">
|
|
||||||
<thead class="table-light text-muted">
|
|
||||||
<tr>
|
|
||||||
<th style="width: 90px;" scope="col">Product</th>
|
|
||||||
<th scope="col">Product Info</th>
|
|
||||||
<th scope="col" class="text-end">Price</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<div class="avatar-md bg-light rounded p-1">
|
|
||||||
<img src="/assets/images/products/img-8.png" alt=""
|
|
||||||
class="img-fluid d-block">
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<h5 class="fs-14"><a href="/apps-ecommerce-product-details"
|
|
||||||
class="text-dark">Sweatshirt for Men (Pink)</a></h5>
|
|
||||||
<p class="text-muted mb-0">$ 119.99 x 2</p>
|
|
||||||
</td>
|
|
||||||
<td class="text-end">$ 239.98</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<div class="avatar-md bg-light rounded p-1">
|
|
||||||
<img src="/assets/images/products/img-7.png" alt=""
|
|
||||||
class="img-fluid d-block">
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<h5 class="fs-14"><a href="/apps-ecommerce-product-details"
|
|
||||||
class="text-dark">Noise Evolve Smartwatch</a></h5>
|
|
||||||
<p class="text-muted mb-0">$ 94.99 x 1</p>
|
|
||||||
</td>
|
|
||||||
<td class="text-end">$ 94.99</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<div class="avatar-md bg-light rounded p-1">
|
|
||||||
<img src="/assets/images/products/img-3.png" alt=""
|
|
||||||
class="img-fluid d-block">
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<h5 class="fs-14"><a href="/apps-ecommerce-product-details"
|
|
||||||
class="text-dark">350 ml Glass Grocery Container</a></h5>
|
|
||||||
<p class="text-muted mb-0">$ 24.99 x 1</p>
|
|
||||||
</td>
|
|
||||||
<td class="text-end">$ 24.99</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="fw-semibold" colspan="2">Sub Total :</td>
|
|
||||||
<td class="fw-semibold text-end">$ 359.96</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="2">Discount <span class="text-muted">(VELZON15)</span> : </td>
|
|
||||||
<td class="text-end">- $ 50.00</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="2">Shipping Charge :</td>
|
|
||||||
<td class="text-end">$ 24.99</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="2">Estimated Tax (12%): </td>
|
|
||||||
<td class="text-end">$ 18.20</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="table-active">
|
|
||||||
<th colspan="2">Total (USD) :</th>
|
|
||||||
<td class="text-end">
|
|
||||||
<span class="fw-semibold">
|
|
||||||
$353.15
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- end card body -->
|
|
||||||
</div>
|
|
||||||
<!-- end card -->
|
|
||||||
</div>
|
|
||||||
<!-- end col -->
|
|
||||||
</div>
|
</div>
|
||||||
<!--end row-->
|
<!--end row-->
|
||||||
</div>
|
</div>
|
||||||
@ -1,13 +0,0 @@
|
|||||||
package com.imprimelibros.erp;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
class ErpApplicationTests {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void contextLoads() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
82
src/test/java/com/imprimelibros/erp/skApiClientTest.java
Normal file
82
src/test/java/com/imprimelibros/erp/skApiClientTest.java
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package com.imprimelibros.erp;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
import com.imprimelibros.erp.externalApi.skApiClient;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
class skApiClientTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private skApiClient apiClient;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPrecioCalculadoDevuelveJson() {
|
||||||
|
String resultado = this.test();
|
||||||
|
|
||||||
|
System.out.println("📦 Resultado de la API:");
|
||||||
|
System.out.println(resultado);
|
||||||
|
|
||||||
|
assertNotNull(resultado, "El resultado no debe ser null");
|
||||||
|
assertTrue(resultado.trim().startsWith("{"), "El resultado debe comenzar con { (JSON)");
|
||||||
|
assertTrue(resultado.trim().endsWith("}"), "El resultado debe terminar con } (JSON)");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String test() {
|
||||||
|
|
||||||
|
Map<String, Object> tamanio = Map.of("ancho", 148, "alto", 210);
|
||||||
|
Map<String, Object> interior = Map.of("papelInterior", "3", "gramajeInterior", 90);
|
||||||
|
Map<String, Object> cubierta = Map.of(
|
||||||
|
"tipoCubierta", "tapaBlanda",
|
||||||
|
"papelCubierta", "2",
|
||||||
|
"gramajeCubierta", 300,
|
||||||
|
"carasImpresion", 2,
|
||||||
|
"solapas", 0,
|
||||||
|
"acabado", "1",
|
||||||
|
"cabezada", "WHI",
|
||||||
|
"lomoRedondo", 0);
|
||||||
|
|
||||||
|
// ✅ Corregido: usamos HashMap porque Map.of no permite null
|
||||||
|
Map<String, Object> sobrecubierta = new HashMap<>();
|
||||||
|
sobrecubierta.put("papel", "2");
|
||||||
|
sobrecubierta.put("gramaje", 170);
|
||||||
|
sobrecubierta.put("solapas", 80);
|
||||||
|
sobrecubierta.put("acabado", null);
|
||||||
|
|
||||||
|
Map<String, Object> servicios = Map.of(
|
||||||
|
"retractilado", 0,
|
||||||
|
"retractilado5", 0,
|
||||||
|
"ferro", 0,
|
||||||
|
"ferroDigital", 0,
|
||||||
|
"marcapaginas", 0,
|
||||||
|
"prototipo", 0);
|
||||||
|
|
||||||
|
Map<String, Object> body = new HashMap<>();
|
||||||
|
body.put("tirada", List.of(50, 100, 150, 500));
|
||||||
|
body.put("tamanio", tamanio);
|
||||||
|
body.put("tipo", "fresado");
|
||||||
|
body.put("clienteId", 1284);
|
||||||
|
body.put("isColor", 1);
|
||||||
|
body.put("isHq", 0);
|
||||||
|
body.put("paginas", 112);
|
||||||
|
body.put("paginasColor", 80);
|
||||||
|
body.put("paginasCuadernillo", 32);
|
||||||
|
body.put("interior", interior);
|
||||||
|
body.put("cubierta", cubierta);
|
||||||
|
body.put("sobrecubierta", sobrecubierta);
|
||||||
|
body.put("guardas", null);
|
||||||
|
body.put("faja", false);
|
||||||
|
body.put("servicios", servicios);
|
||||||
|
|
||||||
|
return apiClient.getPrice(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user