Autosave: 20260807-073833
This commit is contained in:
parent
9f2ee910f3
commit
dd197310a1
@ -326,6 +326,12 @@ if (!isset($availableStores[$storeKey])) {
|
||||
}
|
||||
$storeConfig = $availableStores[$storeKey];
|
||||
$storeLabel = (string) ($storeConfig['label'] ?? strtoupper($storeKey));
|
||||
$recoverablesStoreKey = trim((string) ($storeConfig['recoverables_store_key'] ?? ''));
|
||||
$recoverablesStoreLabel = $recoverablesStoreKey !== '' && isset($availableStores[$recoverablesStoreKey]) ? (string) ($availableStores[$recoverablesStoreKey]['label'] ?? strtoupper($recoverablesStoreKey)) : '';
|
||||
$recoverablesMainStoreKey = trim((string) ($storeConfig['main_store_key'] ?? ''));
|
||||
$recoverablesMainStoreLabel = $recoverablesMainStoreKey !== '' && isset($availableStores[$recoverablesMainStoreKey]) ? (string) ($availableStores[$recoverablesMainStoreKey]['label'] ?? strtoupper($recoverablesMainStoreKey)) : $storeLabel;
|
||||
$recoverablesStoreLabelHtml = htmlspecialchars($storeLabel);
|
||||
$recoverablesMainStoreLabelHtml = htmlspecialchars($recoverablesMainStoreLabel);
|
||||
$usesIncrementalSync = !empty($storeConfig['incremental_sync']);
|
||||
$storeNav = drive_test_store_navigation_state($availableStores, $storeKey);
|
||||
$storeNavGroups = $storeNav['groups'];
|
||||
@ -335,7 +341,7 @@ $activeStoreGroupChildren = $storeNav['active_group_children'] ?? [];
|
||||
$parentStoreLabel = (string) ($storeNav['parent_label'] ?? '');
|
||||
|
||||
$isMainTuaniStore = cc_test_is_tuani_main_store_key($storeKey);
|
||||
$isTuaniRecuperablesStore = $storeKey === 'tuani_recuperables';
|
||||
$isTuaniRecuperablesStore = cc_test_is_recoverables_store_key($storeKey);
|
||||
if ($isTuaniRecuperablesStore && trim((string) ($_GET['view'] ?? '')) === '') {
|
||||
$view = 'todos';
|
||||
}
|
||||
@ -347,17 +353,11 @@ $viewCardColumnClass = $isTuaniRecuperablesStore ? 'col-md-6 col-xl-2' : 'col-md
|
||||
$defaultView = cc_test_callcenter_pro_default_view_key($storeKey);
|
||||
|
||||
$viewCards = $isTuaniRecuperablesStore ? [
|
||||
'pendientes_hoy' => [
|
||||
'label' => 'Carritos recuperables',
|
||||
'heading' => 'Carritos recuperables',
|
||||
'stat_key' => 'pendientes_hoy',
|
||||
'active_class' => 'bg-dark text-white',
|
||||
],
|
||||
'nuevos_hoy' => [
|
||||
'label' => 'Nuevos hoy',
|
||||
'heading' => 'Nuevos hoy',
|
||||
'stat_key' => 'nuevos_hoy',
|
||||
'active_class' => 'bg-primary-subtle border border-primary',
|
||||
'todos' => [
|
||||
'label' => 'Todos',
|
||||
'heading' => 'Todos los pedidos cargados',
|
||||
'stat_key' => 'total',
|
||||
'active_class' => 'bg-light border',
|
||||
],
|
||||
'confirmados' => [
|
||||
'label' => 'Confirmados',
|
||||
@ -383,11 +383,11 @@ $viewCards = $isTuaniRecuperablesStore ? [
|
||||
'stat_key' => 'observados',
|
||||
'active_class' => 'bg-warning-subtle border border-warning',
|
||||
],
|
||||
'todos' => [
|
||||
'label' => 'Todos',
|
||||
'heading' => 'Todos los pedidos cargados',
|
||||
'stat_key' => 'total',
|
||||
'active_class' => 'bg-light border',
|
||||
'pendientes_hoy' => [
|
||||
'label' => $storeLabel,
|
||||
'heading' => $storeLabel,
|
||||
'stat_key' => 'pendientes_hoy',
|
||||
'active_class' => 'bg-dark text-white',
|
||||
],
|
||||
] : [
|
||||
'nuevos_hoy' => [
|
||||
@ -467,7 +467,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: <strong>Carritos recuperables</strong>, <strong>Nuevos hoy</strong>, <strong>Seguimiento</strong>, <strong>Observados</strong>, <strong>Confirmados</strong>, <strong>Recuperados</strong> y <strong>Todos</strong>. La vista <strong>Nuevos hoy</strong> agrupa los pedidos más recientes agregados desde Drive. 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 <strong>TUANI principal</strong>, se marca en gris como <strong>Pedido repetido en tienda</strong> solo en esta bandeja. Las vistas <strong>Carritos recuperables</strong> y <strong>Todos</strong> arrancan en la fila 2000, solo toman pedidos desde esa fila y se ordenan por el número <strong>#D</strong> más alto, lo que mantiene arriba el código más reciente, al más antiguo, en bloques de 200 pedidos.'
|
||||
? 'Estados disponibles: <strong>' . $recoverablesStoreLabelHtml . '</strong>, <strong>Seguimiento</strong>, <strong>Observados</strong>, <strong>Confirmados</strong>, <strong>Recuperados</strong> y <strong>Todos</strong>. Esta bandeja abre por defecto en <strong>Todos</strong>. La 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 <strong>' . $recoverablesMainStoreLabelHtml . ' principal</strong>, se marca en gris como <strong>Pedido repetido en tienda</strong> solo en esta bandeja. Las vistas <strong>' . $recoverablesStoreLabelHtml . '</strong> y <strong>Todos</strong> arrancan en la fila ' . (int) ($storeConfig['startRow'] ?? 0) . ', solo toman pedidos desde esa fila y se ordenan por el número <strong>#D</strong> 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. <strong>Promo Final</strong> 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 <strong>Últimos 4 días hábiles</strong> para concentrar el seguimiento reciente.';
|
||||
|
||||
$errorMessage = null;
|
||||
@ -922,7 +922,7 @@ 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)) {
|
||||
if (cc_test_is_recoverables_store_key($storeKey) && in_array($view, ['pendientes_hoy', 'todos'], true)) {
|
||||
return cc_test_compare_recoverables_orders_desc($a, $b);
|
||||
}
|
||||
|
||||
@ -1042,7 +1042,7 @@ try {
|
||||
}
|
||||
|
||||
if ($view === 'todos') {
|
||||
if (cc_test_is_tuani_recoverables_store_key($storeKey)) {
|
||||
if (cc_test_is_recoverables_store_key($storeKey)) {
|
||||
return cc_test_compare_recoverables_orders_desc($a, $b);
|
||||
}
|
||||
|
||||
@ -1179,14 +1179,14 @@ if (!empty($_GET['ajax_refresh'])) {
|
||||
}
|
||||
|
||||
if ($isTuaniRecuperablesStore) {
|
||||
$pageTitle = 'Carritos recuperables | Bandeja compartida';
|
||||
$pageDescription = 'Bandeja compartida para que cualquier asesora gestione carritos recuperables con vistas de seguimiento y observados desde Drive.';
|
||||
$pageTitle = $storeLabel . ' | Bandeja compartida';
|
||||
$pageDescription = 'Bandeja compartida para que cualquier asesora gestione ' . mb_strtolower($storeLabel) . ' con vistas de seguimiento y observados desde Drive.';
|
||||
} else {
|
||||
$pageTitle = 'Pedidos Asignados | Bandeja de la asesora';
|
||||
$pageDescription = 'Bandeja para que cada asesora gestione sus pedidos asignados con vistas de hoy, últimos 4 días hábiles, estados, historial y acciones.';
|
||||
}
|
||||
|
||||
$callCenterSectionLabel = $isTuaniRecuperablesStore ? 'Carritos recuperables' : 'Pedidos Asignados';
|
||||
$callCenterSectionLabel = $isTuaniRecuperablesStore ? $storeLabel : 'Pedidos Asignados';
|
||||
|
||||
require_once 'layout_header.php';
|
||||
?>
|
||||
@ -1399,7 +1399,7 @@ require_once 'layout_header.php';
|
||||
<?php if ($isTuaniRecuperablesStore): ?>
|
||||
<span class="badge rounded-pill bg-success-subtle text-success-emphasis border px-3 py-2">Solo pedidos válidos: IDs #D...</span>
|
||||
<?php else: ?>
|
||||
<a href="<?php echo htmlspecialchars(cc_test_build_url('call_center_pro.php', ['store' => 'tuani_recuperables', 'view' => 'nuevos_hoy'])); ?>" class="btn btn-sm btn-outline-success">Abrir Carritos recuperables (#D...)</a>
|
||||
<a href="<?php echo htmlspecialchars(cc_test_build_url('call_center_pro.php', ['store' => $recoverablesStoreKey, 'view' => 'todos'])); ?>" class="btn btn-sm btn-outline-success">Abrir <?php echo htmlspecialchars($recoverablesStoreLabel !== '' ? $recoverablesStoreLabel : 'Carritos recuperables'); ?> (#D...)</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="d-flex flex-wrap gap-2 mt-3">
|
||||
@ -1412,7 +1412,7 @@ require_once 'layout_header.php';
|
||||
<?php foreach ($storeNavGroups as $groupKey => $group): ?>
|
||||
<?php $groupConfig = $group['config'] ?? []; ?>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <?php echo $activeStoreGroupKey === $groupKey ? 'active' : ''; ?>" href="<?php echo htmlspecialchars(cc_test_build_url('call_center_pro.php', array_merge($callCenterParams, ['view' => $groupKey === 'tuani_recuperables' ? 'nuevos_hoy' : $view, 'store' => $groupKey]))); ?>">
|
||||
<a class="nav-link <?php echo $activeStoreGroupKey === $groupKey ? 'active' : ''; ?>" href="<?php echo htmlspecialchars(cc_test_build_url('call_center_pro.php', array_merge($callCenterParams, ['view' => cc_test_is_recoverables_store_key($groupKey) ? 'todos' : $view, 'store' => $groupKey]))); ?>">
|
||||
<?php echo htmlspecialchars((string) ($groupConfig['label'] ?? strtoupper((string) $groupKey))); ?>
|
||||
</a>
|
||||
</li>
|
||||
@ -1422,9 +1422,9 @@ require_once 'layout_header.php';
|
||||
<div class="mt-3 p-3 rounded-4 border bg-light">
|
||||
<div class="small text-uppercase text-muted fw-semibold mb-2">Dentro de <?php echo htmlspecialchars($activeStoreGroupLabel); ?></div>
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
<a class="btn btn-sm <?php echo $storeKey === $activeStoreGroupKey ? 'btn-primary' : 'btn-outline-primary'; ?>" href="<?php echo htmlspecialchars(cc_test_build_url('call_center_pro.php', array_merge($callCenterParams, ['view' => $activeStoreGroupKey === 'tuani_recuperables' ? 'nuevos_hoy' : $view, 'store' => $activeStoreGroupKey]))); ?>">Pedidos <?php echo htmlspecialchars($activeStoreGroupLabel); ?></a>
|
||||
<a class="btn btn-sm <?php echo $storeKey === $activeStoreGroupKey ? 'btn-primary' : 'btn-outline-primary'; ?>" href="<?php echo htmlspecialchars(cc_test_build_url('call_center_pro.php', array_merge($callCenterParams, ['view' => cc_test_is_recoverables_store_key($activeStoreGroupKey) ? 'todos' : $view, 'store' => $activeStoreGroupKey]))); ?>">Pedidos <?php echo htmlspecialchars($activeStoreGroupLabel); ?></a>
|
||||
<?php foreach ($activeStoreGroupChildren as $childKey => $childConfig): ?>
|
||||
<a class="btn btn-sm <?php echo $storeKey === $childKey ? 'btn-primary' : 'btn-outline-primary'; ?>" href="<?php echo htmlspecialchars(cc_test_build_url('call_center_pro.php', array_merge($callCenterParams, ['view' => $childKey === 'tuani_recuperables' ? 'nuevos_hoy' : $view, 'store' => $childKey]))); ?>">
|
||||
<a class="btn btn-sm <?php echo $storeKey === $childKey ? 'btn-primary' : 'btn-outline-primary'; ?>" href="<?php echo htmlspecialchars(cc_test_build_url('call_center_pro.php', array_merge($callCenterParams, ['view' => cc_test_is_recoverables_store_key($childKey) ? 'todos' : $view, 'store' => $childKey]))); ?>">
|
||||
<?php echo htmlspecialchars((string) ($childConfig['label'] ?? strtoupper((string) $childKey))); ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
|
||||
@ -223,6 +223,12 @@ if (!isset($availableStores[$storeKey])) {
|
||||
}
|
||||
$storeConfig = $availableStores[$storeKey];
|
||||
$storeLabel = (string) ($storeConfig['label'] ?? strtoupper($storeKey));
|
||||
$recoverablesStoreKey = trim((string) ($storeConfig['recoverables_store_key'] ?? ''));
|
||||
$recoverablesStoreLabel = $recoverablesStoreKey !== '' && isset($availableStores[$recoverablesStoreKey]) ? (string) ($availableStores[$recoverablesStoreKey]['label'] ?? strtoupper($recoverablesStoreKey)) : '';
|
||||
$recoverablesMainStoreKey = trim((string) ($storeConfig['main_store_key'] ?? ''));
|
||||
$recoverablesMainStoreLabel = $recoverablesMainStoreKey !== '' && isset($availableStores[$recoverablesMainStoreKey]) ? (string) ($availableStores[$recoverablesMainStoreKey]['label'] ?? strtoupper($recoverablesMainStoreKey)) : $storeLabel;
|
||||
$recoverablesStoreLabelHtml = htmlspecialchars($storeLabel);
|
||||
$recoverablesMainStoreLabelHtml = htmlspecialchars($recoverablesMainStoreLabel);
|
||||
$usesIncrementalSync = !empty($storeConfig['incremental_sync']);
|
||||
$storeNav = drive_test_store_navigation_state($availableStores, $storeKey);
|
||||
$storeNavGroups = $storeNav['groups'];
|
||||
@ -232,7 +238,7 @@ $activeStoreGroupChildren = $storeNav['active_group_children'] ?? [];
|
||||
$parentStoreLabel = (string) ($storeNav['parent_label'] ?? '');
|
||||
|
||||
$isMainTuaniStore = cc_test_is_tuani_main_store_key($storeKey);
|
||||
$isTuaniRecuperablesStore = $storeKey === 'tuani_recuperables';
|
||||
$isTuaniRecuperablesStore = cc_test_is_recoverables_store_key($storeKey);
|
||||
if ($isTuaniRecuperablesStore && trim((string) ($_GET['view'] ?? '')) === '') {
|
||||
$view = 'todos';
|
||||
}
|
||||
@ -244,17 +250,11 @@ $viewCardColumnClass = $isTuaniRecuperablesStore ? 'col-md-6 col-xl-2' : 'col-md
|
||||
$callCenterDefaultView = ($isMainTuaniStore || $isTuaniRecuperablesStore) ? cc_test_callcenter_pro_default_view_key($storeKey) : $view;
|
||||
|
||||
$viewCards = $isTuaniRecuperablesStore ? [
|
||||
'pendientes_hoy' => [
|
||||
'label' => 'Carritos recuperables',
|
||||
'heading' => 'Carritos recuperables',
|
||||
'stat_key' => 'pendientes_hoy',
|
||||
'active_class' => 'bg-dark text-white',
|
||||
],
|
||||
'nuevos_hoy' => [
|
||||
'label' => 'Nuevos hoy',
|
||||
'heading' => 'Nuevos hoy',
|
||||
'stat_key' => 'nuevos_hoy',
|
||||
'active_class' => 'bg-primary-subtle border border-primary',
|
||||
'todos' => [
|
||||
'label' => 'Todos',
|
||||
'heading' => 'Todos los pedidos cargados',
|
||||
'stat_key' => 'total',
|
||||
'active_class' => 'bg-light border',
|
||||
],
|
||||
'confirmados' => [
|
||||
'label' => 'Confirmados',
|
||||
@ -280,11 +280,11 @@ $viewCards = $isTuaniRecuperablesStore ? [
|
||||
'stat_key' => 'observados',
|
||||
'active_class' => 'bg-warning-subtle border border-warning',
|
||||
],
|
||||
'todos' => [
|
||||
'label' => 'Todos',
|
||||
'heading' => 'Todos los pedidos cargados',
|
||||
'stat_key' => 'total',
|
||||
'active_class' => 'bg-light border',
|
||||
'pendientes_hoy' => [
|
||||
'label' => $storeLabel,
|
||||
'heading' => $storeLabel,
|
||||
'stat_key' => 'pendientes_hoy',
|
||||
'active_class' => 'bg-dark text-white',
|
||||
],
|
||||
] : [
|
||||
'pendientes_hoy' => [
|
||||
@ -358,7 +358,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: <strong>Carritos recuperables</strong>, <strong>Nuevos hoy</strong>, <strong>Seguimiento</strong>, <strong>Observados</strong>, <strong>Confirmados</strong>, <strong>Recuperados</strong> y <strong>Todos</strong>. La vista <strong>Nuevos hoy</strong> agrupa los pedidos más recientes agregados desde Drive. 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 <strong>TUANI principal</strong>, se marca en gris como <strong>Pedido repetido en tienda</strong> solo en esta bandeja. Las vistas <strong>Carritos recuperables</strong> y <strong>Todos</strong> arrancan en la fila 2000, solo toman pedidos desde esa fila y se ordenan por el número <strong>#D</strong> más alto, lo que mantiene arriba el código más reciente, al más antiguo, en bloques de 200 pedidos.'
|
||||
? 'Estados disponibles: <strong>' . $recoverablesStoreLabelHtml . '</strong>, <strong>Seguimiento</strong>, <strong>Observados</strong>, <strong>Confirmados</strong>, <strong>Recuperados</strong> y <strong>Todos</strong>. Esta bandeja abre por defecto en <strong>Todos</strong>. La 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 <strong>' . $recoverablesMainStoreLabelHtml . ' principal</strong>, se marca en gris como <strong>Pedido repetido en tienda</strong> solo en esta bandeja. Las vistas <strong>' . $recoverablesStoreLabelHtml . '</strong> y <strong>Todos</strong> arrancan en la fila ' . (int) ($storeConfig['startRow'] ?? 0) . ', solo toman pedidos desde esa fila y se ordenan por el número <strong>#D</strong> 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. <strong>Promo Final</strong> 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 <strong>Todos</strong> y <strong>Últimos 4 días hábiles</strong>, la llamada y la gestión siguen disponibles desde el panel.';
|
||||
|
||||
$errorMessage = null;
|
||||
@ -1149,7 +1149,7 @@ 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)) {
|
||||
if (cc_test_is_recoverables_store_key($storeKey) && in_array($view, ['pendientes_hoy', 'todos'], true)) {
|
||||
return cc_test_compare_recoverables_orders_desc($a, $b);
|
||||
}
|
||||
|
||||
@ -1227,7 +1227,7 @@ try {
|
||||
}
|
||||
|
||||
if ($view === 'todos') {
|
||||
if (cc_test_is_tuani_recoverables_store_key($storeKey)) {
|
||||
if (cc_test_is_recoverables_store_key($storeKey)) {
|
||||
return cc_test_compare_recoverables_orders_desc($a, $b);
|
||||
}
|
||||
|
||||
@ -1310,14 +1310,14 @@ try {
|
||||
}
|
||||
|
||||
if ($isTuaniRecuperablesStore) {
|
||||
$pageTitle = 'Carritos recuperables | Base de Datos Pedidos';
|
||||
$pageDescription = 'Bandeja compartida para que cualquier asesora revise carritos recuperables con vistas de seguimiento y observados cargados desde Drive.';
|
||||
$pageTitle = $storeLabel . ' | Base de Datos Pedidos';
|
||||
$pageDescription = 'Bandeja compartida para que cualquier asesora revise ' . mb_strtolower($storeLabel) . ' con vistas de seguimiento y observados cargados desde Drive.';
|
||||
} else {
|
||||
$pageTitle = 'Base de Datos Pedidos | Asignación';
|
||||
$pageDescription = 'Bandejas de asignación y gestión de estados para el Call Center, cargadas desde Drive.';
|
||||
}
|
||||
|
||||
$callCenterSectionLabel = $isTuaniRecuperablesStore ? 'Carritos recuperables' : 'Pedidos Asignados';
|
||||
$callCenterSectionLabel = $isTuaniRecuperablesStore ? $storeLabel : 'Pedidos Asignados';
|
||||
|
||||
require_once 'layout_header.php';
|
||||
?>
|
||||
@ -1655,7 +1655,7 @@ require_once 'layout_header.php';
|
||||
<?php if ($isTuaniRecuperablesStore): ?>
|
||||
<span class="badge rounded-pill bg-success-subtle text-success-emphasis border px-3 py-2">Solo pedidos válidos: IDs #D...</span>
|
||||
<?php else: ?>
|
||||
<a href="<?php echo htmlspecialchars(cc_test_build_url('gestiones_callcenter.php', ['store' => 'tuani_recuperables', 'view' => 'nuevos_hoy'])); ?>" class="btn btn-sm btn-outline-success">Abrir Carritos recuperables (#D...)</a>
|
||||
<a href="<?php echo htmlspecialchars(cc_test_build_url('gestiones_callcenter.php', ['store' => $recoverablesStoreKey, 'view' => 'todos'])); ?>" class="btn btn-sm btn-outline-success">Abrir <?php echo htmlspecialchars($recoverablesStoreLabel !== '' ? $recoverablesStoreLabel : 'Carritos recuperables'); ?> (#D...)</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="d-flex flex-wrap gap-2 mt-3">
|
||||
@ -1666,7 +1666,7 @@ require_once 'layout_header.php';
|
||||
<?php foreach ($storeNavGroups as $groupKey => $group): ?>
|
||||
<?php $groupConfig = $group['config'] ?? []; ?>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <?php echo $activeStoreGroupKey === $groupKey ? 'active' : ''; ?>" href="<?php echo htmlspecialchars(cc_test_build_url('gestiones_callcenter.php', array_merge(['view' => $groupKey === 'tuani_recuperables' ? 'nuevos_hoy' : $view, 'store' => $groupKey], $persistedAssessorParams))); ?>">
|
||||
<a class="nav-link <?php echo $activeStoreGroupKey === $groupKey ? 'active' : ''; ?>" href="<?php echo htmlspecialchars(cc_test_build_url('gestiones_callcenter.php', array_merge(['view' => cc_test_is_recoverables_store_key($groupKey) ? 'todos' : $view, 'store' => $groupKey], $persistedAssessorParams))); ?>">
|
||||
<?php echo htmlspecialchars((string) ($groupConfig['label'] ?? strtoupper((string) $groupKey))); ?>
|
||||
</a>
|
||||
</li>
|
||||
@ -1676,9 +1676,9 @@ require_once 'layout_header.php';
|
||||
<div class="mt-3 p-3 rounded-4 border bg-light">
|
||||
<div class="small text-uppercase text-muted fw-semibold mb-2">Dentro de <?php echo htmlspecialchars($activeStoreGroupLabel); ?></div>
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
<a class="btn btn-sm <?php echo $storeKey === $activeStoreGroupKey ? 'btn-primary' : 'btn-outline-primary'; ?>" href="<?php echo htmlspecialchars(cc_test_build_url('gestiones_callcenter.php', array_merge(['view' => $activeStoreGroupKey === 'tuani_recuperables' ? 'nuevos_hoy' : $view, 'store' => $activeStoreGroupKey], $persistedAssessorParams))); ?>">Pedidos <?php echo htmlspecialchars($activeStoreGroupLabel); ?></a>
|
||||
<a class="btn btn-sm <?php echo $storeKey === $activeStoreGroupKey ? 'btn-primary' : 'btn-outline-primary'; ?>" href="<?php echo htmlspecialchars(cc_test_build_url('gestiones_callcenter.php', array_merge(['view' => cc_test_is_recoverables_store_key($activeStoreGroupKey) ? 'todos' : $view, 'store' => $activeStoreGroupKey], $persistedAssessorParams))); ?>">Pedidos <?php echo htmlspecialchars($activeStoreGroupLabel); ?></a>
|
||||
<?php foreach ($activeStoreGroupChildren as $childKey => $childConfig): ?>
|
||||
<a class="btn btn-sm <?php echo $storeKey === $childKey ? 'btn-primary' : 'btn-outline-primary'; ?>" href="<?php echo htmlspecialchars(cc_test_build_url('gestiones_callcenter.php', array_merge(['view' => $childKey === 'tuani_recuperables' ? 'nuevos_hoy' : $view, 'store' => $childKey], $persistedAssessorParams))); ?>">
|
||||
<a class="btn btn-sm <?php echo $storeKey === $childKey ? 'btn-primary' : 'btn-outline-primary'; ?>" href="<?php echo htmlspecialchars(cc_test_build_url('gestiones_callcenter.php', array_merge(['view' => cc_test_is_recoverables_store_key($childKey) ? 'todos' : $view, 'store' => $childKey], $persistedAssessorParams))); ?>">
|
||||
<?php echo htmlspecialchars((string) ($childConfig['label'] ?? strtoupper((string) $childKey))); ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
|
||||
@ -253,7 +253,7 @@ function cc_test_default_assessor_keys(): array
|
||||
function cc_test_is_tuani_store_key(string $storeKey): bool
|
||||
{
|
||||
$storeKey = trim(mb_strtolower($storeKey));
|
||||
return in_array($storeKey, ['flower', 'otra_tienda', 'tuani_recuperables'], true);
|
||||
return in_array($storeKey, ['flower', 'otra_tienda', 'flower_recuperables', 'tuani_recuperables'], true);
|
||||
}
|
||||
|
||||
function cc_test_is_tuani_main_store_key(string $storeKey): bool
|
||||
@ -262,10 +262,15 @@ function cc_test_is_tuani_main_store_key(string $storeKey): bool
|
||||
return in_array($storeKey, ['flower', 'otra_tienda'], true);
|
||||
}
|
||||
|
||||
function cc_test_is_tuani_recoverables_store_key(string $storeKey): bool
|
||||
function cc_test_is_recoverables_store_key(string $storeKey): bool
|
||||
{
|
||||
$storeKey = trim(mb_strtolower($storeKey));
|
||||
return $storeKey === 'tuani_recuperables';
|
||||
return in_array($storeKey, ['flower_recuperables', 'tuani_recuperables'], true);
|
||||
}
|
||||
|
||||
function cc_test_is_tuani_recoverables_store_key(string $storeKey): bool
|
||||
{
|
||||
return cc_test_is_recoverables_store_key($storeKey);
|
||||
}
|
||||
|
||||
function cc_test_callcenter_pro_default_view_key(string $storeKey): string
|
||||
@ -274,8 +279,8 @@ function cc_test_callcenter_pro_default_view_key(string $storeKey): string
|
||||
return 'ultimos_3_dias';
|
||||
}
|
||||
|
||||
if (cc_test_is_tuani_recoverables_store_key($storeKey)) {
|
||||
return 'nuevos_hoy';
|
||||
if (cc_test_is_recoverables_store_key($storeKey)) {
|
||||
return 'todos';
|
||||
}
|
||||
|
||||
return 'pendientes_hoy';
|
||||
@ -358,14 +363,18 @@ if (!function_exists('cc_test_fetch_store_phone_index')) {
|
||||
}
|
||||
|
||||
if (!function_exists('cc_test_mark_recoverables_duplicate_orders')) {
|
||||
function cc_test_mark_recoverables_duplicate_orders(PDO $pdo, array $orders, string $storeKey, string $mainStoreKey = 'otra_tienda'): array
|
||||
function cc_test_mark_recoverables_duplicate_orders(PDO $pdo, array $orders, string $storeKey, string $mainStoreKey = ''): array
|
||||
{
|
||||
$storeKey = trim(mb_strtolower($storeKey));
|
||||
if ($storeKey !== 'tuani_recuperables' || empty($orders)) {
|
||||
if (!cc_test_is_recoverables_store_key($storeKey) || empty($orders)) {
|
||||
return $orders;
|
||||
}
|
||||
|
||||
$mainStoreKey = trim(mb_strtolower($mainStoreKey));
|
||||
if ($mainStoreKey === '') {
|
||||
$mainStoreKey = $storeKey === 'flower_recuperables' ? 'flower' : 'otra_tienda';
|
||||
}
|
||||
|
||||
if ($mainStoreKey === '') {
|
||||
return $orders;
|
||||
}
|
||||
@ -1484,6 +1493,30 @@ function cc_test_followup_tracking_states(): array
|
||||
return ['POR LLAMAR', 'DEVOLVER LLAMADA', 'OBSERVADO', 'SE ENVIO NUMERO DE CUENTA'];
|
||||
}
|
||||
|
||||
function cc_test_recoverable_claimable_states(): array
|
||||
{
|
||||
return cc_test_followup_tracking_states();
|
||||
}
|
||||
|
||||
function cc_test_is_recoverable_claimable_state(string $estado): bool
|
||||
{
|
||||
$estado = cc_test_normalize_state($estado);
|
||||
if ($estado === '') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return in_array($estado, cc_test_recoverable_claimable_states(), true);
|
||||
}
|
||||
|
||||
function cc_test_can_claim_recoverable_order(?array $tracking): bool
|
||||
{
|
||||
if ($tracking === null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return cc_test_is_recoverable_claimable_state((string) ($tracking['estado'] ?? ''));
|
||||
}
|
||||
|
||||
function cc_test_followup_parse_datetime(?string $value): ?DateTimeImmutable
|
||||
{
|
||||
$value = trim((string) $value);
|
||||
|
||||
@ -26,6 +26,23 @@ function drive_test_available_stores(): array
|
||||
'delivery_sync_start_row' => 8687,
|
||||
'delivery_sync_column' => 'W',
|
||||
'min_codigo_number' => 37431,
|
||||
'recoverables_store_key' => 'flower_recuperables',
|
||||
'enforce_db_start_row' => true,
|
||||
'incremental_sync' => true,
|
||||
],
|
||||
// Nueva bandeja recuperable de Flower desde la pestaña compartida.
|
||||
'flower_recuperables' => [
|
||||
'label' => 'Carritos recuperables Flower',
|
||||
'sheet_title' => 'easysell_abandoneds',
|
||||
'spreadsheet_id' => '1SSmQuR9quxeQbMKNMDkRe8-n1gU7WuEfsFaJ3WKFO-c',
|
||||
'startRow' => 1503,
|
||||
'status_sync_start_row' => 1503,
|
||||
'status_sync_column' => 'V',
|
||||
'advisor_sync_start_row' => 1503,
|
||||
'advisor_sync_column' => 'X',
|
||||
'delivery_sync_start_row' => 1503,
|
||||
'delivery_sync_column' => 'W',
|
||||
'main_store_key' => 'flower',
|
||||
'enforce_db_start_row' => true,
|
||||
'incremental_sync' => true,
|
||||
],
|
||||
@ -36,6 +53,7 @@ function drive_test_available_stores(): array
|
||||
'spreadsheet_id' => '1QYKeBJIIqYm6yW6Ka-5gKdxhUHwXOAc0No7RjnimxTw',
|
||||
'sheet_gid' => 1523126328,
|
||||
'startRow' => 6804,
|
||||
'recoverables_store_key' => 'tuani_recuperables',
|
||||
'enforce_db_start_row' => true,
|
||||
'incremental_sync' => true,
|
||||
'status_sync_start_row' => 7207,
|
||||
@ -45,9 +63,9 @@ function drive_test_available_stores(): array
|
||||
'delivery_sync_start_row' => 7291,
|
||||
'delivery_sync_column' => 'W',
|
||||
],
|
||||
// Bandeja compartida de carritos recuperables/abandonados: misma estructura, pero desde la fila 2000.
|
||||
// Bandeja compartida de carritos recuperables Tuani/abandonados: misma estructura, pero desde la fila 2000.
|
||||
'tuani_recuperables' => [
|
||||
'label' => 'Carritos recuperables',
|
||||
'label' => 'Carritos recuperables Tuani',
|
||||
'sheet_title' => 'easysell_abandoneds',
|
||||
'spreadsheet_id' => '1QYKeBJIIqYm6yW6Ka-5gKdxhUHwXOAc0No7RjnimxTw',
|
||||
'sheet_gid' => 965530888,
|
||||
@ -58,6 +76,7 @@ function drive_test_available_stores(): array
|
||||
'advisor_sync_column' => 'X',
|
||||
'delivery_sync_start_row' => 2000,
|
||||
'delivery_sync_column' => 'W',
|
||||
'main_store_key' => 'otra_tienda',
|
||||
'enforce_db_start_row' => true,
|
||||
'incremental_sync' => true,
|
||||
],
|
||||
@ -348,6 +367,7 @@ function drive_test_sync_status_to_sheet(array $sourceOrder, string $estado, ?st
|
||||
}
|
||||
|
||||
$storeConfig = drive_test_get_store_config($storeKey);
|
||||
$sheetTitle = trim((string) ($storeConfig['sheet_title'] ?? ''));
|
||||
$spreadsheetId = trim((string) ($storeConfig['spreadsheet_id'] ?? ''));
|
||||
if ($spreadsheetId === '') {
|
||||
throw new RuntimeException('Configuración de Drive para la tienda no válida.');
|
||||
@ -366,7 +386,7 @@ function drive_test_sync_status_to_sheet(array $sourceOrder, string $estado, ?st
|
||||
$client->addScope(Google\Service\Sheets::SPREADSHEETS);
|
||||
|
||||
$service = new Google\Service\Sheets($client);
|
||||
$statusRange = drive_test_resolve_sheet_a1_range($service, $spreadsheetId, $sheetGid, $statusColumn . $sourceRow);
|
||||
$statusRange = drive_test_resolve_sheet_a1_range($service, $spreadsheetId, $sheetGid, $statusColumn . $sourceRow, $sheetTitle);
|
||||
$estadoNormalizado = cc_test_normalize_state(trim($estado));
|
||||
|
||||
$deliveryDate = trim((string) $deliveryDate);
|
||||
@ -389,7 +409,7 @@ function drive_test_sync_status_to_sheet(array $sourceOrder, string $estado, ?st
|
||||
$deliveryStartRow = drive_test_delivery_sync_start_row($storeKey);
|
||||
if ($deliveryStartRow !== null && $sourceRow >= $deliveryStartRow) {
|
||||
$deliveryColumn = drive_test_delivery_sync_column($storeKey);
|
||||
$deliveryRange = drive_test_resolve_sheet_a1_range($service, $spreadsheetId, $sheetGid, $deliveryColumn . $sourceRow);
|
||||
$deliveryRange = drive_test_resolve_sheet_a1_range($service, $spreadsheetId, $sheetGid, $deliveryColumn . $sourceRow, $sheetTitle);
|
||||
$updates[] = new Google\Service\Sheets\ValueRange([
|
||||
'range' => $deliveryRange,
|
||||
'values' => [[ $deliveryLabel ]],
|
||||
@ -400,7 +420,7 @@ function drive_test_sync_status_to_sheet(array $sourceOrder, string $estado, ?st
|
||||
$advisorStartRow = drive_test_advisor_sync_start_row($storeKey);
|
||||
if ($advisorName !== '' && $advisorStartRow !== null && $sourceRow >= $advisorStartRow) {
|
||||
$advisorColumn = drive_test_advisor_sync_column($storeKey);
|
||||
$advisorRange = drive_test_resolve_sheet_a1_range($service, $spreadsheetId, $sheetGid, $advisorColumn . $sourceRow);
|
||||
$advisorRange = drive_test_resolve_sheet_a1_range($service, $spreadsheetId, $sheetGid, $advisorColumn . $sourceRow, $sheetTitle);
|
||||
$updates[] = new Google\Service\Sheets\ValueRange([
|
||||
'range' => $advisorRange,
|
||||
'values' => [[ $advisorName ]],
|
||||
@ -428,9 +448,15 @@ function drive_test_sync_status_to_sheet(array $sourceOrder, string $estado, ?st
|
||||
];
|
||||
}
|
||||
|
||||
function drive_test_resolve_sheet_a1_range($service, string $spreadsheetId, ?int $sheetGid, string $rangeA1): string
|
||||
function drive_test_resolve_sheet_a1_range($service, string $spreadsheetId, ?int $sheetGid, string $rangeA1, ?string $sheetTitle = null): string
|
||||
{
|
||||
$sheetTitle = trim((string) $sheetTitle);
|
||||
if ($sheetGid === null) {
|
||||
if ($sheetTitle !== '') {
|
||||
$escapedTitle = str_replace("'", "''", $sheetTitle);
|
||||
return "'{$escapedTitle}'!{$rangeA1}";
|
||||
}
|
||||
|
||||
return $rangeA1;
|
||||
}
|
||||
|
||||
@ -502,6 +528,7 @@ function drive_test_extract_codigo_number(?string $codigo): ?int
|
||||
function drive_test_fetch_orders(int $limit = 10, ?int $startRow = null, string $storeKey = 'flower'): array
|
||||
{
|
||||
$storeConfig = drive_test_get_store_config($storeKey);
|
||||
$sheetTitle = trim((string) ($storeConfig['sheet_title'] ?? ''));
|
||||
if ($startRow === null || $startRow <= 0) {
|
||||
$startRow = (int) ($storeConfig['startRow'] ?? 0);
|
||||
}
|
||||
@ -525,7 +552,7 @@ function drive_test_fetch_orders(int $limit = 10, ?int $startRow = null, string
|
||||
|
||||
$service = new Google\Service\Sheets($client);
|
||||
|
||||
$range = drive_test_resolve_sheet_a1_range($service, $spreadsheetId, $sheetGid, $rangeA1);
|
||||
$range = drive_test_resolve_sheet_a1_range($service, $spreadsheetId, $sheetGid, $rangeA1, $sheetTitle);
|
||||
|
||||
$response = $service->spreadsheets_values->get($spreadsheetId, $range);
|
||||
$values = $response->getValues();
|
||||
|
||||
@ -46,6 +46,9 @@ if (in_array($currentAssessorFilter, cc_test_callcenter_assessor_filter_clear_va
|
||||
}
|
||||
$currentCallCenterStore = cc_test_normalize_context_key($_GET['store'] ?? ($_SESSION[cc_test_callcenter_store_session_key()] ?? ''));
|
||||
$currentCallCenterView = cc_test_normalize_context_key($_GET['view'] ?? ($_SESSION[cc_test_callcenter_view_session_key()] ?? ''));
|
||||
if (cc_test_is_tuani_recoverables_store_key($currentCallCenterStore) && $currentCallCenterView === 'nuevos_hoy') {
|
||||
$currentCallCenterView = 'todos';
|
||||
}
|
||||
$shouldPersistAssessor = $currentAssessorFilter !== '';
|
||||
$callCenterPersistentParams = [];
|
||||
if ($shouldPersistAssessor) {
|
||||
|
||||
@ -50,8 +50,9 @@ try {
|
||||
$storeKey = '';
|
||||
}
|
||||
|
||||
$isRecoverablesQueue = $storeKey === 'tuani_recuperables';
|
||||
$canClaimRecoverable = $isRecoverablesQueue && $trackingUserId === null;
|
||||
$isRecoverablesQueue = cc_test_is_recoverables_store_key($storeKey);
|
||||
$canClaimRecoverable = $isRecoverablesQueue && cc_test_can_claim_recoverable_order($tracking);
|
||||
$needsRecoverableClaim = $canClaimRecoverable && ($tracking === null || $trackingUserId !== $asesor_id);
|
||||
|
||||
if ($tracking === null) {
|
||||
if (!$canClaimRecoverable) {
|
||||
@ -65,7 +66,7 @@ try {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($canClaimRecoverable) {
|
||||
if ($needsRecoverableClaim) {
|
||||
cc_test_upsert_assignee($pdo, $pedido_id, $asesor_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ try {
|
||||
|
||||
$service = new Google\Service\Sheets($client);
|
||||
|
||||
$range = drive_test_resolve_sheet_a1_range($service, $spreadsheetId, $sheetGid, $rangeA1);
|
||||
$range = drive_test_resolve_sheet_a1_range($service, $spreadsheetId, $sheetGid, $rangeA1, $sheetTitle);
|
||||
$response = $service->spreadsheets_values->get($spreadsheetId, $range);
|
||||
$values = $response->getValues();
|
||||
|
||||
|
||||
@ -824,7 +824,7 @@ try {
|
||||
|
||||
$sourceOrderForAuth = cc_test_fetch_source_order($pdo, $sourceKey);
|
||||
$sourceStoreKeyForAuth = trim((string) ($sourceOrderForAuth['store_key'] ?? ''));
|
||||
$isRecoverablesQueue = $sourceStoreKeyForAuth === 'tuani_recuperables';
|
||||
$isRecoverablesQueue = cc_test_is_recoverables_store_key($sourceStoreKeyForAuth);
|
||||
|
||||
if (!array_key_exists('numero_cuenta_sede_id', $_POST)) {
|
||||
$numeroCuentaSedeIdCurrent = trim((string) ($currentTracking['numero_cuenta_sede_id'] ?? ''));
|
||||
@ -851,12 +851,12 @@ try {
|
||||
|
||||
$role = (string) ($_SESSION['user_role'] ?? '');
|
||||
$isAdmin = in_array($role, ['Administrador', 'admin'], true);
|
||||
$currentUserId = (int) ($_SESSION['user_id'] ?? 0);
|
||||
$trackingUserId = $currentTracking ? (int) ($currentTracking['user_id'] ?? 0) : null;
|
||||
// En carritos recuperables, los estados de seguimiento siguen siendo retomables por otra asesora.
|
||||
// Solo los confirmados o cerrados quedan bloqueados para nuevas tomas.
|
||||
$canClaimRecoverable = $isRecoverablesQueue && cc_test_can_claim_recoverable_order($currentTracking);
|
||||
if (!$isAdmin) {
|
||||
$currentUserId = (int) ($_SESSION['user_id'] ?? 0);
|
||||
$trackingUserId = $currentTracking ? (int) ($currentTracking['user_id'] ?? 0) : null;
|
||||
// En la bandeja de carritos recuperables, cualquier pedido sin asignar
|
||||
// debe poder ser tomado por la asesora, sin importar el estado inicial.
|
||||
$canClaimRecoverable = $isRecoverablesQueue && $trackingUserId === null;
|
||||
if ($currentTracking === null) {
|
||||
if (!$canClaimRecoverable) {
|
||||
http_response_code(403);
|
||||
@ -1101,6 +1101,10 @@ try {
|
||||
|
||||
$pdo->beginTransaction();
|
||||
|
||||
if (!$isAdmin && $canClaimRecoverable) {
|
||||
cc_test_upsert_assignee($pdo, $sourceKey, $currentUserId);
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare(
|
||||
'INSERT INTO callcenter_test_tracking (
|
||||
source_key,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user