var semail = 0; $(document).ready(function () { // Desactiva todos los autocomplete $('input').attr('autocomplete', 'off'); // Selecciona todos los inputs y desactiva el autocompletado // Cuando se presiona la tecla Enter en txtIdentificacion, dar foco a txtEmail o a txtNombre $(document).on("keydown", "#txtIdentificacion", function (event) { if (event.which === 13 || event.which === 9) { event.preventDefault(); // Evita la acción por defecto (como enviar el formulario) // Verifica si el tipo de cédula seleccionado es "PASAPORTE" if ($("#cmbTipoCedula").val() === "PASAPORTE") { $("#txtNombre").focus(); $("#txtNombre").removeAttr("readonly"); $("#txtNombre").attr("placeholder", "Digite el nombre aqui..."); } else { $("#txtEmail").focus(); } } }); // Cuando se presiona la tecla Enter en txtEmail, dar foco a txtTelefono $(document).on("keydown", "#txtEmail", function (event) { if (event.which === 13 || event.which === 9) { event.preventDefault(); $("#txtTelefono").focus(); } }); // Cuando se presiona la tecla Enter en txtNombre, dar foco a txtEmail $(document).on("keydown", "#txtNombre", function (event) { if (event.which === 13 || event.which === 9) { event.preventDefault(); $("#txtEmail").focus(); } }); // Validar el formato del correo electrónico $("#txtEmail").on("blur", function () { var email = $(this).val().trim(); // Obtener el valor del campo y eliminar espacios en blanco var emailRegex = /^(?!.*[áéíóúÁÉÍÓÚ])(?!.*\.\@)[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; if (email.length > 0) { // Solo validar si hay al menos un carácter if (!emailRegex.test(email)) { MessageBox("Error", "El formato del correo electr\u00f3nico es incorrecto."); semail = 1; $(this).addClass("is-invalid"); // Añadir clase de error } else { $(this).removeClass("is-invalid"); // Remover clase de error si es válido semail = 0; } } else { $(this).removeClass("is-invalid"); // Si está vacío, quitar cualquier error previo semail = 1; } }); // Validación de teléfono para solo números y longitud exacta de 8 dígitos $("#txtTelefono").on("input", function () { var telefono = $(this).val(); // Eliminar caracteres que no sean números $(this).val(telefono.replace(/\D/g, '')); // Si la longitud supera los 8 dígitos, recortamos el valor if ($(this).val().length > 8) { $(this).val($(this).val().substring(0, 8)); } }); // Validación final cuando se pierde el foco $("#txtTelefono").on("blur", function () { var telefono = $(this).val(); //var telefonoRegex = /^\d{8}$/; // Asegurarnos de que tenga exactamente 8 dígitos var telefonoRegex = /^(?!([0-9])\1{7})(?!0)\d{8}$/; // Validar si el teléfono tiene exactamente 8 dígitos numéricos if (telefono !== undefined && telefono != '' && telefono !== null && !telefonoRegex.test(telefono)) { $(this).addClass("is-invalid"); // Añadir clase de error si la validación falla MessageBox("Error", "El tel\u00e9fono debe contener exactamente 8 d\u00edgitos num\u00e9ricos y no puede ser 00000000."); } else { $(this).removeClass("is-invalid"); // Remover clase de error si la validación pasa } }); // Detectar cambios en el input $('#InputCliente').on('input', function () { const inputValue = $(this).val(); if (inputValue.length === 6) { // Verificar si tiene exactamente 6 dígitos // Realiza la llamada AJAX $.ajax({ url: '/Refacturacion/GetClienteNombre', // Ruta al método del controlador type: 'GET', data: { idCliente: inputValue }, // Parámetro que se envía success: function (data) { // Llena el campo InputCliente con el nombre obtenido if (data.Nombre && data.Nombre !== "No encontrado") { $('.idImp').val(data.Nombre); } else { $('.idImp').val("No encontrado"); } }, error: function () { $('.idImp').val("Error al obtener cliente"); } }); } }); // Llama al metodo para validar la identificacion $("#txtIdentificacion").on("input", function () { validarIdentificacion(); }); // Limpia todos los campos $("#cmbTipoCedula").on("change", function () { $("#txtIdentificacion").val(""); $("#errorMensaje").text(""); limpiarCampos(); $("#txtIdentificacion").focus(); // Dar foco automáticamente }); // Llama al metodo para validar la longitud minima para todos los campos requeridos $("#txtIdentificacion").on("blur", function () { validarLongitudMinima(); }); // Metodo que valida la identificacion ingresada function validarIdentificacion() { let tipo = $("#cmbTipoCedula").val(); let input = $("#txtIdentificacion"); let valor = input.val(); let regex, maxLength, minLength, bloqueaCeroInicial = false; switch (tipo) { case "FISICA": regex = /^[1-9][0-9]*$/; // Solo números, sin 0 inicial maxLength = 9; minLength = 9; bloqueaCeroInicial = true; break; case "JURIDICA": regex = /^[0-9]*$/; // Solo números maxLength = 10; minLength = 10; break; case "DIMEX": regex = /^[1-9][0-9]*$/; // Solo números, sin 0 inicial maxLength = 12; minLength = 11; bloqueaCeroInicial = true; break; case "PASAPORTE": regex = /^[a-zA-Z0-9]*$/; // Letras y números maxLength = 20; minLength = 1; break; default: return; } // Bloquea caracteres no permitidos if (!regex.test(valor)) { input.val(valor.slice(0, -1)); } // Limita la longitud máxima if (valor.length > maxLength) { input.val(valor.substring(0, maxLength)); } // Bloquea primer dígito 0 si es necesario if (bloqueaCeroInicial && valor.startsWith("0")) { input.val(valor.substring(1)); } } //Metodo que cierra el modal $('#btnCerrarModalManteCliente').on('click', function () { $('#ClienteNuevo').modal('hide'); }); }); // Metodo para realizar el proceso de obtener la informacion de la identificacion, dando click al txtIdentificacion $(document).on('change keyup', '[id^=txtIdentificacion]', async function (event) { event.preventDefault(); event.stopPropagation(); // Verifica si el evento es "change" o si se presionó "Enter" if (event.type === "change" || (event.type === "keydown" && (event.which === 13 || (event.which === 13)))) { const identificacionValor = this.value; if (identificacionValor) { // Obtener el elemento select const selectElement = document.getElementById('identificacionTipo'); if ($("#cmbTipoCedula").val() === "PASAPORTE") { $("#txtCedula").val($("#txtIdentificacion").val()); $("#txtTipo").val("PASAPORTE"); } else { // Llama al método que realiza todo el proceso await obtenerNombrePorIdentificacion(identificacionValor); } } } }); // Metodo que realiza validacion de campos y si todo esta correcto, llama al metodo IngresarCliente $(document).on("click", "#btnAgregarCliente", async function () { var EMAIL = $("#txtEmail").val().trim(); var CEDULA = $("#txtCedula").val().trim(); var NOMBRE = $("#txtNombre").val().trim(); var TELEFONO = $("#txtTelefono").val().trim(); var TIPO = $("#txtTipo").val().trim(); var faltandatos = true; if (EMAIL == "" || semail == 1) { } else { if (CEDULA == "") { } else { if (NOMBRE == "" || NOMBRE == "null") { } else { if (TELEFONO == "" || TELEFONO.length < 8 || TELEFONO == "00000000") { } else { if (TIPO == "") { } else { faltandatos = false } } } } } if (faltandatos) { MessageBox("Error", "Faltan datos por ingresar o no tienen un formato v\u00e1lido. Favor verificar.") } else { await IngresarCliente(); $("#txtNombre").attr("readonly", true); // Poner de nuevo el atributo readonly en txtCedula limpiarCampos(); limpiarCamposTotales(); } }); // Metodo para validar la longitud minima para los campos requeridos function validarLongitudMinima() { let tipo = $("#cmbTipoCedula").val(); let input = $("#txtIdentificacion"); let valor = input.val(); let minLength = 1; switch (tipo) { case "FISICA": minLength = 9; break; case "JURIDICA": minLength = 10; break; case "DIMEX": minLength = 11; break; case "PASAPORTE": minLength = 1; break; } // Si no cumple con los requisitos, muestra un mensaje con el minimo que debe tener el campo if (valor.length < minLength && valor !== "0" && valor !== "") { MessageBox("Error", "Debe ingresar al menos " + minLength + " caracteres."); input.addClass("is-invalid"); limpiarCampos(); // Limpiar los otros campos } else { $("#errorMensaje").text(""); input.removeClass("is-invalid"); } } // Funcion que realiza la consulta de la identificacion, ya sea a Hacienda o a Equifax async function obtenerNombrePorIdentificacion(valorInput) { $("#ClienteResult").html(""); // Realiza la consulta de la informacion a Hacienda $.ajax({ url: "https://api.hacienda.go.cr/fe/ae?identificacion=" + $("#txtIdentificacion").val().trim(), method: "GET", dataType: "json", timeout: 5000, // 5 segundos de espera success: function (responseHacienda) { console.log(responseHacienda); // Llena la variable tipo de identificacion if (responseHacienda && responseHacienda.nombre) { var tipo = "FISICA"; switch (responseHacienda.tipoIdentificacion) { case "01": tipo = "FISICA"; break; case "02": tipo = "JURIDICA"; break; case "03": tipo = "DIMEX"; break; default: tipo = "FISICA"; break; } // Llena los campos en el formulario $("#txtCedula").val($("#txtIdentificacion").val().trim()); $("#txtNombre").val(responseHacienda.nombre); $("#txtTipo").val(tipo); } }, // Sino encuentra la informacion en Hacienda, hace la llamada al controlador para consultar por la API Equifax error: function (errorHacienda) { $.ajax({ type: 'POST', url: '/MantenimientoClientes/Busqueda/', contentType: 'application/json; charset=utf-8', data: JSON.stringify({ criterio: $("#txtIdentificacion").val().trim(), tipo: $("#cmbTipoCedula").val().trim() }), dataType: 'json', success: function (response) { if (response.Respuesta[0].NombreCompleto.includes("Esta c")) { limpiarCamposTotales(); } else { if (response.Respuesta[0].Nombre1 == '') { MessageBox("Error", "No se pudo encontrar el cliente. Favor intentar de nuevo."); } else { // Llena los datos en el formulario $("#txtCedula").val($("#txtIdentificacion").val().trim()); var nombre2 = response.Respuesta[0].Nombre2; var nombreCompleto = response.Respuesta[0].Nombre1 + " " + (nombre2 && nombre2.trim() !== "" ? nombre2 + " " : "") + response.Respuesta[0].Apellido1 + " " + response.Respuesta[0].Apellido2; $("#txtNombre").val(nombreCompleto); $("#txtTipo").val($("#cmbTipoCedula").val().trim()); } } }, }); } }); } // Funcion para ingresar el cliente al sistema y los datos de hacienda async function IngresarCliente() { $("#loadingCrearCliente").show(); // Obtiene toda la informacion del formulario var EMAIL = $("#txtEmail").val().trim(); var CEDULA = $("#txtCedula").val().trim(); var NOMBRE = $("#txtNombre").val().trim(); var TELEFONO = $("#txtTelefono").val().trim(); var TIPO = $("#txtTipo").val().trim(); // Llama al controlador CrearCliente que realiza el proceso de la creacion de dicho cliente const respuesta = await $.ajax({ url: `/MantenimientoClientes/CrearCliente`, type: 'POST', contentType: 'application/json; charset=utf-8', data: JSON.stringify({ EMAIL, CEDULA, NOMBRE, TELEFONO, TIPO }), dataType: 'json', }); // Si la consulta tiene exito, muestra en la pantalla con el nuevo numero de cliente if (respuesta.Respuesta.Exito) { GuardarDatosHacienda() var respuestadef = respuesta.Respuesta.Mensaje; MessageBox("\u00c9xito", respuestadef); $("#loadingCrearCliente").hide(); } else { // Si la consulta no tiene exito, muestra en la pantalla que hay error MessageBox("Error", respuesta.Respuesta.Mensaje); $("#loadingCrearCliente").hide(); } } // Funcion que limpia los campos function limpiarCampos() { $("#txtCedula, #txtNombre, #txtTipo, #txtEmail, #txtTelefono").val(""); } // Funcion que limpia todos los campos function limpiarCamposTotales() { $("#txtIdentificacion, #txtCedula, #txtNombre, #txtTipo, #txtEmail, #txtTelefono").val(""); } function AbrirModal() { // Abrir el modal del mantenimiento de clientes $("#ClienteNuevo").modal("show"); // Establecer el foco en el campo txtIdentificacion cuando la página cargue setTimeout(() => { $("#txtIdentificacion").focus(); }, 500); } // Funcion para consultar y guardar datos del cliente en Hacienda async function GuardarDatosHacienda() { // Obtiene el valor del campo de identificacin y elimina espacios const identificacion = $("#txtIdentificacion").val().trim(); if (!identificacion) return; const maxIntentos = 2; const delay = 5000; // 5 segundos entre cada consulta for (let intento = 1; intento <= maxIntentos; intento++) { try { // Llama a la API de Hacienda con la cdula ingresada const response = await fetch(`https://api.hacienda.go.cr/fe/ae?identificacion=${identificacion}`); // Si Hacienda responde con "Too Many Requests", reintenta despus de esperar if (response.status === 429) { await new Promise(resolve => setTimeout(resolve, delay)); continue; } const responseHacienda = await response.json(); if (responseHacienda && responseHacienda.nombre) { let tipo = "FISICA"; switch (responseHacienda.tipoIdentificacion) { case "01": tipo = "FISICA"; break; case "02": tipo = "JURIDICA"; break; case "03": tipo = "DIMEX"; break; default: tipo = "FISICA"; break; } // Envia datos al controlador const guardar = await fetch("/MantenimientoClientes/GuardarDatosHacienda", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ identificacion, datos: responseHacienda }) }); const json = await guardar.json(); return; } else { MessageBox("Error", "Hacienda no devolvi\u00f3 datos v\u00e1lidos."); return; } } catch (error) { // Aqu controlamos "Failed to fetch" u otros errores de red if (intento < maxIntentos) { console.warn(`Intento ${intento} fallido con error de red. Reintentando en ${delay / 1000} segundos...`, error.message); await new Promise(resolve => setTimeout(resolve, delay)); } else { console.error("Error durante la llamada a Hacienda (ultimo intento):", error.message); //MessageBox("Error", "No se pudo contactar con Hacienda despues de varios intentos. Error: " + error.message); return; } } } }