antes de la implementación del reenvio de notificaciones a instaladores
This commit is contained in:
parent
8d4580e138
commit
d0430dd891
@ -1,5 +1,13 @@
|
|||||||
# CHANGELOG - SIIP WhatsApp Notifications Plugin
|
# CHANGELOG - SIIP WhatsApp Notifications Plugin
|
||||||
|
|
||||||
|
## VERSIÓN 4.3.1 - 10-03-2026
|
||||||
|
|
||||||
|
### 🐛 Correcciones (Bug Fixes)
|
||||||
|
|
||||||
|
1️⃣ **Fix Notificación de Cambio de Instalador**: Corregido bug crítico en `AbstractMessageNotifierFacade.php` donde al cambiar de técnico en una tarea **"En curso"**, el **nuevo** instalador recibía el mensaje de **desasignación** (❌ "se te ha desasignado la tarea...") en lugar de un mensaje de **asignación** con los datos del cliente.
|
||||||
|
|
||||||
|
**Causa raíz**: La bandera `$changeInstaller=true` se pasaba tanto a la notificación del técnico anterior como a la del nuevo, causando que ambos recibieran la plantilla de desasignación. El fix envía `false` al nuevo técnico para que use la plantilla de asignación normal.
|
||||||
|
|
||||||
## VERSIÓN 4.3.0 - 23-02-2026
|
## VERSIÓN 4.3.0 - 23-02-2026
|
||||||
|
|
||||||
### 🔐 Seguridad y Acceso (Login)
|
### 🔐 Seguridad y Acceso (Login)
|
||||||
|
|||||||
@ -1,12 +1,16 @@
|
|||||||
# SIIP - WhatsApp Notifications & Integrated Payment Portal
|
# SIIP - WhatsApp Notifications & Integrated Payment Portal
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
Este plugin es una solución integral que transforma tu UCRM en un **Portal Administrativo de Última Generación**. No solo automatiza la comunicación por WhatsApp, sino que integra un Dashboard completo para la gestión de pagos online (Stripe/OXXO), visualización de comprobantes y coordinación de equipos técnicos.
|
Este plugin es una solución integral que transforma tu UCRM en un **Portal Administrativo de Última Generación**. No solo automatiza la comunicación por WhatsApp, sino que integra un Dashboard completo para la gestión de pagos online (Stripe/OXXO), visualización de comprobantes y coordinación de equipos técnicos.
|
||||||
|
|
||||||
|
## 🐛 Hotfix v4.3.1 (Installer Notification Fix)
|
||||||
|
|
||||||
|
- **🔧 Fix Cambio de Instalador**: Corregido bug donde el nuevo técnico recibía mensaje de desasignación en vez de asignación al cambiar instalador en una tarea "En curso".
|
||||||
|
|
||||||
## 🔐 Novedades v4.3.0 (Security & Premium UI)
|
## 🔐 Novedades v4.3.0 (Security & Premium UI)
|
||||||
|
|
||||||
- **🛡️ Sistema de Acceso Seguro**: Implementada validación híbrida (Server + Client). El plugin ahora protege las URLs públicas mediante una pantalla de inicio de sesión que requiere credenciales de Administrador de UCRM o autenticación 2FA.
|
- **🛡️ Sistema de Acceso Seguro**: Implementada validación híbrida (Server + Client). El plugin ahora protege las URLs públicas mediante una pantalla de inicio de sesión que requiere credenciales de Administrador de UCRM o autenticación 2FA.
|
||||||
|
|||||||
1256
data/plugin.log
1256
data/plugin.log
File diff suppressed because it is too large
Load Diff
@ -5,13 +5,18 @@
|
|||||||
"displayName": "SIIP - Procesador de Pagos en línea con Stripe, Oxxo y Transferencia, Sincronizador de CallBell y Envío de Notificaciones y comprobantes vía WhatsApp",
|
"displayName": "SIIP - Procesador de Pagos en línea con Stripe, Oxxo y Transferencia, Sincronizador de CallBell y Envío de Notificaciones y comprobantes vía WhatsApp",
|
||||||
"description": "Este plugin sincroniza los clientes del sistema UISP CRM con los contactos de WhatsApp en CallBell, además procesa pagos de Stripe como las trasferencias bancarias y genera referencias de pago vía OXXO, además envía comprobantes de pago en formato imagen PNG o texto vía Whatsapp a los clientes",
|
"description": "Este plugin sincroniza los clientes del sistema UISP CRM con los contactos de WhatsApp en CallBell, además procesa pagos de Stripe como las trasferencias bancarias y genera referencias de pago vía OXXO, además envía comprobantes de pago en formato imagen PNG o texto vía Whatsapp a los clientes",
|
||||||
"url": "https://siip.mx/",
|
"url": "https://siip.mx/",
|
||||||
"version": "4.3.0",
|
"version": "4.3.1",
|
||||||
"unmsVersionCompliancy": {
|
"unmsVersionCompliancy": {
|
||||||
"min": "2.1.0",
|
"min": "2.1.0",
|
||||||
"max": null
|
"max": null
|
||||||
},
|
},
|
||||||
"author": "SIIP INTERNET",
|
"author": "SIIP INTERNET",
|
||||||
"changelog": [
|
"changelog": [
|
||||||
|
{
|
||||||
|
"version": "4.3.1",
|
||||||
|
"date": "2026-03-10",
|
||||||
|
"changes": "Hotfix: Corregido bug donde al cambiar de instalador en una tarea En Curso, el nuevo técnico recibía mensaje de desasignación en vez de asignación."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"date": "2026-02-23",
|
"date": "2026-02-23",
|
||||||
|
|||||||
338
public.php
Executable file → Normal file
338
public.php
Executable file → Normal file
@ -7,10 +7,8 @@ chdir(__DIR__);
|
|||||||
use Ubnt\UcrmPluginSdk\Service\PluginConfigManager;
|
use Ubnt\UcrmPluginSdk\Service\PluginConfigManager;
|
||||||
use Ubnt\UcrmPluginSdk\Service\UcrmApi;
|
use Ubnt\UcrmPluginSdk\Service\UcrmApi;
|
||||||
use Ubnt\UcrmPluginSdk\Service\UcrmSecurity;
|
use Ubnt\UcrmPluginSdk\Service\UcrmSecurity;
|
||||||
use SmsNotifier\Service\PaymentIntentService;
|
|
||||||
|
|
||||||
// Carga manual del servicio
|
// Eliminado: PaymentIntentService ya no se usa aquí
|
||||||
require_once __DIR__ . '/src/Service/PaymentIntentService.php';
|
|
||||||
|
|
||||||
if (!file_exists(__DIR__ . '/data/config.json')) {
|
if (!file_exists(__DIR__ . '/data/config.json')) {
|
||||||
die('Acceso denegado o configuración no encontrada.');
|
die('Acceso denegado o configuración no encontrada.');
|
||||||
@ -18,7 +16,6 @@ if (!file_exists(__DIR__ . '/data/config.json')) {
|
|||||||
|
|
||||||
$configManager = PluginConfigManager::create();
|
$configManager = PluginConfigManager::create();
|
||||||
$config = $configManager->loadConfig();
|
$config = $configManager->loadConfig();
|
||||||
$logger = new \SmsNotifier\Service\Logger();
|
|
||||||
|
|
||||||
// LOG DE EMERGENCIA
|
// LOG DE EMERGENCIA
|
||||||
$debugLogPath = __DIR__ . '/data/debug_public.log';
|
$debugLogPath = __DIR__ . '/data/debug_public.log';
|
||||||
@ -50,11 +47,7 @@ $httpClient = new \GuzzleHttp\Client([
|
|||||||
|
|
||||||
$ucrmApi = new UcrmApi($httpClient, $config['apitoken'] ?? '');
|
$ucrmApi = new UcrmApi($httpClient, $config['apitoken'] ?? '');
|
||||||
|
|
||||||
$stripeService = new PaymentIntentService(
|
$ucrmApi = new UcrmApi($httpClient, $config['apitoken'] ?? '');
|
||||||
$ucrmApi,
|
|
||||||
$config['tokenstripe'] ?? '',
|
|
||||||
$logger
|
|
||||||
);
|
|
||||||
|
|
||||||
// Admins Logic
|
// Admins Logic
|
||||||
$admins = [];
|
$admins = [];
|
||||||
@ -110,19 +103,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_GET['action']) && $_GET['ac
|
|||||||
$authToken = $resp->getHeaderLine('x-auth-token');
|
$authToken = $resp->getHeaderLine('x-auth-token');
|
||||||
|
|
||||||
if ($statusCode === 200 && $authToken) {
|
if ($statusCode === 200 && $authToken) {
|
||||||
$logger->info("NMS Login OK for user: {$username}");
|
|
||||||
echo json_encode(['success' => true, 'token' => $authToken, 'user' => $body]);
|
echo json_encode(['success' => true, 'token' => $authToken, 'user' => $body]);
|
||||||
} elseif ($statusCode === 201) {
|
} elseif ($statusCode === 201) {
|
||||||
$logger->info("NMS Login requires 2FA for user: {$username}");
|
|
||||||
http_response_code(201);
|
http_response_code(201);
|
||||||
echo json_encode(['requires2FA' => true, 'twoFactorToken' => $body]);
|
echo json_encode(['requires2FA' => true, 'twoFactorToken' => $body]);
|
||||||
} else {
|
} else {
|
||||||
$logger->warning("NMS Login failed for user: {$username} (HTTP {$statusCode})");
|
|
||||||
http_response_code($statusCode ?: 401);
|
http_response_code($statusCode ?: 401);
|
||||||
echo json_encode(['error' => $body['message'] ?? 'Credenciales inválidas.', 'statusCode' => $statusCode]);
|
echo json_encode(['error' => $body['message'] ?? 'Credenciales inválidas.', 'statusCode' => $statusCode]);
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$logger->error("NMS Login exception: " . $e->getMessage());
|
|
||||||
http_response_code(500);
|
http_response_code(500);
|
||||||
echo json_encode(['error' => 'Error de conexión con el servidor UISP.']);
|
echo json_encode(['error' => 'Error de conexión con el servidor UISP.']);
|
||||||
}
|
}
|
||||||
@ -146,7 +135,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_GET['action']) && $_GET['ac
|
|||||||
$authToken = $resp->getHeaderLine('x-auth-token');
|
$authToken = $resp->getHeaderLine('x-auth-token');
|
||||||
|
|
||||||
if ($statusCode === 200 && $authToken) {
|
if ($statusCode === 200 && $authToken) {
|
||||||
$logger->info("NMS 2FA Login OK");
|
|
||||||
echo json_encode(['success' => true, 'token' => $authToken, 'user' => $body]);
|
echo json_encode(['success' => true, 'token' => $authToken, 'user' => $body]);
|
||||||
} else {
|
} else {
|
||||||
http_response_code($statusCode ?: 401);
|
http_response_code($statusCode ?: 401);
|
||||||
@ -222,6 +210,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
|
|||||||
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
|
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
|
||||||
$selfUrl = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
|
$selfUrl = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
|
||||||
|
|
||||||
|
$debugLogPath = __DIR__ . '/data/debug_public.log';
|
||||||
|
file_put_contents($debugLogPath, "[" . date('Y-m-d H:i:s') . "] RESEND PAYMENT. URL: $selfUrl" . PHP_EOL, FILE_APPEND);
|
||||||
|
|
||||||
$ch = curl_init($selfUrl);
|
$ch = curl_init($selfUrl);
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
curl_setopt($ch, CURLOPT_POST, true);
|
curl_setopt($ch, CURLOPT_POST, true);
|
||||||
@ -229,10 +220,16 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
|
|||||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
|
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
|
||||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||||
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||||
|
curl_setopt($ch, CURLOPT_POSTREDIR, 3); // Mantener POST y payload en redirects 301/302
|
||||||
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
|
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
|
||||||
$res = curl_exec($ch);
|
$res = curl_exec($ch);
|
||||||
|
$err = curl_error($ch);
|
||||||
|
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
curl_close($ch);
|
curl_close($ch);
|
||||||
|
|
||||||
|
file_put_contents($debugLogPath, "[" . date('Y-m-d H:i:s') . "] RESEND CURL RESULT - Code: $code - Error: $err - Body: $res" . PHP_EOL, FILE_APPEND);
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'message' => 'Notificación disparada.']);
|
echo json_encode(['success' => true, 'message' => 'Notificación disparada.']);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
|
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
|
||||||
@ -271,60 +268,6 @@ if (isset($_GET['action'])) {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($_GET['action'] === 'get_stripe_history') {
|
|
||||||
if (ob_get_level()) ob_end_clean();
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
|
|
||||||
$stripeCustomerId = $_GET['stripeCustomerId'] ?? '';
|
|
||||||
if (!$stripeCustomerId) {
|
|
||||||
echo json_encode(['error' => 'Missing stripeCustomerId']);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$history = $stripeService->getLastPayments($stripeCustomerId);
|
|
||||||
$balance = $stripeService->getCustomerCashBalance($stripeCustomerId);
|
|
||||||
|
|
||||||
echo json_encode([
|
|
||||||
'history' => $history,
|
|
||||||
'cashBalance' => $balance
|
|
||||||
]);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
echo json_encode(['error' => $e->getMessage()]);
|
|
||||||
}
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($_GET['action'] === 'get_oxxo_history') {
|
|
||||||
if (ob_get_level()) ob_end_clean();
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
|
|
||||||
$stripeCustomerId = $_GET['stripeCustomerId'] ?? '';
|
|
||||||
if (!$stripeCustomerId) {
|
|
||||||
echo json_encode(['error' => 'Missing stripeCustomerId']);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$history = $stripeService->getLastOxxoPayments($stripeCustomerId);
|
|
||||||
echo json_encode(['history' => $history]);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
echo json_encode(['error' => $e->getMessage()]);
|
|
||||||
}
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($_GET['action'] === 'search_stripe') {
|
|
||||||
$q = $_GET['q'] ?? '';
|
|
||||||
echo json_encode($stripeService->searchClients($q));
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($_GET['action'] === 'get_stripe_details') {
|
|
||||||
echo json_encode($stripeService->getClientDetails($_GET['id'] ?? null));
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($_GET['action'] === 'image' || $_GET['action'] === 'get_image') {
|
if ($_GET['action'] === 'image' || $_GET['action'] === 'get_image') {
|
||||||
// Image Handler
|
// Image Handler
|
||||||
if (ob_get_level()) ob_end_clean();
|
if (ob_get_level()) ob_end_clean();
|
||||||
@ -355,14 +298,6 @@ if (isset($_GET['action'])) {
|
|||||||
// POST Actions for Intents
|
// POST Actions for Intents
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
if ($_POST['action'] === 'create_intent') {
|
|
||||||
$clientId = $_POST['clientId'] ?? null;
|
|
||||||
$amount = $_POST['amount'] ?? 0;
|
|
||||||
$stripeCustomerId = $_POST['stripeCustomerId'] ?? null;
|
|
||||||
$adminId = $_POST['adminId'] ?? null;
|
|
||||||
echo json_encode($stripeService->createPaymentIntent($clientId, $amount, $stripeCustomerId, $adminId));
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
if ($_POST['action'] === 'create_oxxo_intent') {
|
if ($_POST['action'] === 'create_oxxo_intent') {
|
||||||
try {
|
try {
|
||||||
$builder = new \DI\ContainerBuilder();
|
$builder = new \DI\ContainerBuilder();
|
||||||
@ -451,6 +386,46 @@ $installersData = json_decode($config['installersDataWhatsApp'] ?? '{"instalador
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
gap: 1.5rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 15px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-logo {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
object-fit: contain;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: white;
|
||||||
|
padding: 5px;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-title {
|
||||||
|
margin: 0 0 5px 0;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--text-main);
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-subtitle {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 0.95rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MENU DASHBOARD */
|
/* MENU DASHBOARD */
|
||||||
@ -806,6 +781,45 @@ $installersData = json_decode($config['installersDataWhatsApp'] ?? '{"instalador
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* STRIPE CASH BALANCE BADGE */
|
||||||
|
.balance-badge {
|
||||||
|
align-items: center;
|
||||||
|
background-color: #f1f5f9;
|
||||||
|
color: var(--text-main);
|
||||||
|
padding: 6px 14px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
font-weight: 700;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .balance-badge {
|
||||||
|
background-color: #bfdbfe;
|
||||||
|
/* Light blue background for contrast */
|
||||||
|
color: #1e3a8a;
|
||||||
|
/* Navy blue text */
|
||||||
|
border-color: #93c5fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ENHANCED DARK MODE CONTRAST FOR SEARCH BOXES */
|
||||||
|
[data-theme="dark"] .config-container {
|
||||||
|
background: #1e293b;
|
||||||
|
border: 1px solid #475569;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .search-wrapper .form-control {
|
||||||
|
background: #0f172a;
|
||||||
|
border: 1px solid #475569;
|
||||||
|
color: #f1f5f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .search-wrapper .form-control:focus {
|
||||||
|
border-color: var(--primary-hover);
|
||||||
|
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
/* THEME TOGGLE (Premium) */
|
/* THEME TOGGLE (Premium) */
|
||||||
.theme-toggle {
|
.theme-toggle {
|
||||||
background: var(--bg-card);
|
background: var(--bg-card);
|
||||||
@ -879,14 +893,56 @@ $installersData = json_decode($config['installersDataWhatsApp'] ?? '{"instalador
|
|||||||
|
|
||||||
table {
|
table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: separate;
|
||||||
|
border-spacing: 0;
|
||||||
|
border-radius: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||||
}
|
}
|
||||||
|
|
||||||
th,
|
thead {
|
||||||
td {
|
background-color: var(--primary-surface);
|
||||||
padding: 12px;
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
padding: 16px 12px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-main);
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
border-bottom: 2px solid var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 14px 12px;
|
||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
|
color: var(--text-muted);
|
||||||
|
vertical-align: middle;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr:last-child td {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr:hover td {
|
||||||
|
background-color: rgba(37, 99, 235, 0.04);
|
||||||
|
color: var(--text-main);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] tbody tr:hover td {
|
||||||
|
background-color: rgba(96, 165, 250, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] thead {
|
||||||
|
background-color: rgba(30, 41, 59, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] th {
|
||||||
|
color: #e2e8f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Toast */
|
/* Toast */
|
||||||
@ -1037,9 +1093,75 @@ $installersData = json_decode($config['installersDataWhatsApp'] ?? '{"instalador
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
|
body {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
.form-grid {
|
.form-grid {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
padding: 1.5rem;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-left {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
min-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-logo {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-title {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs {
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab {
|
||||||
|
padding: 10px 16px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-container {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions-row {
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions-row .btn {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-container {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item {
|
||||||
|
min-height: 200px;
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-responsive {
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-group {
|
.form-group {
|
||||||
@ -1468,15 +1590,15 @@ $installersData = json_decode($config['installersDataWhatsApp'] ?? '{"instalador
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<!-- HEADER -->
|
<!-- HEADER -->
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<div style="display: flex; align-items: center; gap: 15px;">
|
<div class="header-left">
|
||||||
<img src="?action=image&file=logo-empresa.png" style="width:80px; height:80px; object-fit: contain; border-radius: 12px; background: white; padding: 5px; border: 1px solid var(--border);">
|
<img src="?action=image&file=logo-empresa.png" class="header-logo">
|
||||||
<div>
|
<div>
|
||||||
<!-- RESTORED HEADER TEXT -->
|
<!-- RESTORED HEADER TEXT -->
|
||||||
<h1 style="margin: 0; font-size: 24px;">Portal Administrativo de Pagos de STRIPE y Notificaciones WhatsApp</h1>
|
<h1 class="header-title">Portal Administrativo de Pagos de STRIPE y Notificaciones WhatsApp</h1>
|
||||||
<p style="margin: 0; color: #666;">Administración de Notificaciones vía WhatsApp, Intenciones de pago con Stripe y Fichas de OXXO Pay</p>
|
<p class="header-subtitle">Administración de Notificaciones vía WhatsApp, Intenciones de pago con Stripe y Fichas de OXXO Pay</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex; gap: 10px; align-items: center;">
|
<div class="header-actions">
|
||||||
<button class="btn btn-secondary hidden" id="btnBackToMenu" onclick="showDashboard()">
|
<button class="btn btn-secondary hidden" id="btnBackToMenu" onclick="showDashboard()">
|
||||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2-2H5a2 2 0 0 1-2-2z" />
|
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2-2H5a2 2 0 0 1-2-2z" />
|
||||||
@ -1484,14 +1606,16 @@ $installersData = json_decode($config['installersDataWhatsApp'] ?? '{"instalador
|
|||||||
</svg>
|
</svg>
|
||||||
Menú Principal
|
Menú Principal
|
||||||
</button>
|
</button>
|
||||||
<button id="logoutBtn" class="btn btn-secondary" style="color: #ef4444; border-color: rgba(239, 68, 68, 0.3); background: rgba(239, 68, 68, 0.05);" onclick="handleLogout()">
|
<?php if (strpos($_SERVER['REQUEST_URI'], '_plugins') !== false): ?>
|
||||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align:middle; margin-right:6px;">
|
<button class="btn btn-secondary" style="color: #ef4444; border-color: rgba(239, 68, 68, 0.3); background: rgba(239, 68, 68, 0.05);" onclick="handleLogout()">
|
||||||
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path>
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align:middle; margin-right:6px;">
|
||||||
<polyline points="16 17 21 12 16 7"></polyline>
|
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path>
|
||||||
<line x1="21" y1="12" x2="9" y2="12"></line>
|
<polyline points="16 17 21 12 16 7"></polyline>
|
||||||
</svg>
|
<line x1="21" y1="12" x2="9" y2="12"></line>
|
||||||
Cerrar Sesión
|
</svg>
|
||||||
</button>
|
Cerrar Sesión
|
||||||
|
</button>
|
||||||
|
<?php endif; ?>
|
||||||
<!-- RESTORED THEME BUTTON -->
|
<!-- RESTORED THEME BUTTON -->
|
||||||
<!-- PREMIUM THEME BUTTON -->
|
<!-- PREMIUM THEME BUTTON -->
|
||||||
<button class="theme-toggle" id="themeBtn" onclick="toggleTheme()">
|
<button class="theme-toggle" id="themeBtn" onclick="toggleTheme()">
|
||||||
@ -1766,7 +1890,7 @@ $installersData = json_decode($config['installersDataWhatsApp'] ?? '{"instalador
|
|||||||
<div id="stripeHistoryContainer" style="display:none; margin-top: 2rem; border-top: 1px solid var(--border); padding-top: 1.5rem;">
|
<div id="stripeHistoryContainer" style="display:none; margin-top: 2rem; border-top: 1px solid var(--border); padding-top: 1.5rem;">
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
|
||||||
<h4 class="section-title" style="margin-bottom: 0;">Historial de Pagos (Últimos 10)</h4>
|
<h4 class="section-title" style="margin-bottom: 0;">Historial de Pagos (Últimos 10)</h4>
|
||||||
<div id="stripeCashBalanceBadge" style="display:none; align-items: center; background-color: #f1f5f9; color: var(--text-main); padding: 5px 12px; border-radius: 8px; font-size: 0.9em; font-weight: 600; border: 1px solid transparent;">
|
<div id="stripeCashBalanceBadge" class="balance-badge" style="display:none;">
|
||||||
<img src="?action=image&file=account-balance.webp" style="width: 32px; height: 32px; margin-right: 8px;">
|
<img src="?action=image&file=account-balance.webp" style="width: 32px; height: 32px; margin-right: 8px;">
|
||||||
<span id="stripeCashBalanceText">Saldo Stripe: $0.00 MXN</span>
|
<span id="stripeCashBalanceText">Saldo Stripe: $0.00 MXN</span>
|
||||||
</div>
|
</div>
|
||||||
@ -1989,12 +2113,7 @@ $installersData = json_decode($config['installersDataWhatsApp'] ?? '{"instalador
|
|||||||
window.handleLogout = () => {
|
window.handleLogout = () => {
|
||||||
sessionStorage.removeItem('nms_auth_token');
|
sessionStorage.removeItem('nms_auth_token');
|
||||||
sessionStorage.removeItem('nms_user');
|
sessionStorage.removeItem('nms_user');
|
||||||
|
window.location.reload();
|
||||||
if (!NEEDS_LOGIN) {
|
|
||||||
window.top.location.href = '/crm/logout';
|
|
||||||
} else {
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -2220,7 +2339,6 @@ $installersData = json_decode($config['installersDataWhatsApp'] ?? '{"instalador
|
|||||||
<td>${new Date(p.createdDate).toLocaleString()}</td>
|
<td>${new Date(p.createdDate).toLocaleString()}</td>
|
||||||
<td>$${p.amount} ${p.currencyCode}</td>
|
<td>$${p.amount} ${p.currencyCode}</td>
|
||||||
<td>${p.methodName}</td>
|
<td>${p.methodName}</td>
|
||||||
<td>${p.methodName}</td>
|
|
||||||
<td>
|
<td>
|
||||||
<button class="btn btn-whatsapp" onclick="resendPayment(${p.id})">
|
<button class="btn btn-whatsapp" onclick="resendPayment(${p.id})">
|
||||||
<img src="?action=image&file=whatsapp-logo-button.png" class="icon-btn" style="margin-right:5px;filter: brightness(0) invert(1);"> Re-enviar Notificación
|
<img src="?action=image&file=whatsapp-logo-button.png" class="icon-btn" style="margin-right:5px;filter: brightness(0) invert(1);"> Re-enviar Notificación
|
||||||
@ -2348,7 +2466,7 @@ $installersData = json_decode($config['installersDataWhatsApp'] ?? '{"instalador
|
|||||||
|
|
||||||
const date = new Date(p.created * 1000).toLocaleString();
|
const date = new Date(p.created * 1000).toLocaleString();
|
||||||
const voucherBtn = p.voucherUrl ?
|
const voucherBtn = p.voucherUrl ?
|
||||||
`<a href="${p.voucherUrl}" target="_blank" class="btn btn-sm btn-outline-primary" style="padding: 2px 8px; font-size: 0.8rem;">Ver Ficha</a>` :
|
`<a href="${p.voucherUrl}" target="_blank" class="btn btn-uniform" style="padding: 4px 12px; font-size: 0.8rem;">Ver Ficha</a>` :
|
||||||
'-';
|
'-';
|
||||||
|
|
||||||
return `<tr>
|
return `<tr>
|
||||||
@ -2655,9 +2773,9 @@ $installersData = json_decode($config['installersDataWhatsApp'] ?? '{"instalador
|
|||||||
balanceBadge.style.color = '#15803d';
|
balanceBadge.style.color = '#15803d';
|
||||||
balanceBadge.style.border = '1px solid #bbf7d0';
|
balanceBadge.style.border = '1px solid #bbf7d0';
|
||||||
} else {
|
} else {
|
||||||
balanceBadge.style.backgroundColor = '#f1f5f9'; // Gray
|
balanceBadge.style.backgroundColor = '';
|
||||||
balanceBadge.style.color = 'var(--text-main)';
|
balanceBadge.style.color = '';
|
||||||
balanceBadge.style.border = '1px solid transparent';
|
balanceBadge.style.border = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2903,16 +3021,6 @@ $installersData = json_decode($config['installersDataWhatsApp'] ?? '{"instalador
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Inicialización: decidir si mostrar login o portal
|
// Inicialización: decidir si mostrar login o portal
|
||||||
sessionStorage.removeItem('nms_force_local_login'); // Cleanup from previous versions
|
|
||||||
|
|
||||||
// Ocultar botón de Cerrar Sesión si estamos dentro del iframe del CRM
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
if (window.top !== window.self) {
|
|
||||||
const logoutBtn = document.getElementById('logoutBtn');
|
|
||||||
if (logoutBtn) logoutBtn.style.display = 'none';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (NEEDS_LOGIN) {
|
if (NEEDS_LOGIN) {
|
||||||
// No hay sesión UCRM, intentar con token almacenado
|
// No hay sesión UCRM, intentar con token almacenado
|
||||||
verifyStoredSession().then(valid => {
|
verifyStoredSession().then(valid => {
|
||||||
|
|||||||
17
scripts-uisp/audit_client_passwords.php
Executable file → Normal file
17
scripts-uisp/audit_client_passwords.php
Executable file → Normal file
@ -438,12 +438,17 @@ function resolveAttributeIds($ucrmApi, $customAttributeKey, $siteAttributeKey, $
|
|||||||
try {
|
try {
|
||||||
$attributes = $ucrmApi->get('custom-attributes', ['attributeType' => 'client']);
|
$attributes = $ucrmApi->get('custom-attributes', ['attributeType' => 'client']);
|
||||||
foreach ($attributes as $attr) {
|
foreach ($attributes as $attr) {
|
||||||
match ($attr['key']) {
|
switch ($attr['key']) {
|
||||||
$customAttributeKey => $customAttributeId = $attr['id'],
|
case $customAttributeKey:
|
||||||
$siteAttributeKey => $siteAttributeId = $attr['id'],
|
$customAttributeId = $attr['id'];
|
||||||
$antenaSectorialAttributeKey => $antenaSectorialAttributeId = $attr['id'],
|
break;
|
||||||
default => null,
|
case $siteAttributeKey:
|
||||||
};
|
$siteAttributeId = $attr['id'];
|
||||||
|
break;
|
||||||
|
case $antenaSectorialAttributeKey:
|
||||||
|
$antenaSectorialAttributeId = $attr['id'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
logMessage("Error fetching attributes: " . $e->getMessage());
|
logMessage("Error fetching attributes: " . $e->getMessage());
|
||||||
|
|||||||
0
scripts-uisp/debug_clients.php
Executable file → Normal file
0
scripts-uisp/debug_clients.php
Executable file → Normal file
0
scripts-uisp/ejemplo_script_actualizador.php
Executable file → Normal file
0
scripts-uisp/ejemplo_script_actualizador.php
Executable file → Normal file
0
scripts-uisp/generate_invalid_password_list.php
Executable file → Normal file
0
scripts-uisp/generate_invalid_password_list.php
Executable file → Normal file
@ -1 +0,0 @@
|
|||||||
10
|
|
||||||
|
BIN
src/.DS_Store
vendored
Normal file
BIN
src/.DS_Store
vendored
Normal file
Binary file not shown.
0
src/Data/NotificationData.php
Executable file → Normal file
0
src/Data/NotificationData.php
Executable file → Normal file
0
src/Data/PluginData.php
Executable file → Normal file
0
src/Data/PluginData.php
Executable file → Normal file
0
src/Data/UcrmData.php
Executable file → Normal file
0
src/Data/UcrmData.php
Executable file → Normal file
0
src/Exception/CurlException.php
Executable file → Normal file
0
src/Exception/CurlException.php
Executable file → Normal file
95
src/Facade/AbstractMessageNotifierFacade.php
Executable file → Normal file
95
src/Facade/AbstractMessageNotifierFacade.php
Executable file → Normal file
@ -24,7 +24,8 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
const SUBJECT_OF_INSTALLER_CHANGE = ["se ha cancelado una tarea que tenías asignada con el folio ", "se te ha desasignado❌ la tarea con el folio "];
|
const SUBJECT_OF_INSTALLER_CHANGE = ["se ha cancelado una tarea que tenías asignada con el folio ", "se te ha desasignado❌ la tarea con el folio "];
|
||||||
const ADDITIONAL_CHANGE_DATA = ["Ya no es necesario realizar la visita técnica.", "En tu lugar asistirá el técnico 👷🏻♂️➡️ "];
|
const ADDITIONAL_CHANGE_DATA = ["Ya no es necesario realizar la visita técnica.", "En tu lugar asistirá el técnico 👷🏻♂️➡️ "];
|
||||||
|
|
||||||
public function __construct(Logger $logger, MessageTextFactory $messageTextFactory, SmsNumberProvider $clientPhoneNumber) {
|
public function __construct(Logger $logger, MessageTextFactory $messageTextFactory, SmsNumberProvider $clientPhoneNumber)
|
||||||
|
{
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
$this->messageTextFactory = $messageTextFactory;
|
$this->messageTextFactory = $messageTextFactory;
|
||||||
$this->clientPhoneNumber = $clientPhoneNumber;
|
$this->clientPhoneNumber = $clientPhoneNumber;
|
||||||
@ -41,22 +42,30 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
$this->ucrmApi = new UcrmApi($client, $config['apitoken'] ?? '');
|
$this->ucrmApi = new UcrmApi($client, $config['apitoken'] ?? '');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function verifyPaymentActionToDo(NotificationData $notificationData): void {
|
public function verifyPaymentActionToDo(NotificationData $notificationData): void
|
||||||
|
{
|
||||||
$arrayPhones = $this->clientPhoneNumber->getUcrmClientNumbers($notificationData, null);
|
$arrayPhones = $this->clientPhoneNumber->getUcrmClientNumbers($notificationData, null);
|
||||||
foreach ($arrayPhones as $type => $phones) {
|
foreach ($arrayPhones as $type => $phones) {
|
||||||
$type = trim(strtolower($type));
|
$type = trim(strtolower($type));
|
||||||
if (!is_array($phones)) continue;
|
if (!is_array($phones)) continue;
|
||||||
foreach ($phones as $phone) {
|
foreach ($phones as $phone) {
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case 'whatsapp': $this->notifyAndUpdate($notificationData, $phone); break;
|
case 'whatsapp':
|
||||||
case 'whatsnotifica': $this->notify($notificationData, $phone); break;
|
$this->notifyAndUpdate($notificationData, $phone);
|
||||||
case 'whatsactualiza': $this->onlyUpdate($notificationData, $phone); break;
|
break;
|
||||||
|
case 'whatsnotifica':
|
||||||
|
$this->notify($notificationData, $phone);
|
||||||
|
break;
|
||||||
|
case 'whatsactualiza':
|
||||||
|
$this->onlyUpdate($notificationData, $phone);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function verifyClientActionToDo(NotificationData $notificationData): void {
|
public function verifyClientActionToDo(NotificationData $notificationData): void
|
||||||
|
{
|
||||||
$arrayPhones = $this->clientPhoneNumber->getUcrmClientNumbers($notificationData, null);
|
$arrayPhones = $this->clientPhoneNumber->getUcrmClientNumbers($notificationData, null);
|
||||||
foreach ($arrayPhones as $type => $phones) {
|
foreach ($arrayPhones as $type => $phones) {
|
||||||
$type = trim(strtolower($type));
|
$type = trim(strtolower($type));
|
||||||
@ -67,7 +76,8 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function verifyServiceActionToDo(NotificationData $notificationData): void {
|
public function verifyServiceActionToDo(NotificationData $notificationData): void
|
||||||
|
{
|
||||||
$arrayPhones = $this->clientPhoneNumber->getUcrmClientNumbers($notificationData, null);
|
$arrayPhones = $this->clientPhoneNumber->getUcrmClientNumbers($notificationData, null);
|
||||||
foreach ($arrayPhones as $type => $phones) {
|
foreach ($arrayPhones as $type => $phones) {
|
||||||
$type = trim(strtolower($type));
|
$type = trim(strtolower($type));
|
||||||
@ -78,7 +88,8 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function verifyJobActionToDo($jsonNotificationData, $reprogramming = null, $changeInstaller = null): void {
|
public function verifyJobActionToDo($jsonNotificationData, $reprogramming = null, $changeInstaller = null): void
|
||||||
|
{
|
||||||
$this->logger->info('Iniciando verifyJobActionToDo');
|
$this->logger->info('Iniciando verifyJobActionToDo');
|
||||||
$clientId = $jsonNotificationData['extraData']['entity']['clientId'];
|
$clientId = $jsonNotificationData['extraData']['entity']['clientId'];
|
||||||
$installerId = $jsonNotificationData['extraData']['entity']['assignedUserId'];
|
$installerId = $jsonNotificationData['extraData']['entity']['assignedUserId'];
|
||||||
@ -94,7 +105,10 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
$installerWhatsApp = '';
|
$installerWhatsApp = '';
|
||||||
$installers = json_decode($config['installersDataWhatsApp'] ?? '{"instaladores":[]}', true);
|
$installers = json_decode($config['installersDataWhatsApp'] ?? '{"instaladores":[]}', true);
|
||||||
foreach ($installers['instaladores'] as $inst) {
|
foreach ($installers['instaladores'] as $inst) {
|
||||||
if ($inst['id'] == $installerId) { $installerWhatsApp = $inst['whatsapp']; break; }
|
if ($inst['id'] == $installerId) {
|
||||||
|
$installerWhatsApp = $inst['whatsapp'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($installerWhatsApp)) $this->logger->warning("No se encontró número de WhatsApp para el instalador ID: $installerId");
|
if (empty($installerWhatsApp)) $this->logger->warning("No se encontró número de WhatsApp para el instalador ID: $installerId");
|
||||||
@ -103,7 +117,10 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
$clientName = trim(($clientCRM['firstName'] ?? '') . ' ' . ($clientCRM['lastName'] ?? ''));
|
$clientName = trim(($clientCRM['firstName'] ?? '') . ' ' . ($clientCRM['lastName'] ?? ''));
|
||||||
$passCRM = '';
|
$passCRM = '';
|
||||||
foreach ($clientCRM['attributes'] as $attr) {
|
foreach ($clientCRM['attributes'] as $attr) {
|
||||||
if ($attr['key'] === 'passwordAntenaCliente') { $passCRM = $attr['value']; break; }
|
if ($attr['key'] === 'passwordAntenaCliente') {
|
||||||
|
$passCRM = $attr['value'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$allPhones = $this->clientPhoneNumber->getAllUcrmClientNumbers($clientCRM);
|
$allPhones = $this->clientPhoneNumber->getAllUcrmClientNumbers($clientCRM);
|
||||||
@ -137,7 +154,10 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
$prevAdmin = $this->ucrmApi->get("users/admins/$prevId", []);
|
$prevAdmin = $this->ucrmApi->get("users/admins/$prevId", []);
|
||||||
$prevWhatsApp = '';
|
$prevWhatsApp = '';
|
||||||
foreach ($installers['instaladores'] as $inst) {
|
foreach ($installers['instaladores'] as $inst) {
|
||||||
if ($inst['id'] == $prevId) { $prevWhatsApp = $inst['whatsapp']; break; }
|
if ($inst['id'] == $prevId) {
|
||||||
|
$prevWhatsApp = $inst['whatsapp'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ($prevWhatsApp) {
|
if ($prevWhatsApp) {
|
||||||
$api->sendJobNotificationWhatsAppToInstaller($this->validarNumeroTelefono($prevWhatsApp), [
|
$api->sendJobNotificationWhatsAppToInstaller($this->validarNumeroTelefono($prevWhatsApp), [
|
||||||
@ -178,7 +198,7 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
"jobDescription" => $jsonNotificationData['extraData']['entity']['description'] ?? 'S/D',
|
"jobDescription" => $jsonNotificationData['extraData']['entity']['description'] ?? 'S/D',
|
||||||
"gmapsLocation" => ($clientCRM['addressGpsLat'] && $clientCRM['addressGpsLon']) ? "https://www.google.com/maps?q={$clientCRM['addressGpsLat']},{$clientCRM['addressGpsLon']}" : 'N/A',
|
"gmapsLocation" => ($clientCRM['addressGpsLat'] && $clientCRM['addressGpsLon']) ? "https://www.google.com/maps?q={$clientCRM['addressGpsLat']},{$clientCRM['addressGpsLon']}" : 'N/A',
|
||||||
"passwordAntenaCliente" => $this->comparePasswords($passCRM, $passVault)
|
"passwordAntenaCliente" => $this->comparePasswords($passCRM, $passVault)
|
||||||
], $reprogramming, $changeInstaller);
|
], $reprogramming, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Gestión del Título / Prefijos
|
// 3. Gestión del Título / Prefijos
|
||||||
@ -196,7 +216,8 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function verifyInvoiceActionToDo(NotificationData $notificationData): void {
|
public function verifyInvoiceActionToDo(NotificationData $notificationData): void
|
||||||
|
{
|
||||||
$arrayPhones = $this->clientPhoneNumber->getUcrmClientNumbers($notificationData, null);
|
$arrayPhones = $this->clientPhoneNumber->getUcrmClientNumbers($notificationData, null);
|
||||||
foreach ($arrayPhones as $type => $phones) {
|
foreach ($arrayPhones as $type => $phones) {
|
||||||
$type = trim(strtolower($type));
|
$type = trim(strtolower($type));
|
||||||
@ -207,7 +228,8 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function notify(NotificationData $notificationData, $phoneToNotify = null): void {
|
public function notify(NotificationData $notificationData, $phoneToNotify = null): void
|
||||||
|
{
|
||||||
$config = PluginConfigManager::create()->loadConfig();
|
$config = PluginConfigManager::create()->loadConfig();
|
||||||
$api = new ClientCallBellAPI($config['apitoken'], $config['ipserver'], $config['tokencallbell']);
|
$api = new ClientCallBellAPI($config['apitoken'], $config['ipserver'], $config['tokencallbell']);
|
||||||
$phone = $this->validarNumeroTelefono($phoneToNotify);
|
$phone = $this->validarNumeroTelefono($phoneToNotify);
|
||||||
@ -216,7 +238,8 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
else $api->sendPaymentNotificationWhatsApp($phone, $notificationData);
|
else $api->sendPaymentNotificationWhatsApp($phone, $notificationData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function notifyAndUpdate(NotificationData $notificationData, $phoneToNotifyAndUpdate = null): void {
|
public function notifyAndUpdate(NotificationData $notificationData, $phoneToNotifyAndUpdate = null): void
|
||||||
|
{
|
||||||
$config = PluginConfigManager::create()->loadConfig();
|
$config = PluginConfigManager::create()->loadConfig();
|
||||||
$api = new ClientCallBellAPI($config['apitoken'], $config['ipserver'], $config['tokencallbell']);
|
$api = new ClientCallBellAPI($config['apitoken'], $config['ipserver'], $config['tokencallbell']);
|
||||||
$phone = $this->validarNumeroTelefono($phoneToNotifyAndUpdate);
|
$phone = $this->validarNumeroTelefono($phoneToNotifyAndUpdate);
|
||||||
@ -234,14 +257,16 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function notifyOverDue(NotificationData $notificationData): void {
|
public function notifyOverDue(NotificationData $notificationData): void
|
||||||
|
{
|
||||||
$config = PluginConfigManager::create()->loadConfig();
|
$config = PluginConfigManager::create()->loadConfig();
|
||||||
$api = new ClientCallBellAPI($config['apitoken'], $config['ipserver'], $config['tokencallbell']);
|
$api = new ClientCallBellAPI($config['apitoken'], $config['ipserver'], $config['tokencallbell']);
|
||||||
$phone = $this->clientPhoneNumber->getUcrmClientNumber($notificationData);
|
$phone = $this->clientPhoneNumber->getUcrmClientNumber($notificationData);
|
||||||
if ($phone) $api->sendOverdueNotificationWhatsApp($phone, $notificationData);
|
if ($phone) $api->sendOverdueNotificationWhatsApp($phone, $notificationData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onlyUpdate(NotificationData $notificationData, $phoneToUpdate): void {
|
public function onlyUpdate(NotificationData $notificationData, $phoneToUpdate): void
|
||||||
|
{
|
||||||
$this->logger->debug("onlyUpdate: Iniciando actualización para teléfono: $phoneToUpdate");
|
$this->logger->debug("onlyUpdate: Iniciando actualización para teléfono: $phoneToUpdate");
|
||||||
$config = PluginConfigManager::create()->loadConfig();
|
$config = PluginConfigManager::create()->loadConfig();
|
||||||
$api = new ClientCallBellAPI($config['apitoken'], $config['ipserver'], $config['tokencallbell']);
|
$api = new ClientCallBellAPI($config['apitoken'], $config['ipserver'], $config['tokencallbell']);
|
||||||
@ -257,7 +282,8 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onlyUpdateService(NotificationData $notificationData, $phoneToUpdate): void {
|
public function onlyUpdateService(NotificationData $notificationData, $phoneToUpdate): void
|
||||||
|
{
|
||||||
$config = PluginConfigManager::create()->loadConfig();
|
$config = PluginConfigManager::create()->loadConfig();
|
||||||
$api = new ClientCallBellAPI($config['apitoken'], $config['ipserver'], $config['tokencallbell']);
|
$api = new ClientCallBellAPI($config['apitoken'], $config['ipserver'], $config['tokencallbell']);
|
||||||
$phone = $this->validarNumeroTelefono($phoneToUpdate);
|
$phone = $this->validarNumeroTelefono($phoneToUpdate);
|
||||||
@ -265,7 +291,8 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
if ($contact) $api->patchServiceStatusWhatsApp($contact, $notificationData);
|
if ($contact) $api->patchServiceStatusWhatsApp($contact, $notificationData);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getVaultCredentialsByClientId($clientId): string {
|
protected function getVaultCredentialsByClientId($clientId): string
|
||||||
|
{
|
||||||
$config = PluginConfigManager::create()->loadConfig();
|
$config = PluginConfigManager::create()->loadConfig();
|
||||||
$ipServer = $config['ipserver'] ?? '';
|
$ipServer = $config['ipserver'] ?? '';
|
||||||
$crm = new Client(['base_uri' => "https://{$ipServer}/crm/api/v1.0/", 'verify' => false]);
|
$crm = new Client(['base_uri' => "https://{$ipServer}/crm/api/v1.0/", 'verify' => false]);
|
||||||
@ -361,7 +388,9 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
$passVault = $vault['credentials'][0]['password'];
|
$passVault = $vault['credentials'][0]['password'];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) { continue; }
|
} catch (\Exception $e) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($passVault) {
|
if ($passVault) {
|
||||||
@ -375,7 +404,9 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
'json' => [['username' => 'ubnt', 'password' => $newPass, 'readOnly' => true]]
|
'json' => [['username' => 'ubnt', 'password' => $newPass, 'readOnly' => true]]
|
||||||
]);
|
]);
|
||||||
$passwordValue = $newPass;
|
$passwordValue = $newPass;
|
||||||
} catch (\Exception $e) { $passwordValue = $newPass; }
|
} catch (\Exception $e) {
|
||||||
|
$passwordValue = $newPass;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$passwordValue = "⚠️ Sin antena";
|
$passwordValue = "⚠️ Sin antena";
|
||||||
}
|
}
|
||||||
@ -392,19 +423,19 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
|
|
||||||
// Evitar sincronización redundante
|
// Evitar sincronización redundante
|
||||||
if ($finalValue === $passCRM) {
|
if ($finalValue === $passCRM) {
|
||||||
return $finalValue;
|
return $finalValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->syncPasswordWithCrm((int)$clientId, $finalValue);
|
$this->syncPasswordWithCrm((int)$clientId, $finalValue);
|
||||||
return $finalValue;
|
return $finalValue;
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->logger->error("Error en getVaultCredentialsByClientId: " . $e->getMessage());
|
$this->logger->error("Error en getVaultCredentialsByClientId: " . $e->getMessage());
|
||||||
return 'Error: ' . $e->getMessage();
|
return 'Error: ' . $e->getMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function syncPasswordWithCrm(int $clientId, string $passVault): void {
|
private function syncPasswordWithCrm(int $clientId, string $passVault): void
|
||||||
|
{
|
||||||
$config = PluginConfigManager::create()->loadConfig();
|
$config = PluginConfigManager::create()->loadConfig();
|
||||||
$crm = new Client(['base_uri' => "https://{$config['ipserver']}/crm/api/v1.0/", 'verify' => false]);
|
$crm = new Client(['base_uri' => "https://{$config['ipserver']}/crm/api/v1.0/", 'verify' => false]);
|
||||||
try {
|
try {
|
||||||
@ -427,10 +458,13 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
$this->logger->info("Sincronizando pass CRM cliente $clientId.");
|
$this->logger->info("Sincronizando pass CRM cliente $clientId.");
|
||||||
$this->patchClientCustomAttribute($clientId, (int)$attributeId, $passVault);
|
$this->patchClientCustomAttribute($clientId, (int)$attributeId, $passVault);
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) { $this->logger->warning("Fallo sincronización pass CRM: " . $e->getMessage()); }
|
} catch (\Exception $e) {
|
||||||
|
$this->logger->warning("Fallo sincronización pass CRM: " . $e->getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function generateStrongPassword(int $length = 16): string {
|
protected function generateStrongPassword(int $length = 16): string
|
||||||
|
{
|
||||||
$lower = 'abcdefghijkmnopqrstuvwxyz'; // Eliminamos 'l'
|
$lower = 'abcdefghijkmnopqrstuvwxyz'; // Eliminamos 'l'
|
||||||
$upper = 'ABCDEFGHJKLMNPQRSTUVWXYZ'; // Eliminamos 'I', 'O'
|
$upper = 'ABCDEFGHJKLMNPQRSTUVWXYZ'; // Eliminamos 'I', 'O'
|
||||||
$digits = '23456789'; // Eliminamos '1', '0'
|
$digits = '23456789'; // Eliminamos '1', '0'
|
||||||
@ -461,7 +495,8 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
return implode('', $pwChars);
|
return implode('', $pwChars);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function patchClientCustomAttribute(int $clientId, int $attributeId, string $value): bool {
|
protected function patchClientCustomAttribute(int $clientId, int $attributeId, string $value): bool
|
||||||
|
{
|
||||||
$config = PluginConfigManager::create()->loadConfig();
|
$config = PluginConfigManager::create()->loadConfig();
|
||||||
$crm = new Client(['base_uri' => "https://{$config['ipserver']}/crm/api/v1.0/", 'verify' => false]);
|
$crm = new Client(['base_uri' => "https://{$config['ipserver']}/crm/api/v1.0/", 'verify' => false]);
|
||||||
try {
|
try {
|
||||||
@ -478,13 +513,15 @@ abstract class AbstractMessageNotifierFacade
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function comparePasswords(?string $crm, ?string $vault): string {
|
protected function comparePasswords(?string $crm, ?string $vault): string
|
||||||
|
{
|
||||||
if ($vault && strpos($vault, 'Error') !== 0) return $vault;
|
if ($vault && strpos($vault, 'Error') !== 0) return $vault;
|
||||||
if ($crm && strpos($crm, 'Error') !== 0) return $crm;
|
if ($crm && strpos($crm, 'Error') !== 0) return $crm;
|
||||||
return '⚠️ Probar pass conocida.';
|
return '⚠️ Probar pass conocida.';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function validarNumeroTelefono($n): string {
|
protected function validarNumeroTelefono($n): string
|
||||||
|
{
|
||||||
if (!$n) return '';
|
if (!$n) return '';
|
||||||
$n = preg_replace('/\D/', '', (string)$n);
|
$n = preg_replace('/\D/', '', (string)$n);
|
||||||
return (strlen($n) === 10) ? '52' . $n : $n;
|
return (strlen($n) === 10) ? '52' . $n : $n;
|
||||||
|
|||||||
0
src/Facade/AbstractOxxoOperationsFacade.php
Executable file → Normal file
0
src/Facade/AbstractOxxoOperationsFacade.php
Executable file → Normal file
27
src/Facade/AbstractStripeOperationsFacade.php
Executable file → Normal file
27
src/Facade/AbstractStripeOperationsFacade.php
Executable file → Normal file
@ -283,21 +283,7 @@ abstract class AbstractStripeOperationsFacade
|
|||||||
try {
|
try {
|
||||||
$clientCRM = $this->ucrmApi->get("clients/$clientId", []);
|
$clientCRM = $this->ucrmApi->get("clients/$clientId", []);
|
||||||
|
|
||||||
// Si intenta crear CLABE pero NO tiene stripeCustomerId, cancelamos
|
// Automaticamente creará el el Stripe Customer si no existe
|
||||||
if ($tagName === 'CREAR CLABE STRIPE') {
|
|
||||||
$hasStripeId = false;
|
|
||||||
foreach ($clientCRM['attributes'] as $attr) {
|
|
||||||
if ($attr['key'] === 'stripeCustomerId' && !empty($attr['value'])) {
|
|
||||||
$hasStripeId = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$hasStripeId) {
|
|
||||||
$this->logger->warning("Cliente $clientId no tiene stripeCustomerId. No se puede crear CLABE.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$customer = $this->createCustomerStripe($stripe, $clientCRM, $generateSpei);
|
$customer = $this->createCustomerStripe($stripe, $clientCRM, $generateSpei);
|
||||||
|
|
||||||
@ -358,10 +344,11 @@ abstract class AbstractStripeOperationsFacade
|
|||||||
|
|
||||||
$customer = $stripe->customers->create($params);
|
$customer = $stripe->customers->create($params);
|
||||||
$this->logger->info("Nuevo Cliente Stripe creado para ID: $clientId. CID: {$customer->id}");
|
$this->logger->info("Nuevo Cliente Stripe creado para ID: $clientId. CID: {$customer->id}");
|
||||||
// Guardar CID en UCRM
|
|
||||||
$this->patchClientCustomAttribute($clientId, (int)$cidAttrId, $customer->id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Guardar CID en UCRM siempre, por si no estaba sincronizado
|
||||||
|
$this->patchClientCustomAttribute($clientId, (int)$cidAttrId, $customer->id);
|
||||||
|
|
||||||
// Si se requiere SPEI, generamos las instrucciones de fondeo para obtener la CLABE
|
// Si se requiere SPEI, generamos las instrucciones de fondeo para obtener la CLABE
|
||||||
if ($generateSpei) {
|
if ($generateSpei) {
|
||||||
try {
|
try {
|
||||||
@ -687,6 +674,7 @@ abstract class AbstractStripeOperationsFacade
|
|||||||
try {
|
try {
|
||||||
$client = $this->ucrmApi->get("clients/$clientId");
|
$client = $this->ucrmApi->get("clients/$clientId");
|
||||||
$targetTagId = null;
|
$targetTagId = null;
|
||||||
|
$remainingTags = [];
|
||||||
foreach ($client['tags'] as $tag) {
|
foreach ($client['tags'] as $tag) {
|
||||||
if ($tag['name'] === $tagName) {
|
if ($tag['name'] === $tagName) {
|
||||||
$targetTagId = $tag['id'];
|
$targetTagId = $tag['id'];
|
||||||
@ -695,8 +683,9 @@ abstract class AbstractStripeOperationsFacade
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($targetTagId) {
|
if ($targetTagId) {
|
||||||
$this->ucrmApi->patch("clients/$clientId/remove-tag/$targetTagId", []);
|
// The proper UCRM endpoint to remove a tag from a client is PATCH /clients/{id}/remove-tag/{tagId}
|
||||||
$this->logger->info("Etiqueta '$tagName' (ID: $targetTagId) removida del cliente $clientId via endpoint especializado.");
|
$this->ucrmApi->patch("clients/$clientId/remove-tag/$targetTagId");
|
||||||
|
$this->logger->info("Etiqueta '$tagName' (ID: $targetTagId) removida del cliente $clientId.");
|
||||||
} else {
|
} else {
|
||||||
$this->logger->debug("Etiqueta '$tagName' no encontrada en el cliente $clientId, nada que remover.");
|
$this->logger->debug("Etiqueta '$tagName' no encontrada en el cliente $clientId, nada que remover.");
|
||||||
}
|
}
|
||||||
|
|||||||
0
src/Facade/AbstractUpdateClientFacade.php
Executable file → Normal file
0
src/Facade/AbstractUpdateClientFacade.php
Executable file → Normal file
14
src/Facade/ClientCallBellAPI.php
Executable file → Normal file
14
src/Facade/ClientCallBellAPI.php
Executable file → Normal file
@ -429,7 +429,15 @@ class ClientCallBellAPI
|
|||||||
$contenidoArchivo = $response->getBody()->getContents();
|
$contenidoArchivo = $response->getBody()->getContents();
|
||||||
|
|
||||||
// Construir el nombre del archivo PDF basado en el cliente
|
// Construir el nombre del archivo PDF basado en el cliente
|
||||||
$fileNameComprobante = 'Comprobante_' . str_replace(' ', '_', $nombre_cliente) . '.pdf';
|
$unwanted_array = array( 'Š'=>'S', 'š'=>'s', 'Ž'=>'Z', 'ž'=>'z', 'À'=>'A', 'Á'=>'A', 'Â'=>'A', 'Ã'=>'A', 'Ä'=>'A', 'Å'=>'A', 'Æ'=>'A', 'Ç'=>'C', 'È'=>'E', 'É'=>'E',
|
||||||
|
'Ê'=>'E', 'Ë'=>'E', 'Ì'=>'I', 'Í'=>'I', 'Î'=>'I', 'Ï'=>'I', 'Ñ'=>'N', 'Ò'=>'O', 'Ó'=>'O', 'Ô'=>'O', 'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O', 'Ù'=>'U',
|
||||||
|
'Ú'=>'U', 'Û'=>'U', 'Ü'=>'U', 'Ý'=>'Y', 'Þ'=>'B', 'ß'=>'Ss', 'à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a', 'å'=>'a', 'æ'=>'a', 'ç'=>'c',
|
||||||
|
'è'=>'e', 'é'=>'e', 'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 'î'=>'i', 'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o', 'ô'=>'o', 'õ'=>'o',
|
||||||
|
'ö'=>'o', 'ø'=>'o', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'ü'=>'u', 'ý'=>'y', 'þ'=>'b', 'ÿ'=>'y' );
|
||||||
|
$clean_name = strtr($nombre_cliente, $unwanted_array);
|
||||||
|
$clean_name = preg_replace('/[^A-Za-z0-9_\-]/', '', str_replace(' ', '_', $clean_name));
|
||||||
|
|
||||||
|
$fileNameComprobante = 'Comprobante_' . $clean_name . '.pdf';
|
||||||
$rutaArchivo = __DIR__ . '/../../comprobantes/' . $fileNameComprobante;
|
$rutaArchivo = __DIR__ . '/../../comprobantes/' . $fileNameComprobante;
|
||||||
|
|
||||||
// Guardar el contenido del PDF en un archivo local
|
// Guardar el contenido del PDF en un archivo local
|
||||||
@ -467,8 +475,8 @@ class ClientCallBellAPI
|
|||||||
$minioService = new MinioStorageService($loggerService);
|
$minioService = new MinioStorageService($loggerService);
|
||||||
|
|
||||||
// 2. Configurar Microservicio
|
// 2. Configurar Microservicio
|
||||||
$ipMicroservice = $config['ipPuppeteer'] ?? 'localhost'; // Reutilizamos IP de Puppeteer
|
$ipMicroservice = $config['ipMicroservice'] ?? 'pdf-cropper-service';
|
||||||
$portMicroservice = '8050'; // Puerto definido en docker-compose
|
$portMicroservice = $config['portMicroservice'] ?? '8000';
|
||||||
$microserviceUrl = "http://{$ipMicroservice}:{$portMicroservice}/process";
|
$microserviceUrl = "http://{$ipMicroservice}:{$portMicroservice}/process";
|
||||||
|
|
||||||
$log->appendLog("Procesando PDF con microservicio: $microserviceUrl" . PHP_EOL);
|
$log->appendLog("Procesando PDF con microservicio: $microserviceUrl" . PHP_EOL);
|
||||||
|
|||||||
0
src/Facade/PluginNotifierFacade.php
Executable file → Normal file
0
src/Facade/PluginNotifierFacade.php
Executable file → Normal file
0
src/Facade/PluginOxxoNotifierFacade.php
Executable file → Normal file
0
src/Facade/PluginOxxoNotifierFacade.php
Executable file → Normal file
0
src/Facade/TwilioNotifierFacade.php
Executable file → Normal file
0
src/Facade/TwilioNotifierFacade.php
Executable file → Normal file
0
src/Facade/pruebas_ucrm_api.php
Executable file → Normal file
0
src/Facade/pruebas_ucrm_api.php
Executable file → Normal file
0
src/Factory/MessageTextFactory.php
Executable file → Normal file
0
src/Factory/MessageTextFactory.php
Executable file → Normal file
0
src/Factory/NotificationDataFactory.php
Executable file → Normal file
0
src/Factory/NotificationDataFactory.php
Executable file → Normal file
0
src/Plugin.php
Executable file → Normal file
0
src/Plugin.php
Executable file → Normal file
0
src/Service/CurlExecutor.php
Executable file → Normal file
0
src/Service/CurlExecutor.php
Executable file → Normal file
0
src/Service/LogCleaner.php
Executable file → Normal file
0
src/Service/LogCleaner.php
Executable file → Normal file
0
src/Service/Logger.php
Executable file → Normal file
0
src/Service/Logger.php
Executable file → Normal file
0
src/Service/MinioStorageService.php
Executable file → Normal file
0
src/Service/MinioStorageService.php
Executable file → Normal file
0
src/Service/OptionsManager.php
Executable file → Normal file
0
src/Service/OptionsManager.php
Executable file → Normal file
0
src/Service/PaymentIntentService.php
Executable file → Normal file
0
src/Service/PaymentIntentService.php
Executable file → Normal file
0
src/Service/PluginDataValidator.php
Executable file → Normal file
0
src/Service/PluginDataValidator.php
Executable file → Normal file
0
src/Service/SmsNumberProvider.php
Executable file → Normal file
0
src/Service/SmsNumberProvider.php
Executable file → Normal file
0
src/Service/UcrmApi.php
Executable file → Normal file
0
src/Service/UcrmApi.php
Executable file → Normal file
13
test_facade_crash.php
Normal file
13
test_facade_crash.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
ini_set('display_errors', '1');
|
||||||
|
|
||||||
|
require_once __DIR__ . '/vendor/autoload.php';
|
||||||
|
require_once __DIR__ . '/src/Facade/PluginNotifierFacade.php';
|
||||||
|
echo "Included successfully\n";
|
||||||
|
|
||||||
|
if (!defined('INCLUDED_AS_LIBRARY')) {
|
||||||
|
define('INCLUDED_AS_LIBRARY', true);
|
||||||
|
}
|
||||||
|
require_once __DIR__ . '/scripts-uisp/audit_client_passwords.php';
|
||||||
|
echo "Audit included successfully\n";
|
||||||
Loading…
Reference in New Issue
Block a user