feat: soporte para modo embebido (?embedded=1) y sincronización con siip-cashier-tools-ui

This commit is contained in:
DANYDHSV 2026-07-27 12:22:22 -06:00
parent ce5013c926
commit c269f2773b
4 changed files with 82 additions and 6 deletions

3
.gitignore vendored
View File

@ -9,7 +9,8 @@
*.jrxml *.jrxml
*.jasper *.jasper
vouchers_oxxo/ vouchers_oxxo/
comprobantes/ comprobantes/*
!comprobantes/.gitkeep
pack-plugin-versioned.php pack-plugin-versioned.php
*.txt *.txt
Callbell Public API.postman_collection.json Callbell Public API.postman_collection.json

1
comprobantes/.gitkeep Normal file
View File

@ -0,0 +1 @@
# Keep directory in git

View File

@ -394,6 +394,15 @@ if (isset($_GET['action'])) {
'description' => mb_substr($job['description'] ?? '', 0, 80) 'description' => mb_substr($job['description'] ?? '', 0, 80)
]; ];
} }
// Ordenar por fecha descendente (de más reciente a más antiguo)
usort($result, function ($a, $b) {
$dateA = $a['date'] ?? '';
$dateB = $b['date'] ?? '';
if ($dateA === $dateB) {
return 0;
}
return ($dateA > $dateB) ? -1 : 1;
});
echo json_encode($result); echo json_encode($result);
} catch (\Exception $e) { } catch (\Exception $e) {
echo json_encode([]); echo json_encode([]);
@ -477,7 +486,67 @@ $installersData = json_decode($config['installersDataWhatsApp'] ?? '{"instalador
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SIIP - Notificaciones y Pagos</title> <title>SIIP - Notificaciones y Pagos</title>
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;700&display=swap" rel="stylesheet">
<script>
// Embedded mode & Session Inheritance
(function() {
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.get('embedded') === '1') {
document.documentElement.classList.add('is-embedded');
if (window.parent && window.parent !== window) {
try {
const parentToken = window.parent.sessionStorage.getItem('nms_auth_token');
const parentUser = window.parent.sessionStorage.getItem('nms_user');
if (parentToken && !sessionStorage.getItem('nms_auth_token')) {
sessionStorage.setItem('nms_auth_token', parentToken);
}
if (parentUser && !sessionStorage.getItem('nms_user')) {
sessionStorage.setItem('nms_user', parentUser);
}
} catch(e) {}
}
document.addEventListener('DOMContentLoaded', function() {
const loginOverlay = document.getElementById('loginOverlay');
if (loginOverlay) {
loginOverlay.style.display = 'none';
loginOverlay.classList.add('hidden');
}
const tabParam = urlParams.get('tab') || urlParams.get('module');
if (tabParam && typeof showModule === 'function') {
showModule(tabParam);
}
if (urlParams.get('hide_nav') === '1') {
const tabsNav = document.querySelector('.tabs');
if (tabsNav) tabsNav.style.display = 'none';
}
const themeParam = urlParams.get('theme');
if (themeParam) {
document.documentElement.setAttribute('data-theme', themeParam);
}
});
}
})();
</script>
<style> <style>
/* Embedded Mode Support */
html.is-embedded #loginOverlay,
html.is-embedded .header,
html.is-embedded #mainDashboard {
display: none !important;
}
html.is-embedded body {
padding: 0.5rem !important;
background-color: var(--bg-body);
}
html.is-embedded .container {
padding: 0 !important;
max-width: 100% !important;
margin: 0 !important;
}
html.is-embedded #moduleView {
display: block !important;
}
:root { :root {
--primary: #2563eb; --primary: #2563eb;
--primary-hover: #1d4ed8; --primary-hover: #1d4ed8;
@ -1795,8 +1864,8 @@ $installersData = json_decode($config['installersDataWhatsApp'] ?? '{"instalador
<div class="menu-container" id="mainDashboard"> <div class="menu-container" id="mainDashboard">
<div class="menu-item" onclick="showModule('installers')"> <div class="menu-item" onclick="showModule('installers')">
<img src="?action=image&file=instalador.png"> <img src="?action=image&file=instalador.png">
<h3>Administrar Instaladores</h3> <h3>Administrar Instaladores y Servicios</h3>
<p>Administra los técnicos e instaladores registrados en el sistema.</p> <p>Administra los técnicos e instaladores registrados en el sistema y los servicios que realizan.</p>
</div> </div>
<div class="menu-item" onclick="showModule('notifications')"> <div class="menu-item" onclick="showModule('notifications')">
<img src="?action=image&file=whatsapp-logo.png"> <img src="?action=image&file=whatsapp-logo.png">
@ -1855,7 +1924,7 @@ $installersData = json_decode($config['installersDataWhatsApp'] ?? '{"instalador
<table id="installersTable"> <table id="installersTable">
<thead> <thead>
<tr> <tr>
<th>ID</th> <th>ID Sistema</th>
<th>Nombre</th> <th>Nombre</th>
<th>WhatsApp</th> <th>WhatsApp</th>
<th>Acciones</th> <th>Acciones</th>
@ -1894,7 +1963,7 @@ $installersData = json_decode($config['installersDataWhatsApp'] ?? '{"instalador
<table id="installerJobsTable"> <table id="installerJobsTable">
<thead> <thead>
<tr> <tr>
<th>Folio</th> <th>ID Servicio</th>
<th>Cliente</th> <th>Cliente</th>
<th>Fecha</th> <th>Fecha</th>
<th>Descripción</th> <th>Descripción</th>
@ -2562,7 +2631,7 @@ $installersData = json_decode($config['installersDataWhatsApp'] ?? '{"instalador
}) : 'S/F'; }) : 'S/F';
const titleClean = job.title.replace('[NOTIFICACION-PENDIENTE]', '').replace('[CLIENTE-SIN-WHATSAPP]', '').trim(); const titleClean = job.title.replace('[NOTIFICACION-PENDIENTE]', '').replace('[CLIENTE-SIN-WHATSAPP]', '').trim();
return `<tr> return `<tr>
<td><strong>#${job.id}</strong></td> <td><strong><a href="${store.publicUrl}/scheduling/job/${job.id}" target="_blank" style="color: var(--primary); text-decoration: underline;">#${job.id}</a></strong></td>
<td>[${job.clientId}] ${job.clientName}</td> <td>[${job.clientId}] ${job.clientName}</td>
<td>${dateFormatted}</td> <td>${dateFormatted}</td>
<td style="max-width:200px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;" title="${job.description}">${titleClean || job.description || 'Sin descripción'}</td> <td style="max-width:200px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;" title="${job.description}">${titleClean || job.description || 'Sin descripción'}</td>

View File

@ -440,6 +440,11 @@ class ClientCallBellAPI
$fileNameComprobante = 'Comprobante_' . $clean_name . '.pdf'; $fileNameComprobante = 'Comprobante_' . $clean_name . '.pdf';
$rutaArchivo = __DIR__ . '/../../comprobantes/' . $fileNameComprobante; $rutaArchivo = __DIR__ . '/../../comprobantes/' . $fileNameComprobante;
// Asegurar que exista la carpeta de comprobantes
if (!is_dir(dirname($rutaArchivo))) {
mkdir(dirname($rutaArchivo), 0777, true);
}
// Guardar el contenido del PDF en un archivo local // Guardar el contenido del PDF en un archivo local
if (file_put_contents($rutaArchivo, $contenidoArchivo) !== false) { if (file_put_contents($rutaArchivo, $contenidoArchivo) !== false) {
$log->appendLog("El archivo PDF se ha descargado y guardado correctamente en: $rutaArchivo" . PHP_EOL); $log->appendLog("El archivo PDF se ha descargado y guardado correctamente en: $rutaArchivo" . PHP_EOL);