Validaciones - Alta de: Proveedores, Transportistas, Transportes y Choferes
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
require_once __DIR__ . '/../helpers/session.php';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once __DIR__ . '/../helpers/session.php';
|
||||
require_once __DIR__ . '/../../config/database.php';
|
||||
require_once __DIR__ . '/../helpers/env.php';
|
||||
|
||||
function lista() {
|
||||
if (!($_SESSION['usuario_id'] ?? false)) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once __DIR__ . '/../helpers/session.php';
|
||||
require_once __DIR__ . '/../../config/database.php';
|
||||
require_once __DIR__ . '/../helpers/env.php';
|
||||
|
||||
// Mostrar tabla de expedientes
|
||||
function index() {
|
||||
@@ -213,9 +214,4 @@ function descargar_zip($id_solicitud)
|
||||
readfile($zip_file);
|
||||
unlink($zip_file);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
// app/controllers/proveedores.php
|
||||
session_start();
|
||||
require_once __DIR__ . '/../helpers/session.php';
|
||||
require_once __DIR__ . '/../../config/database.php';
|
||||
|
||||
// 1) Composer autoload (phpdotenv y demás libs)
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
@@ -5,16 +5,15 @@ use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
|
||||
require_once __DIR__ . '/../../config/database.php';
|
||||
require_once __DIR__ . '/../helpers/session.php';
|
||||
require_once __DIR__ . '/../helpers/env.php';
|
||||
require_once __DIR__ . '/../helpers/crypto.php';
|
||||
loadEnv();
|
||||
|
||||
function index() {
|
||||
include __DIR__ . '/../../views/registro/form.php';
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/../helpers/crypto.php';
|
||||
|
||||
require_once __DIR__ . '/../helpers/env.php';
|
||||
loadEnv();
|
||||
|
||||
function enviar() {
|
||||
// Validar reCAPTCHA
|
||||
$captchaResponse = $_POST['g-recaptcha-response'] ?? '';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once __DIR__ . '/../helpers/session.php';
|
||||
require_once __DIR__ . '/../../config/database.php';
|
||||
// 1) Composer autoload (phpdotenv y demás libs)
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
@@ -1309,7 +1309,7 @@ function generarHtmlNotificacion($datos) {
|
||||
<strong>© {$datos['anioActual']} SIIH</strong> · Desarrollado por
|
||||
<span style='color: #007bff; font-weight: 600;'>AduanaSoft</span>
|
||||
<br>
|
||||
<small style='color: #adb5bd;'>Sistema Integral de Importación y Herramientas</small>
|
||||
<small style='color: #adb5bd;'>Sistema Integral para Importadores de Hidrocarburos</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>";
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once __DIR__ . '/../helpers/session.php';
|
||||
require_once __DIR__ . '/../../config/database.php';
|
||||
require_once __DIR__ . '/../helpers/env.php';
|
||||
|
||||
/** Listado de transportes (sólo activos) para el importador logueado **/
|
||||
function lista() {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<?php
|
||||
session_start();
|
||||
function guardar() {
|
||||
require_once __DIR__ . '/../helpers/session.php';
|
||||
require_once __DIR__ . '/../../config/database.php';
|
||||
require_once __DIR__ . '/../helpers/env.php';
|
||||
|
||||
function guardar() {
|
||||
if (!($_SESSION['usuario_id'] ?? false)) {
|
||||
die("⚠️ No autorizado.");
|
||||
}
|
||||
@@ -41,8 +44,6 @@
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/../../config/database.php';
|
||||
|
||||
function alta() {
|
||||
$conn = getConnection();
|
||||
// 1) Cargar países
|
||||
@@ -393,8 +394,8 @@ function editar() {
|
||||
}
|
||||
|
||||
/** Procesa el POST de actualización **/
|
||||
function actualizar() {
|
||||
session_start();
|
||||
function actualizar()
|
||||
{
|
||||
if (!($_SESSION['usuario_id'] ?? false)) {
|
||||
die("⚠️ No autorizado.");
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<h4>➕ Nuevo Chofer</h4>
|
||||
<div class="card p-4 shadow-sm bg-white">
|
||||
<!-- Se agrega enctype para subir archivos -->
|
||||
<form action="/IMPORTADORES/choferes/guardar" method="POST" enctype="multipart/form-data">
|
||||
<form action="/IMPORTADORES/choferes/guardar" method="POST" enctype="multipart/form-data" id="formAltaChoferes">
|
||||
<div class="mb-3">
|
||||
<label for="transportista_id" class="form-label">Transportista</label>
|
||||
<select name="transportista_id" id="transportista_id" class="form-select" required>
|
||||
@@ -62,12 +62,12 @@
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="numero_licencia" class="form-label">Número de Licencia</label>
|
||||
<input name="numero_licencia" id="numero_licencia" type="text" class="form-control" required>
|
||||
<input name="numero_licencia" id="numero_licencia" type="text" maxlength="11" class="form-control" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="telefono" class="form-label">Teléfono</label>
|
||||
<input name="telefono" id="telefono" type="tel" class="form-control">
|
||||
<input name="telefono" id="telefono" type="tel" maxlength="11" class="form-control">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
@@ -91,6 +91,95 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.getElementById('formAltaChoferes').addEventListener('submit', function(e) {
|
||||
e.preventDefault(); // Prevenir envío por defecto
|
||||
|
||||
// Obtener todos los campos correctamente
|
||||
const transportista_id = document.getElementById('transportista_id').value;
|
||||
const nombre = document.getElementById('nombre').value.trim();
|
||||
const apellido = document.getElementById('apellido').value.trim();
|
||||
const numero_licencia = document.getElementById('numero_licencia').value.trim();
|
||||
const telefono = document.getElementById('telefono').value.trim();
|
||||
const email = document.getElementById('email').value.trim();
|
||||
const fecha_ingreso = document.getElementById('fecha_ingreso').value;
|
||||
const foto = document.getElementById('foto').files[0];
|
||||
|
||||
// Expresiones regulares
|
||||
const telefonoRegex = /^\d{3}\s\d{7}$/;
|
||||
const emailRegex = /^[a-zA-Z0-9._+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
||||
const soloNumerosRegex = /^[0-9]+$/;
|
||||
|
||||
// VALIDAR CAMPOS OBLIGATORIOS PRIMERO
|
||||
if (!transportista_id) {
|
||||
Swal.fire({ icon: 'error', title: 'Transportista requerido', text: 'Por favor selecciona un transportista.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('transportista_id').focus();
|
||||
return;
|
||||
}
|
||||
if (!nombre) {
|
||||
Swal.fire({ icon: 'error', title: 'Nombre requerido', text: 'Por favor ingresa el nombre.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('nombre').focus();
|
||||
return;
|
||||
}
|
||||
if (!apellido) {
|
||||
Swal.fire({ icon: 'error', title: 'Apellido requerido', text: 'Por favor ingresa el apellido.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('apellido').focus();
|
||||
return;
|
||||
}
|
||||
if (!numero_licencia) {
|
||||
Swal.fire({ icon: 'error', title: 'Número de Licencia requerido', text: 'Por favor ingresa el número de licencia.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('numero_licencia').focus();
|
||||
return;
|
||||
}
|
||||
if (!soloNumerosRegex.test(numero_licencia)) {
|
||||
Swal.fire({ icon: 'error', title: 'Número de Licencia inválido', text: 'El número de licencia solo puede contener números', confirmButtonColor: '#dc3545'
|
||||
});
|
||||
document.getElementById('Clave').focus();
|
||||
return;
|
||||
}
|
||||
// VALIDAR CAMPOS OPCIONALES (solo si tienen contenido)
|
||||
if (telefono && !telefonoRegex.test(telefono)) {
|
||||
Swal.fire({ icon: 'error', title: 'Teléfono inválido', text: 'Debe tener 10 dígitos en el formato: 3 dígitos (LADA), espacio, y 7 dígitos. Ejemplo: 123 4567890', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('telefono').focus();
|
||||
return;
|
||||
}
|
||||
if (email && !emailRegex.test(email)) {
|
||||
Swal.fire({ icon: 'error', title: 'Email inválido', text: 'Por favor ingresa una dirección de email válida.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('email').focus();
|
||||
return;
|
||||
}
|
||||
// VALIDAR FECHA DE INGRESO (solo si se proporciona)
|
||||
if (fecha_ingreso) {
|
||||
const fechaIngreso = new Date(fecha_ingreso);
|
||||
const fechaActual = new Date();
|
||||
if (fechaIngreso > fechaActual) {
|
||||
Swal.fire({ icon: 'error', title: 'Fecha inválida', text: 'La fecha de ingreso no puede ser futura.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('fecha_ingreso').focus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// VALIDAR FOTO (solo si se seleccionó)
|
||||
if (foto) {
|
||||
// Validar tamaño (máximo 2 MB)
|
||||
if (foto.size > 2 * 1024 * 1024) {
|
||||
Swal.fire({ icon: 'error', title: 'Foto demasiado grande', text: 'La imagen no debe exceder 2 MB.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('foto').focus();
|
||||
return;
|
||||
}
|
||||
// Validar tipo de archivo
|
||||
const tiposPermitidos = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif'];
|
||||
if (!tiposPermitidos.includes(foto.type)) {
|
||||
Swal.fire({ icon: 'error', title: 'Tipo de archivo inválido', text: 'Solo se permiten archivos de imagen (JPG, PNG, GIF).', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('foto').focus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// SI TODAS LAS VALIDACIONES PASAN, ENVIAR EL FORMULARIO
|
||||
this.submit();
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -35,7 +35,7 @@
|
||||
<div class="content">
|
||||
<h4>✏️ Editar Chofer #<?= (int)$chofer['id_chofer'] ?></h4>
|
||||
<div class="card p-4 shadow-sm bg-white">
|
||||
<form action="/IMPORTADORES/choferes/actualizar" method="POST" enctype="multipart/form-data">
|
||||
<form action="/IMPORTADORES/choferes/actualizar" method="POST" enctype="multipart/form-data" id="formEditChoferes">
|
||||
<input type="hidden" name="id_chofer" value="<?= (int)$chofer['id_chofer'] ?>">
|
||||
|
||||
<!-- Transportista -->
|
||||
@@ -72,14 +72,14 @@
|
||||
<!-- Licencia -->
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="numero_licencia" class="form-label">Número de Licencia</label>
|
||||
<input name="numero_licencia" id="numero_licencia" type="text" class="form-control"
|
||||
<input name="numero_licencia" id="numero_licencia" type="text" maxlength="11" class="form-control"
|
||||
value="<?= htmlspecialchars($chofer['numero_licencia']) ?>" required>
|
||||
</div>
|
||||
|
||||
<!-- Teléfono -->
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="telefono" class="form-label">Teléfono</label>
|
||||
<input name="telefono" id="telefono" type="tel" class="form-control"
|
||||
<input name="telefono" id="telefono" type="tel" maxlength="11" class="form-control"
|
||||
value="<?= htmlspecialchars($chofer['telefono']) ?>">
|
||||
</div>
|
||||
</div>
|
||||
@@ -128,6 +128,94 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.getElementById('formEditChoferes').addEventListener('submit', function(e) {
|
||||
e.preventDefault(); // Prevenir envío por defecto
|
||||
|
||||
// Obtener todos los campos correctamente
|
||||
const transportista_id = document.getElementById('transportista_id').value;
|
||||
const nombre = document.getElementById('nombre').value.trim();
|
||||
const apellido = document.getElementById('apellido').value.trim();
|
||||
const numero_licencia = document.getElementById('numero_licencia').value.trim();
|
||||
const telefono = document.getElementById('telefono').value.trim();
|
||||
const email = document.getElementById('email').value.trim();
|
||||
const fecha_ingreso = document.getElementById('fecha_ingreso').value;
|
||||
const foto = document.getElementById('foto').files[0];
|
||||
|
||||
// Expresiones regulares
|
||||
const telefonoRegex = /^\d{3}\s\d{7}$/;
|
||||
const emailRegex = /^[a-zA-Z0-9._+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
||||
const soloNumerosRegex = /^[0-9]+$/;
|
||||
|
||||
// VALIDAR CAMPOS OBLIGATORIOS PRIMERO
|
||||
if (!transportista_id) {
|
||||
Swal.fire({ icon: 'error', title: 'Transportista requerido', text: 'Por favor selecciona un transportista.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('transportista_id').focus();
|
||||
return;
|
||||
}
|
||||
if (!nombre) {
|
||||
Swal.fire({ icon: 'error', title: 'Nombre requerido', text: 'Por favor ingresa el nombre.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('nombre').focus();
|
||||
return;
|
||||
}
|
||||
if (!apellido) {
|
||||
Swal.fire({ icon: 'error', title: 'Apellido requerido', text: 'Por favor ingresa el apellido.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('apellido').focus();
|
||||
return;
|
||||
}
|
||||
if (!numero_licencia) {
|
||||
Swal.fire({ icon: 'error', title: 'Número de Licencia requerido', text: 'Por favor ingresa el número de licencia.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('numero_licencia').focus();
|
||||
return;
|
||||
}
|
||||
if (!soloNumerosRegex.test(numero_licencia)) {
|
||||
Swal.fire({ icon: 'error', title: 'Número de Licencia inválido', text: 'El número de licencia solo puede contener números', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('Clave').focus();
|
||||
return;
|
||||
}
|
||||
// VALIDAR CAMPOS OPCIONALES (solo si tienen contenido)
|
||||
if (telefono && !telefonoRegex.test(telefono)) {
|
||||
Swal.fire({ icon: 'error', title: 'Teléfono inválido', text: 'Debe tener 10 dígitos en el formato: 3 dígitos (LADA), espacio, y 7 dígitos. Ejemplo: 123 4567890', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('telefono').focus();
|
||||
return;
|
||||
}
|
||||
if (email && !emailRegex.test(email)) {
|
||||
Swal.fire({ icon: 'error', title: 'Email inválido', text: 'Por favor ingresa una dirección de email válida.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('email').focus();
|
||||
return;
|
||||
}
|
||||
// VALIDAR FECHA DE INGRESO (solo si se proporciona)
|
||||
if (fecha_ingreso) {
|
||||
const fechaIngreso = new Date(fecha_ingreso);
|
||||
const fechaActual = new Date();
|
||||
if (fechaIngreso > fechaActual) {
|
||||
Swal.fire({ icon: 'error', title: 'Fecha inválida', text: 'La fecha de ingreso no puede ser futura.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('fecha_ingreso').focus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// VALIDAR FOTO (solo si se seleccionó)
|
||||
if (foto) {
|
||||
// Validar tamaño (máximo 2 MB)
|
||||
if (foto.size > 2 * 1024 * 1024) {
|
||||
Swal.fire({ icon: 'error', title: 'Foto demasiado grande', text: 'La imagen no debe exceder 2 MB.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('foto').focus();
|
||||
return;
|
||||
}
|
||||
// Validar tipo de archivo
|
||||
const tiposPermitidos = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif'];
|
||||
if (!tiposPermitidos.includes(foto.type)) {
|
||||
Swal.fire({ icon: 'error', title: 'Tipo de archivo inválido', text: 'Solo se permiten archivos de imagen (JPG, PNG, GIF).', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('foto').focus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// SI TODAS LAS VALIDACIONES PASAN, ENVIAR EL FORMULARIO
|
||||
this.submit();
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -44,11 +44,11 @@
|
||||
<div class="content">
|
||||
<h4 class="mb-4">➕ Registro de Proveedor</h4>
|
||||
<div class="card p-4 shadow-sm">
|
||||
<form action="/IMPORTADORES/proveedores/guardar" method="POST">
|
||||
<form action="/IMPORTADORES/proveedores/guardar" method="POST" enctype="multipart/form-data" id="formAltaProveedores">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<label for="Clave" class="form-label">Clave *</label>
|
||||
<input type="text" name="Clave" id="Clave" class="form-control" required>
|
||||
<input type="text" name="Clave" id="Clave" class="form-control" maxlength="20" required>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<label for="Nombre" class="form-label">Nombre *</label>
|
||||
@@ -56,7 +56,7 @@
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="RFC" class="form-label">RFC *</label>
|
||||
<input type="text" name="RFC" id="RFC" class="form-control" required>
|
||||
<input type="text" name="RFC" id="RFC" class="form-control" maxlength="13" required>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="Ciudad" class="form-label">Ciudad *</label>
|
||||
@@ -64,7 +64,7 @@
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="Telefono" class="form-label">Teléfono</label>
|
||||
<input type="tel" name="Telefono" id="Telefono" class="form-control">
|
||||
<input type="tel" name="Telefono" id="Telefono" maxlength="11" class="form-control">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="Pais" class="form-label">País</label>
|
||||
@@ -84,7 +84,7 @@
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="CodigoPostal" class="form-label">Código Postal</label>
|
||||
<input type="text" name="CodigoPostal" id="CodigoPostal" class="form-control">
|
||||
<input type="text" name="CodigoPostal" id="CodigoPostal" maxlength="5" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 text-end">
|
||||
@@ -98,5 +98,148 @@
|
||||
<!-- Bootstrap JS Bundle -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
<script>
|
||||
document.getElementById('formAltaProveedores').addEventListener('submit', function(e) {
|
||||
e.preventDefault(); // Prevenir envío por defecto
|
||||
|
||||
// Obtener todos los campos
|
||||
const clave = document.getElementById('Clave').value.trim();
|
||||
const nombre = document.getElementById('Nombre').value.trim();
|
||||
const rfc = document.getElementById('RFC').value.trim().toUpperCase();
|
||||
const ciudad = document.getElementById('Ciudad').value.trim();
|
||||
const telefono = document.getElementById('Telefono').value.trim();
|
||||
const pais = document.getElementById('Pais').value.trim();
|
||||
const entidadFederativa = document.getElementById('EntidadFederativa').value.trim();
|
||||
const municipio = document.getElementById('Municipio').value.trim();
|
||||
const colonia = document.getElementById('Colonia').value.trim();
|
||||
const codigoPostal = document.getElementById('CodigoPostal').value.trim();
|
||||
|
||||
// Expresiones regulares
|
||||
const rfcRegex = /^[A-ZÑ&]{3,4}\d{6}[A-Z0-9]{3}$/;
|
||||
const telefonoRegex = /^\d{3}\s\d{7}$/;
|
||||
const codigoPostalRegex = /^\d{5}$/;
|
||||
const soloLetrasRegex = /^[a-zA-ZáéíóúÁÉÍÓÚñÑ\s]+$/;
|
||||
const alfanumericoRegex = /^[a-zA-Z0-9áéíóúÁÉÍÓÚñÑ\s]+$/;
|
||||
|
||||
// VALIDAR CAMPOS OBLIGATORIOS
|
||||
if (!clave) {
|
||||
Swal.fire({ icon: 'error', title: 'Clave requerida', text: 'Por favor ingresa la clave del proveedor.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('Clave').focus();
|
||||
return;
|
||||
}
|
||||
if (clave.length < 2 || clave.length > 20) {
|
||||
Swal.fire({ icon: 'error', title: 'Clave inválida', text: 'La clave debe tener entre 2 y 20 caracteres.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('Clave').focus();
|
||||
return;
|
||||
}
|
||||
if (!alfanumericoRegex.test(clave)) {
|
||||
Swal.fire({ icon: 'error', title: 'Clave inválida', text: 'La clave solo puede contener letras, números y espacios.', confirmButtonColor: '#dc3545'
|
||||
});
|
||||
document.getElementById('Clave').focus();
|
||||
return;
|
||||
}
|
||||
if (!nombre) {
|
||||
Swal.fire({ icon: 'error', title: 'Nombre requerido', text: 'Por favor ingresa el nombre del proveedor.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('Nombre').focus();
|
||||
return;
|
||||
}
|
||||
if (nombre.length < 2 || nombre.length > 100) {
|
||||
Swal.fire({ icon: 'error', title: 'Nombre inválido', text: 'El nombre debe tener entre 2 y 100 caracteres.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('Nombre').focus();
|
||||
return;
|
||||
}
|
||||
if (!rfc) {
|
||||
Swal.fire({ icon: 'error', title: 'RFC requerido', text: 'Por favor ingresa el RFC del proveedor.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('RFC').focus();
|
||||
return;
|
||||
}
|
||||
if (!rfcRegex.test(rfc)) {
|
||||
Swal.fire({ icon: 'error', title: 'RFC inválido', text: 'El RFC debe tener 12 o 13 caracteres con el formato correcto (ej. ABC123456XYZ).', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('RFC').focus();
|
||||
return;
|
||||
}
|
||||
if (!ciudad) {
|
||||
Swal.fire({ icon: 'error', title: 'Ciudad requerida', text: 'Por favor ingresa la ciudad del proveedor.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('Ciudad').focus();
|
||||
return;
|
||||
}
|
||||
if (!soloLetrasRegex.test(ciudad)) {
|
||||
Swal.fire({ icon: 'error', title: 'Ciudad inválida', text: 'La ciudad solo puede contener letras y espacios.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('Ciudad').focus();
|
||||
return;
|
||||
}
|
||||
// VALIDAR CAMPOS OPCIONALES (solo si tienen contenido)
|
||||
if (telefono) {
|
||||
if (!telefonoRegex.test(telefono)) {
|
||||
Swal.fire({ icon: 'error', title: 'Teléfono inválido', text: 'Debe tener 10 dígitos en el formato: 3 dígitos (LADA), espacio, y 7 dígitos. Ejemplo: 123 4567890', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('Telefono').focus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (pais) {
|
||||
if (!soloLetrasRegex.test(pais)) {
|
||||
Swal.fire({ icon: 'error', title: 'País inválido', text: 'El país solo puede contener letras y espacios.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('Pais').focus();
|
||||
return;
|
||||
}
|
||||
if (pais.length < 2 || pais.length > 50) {
|
||||
Swal.fire({ icon: 'error', title: 'País inválido', text: 'El país debe tener entre 2 y 50 caracteres.', confirmButtonColor: '#dc3545'
|
||||
});
|
||||
document.getElementById('Pais').focus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (entidadFederativa) {
|
||||
if (!soloLetrasRegex.test(entidadFederativa)) {
|
||||
Swal.fire({ icon: 'error', title: 'Entidad Federativa inválida', text: 'La entidad federativa solo puede contener letras y espacios.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('EntidadFederativa').focus();
|
||||
return;
|
||||
}
|
||||
if (entidadFederativa.length < 2 || entidadFederativa.length > 50) {
|
||||
Swal.fire({ icon: 'error', title: 'Entidad Federativa inválida', text: 'La entidad federativa debe tener entre 2 y 50 caracteres.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('EntidadFederativa').focus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (municipio) {
|
||||
if (!soloLetrasRegex.test(municipio)) {
|
||||
Swal.fire({ icon: 'error', title: 'Municipio inválido', text: 'El municipio solo puede contener letras y espacios.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('Municipio').focus();
|
||||
return;
|
||||
}
|
||||
if (municipio.length < 2 || municipio.length > 50) {
|
||||
Swal.fire({ icon: 'error', title: 'Municipio inválido', text: 'El municipio debe tener entre 2 y 50 caracteres.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('Municipio').focus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (colonia) {
|
||||
if (!alfanumericoRegex.test(colonia)) {
|
||||
Swal.fire({ icon: 'error', title: 'Colonia inválida', text: 'La colonia solo puede contener letras, números y espacios.', confirmButtonColor: '#dc3545'
|
||||
});
|
||||
document.getElementById('Colonia').focus();
|
||||
return;
|
||||
}
|
||||
if (colonia.length < 2 || colonia.length > 50) {
|
||||
Swal.fire({ icon: 'error', title: 'Colonia inválida', text: 'La colonia debe tener entre 2 y 50 caracteres.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('Colonia').focus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (codigoPostal) {
|
||||
if (!codigoPostalRegex.test(codigoPostal)) {
|
||||
Swal.fire({ icon: 'error', title: 'Código Postal inválido', text: 'El código postal debe tener exactamente 5 dígitos.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('CodigoPostal').focus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Actualizar el valor del RFC en mayúsculas antes de enviar
|
||||
document.getElementById('RFC').value = rfc;
|
||||
|
||||
// SI TODAS LAS VALIDACIONES PASAN, ENVIAR EL FORMULARIO
|
||||
this.submit();
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -98,7 +98,7 @@
|
||||
<div class="row">
|
||||
<div class="col-md-8 mb-3">
|
||||
<label for="valor_factura" class="form-label">Valor Factura</label>
|
||||
<input id="valor_factura" name="valor_factura" type="number" step="0.01" class="form-control" required>
|
||||
<input id="valor_factura" name="valor_factura" type="number" step="0.01" min="0" class="form-control" required>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label for="vinculacion" class="form-label">Vinculación</label>
|
||||
@@ -244,7 +244,7 @@
|
||||
shouldSort: false
|
||||
});
|
||||
// seleccionar valor actual
|
||||
const current = '<?= htmlspecialchars($factura['proveedor_id'], ENT_QUOTES) ?>';
|
||||
const current = "<?= htmlspecialchars($factura['proveedor_id'], ENT_QUOTES) ?>";
|
||||
if (current) {
|
||||
proveedorChoices.setChoiceByValue(current);
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
<div class="row">
|
||||
<div class="col-md-8 mb-3">
|
||||
<label for="valor_factura" class="form-label">Valor Factura</label>
|
||||
<input id="valor_factura" name="valor_factura" type="number" step="0.01" class="form-control valor-total" required
|
||||
<input id="valor_factura" name="valor_factura" type="number" step="0.01" min="0" class="form-control valor-total" required
|
||||
value="<?= htmlspecialchars($factura['valor_factura']) ?>">
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
@@ -173,8 +173,8 @@
|
||||
<?php if (!empty($partidas)): foreach($partidas as $i=>$p): ?>
|
||||
<tr>
|
||||
<td><input name="partidas[<?= $i ?>][descripcion]" class="form-control" value="<?= htmlspecialchars($p['descripcion']) ?>"></td>
|
||||
<td><input name="partidas[<?= $i ?>][cantidad_comercial]" type="number" step="0.0001" class="form-control" value="<?= htmlspecialchars($p['cantidad_comercial']) ?>"></td>
|
||||
<td><input name="partidas[<?= $i ?>][cantidad_tarifa]" type="number" step="0.0001" class="form-control" value="<?= htmlspecialchars($p['cantidad_tarifa']) ?>"></td>
|
||||
<td><input name="partidas[<?= $i ?>][cantidad_comercial]" type="number" step="0.0001" min="0" class="form-control" value="<?= htmlspecialchars($p['cantidad_comercial']) ?>"></td>
|
||||
<td><input name="partidas[<?= $i ?>][cantidad_tarifa]" type="number" step="0.0001" min="0" class="form-control" value="<?= htmlspecialchars($p['cantidad_tarifa']) ?>"></td>
|
||||
<td>
|
||||
<select name="partidas[<?= $i ?>][unidad_comercial_id]" class="form-select searchable">
|
||||
<option value="">-- Unidad --</option>
|
||||
@@ -185,8 +185,8 @@
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</td>
|
||||
<td><input name="partidas[<?= $i ?>][valor_factura]" type="number" step="0.01" class="form-control valor-partida" value="<?= htmlspecialchars($p['valor_factura']) ?>"></td>
|
||||
<td><input name="partidas[<?= $i ?>][peso_bruto]" type="number" step="0.0001" class="form-control" value="<?= htmlspecialchars($p['peso_bruto']) ?>"></td>
|
||||
<td><input name="partidas[<?= $i ?>][valor_factura]" type="number" step="0.01" min="0" class="form-control valor-partida" value="<?= htmlspecialchars($p['valor_factura']) ?>"></td>
|
||||
<td><input name="partidas[<?= $i ?>][peso_bruto]" type="number" step="0.0001" min="0" class="form-control" value="<?= htmlspecialchars($p['peso_bruto']) ?>"></td>
|
||||
<td>
|
||||
<select name="partidas[<?= $i ?>][tasa_preferencial]" class="form-select searchable">
|
||||
<option value="">-- Selecciona --</option>
|
||||
|
||||
@@ -76,17 +76,24 @@
|
||||
const trans = document.getElementById('transportista').value;
|
||||
const fotoF = document.getElementById('foto').files[0];
|
||||
|
||||
// Validaciones de campos obligatorios
|
||||
if (!veh) {
|
||||
e.preventDefault();
|
||||
return Swal.fire({ icon:'error', title:'Vehículo requerido', text:'Por favor ingresa el nombre del vehículo.' });
|
||||
Swal.fire({ icon:'error', title:'Vehículo requerido', text:'Por favor ingresa el nombre del vehículo.', confirmButtonColor: '#dc3545'});
|
||||
document.querySelector('input[name="veh"]').focus();
|
||||
return;
|
||||
}
|
||||
if (!fisc) {
|
||||
e.preventDefault();
|
||||
return Swal.fire({ icon:'error', title:'Identificador fiscal requerido', text:'Por favor ingresa el identificador fiscal.' });
|
||||
Swal.fire({ icon:'error', title:'Identificador fiscal requerido', text:'Por favor ingresa el identificador fiscal.', confirmButtonColor: '#dc3545' });
|
||||
document.querySelector('input[name="fisc"]').focus();
|
||||
return;
|
||||
}
|
||||
if (!trans) {
|
||||
e.preventDefault();
|
||||
return Swal.fire({ icon:'error', title:'Transportista no seleccionado', text:'Debes elegir un transportista.' });
|
||||
Swal.fire({ icon:'error', title:'Transportista no seleccionado', text:'Debes elegir un transportista.', confirmButtonColor: '#dc3545' });
|
||||
document.querySelector('input[name="trans"]').focus();
|
||||
return;
|
||||
}
|
||||
if (fotoF && fotoF.size > 2 * 1024 * 1024) { // 2 MB
|
||||
e.preventDefault();
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
<input type="hidden" name="id_transporte" value="<?= $t['id_transporte'] ?>">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Vehículo *</label>
|
||||
<label class="form-label">Contenedor *</label>
|
||||
<input name="vehiculo" id="vehEdit" class="form-control"
|
||||
value="<?= htmlspecialchars($t['vehiculo']) ?>" required>
|
||||
</div>
|
||||
@@ -82,28 +82,36 @@
|
||||
|
||||
<script>
|
||||
document.getElementById('formTransEdit').addEventListener('submit', function(e) {
|
||||
// Campos que validamos:
|
||||
const veh = document.getElementById('vehEdit').value.trim();
|
||||
const fisc = document.getElementById('fiscEdit').value.trim();
|
||||
const trans = document.getElementById('trEdit').value;
|
||||
const fotoF = document.getElementById('fotoEdit').files[0];
|
||||
|
||||
// Validaciones de campos obligatorios
|
||||
if (!veh) {
|
||||
e.preventDefault();
|
||||
return Swal.fire({ icon:'error', title:'Vehículo requerido', text:'Por favor ingresa el nombre del vehículo.' });
|
||||
Swal.fire({ icon:'error', title:'Vehículo requerido', text:'Por favor ingresa el nombre del vehículo.', confirmButtonColor: '#dc3545'});
|
||||
document.querySelector('input[name="veh"]').focus();
|
||||
return;
|
||||
}
|
||||
if (!fisc) {
|
||||
e.preventDefault();
|
||||
return Swal.fire({ icon:'error', title:'Identificador fiscal requerido', text:'Por favor ingresa el identificador fiscal.' });
|
||||
Swal.fire({ icon:'error', title:'Identificador fiscal requerido', text:'Por favor ingresa el identificador fiscal.', confirmButtonColor: '#dc3545' });
|
||||
document.querySelector('input[name="fisc"]').focus();
|
||||
return;
|
||||
}
|
||||
if (!trans) {
|
||||
e.preventDefault();
|
||||
return Swal.fire({ icon:'error', title:'Transportista no seleccionado', text:'Debes elegir un transportista.' });
|
||||
Swal.fire({ icon:'error', title:'Transportista no seleccionado', text:'Debes elegir un transportista.', confirmButtonColor: '#dc3545' });
|
||||
document.querySelector('input[name="trans"]').focus();
|
||||
return;
|
||||
}
|
||||
if (fotoF && fotoF.size > 2 * 1024 * 1024) {
|
||||
if (fotoF && fotoF.size > 2 * 1024 * 1024) { // 2 MB
|
||||
e.preventDefault();
|
||||
return Swal.fire({ icon:'error', title:'Foto demasiado grande', text:'La imagen no debe exceder 2 MB.' });
|
||||
}
|
||||
// Si todo OK, se envía
|
||||
// Si todas las validaciones pasan, el formulario se envía.
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -33,32 +33,32 @@
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<label for="clave" class="form-label">Clave *</label>
|
||||
<input name="clave" class="form-control" required>
|
||||
<input name="clave" id="clave" class="form-control" maxlength="8" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label for="nombre" class="form-label">Nombre *</label>
|
||||
<input name="nombre" class="form-control" required>
|
||||
<input name="nombre" id="nombre" class="form-control" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label for="rfc" class="form-label">RFC *</label>
|
||||
<input name="rfc" class="form-control" maxlength="13" required>
|
||||
<input name="rfc" id="rfc" class="form-control" maxlength="13" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label for="curp" class="form-label">CURP *</label>
|
||||
<input name="curp" class="form-control" maxlength="18" required>
|
||||
<input name="curp" id="curp" class="form-control" maxlength="18" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label for="telefono" class="form-label">Teléfono *</label>
|
||||
<input name="telefono" class="form-control" maxlength="11" required>
|
||||
<input name="telefono" id="telefono" class="form-control" maxlength="11" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label for="caat" class="form-label">Código CAAT *</label>
|
||||
<input name="caat" class="form-control" required>
|
||||
<input name="caat" id="caat" class="form-control" maxlength="20" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
@@ -75,7 +75,7 @@
|
||||
|
||||
<div class="col-md-4">
|
||||
<label for="entidad" class="form-label">Entidad *</label>
|
||||
<select id="estado" name="entidad" class="form-select" required disabled>
|
||||
<select id="entidad" name="entidad" class="form-select" required disabled>
|
||||
<option value="">Primero país…</option>
|
||||
</select>
|
||||
</div>
|
||||
@@ -89,7 +89,7 @@
|
||||
|
||||
<div class="col-md-8">
|
||||
<label for="domicilio" class="form-label">Domicilio *</label>
|
||||
<input name="domicilio" class="form-control" required>
|
||||
<input name="domicilio" id="domicilio" class="form-control" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -102,79 +102,201 @@
|
||||
|
||||
<script>
|
||||
document.getElementById('formAltaTransportista').addEventListener('submit', function(e) {
|
||||
const rfcInput = document.querySelector('input[name="rfc"]');
|
||||
const curpInput = document.querySelector('input[name="curp"]');
|
||||
const telefonoInput = document.querySelector('input[name="telefono"]');
|
||||
e.preventDefault(); // Prevenir envío por defecto
|
||||
|
||||
const rfcInput = document.getElementById('rfc');
|
||||
const curpInput = document.getElementById('curp');
|
||||
const telefonoInput = document.getElementById('telefono');
|
||||
|
||||
const rfc = rfcInput.value.trim().toUpperCase();
|
||||
const curp = curpInput.value.trim();
|
||||
const telefono = telefonoInput.value.trim();
|
||||
const clave = document.getElementById('clave').value.trim();
|
||||
const nombre = document.getElementById('nombre').value.trim();
|
||||
const caat = document.getElementById('caat').value.trim();
|
||||
const pais = document.getElementById('pais').value;
|
||||
const entidad = document.getElementById('entidad').value;
|
||||
const ciudad = document.getElementById('ciudad').value;
|
||||
const domicilio = document.getElementById('domicilio').value.trim();
|
||||
|
||||
// Expresiones regulares
|
||||
const curpRegex = /^[A-Z]{4}[0-9]{6}[HM](AS|BC|BS|CC|CL|CM|CS|CH|DF|DG|GT|GR|HG|JC|MC|MN|MS|NT|NL|OC|PL|QT|QR|SP|SL|SR|TC|TS|TL|VZ|YN|ZS)[A-Z]{3}[A-Z0-9]{2}$/;
|
||||
const rfcRegex = /^[A-ZÑ&]{3,4}\d{6}[A-Z0-9]{3}$/;
|
||||
const telefonoRegex = /^\d{3}\s\d{7}$/;
|
||||
const soloNumerosRegex = /^[0-9]+$/;
|
||||
|
||||
// Validación de correo
|
||||
if (!curpRegex.test(curp)) {
|
||||
e.preventDefault();
|
||||
Swal.fire("CURP inválido", "No tiene el formato correcto.", "error");
|
||||
emailInput.focus();
|
||||
// Validaciones de campos obligatorios
|
||||
if (!clave) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'La clave es obligatoria.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('clave').focus();
|
||||
return;
|
||||
}
|
||||
if (clave.length > 8) {
|
||||
Swal.fire({ icon: 'error', title: 'Clave inválida', text: 'La clave no puede tener más de 8 caracteres.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('clave').focus();
|
||||
return;
|
||||
}
|
||||
if (!nombre) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'El nombre es obligatorio.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('nombre').focus();
|
||||
return;
|
||||
}
|
||||
if (!rfc) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'El RFC es obligatorio.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('rfc').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
// Validación de RFC
|
||||
if (!rfcRegex.test(rfc)) {
|
||||
e.preventDefault();
|
||||
Swal.fire("RFC inválido", "El RFC debe tener 12 o 13 caracteres con el formato correcto (ej. ABC123456XYZ).", "error");
|
||||
rfcInput.focus();
|
||||
Swal.fire({ icon: 'error', title: 'RFC inválido', text: 'El RFC debe tener 12 o 13 caracteres con el formato correcto (ej. ABC123456XYZ).', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('rfc').focus();
|
||||
return;
|
||||
}
|
||||
if (!curp) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'El CURP es obligatorio.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('curp').focus();
|
||||
return;
|
||||
}
|
||||
// Validación de CURP (solo si se ingresó)
|
||||
if (curp && !curpRegex.test(curp)) {
|
||||
Swal.fire({ icon: 'error', title: 'CURP inválido', text: 'El CURP no tiene el formato correcto.', confirmButtonColor: '#dc3545'
|
||||
});
|
||||
document.getElementById('curp').focus();
|
||||
return;
|
||||
}
|
||||
if (!telefono) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'El teléfono es obligatorio.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('telefono').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
// Validación de teléfono
|
||||
if (!telefonoRegex.test(telefono)) {
|
||||
e.preventDefault();
|
||||
Swal.fire("Teléfono inválido", "Debe tener 10 dígitos en el formato: 3 dígitos (LADA), espacio, y 7 dígitos. Ejemplo: 123 4567890", "error");
|
||||
phoneInput.focus();
|
||||
Swal.fire({ icon: 'error', title: 'Teléfono inválido', text: 'Debe tener 10 dígitos en el formato: 3 dígitos (LADA), espacio, y 7 dígitos. Ejemplo: 123 4567890', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('telefono').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
// Si no hay errores, enviar el formulario
|
||||
this.submit(); // Esto sí lo envía manualmente
|
||||
if (telefono.length > 11) {
|
||||
Swal.fire({ icon: 'error', title: 'Teléfono inválido', text: 'El teléfono no puede tener más de 11 caracteres.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('telefono').focus();
|
||||
return;
|
||||
}
|
||||
if (!caat) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'El código CAAT es obligatorio.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('caat').focus();
|
||||
return;
|
||||
}
|
||||
if (!soloNumerosRegex.test(caat)) {
|
||||
Swal.fire({ icon: 'error', title: 'Código CAAT inválido', text: 'El código caat solo puede contener números', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('caat').focus();
|
||||
return;
|
||||
}
|
||||
if (!pais) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'Debe seleccionar un país.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('pais').focus();
|
||||
return;
|
||||
}
|
||||
if (!entidad) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'Debe seleccionar un estado.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('entidad').focus();
|
||||
return;
|
||||
}
|
||||
if (!ciudad) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'Debe seleccionar una ciudad.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('ciudad').focus();
|
||||
return;
|
||||
}
|
||||
if (!domicilio) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'El domicilio es obligatorio.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('domicilio').focus();
|
||||
return;
|
||||
}
|
||||
// Si llegamos aquí, todas las validaciones pasaron
|
||||
// Actualizar los valores en los campos antes de enviar
|
||||
document.getElementById('rfc').value = rfc;
|
||||
document.getElementById('curp').value = curp;
|
||||
|
||||
// Enviar el formulario
|
||||
this.submit();
|
||||
});
|
||||
|
||||
// Active inputs entidad y ciudad
|
||||
// Funcionalidad de selects en cascada
|
||||
// 1) Cuando elige país → cargo estados
|
||||
document.getElementById('pais').addEventListener('change', e => {
|
||||
const pid = e.target.value;
|
||||
const sel = document.getElementById('estado');
|
||||
sel.innerHTML = '<option>Cargando…</option>';
|
||||
sel.disabled = true;
|
||||
document.getElementById('ciudad').innerHTML = '<option>Primero estado…</option>';
|
||||
document.getElementById('ciudad').disabled = true;
|
||||
const estadoSelect = document.getElementById('entidad');
|
||||
const ciudadSelect = document.getElementById('ciudad');
|
||||
|
||||
// Resetear selects dependientes
|
||||
estadoSelect.innerHTML = '<option value="">Cargando…</option>';
|
||||
estadoSelect.disabled = true;
|
||||
ciudadSelect.innerHTML = '<option value="">Primero estado…</option>';
|
||||
ciudadSelect.disabled = true;
|
||||
|
||||
if (!pid) {
|
||||
estadoSelect.innerHTML = '<option value="">Primero país…</option>';
|
||||
return;
|
||||
}
|
||||
|
||||
// Simulación de carga de estados (reemplaza con tu endpoint real)
|
||||
fetch(`/IMPORTADORES/transportistas/estados?pais=${pid}`)
|
||||
.then(r=>r.json())
|
||||
.then(list=>{
|
||||
sel.innerHTML = '<option value="">Selecciona estado</option>';
|
||||
list.forEach(st => sel.add(new Option(st.nombre, st.id_estado)));
|
||||
sel.disabled = false;
|
||||
.then(r => {
|
||||
if (!r.ok) throw new Error('Error al cargar estados');
|
||||
return r.json();
|
||||
})
|
||||
.then(list => {
|
||||
estadoSelect.innerHTML = '<option value="">Selecciona estado</option>';
|
||||
list.forEach(st => {
|
||||
const option = new Option(st.nombre, st.id_estado);
|
||||
estadoSelect.add(option);
|
||||
});
|
||||
estadoSelect.disabled = false;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
estadoSelect.innerHTML = '<option value="">Error al cargar</option>';
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Error',
|
||||
text: 'No se pudieron cargar los estados',
|
||||
confirmButtonColor: '#dc3545'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// 2) Cuando elige estado → cargo ciudades
|
||||
document.getElementById('estado').addEventListener('change', e => {
|
||||
document.getElementById('entidad').addEventListener('change', e => {
|
||||
const eid = e.target.value;
|
||||
const sel = document.getElementById('ciudad');
|
||||
sel.innerHTML = '<option>Cargando…</option>';
|
||||
sel.disabled = true;
|
||||
const ciudadSelect = document.getElementById('ciudad');
|
||||
|
||||
ciudadSelect.innerHTML = '<option value="">Cargando…</option>';
|
||||
ciudadSelect.disabled = true;
|
||||
|
||||
if (!eid) {
|
||||
ciudadSelect.innerHTML = '<option value="">Primero estado…</option>';
|
||||
return;
|
||||
}
|
||||
|
||||
// Simulación de carga de ciudades (reemplaza con tu endpoint real)
|
||||
fetch(`/IMPORTADORES/transportistas/ciudades?estado=${eid}`)
|
||||
.then(r=>r.json())
|
||||
.then(list=>{
|
||||
sel.innerHTML = '<option value="">Selecciona ciudad</option>';
|
||||
list.forEach(ct => sel.add(new Option(ct.nombre, ct.id_ciudad)));
|
||||
sel.disabled = false;
|
||||
.then(r => {
|
||||
if (!r.ok) throw new Error('Error al cargar ciudades');
|
||||
return r.json();
|
||||
})
|
||||
.then(list => {
|
||||
ciudadSelect.innerHTML = '<option value="">Selecciona ciudad</option>';
|
||||
list.forEach(ct => {
|
||||
const option = new Option(ct.nombre, ct.id_ciudad);
|
||||
ciudadSelect.add(option);
|
||||
});
|
||||
ciudadSelect.disabled = false;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
ciudadSelect.innerHTML = '<option value="">Error al cargar</option>';
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Error',
|
||||
text: 'No se pudieron cargar las ciudades',
|
||||
confirmButtonColor: '#dc3545'
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<!-- SweetAlert2 -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||
<style>
|
||||
body { font-family: 'Segoe UI', sans-serif; background-color: #f4f6f9; }
|
||||
.sidebar { width: 220px; height: 100vh; background-color: #343a40; position: fixed; top: 0; left: 0; padding-top: 56px; z-index: 1040; }
|
||||
@@ -32,38 +34,38 @@
|
||||
|
||||
<div class="content">
|
||||
<h4 class="mb-4">✏️ Editar Transportista #<?= $t['id_transportista'] ?></h4>
|
||||
<form action="/IMPORTADORES/transportistas/actualizar" method="POST" class="card p-4 shadow-sm">
|
||||
<form action="/IMPORTADORES/transportistas/actualizar" method="POST" class="card p-4 shadow-sm" id="formEditTransportista">
|
||||
<input type="hidden" name="id_transportista" value="<?= $t['id_transportista'] ?>">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Clave</label>
|
||||
<input name="clave" value="<?= htmlspecialchars($t['clave_identificador']) ?>"
|
||||
class="form-control" required>
|
||||
id="clave" class="form-control" maxlength="8" required>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Nombre</label>
|
||||
<input name="nombre" value="<?= htmlspecialchars($t['nombre']) ?>"
|
||||
class="form-control" required>
|
||||
id="nombre" class="form-control" required>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">RFC</label>
|
||||
<input name="rfc" value="<?= htmlspecialchars($t['rfc']) ?>"
|
||||
class="form-control" required>
|
||||
id="rfc" class="form-control" maxlength="13" required>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">CURP</label>
|
||||
<input name="curp" value="<?= htmlspecialchars($t['curp']) ?>"
|
||||
class="form-control">
|
||||
id="curp" class="form-control" maxlength="18">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Teléfono</label>
|
||||
<input name="telefono" value="<?= htmlspecialchars($t['telefono']) ?>"
|
||||
class="form-control" required>
|
||||
id="telefono" class="form-control" maxlength="11" required>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Código CAAT</label>
|
||||
<input name="caat" value="<?= htmlspecialchars($t['caat']) ?>"
|
||||
class="form-control" required>
|
||||
id="caat" class="form-control" maxlength="20" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
@@ -80,7 +82,7 @@
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Estado</label>
|
||||
<select id="estado" name="entidad" class="form-select" required>
|
||||
<select id="entidad" name="entidad" class="form-select" required>
|
||||
<option value="">Selecciona estado</option>
|
||||
<?php foreach($estados as $e): ?>
|
||||
<option value="<?= $e['id_estado'] ?>"
|
||||
@@ -105,7 +107,7 @@
|
||||
|
||||
<div class="col-md-12">
|
||||
<label class="form-label">Domicilio Completo</label>
|
||||
<textarea name="domicilio" class="form-control" rows="3" required><?= htmlspecialchars($t['domicilio']) ?></textarea>
|
||||
<textarea name="domicilio" id="domicilio" class="form-control" rows="3" required><?= htmlspecialchars($t['domicilio']) ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-end mt-4">
|
||||
@@ -116,31 +118,202 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Al cambiar país → recargar estados
|
||||
document.getElementById('pais').addEventListener('change', function(){
|
||||
const pid = this.value, selE = document.getElementById('estado');
|
||||
selE.innerHTML = '<option>Cargando…</option>'; selE.disabled = true;
|
||||
document.getElementById('formEditTransportista').addEventListener('submit', function(e) {
|
||||
e.preventDefault(); // Prevenir envío por defecto
|
||||
|
||||
const rfcInput = document.getElementById('rfc');
|
||||
const curpInput = document.getElementById('curp');
|
||||
const telefonoInput = document.getElementById('telefono');
|
||||
|
||||
const rfc = rfcInput.value.trim().toUpperCase();
|
||||
const curp = curpInput.value.trim();
|
||||
const telefono = telefonoInput.value.trim();
|
||||
const clave = document.getElementById('clave').value.trim();
|
||||
const nombre = document.getElementById('nombre').value.trim();
|
||||
const caat = document.getElementById('caat').value.trim();
|
||||
const pais = document.getElementById('pais').value;
|
||||
const entidad = document.getElementById('entidad').value;
|
||||
const ciudad = document.getElementById('ciudad').value;
|
||||
const domicilio = document.getElementById('domicilio').value.trim();
|
||||
|
||||
// Expresiones regulares
|
||||
const curpRegex = /^[A-Z]{4}[0-9]{6}[HM](AS|BC|BS|CC|CL|CM|CS|CH|DF|DG|GT|GR|HG|JC|MC|MN|MS|NT|NL|OC|PL|QT|QR|SP|SL|SR|TC|TS|TL|VZ|YN|ZS)[A-Z]{3}[A-Z0-9]{2}$/;
|
||||
const rfcRegex = /^[A-ZÑ&]{3,4}\d{6}[A-Z0-9]{3}$/;
|
||||
const telefonoRegex = /^\d{3}\s\d{7}$/;
|
||||
const soloNumerosRegex = /^[0-9]+$/;
|
||||
|
||||
// Validaciones de campos obligatorios
|
||||
if (!clave) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'La clave es obligatoria.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('clave').focus();
|
||||
return;
|
||||
}
|
||||
if (clave.length > 8) {
|
||||
Swal.fire({ icon: 'error', title: 'Clave inválida', text: 'La clave no puede tener más de 8 caracteres.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('clave').focus();
|
||||
return;
|
||||
}
|
||||
if (!nombre) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'El nombre es obligatorio.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('nombre').focus();
|
||||
return;
|
||||
}
|
||||
if (!rfc) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'El RFC es obligatorio.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('rfc').focus();
|
||||
return;
|
||||
}
|
||||
if (!rfcRegex.test(rfc)) {
|
||||
Swal.fire({ icon: 'error', title: 'RFC inválido', text: 'El RFC debe tener 12 o 13 caracteres con el formato correcto (ej. ABC123456XYZ).', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('rfc').focus();
|
||||
return;
|
||||
}
|
||||
if (!curp) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'El CURP es obligatorio.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('curp').focus();
|
||||
return;
|
||||
}
|
||||
// Validación de CURP (solo si se ingresó)
|
||||
if (curp && !curpRegex.test(curp)) {
|
||||
Swal.fire({ icon: 'error', title: 'CURP inválido', text: 'El CURP no tiene el formato correcto.', confirmButtonColor: '#dc3545'
|
||||
});
|
||||
document.getElementById('curp').focus();
|
||||
return;
|
||||
}
|
||||
if (!telefono) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'El teléfono es obligatorio.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('telefono').focus();
|
||||
return;
|
||||
}
|
||||
if (!telefonoRegex.test(telefono)) {
|
||||
Swal.fire({ icon: 'error', title: 'Teléfono inválido', text: 'Debe tener 10 dígitos en el formato: 3 dígitos (LADA), espacio, y 7 dígitos. Ejemplo: 123 4567890', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('telefono').focus();
|
||||
return;
|
||||
}
|
||||
if (telefono.length > 11) {
|
||||
Swal.fire({ icon: 'error', title: 'Teléfono inválido', text: 'El teléfono no puede tener más de 11 caracteres.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('telefono').focus();
|
||||
return;
|
||||
}
|
||||
if (!caat) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'El código CAAT es obligatorio.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('caat').focus();
|
||||
return;
|
||||
}
|
||||
if (!soloNumerosRegex.test(caat)) {
|
||||
Swal.fire({ icon: 'error', title: 'Código CAAT inválido', text: 'El código caat solo puede contener números', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('caat').focus();
|
||||
return;
|
||||
}
|
||||
if (!pais) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'Debe seleccionar un país.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('pais').focus();
|
||||
return;
|
||||
}
|
||||
if (!entidad) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'Debe seleccionar un estado.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('entidad').focus();
|
||||
return;
|
||||
}
|
||||
if (!ciudad) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'Debe seleccionar una ciudad.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('ciudad').focus();
|
||||
return;
|
||||
}
|
||||
if (!domicilio) {
|
||||
Swal.fire({ icon: 'error', title: 'Campo requerido', text: 'El domicilio es obligatorio.', confirmButtonColor: '#dc3545' });
|
||||
document.getElementById('domicilio').focus();
|
||||
return;
|
||||
}
|
||||
// Si llegamos aquí, todas las validaciones pasaron
|
||||
// Actualizar los valores en los campos antes de enviar
|
||||
document.getElementById('rfc').value = rfc;
|
||||
document.getElementById('curp').value = curp;
|
||||
|
||||
// Enviar el formulario
|
||||
this.submit();
|
||||
});
|
||||
|
||||
// Funcionalidad de selects en cascada
|
||||
// 1) Cuando elige país → cargo estados
|
||||
document.getElementById('pais').addEventListener('change', e => {
|
||||
const pid = e.target.value;
|
||||
const estadoSelect = document.getElementById('entidad');
|
||||
const ciudadSelect = document.getElementById('ciudad');
|
||||
|
||||
// Resetear selects dependientes
|
||||
estadoSelect.innerHTML = '<option value="">Cargando…</option>';
|
||||
estadoSelect.disabled = true;
|
||||
ciudadSelect.innerHTML = '<option value="">Primero estado…</option>';
|
||||
ciudadSelect.disabled = true;
|
||||
|
||||
if (!pid) {
|
||||
estadoSelect.innerHTML = '<option value="">Primero país…</option>';
|
||||
return;
|
||||
}
|
||||
|
||||
// Simulación de carga de estados (reemplaza con tu endpoint real)
|
||||
fetch(`/IMPORTADORES/transportistas/estados?pais=${pid}`)
|
||||
.then(r=>r.json())
|
||||
.then(list=>{
|
||||
selE.innerHTML = '<option value="">Selecciona estado</option>';
|
||||
list.forEach(e=> selE.add(new Option(e.nombre,e.id_estado)) );
|
||||
selE.disabled = false;
|
||||
// Dispara cambio para recargar ciudades
|
||||
selE.dispatchEvent(new Event('change'));
|
||||
.then(r => {
|
||||
if (!r.ok) throw new Error('Error al cargar estados');
|
||||
return r.json();
|
||||
})
|
||||
.then(list => {
|
||||
estadoSelect.innerHTML = '<option value="">Selecciona estado</option>';
|
||||
list.forEach(st => {
|
||||
const option = new Option(st.nombre, st.id_estado);
|
||||
estadoSelect.add(option);
|
||||
});
|
||||
estadoSelect.disabled = false;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
estadoSelect.innerHTML = '<option value="">Error al cargar</option>';
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Error',
|
||||
text: 'No se pudieron cargar los estados',
|
||||
confirmButtonColor: '#dc3545'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Al cambiar estado → recargar ciudades
|
||||
document.getElementById('estado').addEventListener('change', function(){
|
||||
const eid = this.value, selC = document.getElementById('ciudad');
|
||||
selC.innerHTML = '<option>Cargando…</option>'; selC.disabled = true;
|
||||
// 2) Cuando elige estado → cargo ciudades
|
||||
document.getElementById('entidad').addEventListener('change', e => {
|
||||
const eid = e.target.value;
|
||||
const ciudadSelect = document.getElementById('ciudad');
|
||||
|
||||
ciudadSelect.innerHTML = '<option value="">Cargando…</option>';
|
||||
ciudadSelect.disabled = true;
|
||||
|
||||
if (!eid) {
|
||||
ciudadSelect.innerHTML = '<option value="">Primero estado…</option>';
|
||||
return;
|
||||
}
|
||||
|
||||
// Simulación de carga de ciudades (reemplaza con tu endpoint real)
|
||||
fetch(`/IMPORTADORES/transportistas/ciudades?estado=${eid}`)
|
||||
.then(r=>r.json())
|
||||
.then(list=>{
|
||||
selC.innerHTML = '<option value="">Selecciona ciudad</option>';
|
||||
list.forEach(c=> selC.add(new Option(c.nombre,c.id_ciudad)) );
|
||||
selC.disabled = false;
|
||||
.then(r => {
|
||||
if (!r.ok) throw new Error('Error al cargar ciudades');
|
||||
return r.json();
|
||||
})
|
||||
.then(list => {
|
||||
ciudadSelect.innerHTML = '<option value="">Selecciona ciudad</option>';
|
||||
list.forEach(ct => {
|
||||
const option = new Option(ct.nombre, ct.id_ciudad);
|
||||
ciudadSelect.add(option);
|
||||
});
|
||||
ciudadSelect.disabled = false;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
ciudadSelect.innerHTML = '<option value="">Error al cargar</option>';
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Error',
|
||||
text: 'No se pudieron cargar las ciudades',
|
||||
confirmButtonColor: '#dc3545'
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user