trabajando en resumen

This commit is contained in:
Jaime Jiménez
2025-08-24 21:02:42 +02:00
parent baf4cb6ae5
commit 6b883ffab2
18 changed files with 1659 additions and 226 deletions

View File

@ -13,7 +13,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Map;
import java.util.HashMap;
import java.util.function.Supplier;
import java.util.List;
@Service
public class skApiClient {
@ -30,7 +29,6 @@ public class skApiClient {
}
public String getPrice(Map<String, Object> requestBody) {
return performWithRetry(() -> {
String url = this.skApiUrl + "api/calcular";
@ -46,35 +44,43 @@ public class skApiClient {
entity,
String.class);
return response.getBody();
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) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setBearerAuth(authService.getToken());
Map<String, Object> request = new HashMap<>(requestBody);
Map<String, Object> data = new HashMap<>();
try {
String jsonResponse = performWithRetry(() -> {
String url = this.skApiUrl + "api/calcular-solapas";
data.put("clienteId", request.get("clienteId"));
data.put("tamanio", (Map<String, Object>) request.get("tamanio"));
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", request.get("paginas"));
data.put("paginasColor", request.get("paginasColor"));
data.put("paginas", requestBody.get("paginas"));
data.put("paginasColor", requestBody.get("paginasColor"));
data.put("papelInteriorDiferente", 0);
data.put("paginasCuadernillo", request.get("paginasCuadernillo"));
data.put("tipo", request.get("tipo"));
data.put("isColor", request.get("isColor"));
data.put("isHq", request.get("isHq"));
data.put("interior", request.get("interior"));
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);
@ -88,19 +94,19 @@ public class skApiClient {
});
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);
}
int solapas = root.get("data").asInt();
return solapas;
return root.get("data").asInt();
} catch (JsonProcessingException e) {
// No se puede calcular el interior, por lo que las solapas seran el 80% del
// ancho
Map<String, Object> tamanio = (Map<String, Object>)data.get("tamanio");
// 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: " + data);
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
@ -108,6 +114,38 @@ public class skApiClient {
}
}
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
******************/

View File

@ -14,7 +14,7 @@ import jakarta.persistence.*;
@Tamanio(groups = PresupuestoValidationGroups.DatosGenerales.class)
@Entity
@Table(name = "presupuesto")
public class Presupuesto {
public class Presupuesto implements Cloneable{
public enum TipoEncuadernacion {
fresado, cosido, grapado, espiral, wireo
@ -28,6 +28,15 @@ public class Presupuesto {
tapaBlanda, tapaDura, tapaDuraLomoRedondo
}
@Override
public Presupuesto clone() {
try {
return (Presupuesto) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ -59,6 +68,9 @@ public class Presupuesto {
@Column(name = "tirada4")
private Integer tirada4;
@Column(name = "selected_tirada")
private Integer selectedTirada;
@NotNull(message = "{presupuesto.errores.ancho}", groups = PresupuestoValidationGroups.DatosGenerales.class)
@Column(name = "ancho")
private Integer ancho;
@ -134,10 +146,32 @@ public class Presupuesto {
@NotNull(message = "{presupuesto.errores.acabado-cubierta}", groups = PresupuestoValidationGroups.Cubierta.class)
@Column(name = "acabado")
private Integer acabado = 1;
// Getters y Setters
@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() {
return autor;
}
@ -382,4 +416,101 @@ public class Presupuesto {
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;
}
}

View File

@ -6,16 +6,18 @@ import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.List;
import java.util.Collections;
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.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;
@ -30,6 +32,9 @@ public class PresupuestoController {
@Autowired
protected skApiClient apiClient;
@Autowired
protected MessageSource messageSource;
@PostMapping("/public/validar/datos-generales")
public ResponseEntity<?> validarDatosGenerales(
@Validated(PresupuestoValidationGroups.DatosGenerales.class) Presupuesto presupuesto,
@ -80,6 +85,63 @@ public class PresupuestoController {
return ResponseEntity.ok(resultado);
}
@PostMapping("/public/validar/cubierta")
public ResponseEntity<?> validarCubierta(
@Validated(PresupuestoValidationGroups.Cubierta.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);
}
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"));
}
@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,
@ -212,4 +274,24 @@ public class PresupuestoController {
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);
}
}

View File

@ -8,15 +8,21 @@ 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 {
@ -27,6 +33,9 @@ public class PresupuestoService {
@Autowired
protected MessageSource messageSource;
@Autowired
protected skApiClient skApiClient;
private final PresupuestadorItems presupuestadorItems;
public PresupuestoService(PresupuestadorItems presupuestadorItems) {
@ -228,7 +237,7 @@ public class PresupuestoService {
List<String> gramajes = new ArrayList<>();
final int CARTULINA_GRAFICA_ID = 3;
final int CARTULINA_GRAFICA_ID = 5;
final int ESTUCADO_MATE_ID = 2;
if (presupuesto.getPapelCubiertaId() != null && presupuesto.getPapelCubiertaId() == CARTULINA_GRAFICA_ID) {
@ -269,17 +278,11 @@ public class PresupuestoService {
"gramajeCubierta", presupuesto.getGramajeCubierta(),
"carasImpresion", presupuesto.getCubiertaCaras(),
"solapas", presupuesto.getSolapasCubierta() ? presupuesto.getTamanioSolapasCubierta() : 0,
"acabado", 0, //// Añadir acabados
"acabado", presupuesto.getAcabado(),
"cabezada", presupuesto.getCabezada(),
"lomoRedondo", presupuesto.getTipoCubierta() == TipoCubierta.tapaDuraLomoRedondo ? 1 : 0);
/*
* 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,
@ -303,9 +306,25 @@ public class PresupuestoService {
body.put("paginasCuadernillo", SK_PAGINAS_CUADERNILLO);
body.put("interior", interior);
body.put("cubierta", cubierta);
// body.put("sobrecubierta", sobrecubierta);
body.put("guardas", null);
body.put("faja", false);
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;
@ -372,7 +391,8 @@ public class PresupuestoService {
});
opciones.add(new HashMap<>() {
{
put("name", messageSource.getMessage("presupuesto.acabado-plastificado-mate-1c-antirrayado", null, locale));
put("name",
messageSource.getMessage("presupuesto.acabado-plastificado-mate-1c-antirrayado", null, locale));
put("sk-id", 8);
}
});
@ -405,4 +425,157 @@ public class PresupuestoService {
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;
}
}

View File

@ -112,7 +112,7 @@ public class PresupuestadorItems {
"/assets/images/imprimelibros/presupuestador/cartulina-grafica.png",
"",
messageSource.getMessage("presupuesto.cartulina-grafica-cubierta", null, locale),
Map.of("sk-id", "3"),
Map.of("sk-id", "5"),
false);
}