Autosave: 20260725-015655

This commit is contained in:
Flatlogic Bot 2026-07-25 01:55:30 +00:00
parent 9da54710dc
commit 8633846941
3 changed files with 80 additions and 176 deletions

View File

@ -24,70 +24,6 @@ if (!cc_test_current_user_can_access_module($pdo)) {
exit();
}
if (isset($_GET['ajax']) && $_GET['ajax'] === 'panel_status') {
header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
$panelStoreKey = trim(mb_strtolower((string) ($_GET['store'] ?? 'flower')));
$availablePanelStores = drive_test_available_stores();
if (!isset($availablePanelStores[$panelStoreKey])) {
$panelStoreKey = 'flower';
}
$currentUserId = (int) ($_SESSION['user_id'] ?? 0);
if ($currentUserId <= 0) {
http_response_code(401);
echo json_encode([
'success' => false,
'message' => 'Sesión no válida.',
]);
exit();
}
try {
if ($panelStoreKey === 'tuani_recuperables') {
$panelOrders = drive_test_fetch_orders_from_db($pdo, $panelStoreKey);
$panelTracking = drive_test_fetch_tracking($pdo, array_column($panelOrders, 'source_key'));
$panelOrders = drive_test_merge_tracking($panelOrders, $panelTracking);
$panelOrders = array_values(array_filter($panelOrders, static function (array $order): bool {
return empty($order['eliminado']);
}));
$panelOrders = cc_test_mark_recoverables_duplicate_orders($pdo, $panelOrders, $panelStoreKey);
} else {
$stmtPanel = $pdo->prepare("
SELECT source_key, user_id, estado, assigned_at, updated_at, eliminado_at
FROM callcenter_test_tracking
WHERE user_id = ? AND eliminado_at IS NULL
ORDER BY source_key
");
$stmtPanel->execute([$currentUserId]);
$panelOrders = $stmtPanel->fetchAll(PDO::FETCH_ASSOC);
}
$panelSignatureParts = [cc_test_panel_orders_signature($panelOrders)];
if ($panelStoreKey === 'otra_tienda') {
$panelAssessors = cc_test_fetch_assessors($pdo);
$panelRepartoSettings = cc_test_fetch_reparto_settings($pdo, $panelStoreKey, $panelAssessors);
$panelSignatureParts[] = cc_test_reparto_settings_signature($panelRepartoSettings);
}
echo json_encode([
'success' => true,
'signature' => sha1(implode('|', $panelSignatureParts)),
'total' => count($panelOrders),
]);
} catch (Throwable $exception) {
error_log('Panel status check failed: ' . $exception->getMessage());
http_response_code(500);
echo json_encode([
'success' => false,
'message' => 'No se pudo verificar el panel.',
]);
}
exit();
}
$sedesShalom = cc_test_fetch_shalom_sedes($pdo);
function cc_test_parse_datetime(?string $value): ?DateTimeImmutable
@ -298,6 +234,7 @@ $parentStoreLabel = (string) ($storeNav['parent_label'] ?? '');
$isMainTuaniStore = cc_test_is_tuani_main_store_key($storeKey);
$isTuaniRecuperablesStore = $storeKey === 'tuani_recuperables';
$canShowTuaniLogisticaButton = $isMainTuaniStore || $isTuaniRecuperablesStore;
$viewCardColumnClass = $isTuaniRecuperablesStore ? 'col-md-6 col-xl-2' : 'col-md-6 col-xl-2';
$viewCards = $isTuaniRecuperablesStore ? [
@ -435,7 +372,6 @@ $stats = [
'cerrados' => 0,
];
$panelSignature = '';
$repartoSettings = [
'store_key' => $storeKey,
'reparto_mode' => 'manual',
@ -687,7 +623,7 @@ try {
$order['promo_final_evidencia_cargada'] = trim((string) ($order['promo_final_evidencia_path'] ?? '')) !== '';
$order['es_promo_final'] = $order['promo_final_habilitado'] && $order['promo_final_evidencia_cargada'];
$order['promo_final_pendiente'] = $order['promo_final_habilitado'] && !$order['promo_final_evidencia_cargada'];
$order['pendiente_logistica_destino'] = $isMainTuaniStore ? cc_test_pending_logistica_destination($order) : null;
$order['pendiente_logistica_destino'] = cc_test_is_tuani_store_key($storeKey) ? cc_test_pending_logistica_destination($order) : null;
$order['pendiente_logistica'] = $order['pendiente_logistica_destino'] !== null;
$order['es_nuevo_hoy'] = $assignedDate ? $assignedDate->format('Y-m-d') === $todayStart->format('Y-m-d') : false;
@ -772,11 +708,6 @@ try {
'footnote' => $performanceFootnote,
]);
$panelSignature = cc_test_panel_orders_signature($orders);
if ($isMainTuaniStore) {
$panelSignature .= '|'. cc_test_reparto_settings_signature($repartoSettings);
}
$visibleOrders = array_values(array_filter($orders, static function (array $order) use ($view, $selectedAssessorFilter, $todayStart): bool {
if ($selectedAssessorFilter !== '' && !($order['matches_assessor_filter'] ?? false)) {
return false;
@ -1094,7 +1025,7 @@ require_once 'layout_header.php';
}
</style>
<main class="container-fluid py-4" data-cc-panel-root="1" data-panel-signature="<?php echo htmlspecialchars($panelSignature); ?>" data-panel-poll-url="<?php echo htmlspecialchars(cc_test_build_url('call_center_pro.php', array_merge($callCenterParams, ['ajax' => 'panel_status']))); ?>" data-panel-poll-interval="6000">
<main class="container-fluid py-4" data-cc-panel-root="1">
<section class="mb-4">
<div class="d-flex flex-column flex-xl-row justify-content-between align-items-xl-center gap-3">
<div>
@ -1133,8 +1064,9 @@ require_once 'layout_header.php';
<span class="badge rounded-pill text-bg-light border px-3 py-2">Drive detectado: <?php echo (int) $totalRows; ?> filas</span>
<span class="badge rounded-pill text-bg-light border px-3 py-2">Agregados: <?php echo (int) $agregadosCount; ?></span>
<span class="badge rounded-pill text-bg-light border px-3 py-2"><?php if ($usesIncrementalSync && $lastProcessedRow !== null): ?><?php echo htmlspecialchars(mb_strtoupper($storeLabel)); ?>: distribución desde fila <?php echo (int) ($storeConfig['startRow'] ?? $startRow); ?> · último procesado <?php echo (int) $lastProcessedRow; ?><?php else: ?>Extracción: desde fila <?php echo (int) $startRow; ?><?php endif; ?></span>
<span class="badge rounded-pill text-bg-light border px-3 py-2">Auto actualización: activa</span>
<span class="badge rounded-pill text-bg-light border px-3 py-2">Actualización manual</span>
<a href="test_importar_drive.php?store=<?php echo htmlspecialchars($storeKey); ?>" class="btn btn-outline-primary btn-sm">Ver vista previa Drive</a>
<button type="button" class="btn btn-primary btn-sm" onclick="window.location.reload();"><i class="bi bi-arrow-clockwise me-1"></i>Actualizar pedidos</button>
</div>
</div>
</section>
@ -1262,28 +1194,28 @@ require_once 'layout_header.php';
default => '',
};
$subirLogisticaButtonLabel = 'Subir pedido';
$subirLogisticaNoteClass = 'small mt-2 text-muted';
$subirLogisticaNoteClass = 'alert alert-secondary py-2 px-3 mt-2 mb-0';
$subirLogisticaNoteHtml = 'Selecciona <strong>CONFIRMADO CONTRAENTREGA</strong> o <strong>CONFIRMADO ENVIO</strong> para enviarlo a logística.';
if ($isMainTuaniStore) {
if ($canShowTuaniLogisticaButton) {
if ($order['estado'] === 'CONFIRMADO CONTRAENTREGA') {
if (!empty($order['ruta_contraentrega_pedido_id'])) {
$subirLogisticaButtonLabel = 'Actualizar en ruta';
$subirLogisticaNoteClass = 'small mt-2 text-success fw-semibold';
$subirLogisticaNoteClass = 'alert alert-success py-2 px-3 mt-2 mb-0';
$subirLogisticaNoteHtml = 'En Ruta Contraentrega #' . (int) $order['ruta_contraentrega_pedido_id'] . '. Si cambias algo, usa este botón para actualizarlo.';
} else {
$subirLogisticaButtonLabel = 'Subir a ruta';
$subirLogisticaNoteClass = 'small mt-2 text-warning-emphasis';
$subirLogisticaNoteHtml = '<strong>PENDIENTE A SUBIR</strong>: este pedido ya está en <strong>CONFIRMADO CONTRAENTREGA</strong>. Súbelo a Ruta Contraentrega con este botón.';
$subirLogisticaNoteClass = 'alert alert-warning py-2 px-3 mt-2 mb-0';
$subirLogisticaNoteHtml = '<strong>ALERTA:</strong> este pedido está en <strong>CONFIRMADO CONTRAENTREGA</strong>, pero aún no se ha subido a Ruta Contraentrega. Usa este botón para subirlo.';
}
} elseif ($order['estado'] === 'CONFIRMADO ENVIO') {
if (!empty($order['pedido_rotulado_pedido_id'])) {
$subirLogisticaButtonLabel = 'Actualizar rotulado';
$subirLogisticaNoteClass = 'small mt-2 text-success fw-semibold';
$subirLogisticaNoteClass = 'alert alert-success py-2 px-3 mt-2 mb-0';
$subirLogisticaNoteHtml = 'En Pedidos Rotulados #' . (int) $order['pedido_rotulado_pedido_id'] . '. Si cambias algo, usa este botón para actualizarlo.';
} else {
$subirLogisticaButtonLabel = 'Subir a rotulados';
$subirLogisticaNoteClass = 'small mt-2 text-warning-emphasis';
$subirLogisticaNoteHtml = '<strong>PENDIENTE A SUBIR</strong>: este pedido ya está en <strong>CONFIRMADO ENVIO</strong>. Súbelo a Pedidos Rotulados con este botón.';
$subirLogisticaNoteClass = 'alert alert-warning py-2 px-3 mt-2 mb-0';
$subirLogisticaNoteHtml = '<strong>ALERTA:</strong> este pedido está en <strong>CONFIRMADO ENVIO</strong>, pero aún no se ha subido a Pedidos Rotulados. Usa este botón para subirlo.';
}
}
}
@ -1463,7 +1395,7 @@ require_once 'layout_header.php';
</div>
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2">
<h3 class="modal-title h5 mb-0"><?php echo htmlspecialchars(cc_test_display_value($order['nombre'], 'Cliente sin nombre')); ?></h3>
<?php if ($isMainTuaniStore): ?>
<?php if ($canShowTuaniLogisticaButton): ?>
<button type="button" class="btn btn-primary btn-sm px-3" id="subir-logistica-<?php echo htmlspecialchars($order['source_key']); ?>" data-route-pedido-id="<?php echo (int) ($order['ruta_contraentrega_pedido_id'] ?? 0); ?>" data-rotulado-pedido-id="<?php echo (int) ($order['pedido_rotulado_pedido_id'] ?? 0); ?>" onclick="guardarGestion('<?php echo htmlspecialchars($order['source_key']); ?>', this, { subirLogistica: true })"><?php echo htmlspecialchars($subirLogisticaButtonLabel); ?></button>
<?php endif; ?>
</div>
@ -1498,8 +1430,8 @@ require_once 'layout_header.php';
</div>
</div>
<?php endif; ?>
<?php if ($isMainTuaniStore): ?>
<div class="<?php echo htmlspecialchars($subirLogisticaNoteClass); ?>" id="subir-logistica-note-<?php echo htmlspecialchars($order['source_key']); ?>"><?php echo $subirLogisticaNoteHtml; ?></div>
<?php if ($canShowTuaniLogisticaButton): ?>
<div class="<?php echo htmlspecialchars($subirLogisticaNoteClass); ?>" id="subir-logistica-note-<?php echo htmlspecialchars($order['source_key']); ?>" role="alert"><?php echo $subirLogisticaNoteHtml; ?></div>
<?php endif; ?>
</div>
<button type="button" class="btn-close mt-1" data-bs-dismiss="modal" aria-label="Cerrar"></button>
@ -1841,7 +1773,7 @@ require_once 'layout_header.php';
<div class="modal-footer d-flex justify-content-between flex-wrap gap-2">
<div class="small text-muted">
<?php if ($isMainTuaniStore): ?>
<?php if ($canShowTuaniLogisticaButton): ?>
<strong>Guardar gestión</strong> solo guarda el historial. Para enviarlo a logística, usa el <strong>botón del encabezado</strong> junto al nombre del cliente.
<?php else: ?>
Los cambios se guardan en la base local del módulo de prueba.
@ -2061,10 +1993,10 @@ function updateLogisticaButton(sourceKey) {
button.disabled = false;
button.textContent = routeId > 0 ? 'Actualizar en ruta' : 'Subir a ruta';
if (note) {
note.className = 'small mt-2 ' + (routeId > 0 ? 'text-success fw-semibold' : 'text-warning-emphasis');
note.className = 'alert ' + (routeId > 0 ? 'alert-success' : 'alert-warning') + ' py-2 px-3 mt-2 mb-0';
note.innerHTML = routeId > 0
? 'En Ruta Contraentrega #' + routeId + '. Si cambias algo, usa este botón para actualizarlo.'
: '<strong>PENDIENTE A SUBIR</strong>: este pedido ya está en <strong>CONFIRMADO CONTRAENTREGA</strong>. Súbelo a Ruta Contraentrega con este botón.';
: '<strong>ALERTA:</strong> este pedido está en <strong>CONFIRMADO CONTRAENTREGA</strong>, pero aún no se ha subido a Ruta Contraentrega. Usa este botón para subirlo.';
}
return;
}
@ -2073,10 +2005,10 @@ function updateLogisticaButton(sourceKey) {
button.disabled = false;
button.textContent = rotuladoId > 0 ? 'Actualizar rotulado' : 'Subir a rotulados';
if (note) {
note.className = 'small mt-2 ' + (rotuladoId > 0 ? 'text-success fw-semibold' : 'text-warning-emphasis');
note.className = 'alert ' + (rotuladoId > 0 ? 'alert-success' : 'alert-warning') + ' py-2 px-3 mt-2 mb-0';
note.innerHTML = rotuladoId > 0
? 'En Pedidos Rotulados #' + rotuladoId + '. Si cambias algo, usa este botón para actualizarlo.'
: '<strong>PENDIENTE A SUBIR</strong>: este pedido ya está en <strong>CONFIRMADO ENVIO</strong>. Súbelo a Pedidos Rotulados con este botón.';
: '<strong>ALERTA:</strong> este pedido está en <strong>CONFIRMADO ENVIO</strong>, pero aún no se ha subido a Pedidos Rotulados. Usa este botón para subirlo.';
}
return;
}
@ -2084,7 +2016,7 @@ function updateLogisticaButton(sourceKey) {
button.disabled = true;
button.textContent = 'Subir pedido';
if (note) {
note.className = 'small mt-2 text-muted';
note.className = 'alert alert-secondary py-2 px-3 mt-2 mb-0';
note.textContent = 'Selecciona CONFIRMADO CONTRAENTREGA o CONFIRMADO ENVIO para enviarlo a logística.';
}
}
@ -2615,66 +2547,8 @@ window.setTimeout(syncServerAssessorSelects, 0);
window.setTimeout(syncServerAssessorSelects, 120);
window.setTimeout(syncServerAssessorSelects, 600);
const ccPanelLiveEnabled = <?php echo ($isAdmin || $isTuaniRecuperablesStore) ? 'false' : 'true'; ?>;
if (ccPanelLiveEnabled) {
const ccPanelRoot = document.querySelector('[data-cc-panel-root="1"]');
if (ccPanelRoot) {
const ccPanelPollUrl = ccPanelRoot.dataset.panelPollUrl || '';
const ccPanelInterval = parseInt(ccPanelRoot.dataset.panelPollInterval || '6000', 10) || 6000;
let ccPanelSignature = ccPanelRoot.dataset.panelSignature || '';
let ccPanelPolling = false;
const ccPanelCheck = async () => {
if (ccPanelPolling || !ccPanelPollUrl) {
return;
}
ccPanelPolling = true;
try {
const url = new URL(ccPanelPollUrl, window.location.href);
url.searchParams.set('_ts', Date.now().toString());
const response = await fetch(url.toString(), {
cache: 'no-store',
credentials: 'same-origin'
});
if (!response.ok) {
return;
}
const data = await response.json();
if (!data || !data.success) {
return;
}
const nextSignature = String(data.signature || '');
if (nextSignature && nextSignature !== ccPanelSignature) {
ccPanelSignature = nextSignature;
window.location.reload();
}
} catch (error) {
console.warn('Panel update check failed:', error);
} finally {
ccPanelPolling = false;
}
};
window.setTimeout(ccPanelCheck, 2500);
window.setInterval(ccPanelCheck, ccPanelInterval);
document.addEventListener('visibilitychange', function () {
if (!document.hidden) {
ccPanelCheck();
}
});
}
}
if (ccPanelLiveEnabled) {
window.setInterval(function () {
window.location.reload();
}, 600000);
}
</script>
<?php require_once 'layout_footer.php'; ?>

View File

@ -167,14 +167,18 @@ function cc_test_import_time(array $order): int
return (int) ($order['id'] ?? 0);
}
function cc_test_tuani_reparto_is_eligible(array $order, string $storeKey, array $storeConfig): bool
{
return true;
if (!function_exists('cc_test_tuani_reparto_is_eligible')) {
function cc_test_tuani_reparto_is_eligible(array $order, string $storeKey, array $storeConfig): bool
{
return true;
}
}
function cc_test_filter_reparto_orders(array $orders, string $storeKey, array $storeConfig): array
{
return $orders;
if (!function_exists('cc_test_filter_reparto_orders')) {
function cc_test_filter_reparto_orders(array $orders, string $storeKey, array $storeConfig): array
{
return $orders;
}
}
function cc_test_followup_semaforo(array $order): ?array
@ -206,6 +210,7 @@ $parentStoreLabel = (string) ($storeNav['parent_label'] ?? '');
$isMainTuaniStore = cc_test_is_tuani_main_store_key($storeKey);
$isTuaniRecuperablesStore = $storeKey === 'tuani_recuperables';
$canShowTuaniLogisticaButton = $isMainTuaniStore || $isTuaniRecuperablesStore;
$viewCardColumnClass = $isTuaniRecuperablesStore ? 'col-md-6 col-xl-2' : 'col-md-6 col-xl-2';
$viewCards = $isTuaniRecuperablesStore ? [
@ -879,7 +884,7 @@ try {
$order['promo_final_evidencia_cargada'] = trim((string) ($order['promo_final_evidencia_path'] ?? '')) !== '';
$order['es_promo_final'] = $order['promo_final_habilitado'] && $order['promo_final_evidencia_cargada'];
$order['promo_final_pendiente'] = $order['promo_final_habilitado'] && !$order['promo_final_evidencia_cargada'];
$order['pendiente_logistica_destino'] = $isMainTuaniStore ? cc_test_pending_logistica_destination($order) : null;
$order['pendiente_logistica_destino'] = cc_test_is_tuani_store_key($storeKey) ? cc_test_pending_logistica_destination($order) : null;
$order['pendiente_logistica'] = $order['pendiente_logistica_destino'] !== null;
$order['es_nuevo_hoy'] = $firstSeenDate ? $firstSeenDate->format('Y-m-d') === $todayStart->format('Y-m-d') : false;
@ -1489,12 +1494,13 @@ require_once 'layout_header.php';
<span class="badge rounded-pill text-bg-light border px-3 py-2">Drive detectado: <?php echo (int) $totalRows; ?> filas</span>
<span class="badge rounded-pill text-bg-light border px-3 py-2">Agregados: <?php echo (int) $agregadosCount; ?></span>
<span class="badge rounded-pill text-bg-light border px-3 py-2"><?php if ($usesIncrementalSync && $lastProcessedRow !== null): ?><?php echo htmlspecialchars(mb_strtoupper($storeLabel)); ?>: distribución desde fila <?php echo (int) ($storeConfig['startRow'] ?? $startRow); ?> · último procesado <?php echo (int) $lastProcessedRow; ?><?php else: ?>Extracción: desde fila <?php echo (int) $startRow; ?><?php endif; ?></span>
<span class="badge rounded-pill text-bg-light border px-3 py-2">Auto actualización: cada 10 min</span>
<span class="badge rounded-pill text-bg-light border px-3 py-2">Actualización manual</span>
<?php if ($selectedAssessorFilterLabel !== ''): ?>
<span class="badge rounded-pill bg-primary-subtle text-primary-emphasis border px-3 py-2">Asesora: <?php echo htmlspecialchars($selectedAssessorFilterLabel); ?></span>
<a href="<?php echo htmlspecialchars(cc_test_build_url('gestiones_callcenter.php', ['view' => $view, 'store' => $storeKey, 'assessor' => 'TODAS'])); ?>" class="btn btn-outline-secondary btn-sm">Ver todas</a>
<?php endif; ?>
<a href="test_importar_drive.php?store=<?php echo htmlspecialchars($storeKey); ?>" class="btn btn-outline-primary btn-sm">Ver vista previa Drive</a>
<button type="button" class="btn btn-primary btn-sm" onclick="window.location.reload();"><i class="bi bi-arrow-clockwise me-1"></i>Actualizar pedidos</button>
</div>
</div>
</section>
@ -1844,28 +1850,28 @@ require_once 'layout_header.php';
default => '',
};
$subirLogisticaButtonLabel = 'Subir pedido';
$subirLogisticaNoteClass = 'small mt-2 text-muted';
$subirLogisticaNoteClass = 'alert alert-secondary py-2 px-3 mt-2 mb-0';
$subirLogisticaNoteHtml = 'Selecciona <strong>CONFIRMADO CONTRAENTREGA</strong> o <strong>CONFIRMADO ENVIO</strong> para enviarlo a logística.';
if ($isMainTuaniStore) {
if ($canShowTuaniLogisticaButton) {
if ($order['estado'] === 'CONFIRMADO CONTRAENTREGA') {
if (!empty($order['ruta_contraentrega_pedido_id'])) {
$subirLogisticaButtonLabel = 'Actualizar en ruta';
$subirLogisticaNoteClass = 'small mt-2 text-success fw-semibold';
$subirLogisticaNoteClass = 'alert alert-success py-2 px-3 mt-2 mb-0';
$subirLogisticaNoteHtml = 'En Ruta Contraentrega #' . (int) $order['ruta_contraentrega_pedido_id'] . '. Si cambias algo, usa este botón para actualizarlo.';
} else {
$subirLogisticaButtonLabel = 'Subir a ruta';
$subirLogisticaNoteClass = 'small mt-2 text-warning-emphasis';
$subirLogisticaNoteHtml = '<strong>PENDIENTE A SUBIR</strong>: este pedido ya está en <strong>CONFIRMADO CONTRAENTREGA</strong>. Súbelo a Ruta Contraentrega con este botón.';
$subirLogisticaNoteClass = 'alert alert-warning py-2 px-3 mt-2 mb-0';
$subirLogisticaNoteHtml = '<strong>ALERTA:</strong> este pedido está en <strong>CONFIRMADO CONTRAENTREGA</strong>, pero aún no se ha subido a Ruta Contraentrega. Usa este botón para subirlo.';
}
} elseif ($order['estado'] === 'CONFIRMADO ENVIO') {
if (!empty($order['pedido_rotulado_pedido_id'])) {
$subirLogisticaButtonLabel = 'Actualizar rotulado';
$subirLogisticaNoteClass = 'small mt-2 text-success fw-semibold';
$subirLogisticaNoteClass = 'alert alert-success py-2 px-3 mt-2 mb-0';
$subirLogisticaNoteHtml = 'En Pedidos Rotulados #' . (int) $order['pedido_rotulado_pedido_id'] . '. Si cambias algo, usa este botón para actualizarlo.';
} else {
$subirLogisticaButtonLabel = 'Subir a rotulados';
$subirLogisticaNoteClass = 'small mt-2 text-warning-emphasis';
$subirLogisticaNoteHtml = '<strong>PENDIENTE A SUBIR</strong>: este pedido ya está en <strong>CONFIRMADO ENVIO</strong>. Súbelo a Pedidos Rotulados con este botón.';
$subirLogisticaNoteClass = 'alert alert-warning py-2 px-3 mt-2 mb-0';
$subirLogisticaNoteHtml = '<strong>ALERTA:</strong> este pedido está en <strong>CONFIRMADO ENVIO</strong>, pero aún no se ha subido a Pedidos Rotulados. Usa este botón para subirlo.';
}
}
}
@ -2073,7 +2079,7 @@ require_once 'layout_header.php';
</div>
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2">
<h3 class="modal-title h5 mb-0"><?php echo htmlspecialchars(cc_test_display_value($order['nombre'], 'Cliente sin nombre')); ?></h3>
<?php if ($isMainTuaniStore): ?>
<?php if ($canShowTuaniLogisticaButton): ?>
<button type="button" class="btn btn-primary btn-sm px-3" id="subir-logistica-<?php echo htmlspecialchars($order['source_key']); ?>" data-route-pedido-id="<?php echo (int) ($order['ruta_contraentrega_pedido_id'] ?? 0); ?>" data-rotulado-pedido-id="<?php echo (int) ($order['pedido_rotulado_pedido_id'] ?? 0); ?>" onclick="guardarGestion('<?php echo htmlspecialchars($order['source_key']); ?>', this, { subirLogistica: true })"><?php echo htmlspecialchars($subirLogisticaButtonLabel); ?></button>
<?php endif; ?>
</div>
@ -2108,8 +2114,8 @@ require_once 'layout_header.php';
</div>
</div>
<?php endif; ?>
<?php if ($isMainTuaniStore): ?>
<div class="<?php echo htmlspecialchars($subirLogisticaNoteClass); ?>" id="subir-logistica-note-<?php echo htmlspecialchars($order['source_key']); ?>"><?php echo $subirLogisticaNoteHtml; ?></div>
<?php if ($canShowTuaniLogisticaButton): ?>
<div class="<?php echo htmlspecialchars($subirLogisticaNoteClass); ?>" id="subir-logistica-note-<?php echo htmlspecialchars($order['source_key']); ?>" role="alert"><?php echo $subirLogisticaNoteHtml; ?></div>
<?php endif; ?>
</div>
<button type="button" class="btn-close mt-1" data-bs-dismiss="modal" aria-label="Cerrar"></button>
@ -2451,7 +2457,7 @@ require_once 'layout_header.php';
<div class="modal-footer d-flex justify-content-between flex-wrap gap-2">
<div class="small text-muted">
<?php if ($isMainTuaniStore): ?>
<?php if ($canShowTuaniLogisticaButton): ?>
<strong>Guardar gestión</strong> solo guarda el historial. Para enviarlo a logística, usa el <strong>botón del encabezado</strong> junto al nombre del cliente.
<?php else: ?>
Los cambios se guardan en la base local del módulo de prueba.
@ -2716,10 +2722,10 @@ function updateLogisticaButton(sourceKey) {
button.disabled = false;
button.textContent = routeId > 0 ? 'Actualizar en ruta' : 'Subir a ruta';
if (note) {
note.className = 'small mt-2 ' + (routeId > 0 ? 'text-success fw-semibold' : 'text-warning-emphasis');
note.className = 'alert ' + (routeId > 0 ? 'alert-success' : 'alert-warning') + ' py-2 px-3 mt-2 mb-0';
note.innerHTML = routeId > 0
? 'En Ruta Contraentrega #' + routeId + '. Si cambias algo, usa este botón para actualizarlo.'
: '<strong>PENDIENTE A SUBIR</strong>: este pedido ya está en <strong>CONFIRMADO CONTRAENTREGA</strong>. Súbelo a Ruta Contraentrega con este botón.';
: '<strong>ALERTA:</strong> este pedido está en <strong>CONFIRMADO CONTRAENTREGA</strong>, pero aún no se ha subido a Ruta Contraentrega. Usa este botón para subirlo.';
}
return;
}
@ -2728,10 +2734,10 @@ function updateLogisticaButton(sourceKey) {
button.disabled = false;
button.textContent = rotuladoId > 0 ? 'Actualizar rotulado' : 'Subir a rotulados';
if (note) {
note.className = 'small mt-2 ' + (rotuladoId > 0 ? 'text-success fw-semibold' : 'text-warning-emphasis');
note.className = 'alert ' + (rotuladoId > 0 ? 'alert-success' : 'alert-warning') + ' py-2 px-3 mt-2 mb-0';
note.innerHTML = rotuladoId > 0
? 'En Pedidos Rotulados #' + rotuladoId + '. Si cambias algo, usa este botón para actualizarlo.'
: '<strong>PENDIENTE A SUBIR</strong>: este pedido ya está en <strong>CONFIRMADO ENVIO</strong>. Súbelo a Pedidos Rotulados con este botón.';
: '<strong>ALERTA:</strong> este pedido está en <strong>CONFIRMADO ENVIO</strong>, pero aún no se ha subido a Pedidos Rotulados. Usa este botón para subirlo.';
}
return;
}
@ -2739,7 +2745,7 @@ function updateLogisticaButton(sourceKey) {
button.disabled = true;
button.textContent = 'Subir pedido';
if (note) {
note.className = 'small mt-2 text-muted';
note.className = 'alert alert-secondary py-2 px-3 mt-2 mb-0';
note.textContent = 'Selecciona CONFIRMADO CONTRAENTREGA o CONFIRMADO ENVIO para enviarlo a logística.';
}
}
@ -3573,9 +3579,8 @@ if (bulkAssignForm) {
syncBulkAssignSelectionUi();
}
window.setInterval(function () {
window.location.reload();
}, 600000);
</script>
<?php require_once 'layout_footer.php'; ?>

View File

@ -688,6 +688,31 @@ function cc_test_load_reparto_orders(PDO $pdo, string $storeKey): array
}));
}
function cc_test_tuani_reparto_is_eligible(array $order, string $storeKey, array $storeConfig): bool
{
return true;
}
if (!function_exists('cc_test_filter_reparto_orders')) {
function cc_test_filter_reparto_orders(array $orders, string $storeKey, array $storeConfig): array
{
$filteredOrders = [];
foreach ($orders as $order) {
if (!is_array($order)) {
continue;
}
if (!cc_test_tuani_reparto_is_eligible($order, $storeKey, $storeConfig)) {
continue;
}
$filteredOrders[] = $order;
}
return array_values($filteredOrders);
}
}
function cc_test_run_locked_reparto_job(PDO $pdo, string $storeKey, array $assessors, callable $loadOrders, array $settings = [], ?callable $filterOrders = null, int $lockTimeoutSeconds = 5): array
{
$lockName = cc_test_reparto_lock_name($storeKey);