This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
// app/controllers/proveedores.php
|
||||
|
||||
session_start();
|
||||
|
||||
// 1) Composer autoload (phpdotenv y demás libs)
|
||||
@@ -10,13 +9,9 @@ require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
require_once __DIR__ . '/../helpers/env.php';
|
||||
loadEnv();
|
||||
|
||||
/**
|
||||
* Obtiene (y cachea en sesión) el JWT de la API usando las credenciales de $_ENV
|
||||
*/
|
||||
/**
|
||||
* Obtiene (y cachea) el JWT de la API usando credenciales de $_ENV
|
||||
* Gestiona expiración: asume 1 hora de vida y renueva si ha pasado.
|
||||
*/
|
||||
/** Obtiene (y cachea en sesión) el JWT de la API usando las credenciales de $_ENV **/
|
||||
/** Obtiene (y cachea) el JWT de la API usando credenciales de $_ENV
|
||||
* Gestiona expiración: asume 1 hora de vida y renueva si ha pasado. **/
|
||||
function getApiToken(): ?string
|
||||
{
|
||||
// Duración en segundos del token (60 min)
|
||||
@@ -66,11 +61,8 @@ function getApiToken(): ?string
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* GET /IMPORTADORES/proveedores
|
||||
* Muestra la vista de listado
|
||||
*/
|
||||
/** GET /IMPORTADORES/proveedores
|
||||
* Muestra la vista de listado **/
|
||||
function index()
|
||||
{
|
||||
lista();
|
||||
@@ -85,14 +77,10 @@ function lista()
|
||||
include __DIR__ . '/../../views/proveedores/lista.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /IMPORTADORES/proveedores/ajax_lista
|
||||
* Devuelve JSON para DataTables
|
||||
*/
|
||||
/**
|
||||
* GET /IMPORTADORES/proveedores/ajax_lista
|
||||
* Devuelve JSON para DataTables (siempre HTTP 200)
|
||||
*/
|
||||
/** GET /IMPORTADORES/proveedores/ajax_lista
|
||||
* Devuelve JSON para DataTables
|
||||
* GET /IMPORTADORES/proveedores/ajax_lista
|
||||
* Devuelve JSON para DataTables (siempre HTTP 200) **/
|
||||
function ajax_lista()
|
||||
{
|
||||
// 1) Fijamos el header JSON
|
||||
@@ -164,10 +152,8 @@ function ajax_lista()
|
||||
echo json_encode(['data' => $dataList]);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /IMPORTADORES/proveedores/eliminar
|
||||
* Llama a DELETE /api/proveedores/:clave y redirige
|
||||
*/
|
||||
/** GET /IMPORTADORES/proveedores/eliminar
|
||||
* Llama a DELETE /api/proveedores/:clave y redirige **/
|
||||
function eliminar()
|
||||
{
|
||||
$token = getApiToken();
|
||||
@@ -207,10 +193,8 @@ function crear()
|
||||
include __DIR__ . '/../../views/proveedores/crear.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /IMPORTADORES/proveedores/guardar
|
||||
* Procesa el alta de un nuevo proveedor contra la API WinSAAI.
|
||||
*/
|
||||
/** POST /IMPORTADORES/proveedores/guardar
|
||||
* Procesa el alta de un nuevo proveedor contra la API WinSAAI. **/
|
||||
function guardar()
|
||||
{
|
||||
// 1) Validar sesión
|
||||
|
||||
@@ -164,7 +164,7 @@ function guardar()
|
||||
$transportista_id = $_POST['transportista_id'] ?? null;
|
||||
$chofer_id = $_POST['chofer_id'] ?? null;
|
||||
$status = isset($_POST['status']) ? 1 : 0;
|
||||
$proveedor_clave = trim($_POST['proveedor_id'] ?? '');
|
||||
$proveedor_clave = trim($_POST['proveedor_id'] ?? '');
|
||||
|
||||
if (empty($num_factura) || empty($fecha) || empty($transportista_id) || empty($chofer_id)) {
|
||||
die("❌ Faltan campos obligatorios.");
|
||||
@@ -933,14 +933,80 @@ function generarHTMLPDF($solicitud, $partidas, $nombre_sistema, $siglas, $logo_u
|
||||
($solicitud['codigo_postal'] ?? '')
|
||||
);
|
||||
|
||||
// Calcular totales
|
||||
$subtotal = 0;
|
||||
// Calcular el total sumando todas las partidas
|
||||
$total = 0;
|
||||
foreach ($partidas as $partida) {
|
||||
$subtotal += (float)$partida['valor_factura'];
|
||||
$total += (float)($partida['valor_factura'] ?? 0);
|
||||
}
|
||||
|
||||
// Función para convertir número a texto
|
||||
function numeroATexto($numero) {
|
||||
$unidades = ['', 'uno', 'dos', 'tres', 'cuatro', 'cinco', 'seis', 'siete', 'ocho', 'nueve'];
|
||||
$decenas = ['', '', 'veinte', 'treinta', 'cuarenta', 'cincuenta', 'sesenta', 'setenta', 'ochenta', 'noventa'];
|
||||
$especiales = ['diez', 'once', 'doce', 'trece', 'catorce', 'quince', 'dieciséis', 'diecisiete', 'dieciocho', 'diecinueve'];
|
||||
$centenas = ['', 'ciento', 'doscientos', 'trescientos', 'cuatrocientos', 'quinientos', 'seiscientos', 'setecientos', 'ochocientos', 'novecientos'];
|
||||
|
||||
if ($numero == 0) return 'cero';
|
||||
if ($numero == 100) return 'cien';
|
||||
if ($numero == 1000) return 'mil';
|
||||
if ($numero == 1000000) return 'un millón';
|
||||
|
||||
$resultado = '';
|
||||
|
||||
// Millones
|
||||
if ($numero >= 1000000) {
|
||||
$millones = intval($numero / 1000000);
|
||||
if ($millones == 1) {
|
||||
$resultado .= 'un millón ';
|
||||
} else {
|
||||
$resultado .= numeroATexto($millones) . ' millones ';
|
||||
}
|
||||
$numero %= 1000000;
|
||||
}
|
||||
|
||||
// Miles
|
||||
if ($numero >= 1000) {
|
||||
$miles = intval($numero / 1000);
|
||||
if ($miles == 1) {
|
||||
$resultado .= 'mil ';
|
||||
} else {
|
||||
$resultado .= numeroATexto($miles) . ' mil ';
|
||||
}
|
||||
$numero %= 1000;
|
||||
}
|
||||
|
||||
// Centenas
|
||||
if ($numero >= 100) {
|
||||
$resultado .= $centenas[intval($numero / 100)] . ' ';
|
||||
$numero %= 100;
|
||||
}
|
||||
|
||||
// Decenas y unidades
|
||||
if ($numero >= 20) {
|
||||
$resultado .= $decenas[intval($numero / 10)];
|
||||
if ($numero % 10 != 0) {
|
||||
$resultado .= ' y ' . $unidades[$numero % 10];
|
||||
}
|
||||
} elseif ($numero >= 10) {
|
||||
$resultado .= $especiales[$numero - 10];
|
||||
} elseif ($numero > 0) {
|
||||
$resultado .= $unidades[$numero];
|
||||
}
|
||||
|
||||
return trim($resultado);
|
||||
}
|
||||
|
||||
// Convertir total a texto
|
||||
$partes = explode('.', number_format($total, 2, '.', ''));
|
||||
$pesos = (int)$partes[0];
|
||||
$centavos = (int)$partes[1];
|
||||
|
||||
$total_texto = strtoupper(numeroATexto($pesos)) . ' PESOS';
|
||||
if ($centavos > 0) {
|
||||
$total_texto .= ' CON ' . str_pad($centavos, 2, '0', STR_PAD_LEFT) . '/100 M.N.';
|
||||
} else {
|
||||
$total_texto .= ' 00/100 M.N.';
|
||||
}
|
||||
$descuento_pct = 0; // Puedes calcularlo si tienes descuentos
|
||||
$descuento = $subtotal * ($descuento_pct / 100);
|
||||
$total = $subtotal - $descuento;
|
||||
|
||||
$html = '
|
||||
<!DOCTYPE html>
|
||||
@@ -950,83 +1016,86 @@ function generarHTMLPDF($solicitud, $partidas, $nombre_sistema, $siglas, $logo_u
|
||||
<title>Solicitud de Importación</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; font-size: 9px; margin: 0; padding: 15px; line-height: 1.2; }
|
||||
.header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 10px; border-bottom: 2px solid #000; padding-bottom: 10px; }
|
||||
.logo-section { width: 120px; }
|
||||
<!-- Encabezado -->
|
||||
.header { margin-bottom: 10px; border-bottom: 2px solid #000; padding-bottom: 10px; font-size: 10px; }
|
||||
.logo-section { width: 20%; text-align: left; vertical-align: center; }
|
||||
.logo { max-width: 100px; height: auto; }
|
||||
.company-info { flex: 1; text-align: center; margin: 0 20px; }
|
||||
.company-name { font-weight: bold; font-size: 12px; margin-bottom: 3px; }
|
||||
.invoice-info { width: 180px; border: 1px solid #000; padding: 8px; }
|
||||
.invoice-title { background-color: #f0f0f0; text-align: center; font-weight: bold; margin-bottom: 5px; padding: 3px; }
|
||||
.info-section { display: flex; margin-bottom: 15px; }
|
||||
.client-info, .dates-info { flex: 1; border: 1px solid #000; margin-right: 10px; padding: 8px; }
|
||||
.dates-info { margin-right: 0; width: 200px; }
|
||||
.section-title { background-color: #d0d0d0; font-weight: bold; padding: 3px; margin-bottom: 5px; text-align: center; }
|
||||
.products-table { width: 100%; border-collapse: collapse; margin-bottom: 15px; border: 1px solid #000; }
|
||||
.products-table th,
|
||||
.products-table td { border: 1px solid #000; padding: 4px; text-align: left; font-size: 8px; }
|
||||
.products-table th { background-color: #f0f0f0; font-weight: bold; text-align: center; }
|
||||
.company-info { width: 60%; text-align: center; vertical-align: top; }
|
||||
.company-name { font-weight: bold; font-size: 25px; margin-bottom: 3px; }
|
||||
.invoice-info { width: 20%; text-align: right; vertical-align: top; font-size: 12px; }
|
||||
<!-- Información del Cliente -->
|
||||
.info-section { margin-bottom: 10px; border-bottom: 2px solid #000; padding-bottom: 10px; }
|
||||
.client-info { width: 75%; border: 0.5px solid #000; margin-right: 10px; }
|
||||
.field { border-bottom: 0.5px solid #000; padding: 5px; font-size: 12px; }
|
||||
.dates-info { width: 25%; border: 0.5px solid #000; }
|
||||
.section-title { background-color: #d0d0d0; font-weight: bold; padding: 5px; text-align: center; font-size: 12px; border-right: 0.5px solid #000; }
|
||||
<!-- Partidas -->
|
||||
.products-table { border-collapse: collapse; margin-bottom: 15px; border: 1px solid #000; }
|
||||
.products-table td { border: 0.5px solid #000; padding: 10px; text-align: center; font-size: 10px; }
|
||||
.products-table th { border: 0.5px solid #000; padding: 5px; background-color: #d0d0d0; font-weight: bold; text-align: center; }
|
||||
.text-center { text-align: center; }
|
||||
.text-right { text-align: right; }
|
||||
.font-bold { font-weight: bold; }
|
||||
.totals-section { float: right; width: 250px; margin-top: 10px; }
|
||||
.total-row { display: flex; justify-content: space-between; margin-bottom: 3px; }
|
||||
.footer-info { clear: both; margin-top: 30px; font-size: 8px; background-color: #e0e0e0; padding: 5px; text-align: center; }
|
||||
<!-- Total -->
|
||||
.totals-section { float: right; width: 250px; }
|
||||
.total-row { display: flex; justify-content: space-between; margin-top: 25px; font-size: 12px; }
|
||||
<!-- Nota inferior -->
|
||||
.footer-info { }
|
||||
.footer-note { font-size: 10px; background-color: #d0d0d0; padding: 5px; border: 0.5px solid #000; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- ENCABEZADO -->
|
||||
<div class="header">
|
||||
<div class="logo-section">
|
||||
<img src="' . $logo_url . '" alt="Logo" class="logo">
|
||||
<div style="font-size: 8px; margin-top: 5px;">' . htmlspecialchars($siglas) . '</div>
|
||||
</div>
|
||||
|
||||
<div class="company-info">
|
||||
<div class="company-name">' . htmlspecialchars($nombre_sistema) . '</div>
|
||||
<div>' . htmlspecialchars($direccion_completa ?: 'Dirección no disponible') . '</div>
|
||||
<div>RFC: ' . htmlspecialchars($solicitud['importador_rfc'] ?? 'No disponible') . '</div>
|
||||
<div>Tel: ' . htmlspecialchars($solicitud['telefono'] ?? 'No disponible') . '</div>
|
||||
<div>Email: ' . htmlspecialchars($solicitud['correo'] ?? 'No disponible') . '</div>
|
||||
</div>
|
||||
|
||||
<div class="invoice-info">
|
||||
<div class="invoice-title">Solicitud de Importación</div>
|
||||
<div><strong>No. ' . htmlspecialchars($solicitud['id_solicitud']) . '</strong></div>
|
||||
<div>Régimen simplificado de confianza (RESICO) - 626</div>
|
||||
</div>
|
||||
</div>
|
||||
<table class="header" cellspacing="0" cellpadding="0" width="100%">
|
||||
<tr>
|
||||
<td class="logo-section">
|
||||
<img src="' . $logo_url . '" alt="Logo" class="logo"><br>
|
||||
</td>
|
||||
<td class="company-info">
|
||||
<div class="company-name">' . htmlspecialchars($nombre_sistema) . '</div>
|
||||
<div>' . htmlspecialchars($direccion_completa ?: 'Dirección no disponible') . '</div>
|
||||
<div>RFC: ' . htmlspecialchars($solicitud['importador_rfc'] ?? 'No disponible') . '</div>
|
||||
<div>Tel: ' . htmlspecialchars($solicitud['telefono'] ?? 'No disponible') . '</div>
|
||||
<div>Email: ' . htmlspecialchars($solicitud['correo'] ?? 'No disponible') . '</div>
|
||||
</td>
|
||||
<td class="invoice-info">
|
||||
<div class="invoice-title">Solicitud de Importación</div>
|
||||
<div><strong>No. ' . htmlspecialchars($solicitud['id_solicitud']) . '</strong></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br><br><br><br>
|
||||
|
||||
<!-- INFORMACIÓN DEL CLIENTE Y FECHAS -->
|
||||
<div class="info-section">
|
||||
<div class="client-info">
|
||||
<div class="section-title">RAZÓN SOCIAL / ' . htmlspecialchars($solicitud['importador_nombre'] ?? 'No disponible') . '</div>
|
||||
<div><strong>DOMICILIO FISCAL:</strong> ' . htmlspecialchars($direccion_completa) . '</div>
|
||||
<div style="margin-top: 10px;">
|
||||
<div><strong>RFC:</strong> ' . htmlspecialchars($solicitud['importador_rfc'] ?? 'No disponible') . '</div>
|
||||
<div><strong>TELÉFONO:</strong> ' . htmlspecialchars($solicitud['telefono'] ?? 'No disponible') . '</div>
|
||||
</div>
|
||||
<div style="margin-top: 10px;">
|
||||
<div><strong>RÉGIMEN FISCAL:</strong> 601-General de Ley Personas Morales</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dates-info">
|
||||
<div class="section-title">FECHA DE EXPEDICIÓN</div>
|
||||
<div class="text-center font-bold" style="font-size: 12px;">' . $fecha_expedicion . '</div>
|
||||
<div class="section-title" style="margin-top: 10px;">FECHA DE VENCIMIENTO</div>
|
||||
<div class="text-center font-bold" style="font-size: 12px;">' . $fecha_vencimiento . '</div>
|
||||
</div>
|
||||
</div>
|
||||
<table class="info-section" cellspacing="0" cellpadding="0" width="100%">
|
||||
<tr>
|
||||
<td class="client-info">
|
||||
<div class="field"><strong>RAZÓN SOCIAL:</strong> ' . htmlspecialchars($solicitud['importador_nombre'] ?? 'No disponible') . '</div>
|
||||
<div class="field"><strong>DOMICILIO FISCAL:</strong> ' . htmlspecialchars($direccion_completa) . '</div>
|
||||
<div class="field"><strong>RFC:</strong> ' . htmlspecialchars($solicitud['importador_rfc'] ?? 'No disponible') . '</div>
|
||||
<div class="field"><strong>TELÉFONO:</strong> ' . htmlspecialchars($solicitud['telefono'] ?? 'No disponible') . '</div>
|
||||
<div class="field"><strong>RÉGIMEN FISCAL:</strong> 601-General de Ley Personas Morales</div>
|
||||
</td>
|
||||
<td class="dates-info">
|
||||
<table width="100%" cellspacing="0" cellpadding="2">
|
||||
<tr><td class="section-title">FECHA DE EXPEDICIÓN</td></tr>
|
||||
<tr><td class="text-center font-bold" style="font-size: 12px; border-bottom: 0.5px solid #000; padding-bottom: 15px; padding-top: 12.5px;">' . $fecha_expedicion . '</td></tr>
|
||||
<tr><td class="section-title" style="padding-top: 10px;">FECHA DE VENCIMIENTO</td></tr>
|
||||
<tr><td class="text-center font-bold" style="font-size: 12px; padding-bottom: 15px; padding-top: 12.5px;">' . $fecha_vencimiento . '</td></tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br><br><br>
|
||||
|
||||
<!-- TABLA DE PRODUCTOS/PARTIDAS -->
|
||||
<table class="products-table">
|
||||
<table class="products-table" cellspacing="0" cellpadding="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Producto</th>
|
||||
<th>Unidad de Medida</th>
|
||||
<th>Precio Unitario</th>
|
||||
<th>Cantidad</th>
|
||||
<th>Descuento</th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -1041,10 +1110,9 @@ function generarHTMLPDF($solicitud, $partidas, $nombre_sistema, $siglas, $logo_u
|
||||
$html .= '<tr>
|
||||
<td>' . htmlspecialchars($partida['descripcion']) . '</td>
|
||||
<td>' . htmlspecialchars($partida['unidad_descripcion'] ?? 'Unidad de servicio (E48)') . '</td>
|
||||
<td class="text-right">$' . number_format($precio_unitario > 0 ? $precio_unitario : $valor_partida, 2) . '</td>
|
||||
<td class="text-center">' . number_format($cantidad > 0 ? $cantidad : 1, 0) . '</td>
|
||||
<td class="text-right">' . number_format($descuento_pct, 1) . '%</td>
|
||||
<td class="text-right">$' . number_format($valor_partida, 2) . '</td>
|
||||
<td>$' . number_format($precio_unitario > 0 ? $precio_unitario : $valor_partida, 2) . '</td>
|
||||
<td>' . number_format($cantidad > 0 ? $cantidad : 1, 0) . '</td>
|
||||
<td>$' . number_format($valor_partida, 2) . '</td>
|
||||
</tr>';
|
||||
}
|
||||
|
||||
@@ -1052,19 +1120,19 @@ function generarHTMLPDF($solicitud, $partidas, $nombre_sistema, $siglas, $logo_u
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- NOTA INFERIOR -->
|
||||
<div class="footer-info">
|
||||
<div class="footer-note">' . $total_texto . '</div>
|
||||
</div>
|
||||
|
||||
<!-- TOTALES -->
|
||||
<div class="totals-section">
|
||||
<div class="total-row">
|
||||
<div class="total-row text-right">
|
||||
<span><strong>Total:</strong></span>
|
||||
<span><strong>$' . number_format($total, 2) . '</strong></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- NOTA INFERIOR -->
|
||||
<div class="footer-note">
|
||||
Veinticinco mil seiscientos 50/100 M.N
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user