diff --git "a/; $pos=strpos($body,$marker); if($pos===false){ echo \"no-marker\\n\"; exit; } $start=$pos+strlen($marker); $end=strpos($body,\"<\",$start); echo substr($body,$start,$end-$start),\"\\n\";" "b/; $pos=strpos($body,$marker); if($pos===false){ echo \"no-marker\\n\"; exit; } $start=$pos+strlen($marker); $end=strpos($body,\"<\",$start); echo substr($body,$start,$end-$start),\"\\n\";" new file mode 100644 index 00000000..e69de29b diff --git a/call_center_pro.php b/call_center_pro.php index ed020090..6826a05b 100644 --- a/call_center_pro.php +++ b/call_center_pro.php @@ -317,11 +317,10 @@ function cc_test_panel_orders_signature(array $orders): string return sha1(json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); } -$view = trim((string) ($_GET['view'] ?? '')); +$view = cc_test_resolve_callcenter_context_key($_GET['view'] ?? '', cc_test_callcenter_view_session_key()); -$storeKey = trim((string) ($_GET['store'] ?? 'flower')); -$storeKey = mb_strtolower($storeKey); $availableStores = drive_test_available_stores(); +$storeKey = cc_test_resolve_callcenter_context_key($_GET['store'] ?? '', cc_test_callcenter_store_session_key(), 'flower'); if (!isset($availableStores[$storeKey])) { $storeKey = 'flower'; } @@ -337,6 +336,9 @@ $parentStoreLabel = (string) ($storeNav['parent_label'] ?? ''); $isMainTuaniStore = cc_test_is_tuani_main_store_key($storeKey); $isTuaniRecuperablesStore = $storeKey === 'tuani_recuperables'; +if ($isTuaniRecuperablesStore && trim((string) ($_GET['view'] ?? '')) === '') { + $view = 'todos'; +} $canShowTuaniLogisticaButton = $isMainTuaniStore || $isTuaniRecuperablesStore; $viewCardColumnClass = $isTuaniRecuperablesStore ? 'col-md-6 col-xl-2' : 'col-md-6 col-xl-2'; $defaultView = cc_test_callcenter_pro_default_view_key($storeKey); @@ -456,7 +458,7 @@ $_SESSION[cc_test_callcenter_store_session_key()] = cc_test_normalize_context_ke $_SESSION[cc_test_callcenter_view_session_key()] = cc_test_normalize_context_key($view); $viewStatesNote = $isTuaniRecuperablesStore - ? 'Estados disponibles: Carritos recuperables, Seguimiento, Observados, Confirmados, Recuperados y Todos. Esta bandeja compartida está disponible para cualquier asesora y, cuando una asesora gestiona un carrito recuperable, el sistema lo asigna automáticamente a quien lo trabaja. Si el teléfono ya existe en TUANI principal, se marca en gris como Pedido repetido en tienda solo en esta bandeja. La vista Todos arranca en la fila 2000 y se pagina en bloques de 200 pedidos.' + ? 'Estados disponibles: Carritos recuperables, Seguimiento, Observados, Confirmados, Recuperados y Todos. Esta bandeja compartida está disponible para cualquier asesora y, cuando una asesora gestiona un carrito recuperable, el sistema lo asigna automáticamente a quien lo trabaja. Si el teléfono ya existe en TUANI principal, se marca en gris como Pedido repetido en tienda solo en esta bandeja. Las vistas Carritos recuperables y Todos arrancan en la fila 2000, solo toman pedidos desde esa fila y se ordenan por el número #D más alto, lo que mantiene arriba el código más reciente, al más antiguo, en bloques de 200 pedidos.' : 'Estados disponibles: Por llamar, Devolver llamada, Observado, Se envió número de cuenta, Confirmado contraentrega, Confirmado envío, Cancelado y Repetido. Promo Final se habilita para mover el pedido desde el Día 4; la imagen de sustento se puede cargar desde el Día 3 para dejarlo listo antes del pase. Además, esta bandeja principal incluye reparto intercalado diario: en modo automático reparte pedidos sin asignar entre asesoras activas; en modo manual el supervisor los mueve pedido por pedido. También puedes usar la vista Últimos 4 días hábiles para concentrar el seguimiento reciente.'; $errorMessage = null; @@ -475,6 +477,7 @@ $recoverablesImportCount = 0; $recoverablesFirstSourceRow = null; $recoverablesLastSourceRow = null; $startRow = (int) ($storeConfig['startRow'] ?? 0); +$recoverablesMinimumSourceRow = $isTuaniRecuperablesStore ? (int) ($storeConfig['startRow'] ?? 0) : 0; $catalogoProductos = []; $stats = [ 'total' => 0, @@ -562,6 +565,9 @@ try { $orders = array_values(array_filter($orders, static function (array $order): bool { return empty($order['eliminado']); })); + if ($isTuaniRecuperablesStore) { + $orders = cc_test_filter_recoverables_orders($orders, $recoverablesMinimumSourceRow); + } $postedAction = trim((string) ($_POST['action'] ?? '')); if ($_SERVER['REQUEST_METHOD'] === 'POST') { @@ -868,6 +874,10 @@ try { $aImport = cc_test_import_time($a); $bImport = cc_test_import_time($b); + if (cc_test_is_tuani_recoverables_store_key($storeKey) && in_array($view, ['pendientes_hoy', 'todos'], true)) { + return cc_test_compare_recoverables_orders_desc($a, $b); + } + if ($view === 'nuevos_hoy') { $aOrderNumberValue = cc_test_order_priority_value($a); $bOrderNumberValue = cc_test_order_priority_value($b); @@ -984,6 +994,10 @@ try { } if ($view === 'todos') { + if (cc_test_is_tuani_recoverables_store_key($storeKey)) { + return cc_test_compare_recoverables_orders_desc($a, $b); + } + if ($aImport !== $bImport) { return $bImport <=> $aImport; } @@ -991,9 +1005,7 @@ try { $aSourceRow = (int) ($a['source_row'] ?? 0); $bSourceRow = (int) ($b['source_row'] ?? 0); if ($aSourceRow !== $bSourceRow) { - return cc_test_is_tuani_recoverables_store_key($storeKey) - ? ($aSourceRow <=> $bSourceRow) - : ($bSourceRow <=> $aSourceRow); + return $bSourceRow <=> $aSourceRow; } $aId = (int) ($a['id'] ?? 0); @@ -1354,6 +1366,14 @@ require_once 'layout_header.php';

+
+ Tienda activa: + + Solo pedidos válidos: IDs #D... + + Abrir Carritos recuperables (#D...) + +
Base de Datos Pedidos diff --git a/gestiones_callcenter.php b/gestiones_callcenter.php index 8f6e3b61..618365cf 100644 --- a/gestiones_callcenter.php +++ b/gestiones_callcenter.php @@ -214,11 +214,10 @@ function cc_test_followup_semaforo(array $order): ?array } $defaultView = 'todos'; -$view = trim((string) ($_GET['view'] ?? $defaultView)); +$view = cc_test_resolve_callcenter_context_key($_GET['view'] ?? '', cc_test_callcenter_view_session_key()); -$storeKey = trim((string) ($_GET['store'] ?? 'flower')); -$storeKey = mb_strtolower($storeKey); $availableStores = drive_test_available_stores(); +$storeKey = cc_test_resolve_callcenter_context_key($_GET['store'] ?? '', cc_test_callcenter_store_session_key(), 'flower'); if (!isset($availableStores[$storeKey])) { $storeKey = 'flower'; } @@ -234,6 +233,9 @@ $parentStoreLabel = (string) ($storeNav['parent_label'] ?? ''); $isMainTuaniStore = cc_test_is_tuani_main_store_key($storeKey); $isTuaniRecuperablesStore = $storeKey === 'tuani_recuperables'; +if ($isTuaniRecuperablesStore && trim((string) ($_GET['view'] ?? '')) === '') { + $view = 'todos'; +} $canShowTuaniLogisticaButton = $isMainTuaniStore || $isTuaniRecuperablesStore; $viewCardColumnClass = $isTuaniRecuperablesStore ? 'col-md-6 col-xl-2' : 'col-md-6 col-xl-2'; $callCenterDefaultView = ($isMainTuaniStore || $isTuaniRecuperablesStore) ? cc_test_callcenter_pro_default_view_key($storeKey) : $view; @@ -347,7 +349,7 @@ $_SESSION[cc_test_callcenter_store_session_key()] = cc_test_normalize_context_ke $_SESSION[cc_test_callcenter_view_session_key()] = cc_test_normalize_context_key($view); $viewStatesNote = $isTuaniRecuperablesStore - ? 'Estados disponibles: Carritos recuperables, Seguimiento, Observados, Confirmados, Recuperados y Todos. Esta bandeja compartida está disponible para cualquier asesora y, cuando una asesora gestiona un carrito recuperable, el sistema lo asigna automáticamente a quien lo trabaja. Si el teléfono ya existe en TUANI principal, se marca en gris como Pedido repetido en tienda solo en esta bandeja. La vista Todos arranca en la fila 2000 y se pagina en bloques de 200 pedidos.' + ? 'Estados disponibles: Carritos recuperables, Seguimiento, Observados, Confirmados, Recuperados y Todos. Esta bandeja compartida está disponible para cualquier asesora y, cuando una asesora gestiona un carrito recuperable, el sistema lo asigna automáticamente a quien lo trabaja. Si el teléfono ya existe en TUANI principal, se marca en gris como Pedido repetido en tienda solo en esta bandeja. Las vistas Carritos recuperables y Todos arrancan en la fila 2000, solo toman pedidos desde esa fila y se ordenan por el número #D más alto, lo que mantiene arriba el código más reciente, al más antiguo, en bloques de 200 pedidos.' : 'Estados disponibles: Por llamar, Devolver llamada, Observado, Se envió número de cuenta, Confirmado contraentrega, Confirmado envío, Cancelado y Repetido. Promo Final se habilita para mover el pedido desde el Día 4; la imagen de sustento se puede cargar desde el Día 3 para dejarlo listo. En las vistas Todos y Últimos 4 días hábiles, la llamada y la gestión siguen disponibles desde el panel.'; $errorMessage = null; @@ -399,6 +401,7 @@ $advisorOpenCounts = []; $advisorTotalCounts = []; $recommendedAssessorKey = null; $startRow = (int) ($storeConfig['startRow'] ?? 0); +$recoverablesMinimumSourceRow = $isTuaniRecuperablesStore ? (int) ($storeConfig['startRow'] ?? 0) : 0; $catalogoProductos = []; $stats = [ 'total' => 0, @@ -488,6 +491,9 @@ try { $orders = array_values(array_filter($orders, static function (array $order): bool { return empty($order['eliminado']); })); + if ($isTuaniRecuperablesStore) { + $orders = cc_test_filter_recoverables_orders($orders, $recoverablesMinimumSourceRow); + } if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'assign_assessor') { $sourceKey = trim((string) ($_POST['source_key'] ?? '')); @@ -1095,6 +1101,10 @@ try { $aImport = cc_test_import_time($a); $bImport = cc_test_import_time($b); + if (cc_test_is_tuani_recoverables_store_key($storeKey) && in_array($view, ['pendientes_hoy', 'todos'], true)) { + return cc_test_compare_recoverables_orders_desc($a, $b); + } + if ($view === 'promo_final') { $aDays = (int) ($a['dias_seguimiento'] ?? 0); $bDays = (int) ($b['dias_seguimiento'] ?? 0); @@ -1169,6 +1179,10 @@ try { } if ($view === 'todos') { + if (cc_test_is_tuani_recoverables_store_key($storeKey)) { + return cc_test_compare_recoverables_orders_desc($a, $b); + } + if ($aImport !== $bImport) { return $bImport <=> $aImport; } @@ -1176,9 +1190,7 @@ try { $aSourceRow = (int) ($a['source_row'] ?? 0); $bSourceRow = (int) ($b['source_row'] ?? 0); if ($aSourceRow !== $bSourceRow) { - return cc_test_is_tuani_recoverables_store_key($storeKey) - ? ($aSourceRow <=> $bSourceRow) - : ($bSourceRow <=> $aSourceRow); + return $bSourceRow <=> $aSourceRow; } $aId = (int) ($a['id'] ?? 0); @@ -1610,6 +1622,14 @@ require_once 'layout_header.php';

Base de Datos Pedidos

+
+ Tienda activa: + + Solo pedidos válidos: IDs #D... + + Abrir Carritos recuperables (#D...) + +
Bandeja principal diff --git a/includes/callcenter_test_helpers.php b/includes/callcenter_test_helpers.php index 1a31000b..03768002 100644 --- a/includes/callcenter_test_helpers.php +++ b/includes/callcenter_test_helpers.php @@ -1065,6 +1065,88 @@ function cc_test_normalize_context_key(?string $value): string return mb_strtolower($value); } +function cc_test_resolve_callcenter_context_key(?string $incomingValue, string $sessionKey, string $fallback = ''): string +{ + $incomingValue = cc_test_normalize_context_key($incomingValue ?? ''); + if ($incomingValue !== '') { + return $incomingValue; + } + + $sessionValue = cc_test_normalize_context_key($_SESSION[$sessionKey] ?? ''); + if ($sessionValue !== '') { + return $sessionValue; + } + + return cc_test_normalize_context_key($fallback); +} + +function cc_test_is_recoverables_order_code(?string $codigo): bool +{ + $codigo = trim((string) $codigo); + if ($codigo === '') { + return false; + } + + $codigo = ltrim($codigo, '#'); + return preg_match('/^D\d+$/i', $codigo) === 1; +} + +function cc_test_recoverables_order_sort_value(array $order): int +{ + $codigo = trim((string) ($order['codigo'] ?? '')); + if ($codigo !== '' && preg_match('/^#?D(\d+)$/i', $codigo, $matches) === 1) { + return (int) ($matches[1] ?? 0); + } + + $sourceRow = (int) ($order['source_row'] ?? 0); + if ($sourceRow > 0) { + return $sourceRow; + } + + return (int) ($order['id'] ?? 0); +} + +function cc_test_filter_recoverables_orders(array $orders, int $minimumSourceRow = 0): array +{ + $minimumSourceRow = max(0, $minimumSourceRow); + + return array_values(array_filter($orders, static function (array $order) use ($minimumSourceRow): bool { + if (!cc_test_is_recoverables_order_code($order['codigo'] ?? '')) { + return false; + } + + $sourceRow = (int) ($order['source_row'] ?? 0); + if ($minimumSourceRow > 0 && $sourceRow < $minimumSourceRow) { + return false; + } + + return true; + })); +} + +function cc_test_compare_recoverables_orders_desc(array $a, array $b): int +{ + $aValue = cc_test_recoverables_order_sort_value($a); + $bValue = cc_test_recoverables_order_sort_value($b); + if ($aValue !== $bValue) { + return $bValue <=> $aValue; + } + + $aSourceRow = (int) ($a['source_row'] ?? 0); + $bSourceRow = (int) ($b['source_row'] ?? 0); + if ($aSourceRow !== $bSourceRow) { + return $bSourceRow <=> $aSourceRow; + } + + $aId = (int) ($a['id'] ?? 0); + $bId = (int) ($b['id'] ?? 0); + if ($aId !== $bId) { + return $bId <=> $aId; + } + + return strcmp((string) ($a['source_key'] ?? ''), (string) ($b['source_key'] ?? '')); +} + function cc_test_resolve_callcenter_assessor_filter(array $assessors, ?string $incomingFilter = null, bool $useSessionFallback = true, bool $persistSession = true): string { $sessionKey = cc_test_callcenter_assessor_filter_session_key();