diff --git a/assets/css/style.css b/assets/css/style.css index 5c269227..3f9c99b8 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -411,4 +411,20 @@ h1, .h1 { .table td, .table th { padding: 0.5rem; } -} \ No newline at end of file +} + +/* Call center: Estado badge colors */ +.cc-badge-orange { + background-color: #ffb74d !important; + color: #9a5a00 !important; + border: 1px solid #ff9800 !important; +} + +/* Call center: Estado de fila (sombreado completo) */ +.cc-callcenter-row td { + background-color: var(--cc-row-bg, #ffffff) !important; +} + +.cc-callcenter-row:hover td { + background-color: var(--cc-row-bg, #ffffff) !important; +} diff --git a/call_center_pro.php b/call_center_pro.php index 8f8113e9..4ec2e54c 100644 --- a/call_center_pro.php +++ b/call_center_pro.php @@ -84,16 +84,18 @@ function cc_test_order_label(array $order): string function cc_test_badge_class(string $estado): string { return match (cc_test_normalize_state($estado)) { - 'CONFIRMADO CONTRAENTREGA', 'CONFIRMADO ENVIO' => 'bg-success-subtle text-success-emphasis', - 'DEVOLVER LLAMADA' => 'bg-info-subtle text-info-emphasis', + 'POR LLAMAR', 'DEVOLVER LLAMADA' => 'bg-white text-dark border', 'OBSERVADO' => 'bg-warning-subtle text-warning-emphasis', + 'SE ENVIO NUMERO DE CUENTA' => 'bg-success-subtle text-success-emphasis', + 'CONFIRMADO CONTRAENTREGA' => 'cc-badge-orange', + 'CONFIRMADO ENVIO' => 'bg-success text-white', 'CANCELADO' => 'bg-danger-subtle text-danger-emphasis', 'REPETIDO' => 'bg-secondary-subtle text-secondary-emphasis', - 'SE ENVIO NUMERO DE CUENTA' => 'bg-primary-subtle text-primary-emphasis', - default => 'bg-dark-subtle text-dark-emphasis', + default => 'bg-white text-dark border', }; } + function cc_test_order_time(array $order): int { foreach (['proxima_llamada_at', 'numero_cuenta_enviado_at', 'ultima_gestion_at', 'seguimiento_actualizado', 'import_id'] as $field) { @@ -117,7 +119,7 @@ function cc_test_followup_semaforo(array $order): ?array $view = $_GET['view'] ?? 'pendientes_hoy'; $allowedViews = [ - 'pendientes_hoy' => 'Pendientes de hoy', + 'pendientes_hoy' => 'Pendientes por llamar', 'nuevos_hoy' => 'Nuevos de hoy', 'confirmados' => 'Confirmados', 'seguimiento' => 'Seguimiento', @@ -191,7 +193,27 @@ try { throw new RuntimeException('No se encontró la asesora seleccionada.'); } - cc_test_upsert_assignee($pdo, $sourceKey, $selectedAssessor ? (int) $selectedAssessor['id'] : null); + $targetUserId = $selectedAssessor ? (int) $selectedAssessor['id'] : null; + + $stmtCurrent = $pdo->prepare('SELECT user_id FROM callcenter_test_tracking WHERE source_key = ? LIMIT 1'); + $stmtCurrent->execute([$sourceKey]); + $currentUserIdRaw = $stmtCurrent->fetchColumn(); + $currentUserId = $currentUserIdRaw !== null ? ((int) $currentUserIdRaw > 0 ? (int) $currentUserIdRaw : null) : null; + + // Si el pedido ya está asignado, evitamos que se reasigne a otra asesora (solo permitimos dejarlo sin asignar). + if ($currentUserId !== null && $targetUserId !== null && (int) $currentUserId !== (int) $targetUserId) { + $currentLabel = 'otra asesora'; + foreach ($assessors as $assessorKey => $assessor) { + if ((int) ($assessor['id'] ?? 0) === (int) $currentUserId) { + $currentLabel = (string) ($assessor['label'] ?? $assessorKey); + break; + } + } + + throw new RuntimeException('Este pedido ya está asignado a ' . $currentLabel . '. Para cambiarlo primero déjalo en "Sin asignar".'); + } + + cc_test_upsert_assignee($pdo, $sourceKey, $targetUserId); $noticeMessage = $selectedAssessor ? 'Pedido asignado a ' . $selectedAssessor['label'] . '.' : 'Pedido dejado sin asignar.'; @@ -229,8 +251,7 @@ try { $proximaDate = cc_test_parse_datetime($order['proxima_llamada_at'] ?? null); $order['es_nuevo_hoy'] = $importDate ? $importDate->format('Y-m-d') === $todayStart->format('Y-m-d') : false; - $order['es_pendiente_hoy'] = in_array($order['estado'], $openStates, true) - && ($proximaDate === null || $proximaDate <= $todayEnd); + $order['es_pendiente_hoy'] = in_array($order['estado'], $openStates, true); $order['es_cerrado'] = in_array($order['estado'], $closedStates, true); $stats['total']++; @@ -336,7 +357,7 @@ require_once 'layout_header.php';
-
Pendientes de hoy
+
Pendientes por llamar
@@ -447,7 +468,7 @@ require_once 'layout_header.php'; $historial = cc_test_fetch_historial(db(), $order['source_key']); ob_start(); ?> - +
ID Drive:
@@ -494,18 +515,69 @@ require_once 'layout_header.php';
-
- - -
Asignar a asesora
- - -
+ 0 ? (int) $orderUserId : null) : null; + $unassigned = $orderUserIdNorm === null; + $assignedAssessorKey = null; + if (!$unassigned) { + foreach ($assessors as $assessorKey => $assessor) { + if ((int) ($assessor['id'] ?? 0) === (int) $orderUserIdNorm) { + $assignedAssessorKey = (string) $assessorKey; + break; + } + } + } + + $assignFormClass = 'border rounded-3 p-2 text-start shadow-sm'; + if ($unassigned) { + $assignFormClass .= ' bg-light'; + } elseif ($assignedAssessorKey === 'KARINA') { + $assignFormClass .= ' bg-primary-subtle border-primary'; + } elseif ($assignedAssessorKey === 'ESTEFANYA') { + $assignFormClass .= ' bg-success-subtle border-success'; + } else { + $assignFormClass .= ' bg-secondary-subtle border-secondary'; + } + + $selectedAssessorKeyForSelect = $unassigned ? '' : ($assignedAssessorKey !== null ? (string) $assignedAssessorKey : ''); + + $buttonLabel = $unassigned + ? 'Asignar pedido' + : ($assignedAssessorKey !== null ? 'Guardar asignación' : 'Desasignar'); + ?> + +
+ + + +
+
Asignar a asesora
+ + Sin asignar + + KARINA + + ESTEFANYA + + Asignado + +
+ + + + +
+ + diff --git a/includes/callcenter_test_helpers.php b/includes/callcenter_test_helpers.php index 61835d1a..0703d5b7 100644 --- a/includes/callcenter_test_helpers.php +++ b/includes/callcenter_test_helpers.php @@ -311,6 +311,41 @@ function cc_test_state_label(string $estado): string }; } + + +function cc_test_row_background_style(string $estado): string +{ + $color = match (cc_test_normalize_state($estado)) { + // Blanco + 'POR LLAMAR', 'DEVOLVER LLAMADA' => '#ffffff', + + // Amarillo + 'OBSERVADO' => '#fff3cd', + + // Verde claro + 'SE ENVIO NUMERO DE CUENTA' => '#d1e7dd', + + // Naranja + 'CONFIRMADO CONTRAENTREGA' => '#ffb74d', + + // Verde + 'CONFIRMADO ENVIO' => '#b6f1c7', + + // Rojo + 'CANCELADO' => '#f8d7da', + + // Plomo + 'REPETIDO' => '#d6d8db', + + default => '#ffffff', + }; + + // We set a CSS variable so we can paint the entire row (all cells). + // Bootstrap/table styles often apply opaque backgrounds to , which can hide + // the background. A CSS rule below will apply this variable to every cell. + return '--cc-row-bg:' . $color . ';'; +} + if (!function_exists('cc_test_table_exists')) { function cc_test_table_exists(PDO $pdo, string $tableName): bool { diff --git a/includes/drive_test_orders.php b/includes/drive_test_orders.php index 61b8cec7..34f552c1 100644 --- a/includes/drive_test_orders.php +++ b/includes/drive_test_orders.php @@ -219,7 +219,7 @@ function drive_test_fetch_tracking(PDO $pdo, array $sourceKeys): array cc_test_ensure_tracking_table($pdo); $placeholders = implode(',', array_fill(0, count($sourceKeys), '?')); - $stmt = $pdo->prepare("SELECT source_key, estado, nota_seguimiento, user_id, direccion, referencia, agencia, sede_agencia, sede, ciudad, distrito, dni, observaciones, producto, cantidad, precio, confirmacion_producto, confirmacion_cantidad, confirmacion_precio, proxima_llamada_at, fecha_entrega_programada, numero_cuenta_enviado_at, ultima_gestion_at, updated_at FROM callcenter_test_tracking WHERE source_key IN ($placeholders)"); + $stmt = $pdo->prepare("SELECT source_key, estado, nota_seguimiento, user_id, direccion, referencia, agencia, sede_agencia, sede, ciudad, distrito, dni, observaciones, producto, cantidad, precio, confirmacion_producto, confirmacion_cantidad, confirmacion_precio, confirmacion_producto_extra, confirmacion_cantidad_extra, confirmacion_precio_extra, proxima_llamada_at, fecha_entrega_programada, numero_cuenta_enviado_at, ultima_gestion_at, updated_at FROM callcenter_test_tracking WHERE source_key IN ($placeholders)"); $stmt->execute($sourceKeys); $tracking = []; @@ -232,13 +232,14 @@ function drive_test_fetch_tracking(PDO $pdo, array $sourceKeys): array function drive_test_merge_tracking(array $orders, array $tracking): array { - $editableFields = ['direccion', 'referencia', 'agencia', 'sede_agencia', 'sede', 'ciudad', 'distrito', 'dni', 'observaciones', 'producto', 'cantidad', 'precio', 'confirmacion_producto', 'confirmacion_cantidad', 'confirmacion_precio']; + $editableFields = ['direccion', 'referencia', 'agencia', 'sede_agencia', 'sede', 'ciudad', 'distrito', 'dni', 'observaciones', 'producto', 'cantidad', 'precio', 'confirmacion_producto', 'confirmacion_cantidad', 'confirmacion_precio', 'confirmacion_producto_extra', 'confirmacion_cantidad_extra', 'confirmacion_precio_extra']; foreach ($orders as &$order) { $current = $tracking[$order['source_key']] ?? null; $order['estado'] = $current['estado'] ?? 'POR LLAMAR'; $order['nota_seguimiento'] = $current['nota_seguimiento'] ?? ''; - $order['user_id'] = array_key_exists('user_id', (array) $current) ? ($current['user_id'] !== null ? (int) $current['user_id'] : null) : null; + $userId = array_key_exists('user_id', (array) $current) ? $current['user_id'] : null; + $order['user_id'] = $userId !== null ? ((int) $userId > 0 ? (int) $userId : null) : null; $order['seguimiento_actualizado'] = $current['updated_at'] ?? null; $order['proxima_llamada_at'] = $current['proxima_llamada_at'] ?? null; $order['fecha_entrega_programada'] = $current['fecha_entrega_programada'] ?? null; diff --git a/ruta_contraentrega.php b/ruta_contraentrega.php index 784b3c42..0c6f390e 100644 --- a/ruta_contraentrega.php +++ b/ruta_contraentrega.php @@ -247,6 +247,48 @@ include 'layout_header.php'; white-space: normal; font-size: 0.82rem; } + + + /* Contraentrega: icono para ver/subir verificación (foto + tracking) */ + #pedidos-table .cc-verificacion-btn { + width: 36px; + height: 36px; + padding: 0; + border-radius: 12px; + display: inline-flex; + align-items: center; + justify-content: center; + line-height: 1; + font-size: 1.1rem; + } + #pedidos-table .cc-verificacion-btn.cc-status-none { + background: #e9ecef; + color: #0d6efd; + border: 1px solid rgba(0,0,0,0.06); + } + #pedidos-table .cc-verificacion-btn.cc-status-pending { + background: #fff3cd; + color: #5f4700; + border: 1px solid rgba(0,0,0,0.06); + } + #pedidos-table .cc-verificacion-btn.cc-status-match { + background: #198754; + color: #fff; + border: 1px solid rgba(0,0,0,0.06); + } + .cc-verificacion-img-preview { + max-width: 100%; + max-height: 360px; + object-fit: contain; + background: #f8f9fa; + border-radius: 14px; + border: 1px solid rgba(0,0,0,0.06); + } + .cc-inline-code { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + word-break: break-word; + } +
@@ -317,7 +359,7 @@ include 'layout_header.php'; - + @@ -346,7 +388,31 @@ include 'layout_header.php'; - + +
IDID Seguimiento Paquete Estado
+
+ + +
+
@@ -456,7 +522,291 @@ include 'layout_header.php'; - + + + + + + +