ALTA PROVEEDORES
LISTADO Y ALTA DE PROVEEDORES
This commit is contained in:
2
.env
2
.env
@@ -1,4 +1,4 @@
|
|||||||
DB_HOST=DESKTOP-22T88B6
|
DB_HOST=LOCALHOST
|
||||||
DB_DATABASE=Importaciones_HC
|
DB_DATABASE=Importaciones_HC
|
||||||
DB_USERNAME=sa
|
DB_USERNAME=sa
|
||||||
DB_PASSWORD=Soluciones01
|
DB_PASSWORD=Soluciones01
|
||||||
|
|||||||
@@ -180,3 +180,92 @@ function eliminar()
|
|||||||
header('Location: /IMPORTADORES/proveedores?deleted=' . ($status===200||$status===204 ? 'ok':'error'));
|
header('Location: /IMPORTADORES/proveedores?deleted=' . ($status===200||$status===204 ? 'ok':'error'));
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function crear()
|
||||||
|
{
|
||||||
|
// 1) Aseguramos que el usuario esté logueado
|
||||||
|
if (empty($_SESSION['usuario_id'])) {
|
||||||
|
header('Location: /IMPORTADORES/login');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Cargamos la vista
|
||||||
|
include __DIR__ . '/../../views/proveedores/crear.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /IMPORTADORES/proveedores/guardar
|
||||||
|
* Procesa el alta de un nuevo proveedor contra la API WinSAAI.
|
||||||
|
*/
|
||||||
|
function guardar()
|
||||||
|
{
|
||||||
|
// 1) Validar sesión
|
||||||
|
if (empty($_SESSION['usuario_id'])) {
|
||||||
|
header('Location: /IMPORTADORES/login');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Recoger datos del formulario
|
||||||
|
$payload = [
|
||||||
|
'Clave' => trim($_POST['Clave'] ?? ''),
|
||||||
|
'Nombre' => trim($_POST['Nombre'] ?? ''),
|
||||||
|
'RFC' => trim($_POST['RFC'] ?? ''),
|
||||||
|
'Ciudad' => trim($_POST['Ciudad'] ?? ''),
|
||||||
|
'Telefono' => trim($_POST['Telefono'] ?? ''),
|
||||||
|
'Pais' => trim($_POST['Pais'] ?? ''),
|
||||||
|
'Colonia' => trim($_POST['Colonia'] ?? ''),
|
||||||
|
'Municipio' => trim($_POST['Municipio'] ?? ''),
|
||||||
|
'CodigoPostal' => trim($_POST['CodigoPostal'] ?? ''),
|
||||||
|
'EntidadFederativa' => trim($_POST['EntidadFederativa'] ?? ''),
|
||||||
|
];
|
||||||
|
|
||||||
|
// 3) Validar campos obligatorios
|
||||||
|
if ($payload['Clave']==='' || $payload['Nombre']==='' || $payload['RFC']==='' || $payload['Ciudad']==='') {
|
||||||
|
$_SESSION['flash_error'] = 'Clave, Nombre, RFC y Ciudad son obligatorios.';
|
||||||
|
header('Location: /IMPORTADORES/proveedores/crear');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4) Obtener JWT
|
||||||
|
$token = getApiToken();
|
||||||
|
if (!$token) {
|
||||||
|
$_SESSION['flash_error'] = 'No fue posible autenticar contra la API.';
|
||||||
|
header('Location: /IMPORTADORES/proveedores/crear');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5) Llamada a la API para crear el proveedor
|
||||||
|
$url = rtrim($_ENV['API_URL'] ?? '', '/') . '/api/proveedores';
|
||||||
|
$ch = curl_init($url);
|
||||||
|
curl_setopt_array($ch, [
|
||||||
|
CURLOPT_POST => true,
|
||||||
|
CURLOPT_HTTPHEADER => [
|
||||||
|
"Authorization: Bearer $token",
|
||||||
|
'Content-Type: application/json'
|
||||||
|
],
|
||||||
|
CURLOPT_POSTFIELDS => json_encode($payload),
|
||||||
|
CURLOPT_RETURNTRANSFER => true,
|
||||||
|
CURLOPT_TIMEOUT => 10,
|
||||||
|
]);
|
||||||
|
$resp = curl_exec($ch);
|
||||||
|
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
// 6) Manejar respuesta
|
||||||
|
if ($status === 201) {
|
||||||
|
// Éxito
|
||||||
|
header('Location: /IMPORTADORES/proveedores?created=ok');
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
// Error, opcionalmente parsear mensaje
|
||||||
|
$msg = '';
|
||||||
|
if ($json = json_decode($resp, true)) {
|
||||||
|
$msg = $json['mensaje'] ?? $json['error'] ?? '';
|
||||||
|
}
|
||||||
|
$_SESSION['flash_error'] = "Error al crear proveedor (HTTP $status) $msg";
|
||||||
|
header('Location: /IMPORTADORES/proveedores/crear');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
128
views/proveedores/crear.php
Normal file
128
views/proveedores/crear.php
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
<!-- views/proveedores/crear.php -->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="es">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>➕ Registro de Proveedor</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<!-- Bootstrap CSS -->
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<!-- 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; /* coincide con navbar */
|
||||||
|
z-index: 1040;
|
||||||
|
}
|
||||||
|
.sidebar .nav-link {
|
||||||
|
color: #ccc;
|
||||||
|
padding: 12px 20px;
|
||||||
|
}
|
||||||
|
.sidebar .nav-link:hover,
|
||||||
|
.sidebar .nav-link.active {
|
||||||
|
background-color: #495057;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
margin-top: 56px;
|
||||||
|
padding: 40px 20px;
|
||||||
|
background-color: #f4f6f9;
|
||||||
|
transition: margin-left .3s ease;
|
||||||
|
}
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.content { margin-left: 250px; }
|
||||||
|
}
|
||||||
|
@media (max-width: 767.98px) {
|
||||||
|
.content { margin-left: 0; }
|
||||||
|
}
|
||||||
|
.card { border-radius: 12px; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// Mostrar alerta si hay error en sesión
|
||||||
|
if (!empty($_SESSION['flash_error'])):
|
||||||
|
?>
|
||||||
|
<script>
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'error',
|
||||||
|
title: 'Error al registrar',
|
||||||
|
text: '<?= addslashes($_SESSION['flash_error']) ?>'
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<?php
|
||||||
|
unset($_SESSION['flash_error']);
|
||||||
|
endif;
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php include __DIR__ . '/../partials/sidebar_importador.php'; ?>
|
||||||
|
|
||||||
|
<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">
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<label for="Nombre" class="form-label">Nombre *</label>
|
||||||
|
<input type="text" name="Nombre" id="Nombre" class="form-control" required>
|
||||||
|
</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>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="Ciudad" class="form-label">Ciudad *</label>
|
||||||
|
<input type="text" name="Ciudad" id="Ciudad" class="form-control" required>
|
||||||
|
</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">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="Pais" class="form-label">País</label>
|
||||||
|
<input type="text" name="Pais" id="Pais" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="EntidadFederativa" class="form-label">Entidad Federativa</label>
|
||||||
|
<input type="text" name="EntidadFederativa" id="EntidadFederativa" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="Municipio" class="form-label">Municipio</label>
|
||||||
|
<input type="text" name="Municipio" id="Municipio" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="Colonia" class="form-label">Colonia</label>
|
||||||
|
<input type="text" name="Colonia" id="Colonia" class="form-control">
|
||||||
|
</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">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-4 text-end">
|
||||||
|
<a href="/IMPORTADORES/proveedores" class="btn btn-secondary me-2">Cancelar</a>
|
||||||
|
<button type="submit" class="btn btn-primary">Guardar Proveedor</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Bootstrap JS Bundle -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,14 +1,24 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="es">
|
<html lang="es">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>📄 Listado de Proveedores</title>
|
<title>📄 Listado de Proveedores</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<!-- Bootstrap y DataTables CSS -->
|
<!-- Bootstrap CSS -->
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<!-- DataTables CSS -->
|
||||||
<link href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css" rel="stylesheet">
|
<link href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css" rel="stylesheet">
|
||||||
|
<!-- SweetAlert2 -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
body { background: #f4f6f9; font-family: 'Segoe UI', sans-serif; }
|
table.dataTable thead th { background: #343a40; color: #fff; }
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Segoe UI', sans-serif;
|
||||||
|
background-color: #f4f6f9;
|
||||||
|
}
|
||||||
.sidebar {
|
.sidebar {
|
||||||
width: 220px;
|
width: 220px;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
@@ -16,31 +26,32 @@
|
|||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
padding-top: 56px; /* Alineado con la altura de la navbar */
|
padding-top: 56px; /* coincide con la navbar */
|
||||||
z-index: 1040; /* Asegura que esté por encima del contenido */
|
z-index: 1040;
|
||||||
}
|
}
|
||||||
.sidebar .nav-link {
|
.sidebar .nav-link {
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
padding: 12px 20px;
|
padding: 12px 20px;
|
||||||
}
|
}
|
||||||
.sidebar .nav-link:hover, .sidebar .nav-link.active {
|
.sidebar .nav-link:hover,
|
||||||
|
.sidebar .nav-link.active {
|
||||||
background-color: #495057;
|
background-color: #495057;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
.content {
|
|
||||||
margin-top: 56px; /* Ajusta debajo de navbar */
|
|
||||||
padding: 40px 20px;
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
background-color: #f4f6f9; /* Asegura fondo uniforme */
|
|
||||||
transition: margin-left 0.3s ease;
|
|
||||||
}
|
|
||||||
.navbar {
|
.navbar {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: 1050;
|
z-index: 1050;
|
||||||
}
|
}
|
||||||
|
.content {
|
||||||
|
margin-top: 56px; /* deja espacio para la navbar */
|
||||||
|
padding: 40px 20px;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
background-color: #f4f6f9;
|
||||||
|
transition: margin-left .3s ease;
|
||||||
|
}
|
||||||
/* A partir de dispositivos medianos (>=768px), deja espacio lateral */
|
/* A partir de dispositivos medianos (>=768px), deja espacio lateral */
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.content {
|
.content {
|
||||||
@@ -59,15 +70,18 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<!-- Sidebar -->
|
||||||
<?php include __DIR__ . '/../partials/sidebar_importador.php'; ?>
|
<?php include __DIR__ . '/../partials/sidebar_importador.php'; ?>
|
||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<br> <br>
|
|
||||||
<h4 class="mb-4">📄 Listado de Proveedores</h4>
|
<h4 class="mb-4">📄 Listado de Proveedores</h4>
|
||||||
|
<a href="/IMPORTADORES/proveedores/crear" class="btn btn-success mb-3">➕ Nuevo Proveedor</a>
|
||||||
|
|
||||||
<div class="card p-3 shadow-sm">
|
<div class="card p-3 shadow-sm">
|
||||||
<table id="proveedores-table" class="display nowrap" style="width:100%">
|
<br>
|
||||||
|
<table id="proveedores-table" class="table table-striped nowrap" style="width:100%">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Clave</th>
|
<th>Clave</th>
|
||||||
@@ -82,47 +96,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- JS: jQuery, DataTables, Bootstrap, SweetAlert2 -->
|
<!-- JS: jQuery, DataTables, Bootstrap Bundle -->
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
<script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
<script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
$(function(){
|
|
||||||
$('#proveedores-table').DataTable({
|
|
||||||
serverSide: true,
|
|
||||||
processing: true,
|
|
||||||
ajax: {
|
|
||||||
url: '/IMPORTADORES/proveedores/ajax_lista',
|
|
||||||
type: 'GET',
|
|
||||||
dataSrc: function(json) {
|
|
||||||
if (!json || !Array.isArray(json.data)) {
|
|
||||||
console.error('Respuesta inválida de ajax_lista:', json);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return json.data;
|
|
||||||
},
|
|
||||||
error: function(xhr, status, error) {
|
|
||||||
console.error('Error Ajax:', status, error, '\nResponse:', xhr.responseText);
|
|
||||||
Swal.fire({
|
|
||||||
icon: 'error',
|
|
||||||
title: 'Error al cargar proveedores',
|
|
||||||
text: 'Revisa la consola para más detalles.',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
columns: [
|
|
||||||
{ data: 0 }, { data: 1 }, { data: 2 },
|
|
||||||
{ data: 3 }, { data: 4 }, { data: 5 }
|
|
||||||
],
|
|
||||||
language: {
|
|
||||||
url: '//cdn.datatables.net/plug-ins/1.13.4/i18n/es-ES.json'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function confirmDelete(clave) {
|
function confirmDelete(clave) {
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
title: '¿Desactivar proveedor?',
|
title: '¿Desactivar proveedor?',
|
||||||
@@ -139,6 +118,33 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(function(){
|
||||||
|
$('#proveedores-table').DataTable({
|
||||||
|
processing: true,
|
||||||
|
serverSide: false,
|
||||||
|
pageLength: 25,
|
||||||
|
lengthMenu: [10,25,50,100],
|
||||||
|
scrollX: true,
|
||||||
|
ajax: {
|
||||||
|
url: '/IMPORTADORES/proveedores/ajax_lista',
|
||||||
|
type: 'GET',
|
||||||
|
dataSrc: 'data'
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{ data: 0 },
|
||||||
|
{ data: 1 },
|
||||||
|
{ data: 2 },
|
||||||
|
{ data: 3 },
|
||||||
|
{ data: 4, className: 'text-center' },
|
||||||
|
{ data: 5, className: 'text-center' }
|
||||||
|
],
|
||||||
|
language: {
|
||||||
|
processing: '<div class="spinner-border text-primary" role="status"><span class="visually-hidden">Cargando...</span></div>',
|
||||||
|
url: '//cdn.datatables.net/plug-ins/1.13.4/i18n/es-ES.json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
<?php if (isset($_GET['deleted']) && $_GET['deleted']==='ok'): ?>
|
<?php if (isset($_GET['deleted']) && $_GET['deleted']==='ok'): ?>
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
icon: 'success',
|
icon: 'success',
|
||||||
|
|||||||
Reference in New Issue
Block a user