From 4a8c7a39ad8281e531f26819648fae20a9992016 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Thu, 23 Jul 2026 22:46:09 +0000 Subject: [PATCH] Autosave: 20260723-224733 --- call_center_pro.php | 137 +++--------- ...and_callcenter_test_orders_precio_text.sql | 12 ++ gestiones_callcenter.php | 204 +++++++++++++++++- includes/callcenter_test_management.php | 60 +++++- includes/drive_test_orders.php | 108 ++++++++-- 5 files changed, 384 insertions(+), 137 deletions(-) create mode 100644 db/migrations/094_expand_callcenter_test_orders_precio_text.sql diff --git a/call_center_pro.php b/call_center_pro.php index fa8e08df..563a1606 100644 --- a/call_center_pro.php +++ b/call_center_pro.php @@ -897,6 +897,25 @@ require_once 'layout_header.php'; line-height: 1.15; } +.cc-callcenter-table { + min-width: 1600px; +} + +.cc-callcenter-table thead th { + position: sticky; + top: 0; + z-index: 4; + background-color: #f8f9fa; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .08); + vertical-align: bottom; +} + +.cc-callcenter-table tbody td { + vertical-align: top; + overflow-wrap: anywhere; + word-break: break-word; +} + .cc-callcenter-assign-form { width: 100%; padding: .72rem !important; @@ -1154,106 +1173,6 @@ require_once 'layout_header.php'; - - -
-
-
-
-
- Reparto - - Siguiente: - - Sin asesoras disponibles - - Sin asignar: -
-

Reparto intercalado diario

-

Las asesoras activas reciben los pedidos sin asignar en orden. Si una está pausada o ausente, se salta automáticamente. El supervisor puede cambiar el estado en cualquier momento.

-
- Asesoras totales: - Disponibles: - Ciclo: -
-
- - - · - - -
-
- -
-
- - - - - - -
- - -
-
- -
-
-
-
- -
- -
-
- -
-
- -
-
-
- - - - - - - -
-
- -
-
-
Control de reparto
-
Solo el administrador puede cambiar el modo o pausar asesoras. Tú ves aquí el orden intercalado y el siguiente turno.
-
-
- -
-
-
-
@@ -1265,12 +1184,12 @@ require_once 'layout_header.php'; Asesora: - pedidos en esta bandeja + pedidos únicos en esta bandeja
- +
@@ -1287,9 +1206,9 @@ require_once 'layout_header.php'; @@ -2623,7 +2542,7 @@ if (airDroidCopyButton) { }); } -const ccPanelLiveEnabled = ; +const ccPanelLiveEnabled = ; if (ccPanelLiveEnabled) { const ccPanelRoot = document.querySelector('[data-cc-panel-root="1"]'); if (ccPanelRoot) { @@ -2678,9 +2597,11 @@ if (ccPanelLiveEnabled) { } } -window.setInterval(function () { - window.location.reload(); -}, 600000); +if (ccPanelLiveEnabled) { + window.setInterval(function () { + window.location.reload(); + }, 600000); +} diff --git a/db/migrations/094_expand_callcenter_test_orders_precio_text.sql b/db/migrations/094_expand_callcenter_test_orders_precio_text.sql new file mode 100644 index 00000000..2ffd00d9 --- /dev/null +++ b/db/migrations/094_expand_callcenter_test_orders_precio_text.sql @@ -0,0 +1,12 @@ +-- 094_expand_callcenter_test_orders_precio_text.sql +-- Expand callcenter_test_orders text fields so long or misaligned Drive values do not break TUANI panel loads. +ALTER TABLE callcenter_test_orders + MODIFY COLUMN codigo TEXT NULL, + MODIFY COLUMN import_id TEXT NULL, + MODIFY COLUMN nombre TEXT NULL, + MODIFY COLUMN celular TEXT NULL, + MODIFY COLUMN cantidad TEXT NULL, + MODIFY COLUMN precio TEXT NULL, + MODIFY COLUMN pais TEXT NULL, + MODIFY COLUMN coordenadas TEXT NULL, + MODIFY COLUMN metodo TEXT NULL; diff --git a/gestiones_callcenter.php b/gestiones_callcenter.php index bb413ed4..4df7c441 100644 --- a/gestiones_callcenter.php +++ b/gestiones_callcenter.php @@ -12,7 +12,7 @@ $departamentosContraentrega = array_keys($provinciasPorDepartamentoContraentrega $sedesShalom = cc_test_fetch_shalom_sedes(db()); $pageTitle = 'Base de Datos Pedidos | Asignación'; -$pageDescription = 'Bandejas de asignación y gestión de estados para el Call Center, cargadas desde Drive.'; +$pageDescription = 'Bandejas de asignación, reparto intercalado diario y gestión de estados para el Call Center, cargadas desde Drive.'; $role = (string) ($_SESSION['user_role'] ?? ''); if (!in_array($role, ['Administrador', 'admin'], true)) { @@ -163,6 +163,17 @@ 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; +} + +function cc_test_filter_reparto_orders(array $orders, string $storeKey, array $storeConfig): array +{ + return $orders; +} + function cc_test_followup_semaforo(array $order): ?array { if (cc_test_normalize_state((string) ($order['estado'] ?? '')) !== 'SE ENVIO NUMERO DE CUENTA') { @@ -311,6 +322,30 @@ $totalRows = 0; $agregadosCount = 0; $lastProcessedRow = null; +$repartoSettings = [ + 'store_key' => $storeKey, + 'reparto_mode' => 'manual', + 'rotation_date' => null, + 'rotation_index' => 0, + 'assessor_states' => [], +]; +$repartoPreview = [ + 'mode' => 'manual', + 'mode_label' => 'Manual', + 'sequence' => [], + 'ordered_keys' => [], + 'states' => [], + 'available_count' => 0, + 'total_count' => 0, + 'rotation_index' => 0, + 'rotation_date' => null, + 'next_key' => null, + 'next_label' => '', + 'next_position' => null, +]; +$repartoUnassignedCount = 0; +$repartoEligibleUnassignedCount = 0; + $cupoObjetivoPorAsesora = 10; $advisorOpenCounts = []; $advisorTotalCounts = []; @@ -334,6 +369,9 @@ try { cc_test_ensure_tracking_table($pdo); cc_test_ensure_historial_llamadas_table($pdo); $assessors = cc_test_fetch_assessors($pdo); + if ($isMainTuaniStore) { + $repartoSettings = cc_test_fetch_reparto_settings($pdo, $storeKey, $assessors); + } try { $stmtProductos = $pdo->query("SELECT id, nombre FROM products ORDER BY nombre ASC"); @@ -611,6 +649,10 @@ try { continue; } + if (!cc_test_tuani_reparto_is_eligible($o, $storeKey, $storeConfig)) { + continue; + } + $estadoNorm = cc_test_normalize_state((string) ($o['estado'] ?? '')); if (!in_array($estadoNorm, $openStates, true)) { continue; @@ -712,6 +754,76 @@ try { } + if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'save_reparto_config') { + if (!$isMainTuaniStore) { + throw new RuntimeException('Esta configuración solo aplica a TUANI principal.'); + } + + $postedMode = cc_test_normalize_reparto_mode($_POST['reparto_mode'] ?? 'manual'); + $postedStates = $_POST['assessor_state'] ?? []; + if (!is_array($postedStates)) { + $postedStates = []; + } + + $repartoSettings['reparto_mode'] = 'manual'; + $repartoSettings['assessor_states'] = cc_test_reparto_normalize_states($postedStates, $assessors); + cc_test_upsert_reparto_settings($pdo, $storeKey, $repartoSettings); + $noticeMessage = 'Configuración de reparto guardada.'; + } elseif ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'run_daily_reparto') { + if (!$isMainTuaniStore) { + throw new RuntimeException('El reparto intercalado solo está disponible en TUANI principal.'); + } + + $repartoOrders = cc_test_filter_reparto_orders($orders, $storeKey, $storeConfig); + if (empty($repartoOrders)) { + $repartoResult = [ + 'assigned_count' => 0, + 'settings' => $repartoSettings, + 'message' => 'No hay pedidos pendientes para repartir.', + ]; + } else { + $repartoResult = cc_test_apply_daily_reparto($pdo, $storeKey, $repartoOrders, $assessors, $repartoSettings); + } + $assignedCount = (int) ($repartoResult['assigned_count'] ?? 0); + $noticeMessage = $assignedCount > 0 + ? 'Reparto intercalado: ' . $assignedCount . ' pedido(s) asignado(s).' + : (string) ($repartoResult['message'] ?? 'No había pedidos pendientes o no había asesoras disponibles.'); + if ($assignedCount > 0) { + $tracking = drive_test_fetch_tracking($pdo, array_column($orders, 'source_key')); + $orders = drive_test_merge_tracking($orders, $tracking); + } + $repartoSettings = $repartoResult['settings'] ?? $repartoSettings; + } + + if ($isMainTuaniStore && ($repartoSettings['reparto_mode'] ?? 'manual') === 'automatico') { + $repartoOrders = cc_test_filter_reparto_orders($orders, $storeKey, $storeConfig); + $autoRepartoResult = cc_test_apply_daily_reparto($pdo, $storeKey, $repartoOrders, $assessors, $repartoSettings); + $autoAssignedCount = (int) ($autoRepartoResult['assigned_count'] ?? 0); + if ($autoAssignedCount > 0) { + $noticeMessage = trim((string) ($noticeMessage !== null ? $noticeMessage . ' ' : '') . 'Reparto automático: ' . $autoAssignedCount . ' pedido(s) asignado(s).'); + $tracking = drive_test_fetch_tracking($pdo, array_column($orders, 'source_key')); + $orders = drive_test_merge_tracking($orders, $tracking); + } + $repartoSettings = $autoRepartoResult['settings'] ?? $repartoSettings; + } + + if ($isMainTuaniStore) { + $repartoSettings = cc_test_fetch_reparto_settings($pdo, $storeKey, $assessors); + $repartoSettings['reparto_mode'] = 'manual'; + } + $repartoPreview = cc_test_reparto_preview($assessors, $repartoSettings); + $repartoEligibleOrders = cc_test_filter_reparto_orders($orders, $storeKey, $storeConfig); + foreach ($repartoEligibleOrders as $repartoOrder) { + if ((int) ($repartoOrder['user_id'] ?? 0) <= 0) { + $repartoEligibleUnassignedCount++; + } + } + foreach ($orders as $repartoOrder) { + if ((int) ($repartoOrder['user_id'] ?? 0) <= 0) { + $repartoUnassignedCount++; + } + } + $sourceKeys = array_column($orders, 'source_key'); $callCounts = []; if (!empty($sourceKeys)) { @@ -1369,13 +1481,99 @@ require_once 'layout_header.php'; + + +
+
+
+
+
+ Reparto + + Siguiente: + + Sin asesoras disponibles + + Sin asignar: + Elegibles para reparto: +
+

Reparto de pedidos pendientes

+

El historial anterior se mantiene visible. El reparto manual trabaja sobre los pedidos actuales sin ocultar los anteriores.

+
+ Asesoras totales: + Disponibles: + Ciclo: +
+
+ + + · + + +
+
+
+
+ + + +
+ + +
+
+ +
+
+
+
+ +
+ +
+
+ +
+
+ +
+ +
+ + + + + +
+
+
+
+ +

- pedidos en esta bandeja + pedidos únicos en esta bandeja
@@ -1418,7 +1616,7 @@ require_once 'layout_header.php';
diff --git a/includes/callcenter_test_management.php b/includes/callcenter_test_management.php index af584ecc..bb44db65 100644 --- a/includes/callcenter_test_management.php +++ b/includes/callcenter_test_management.php @@ -160,10 +160,10 @@ function cc_test_ensure_schema(PDO $pdo): void $pdo->exec("CREATE TABLE IF NOT EXISTS `callcenter_test_orders` ( `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, `source_key` CHAR(40) NOT NULL, - `codigo` VARCHAR(80) DEFAULT NULL, - `import_id` VARCHAR(120) DEFAULT NULL, + `codigo` TEXT NULL, + `import_id` TEXT NULL, `drive_imported_at` DATETIME NULL, - `nombre` VARCHAR(255) DEFAULT NULL, + `nombre` TEXT NULL, `direccion_drive` TEXT NULL, `referencia_drive` TEXT NULL, `sede_drive` VARCHAR(120) NULL, @@ -171,13 +171,13 @@ function cc_test_ensure_schema(PDO $pdo): void `distrito_drive` VARCHAR(120) NULL, `dni_drive` LONGTEXT NULL, `observaciones_drive` TEXT NULL, - `celular` VARCHAR(40) DEFAULT NULL, + `celular` TEXT NULL, `producto` TEXT NULL, - `cantidad` VARCHAR(60) NULL, - `precio` VARCHAR(60) NULL, - `pais` VARCHAR(80) NULL, - `coordenadas` VARCHAR(255) NULL, - `metodo` VARCHAR(120) NULL, + `cantidad` TEXT NULL, + `precio` TEXT NULL, + `pais` TEXT NULL, + `coordenadas` TEXT NULL, + `metodo` TEXT NULL, `first_seen_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `last_seen_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY `uniq_callcenter_test_orders_source_key` (`source_key`), @@ -205,6 +205,48 @@ function cc_test_ensure_schema(PDO $pdo): void error_log('cc_test_ensure_schema: ' . $exception->getMessage()); } + $textColumns = [ + 'codigo' => 'AFTER `source_key`', + 'import_id' => 'AFTER `codigo`', + 'nombre' => 'AFTER `import_id`', + 'celular' => 'AFTER `observaciones_drive`', + 'cantidad' => 'AFTER `producto`', + 'precio' => 'AFTER `cantidad`', + 'pais' => 'AFTER `precio`', + 'coordenadas' => 'AFTER `pais`', + 'metodo' => 'AFTER `coordenadas`', + ]; + + foreach ($textColumns as $columnName => $afterClause) { + cc_test_ensure_column($pdo, 'callcenter_test_orders', $columnName, "TEXT NULL {$afterClause}"); + } + + try { + $colStmt = $pdo->prepare(" + SELECT COLUMN_NAME, DATA_TYPE + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'callcenter_test_orders' + AND COLUMN_NAME IN ('codigo', 'import_id', 'nombre', 'celular', 'cantidad', 'precio', 'pais', 'coordenadas', 'metodo') + "); + $colStmt->execute(); + + $dataTypes = []; + foreach ($colStmt->fetchAll(PDO::FETCH_ASSOC) as $row) { + $columnName = strtolower((string) ($row['COLUMN_NAME'] ?? '')); + $dataTypes[$columnName] = strtolower((string) ($row['DATA_TYPE'] ?? '')); + } + + foreach ($textColumns as $columnName => $afterClause) { + $dataType = $dataTypes[$columnName] ?? ''; + if (!in_array($dataType, ['text', 'mediumtext', 'longtext'], true)) { + $pdo->exec("ALTER TABLE `callcenter_test_orders` MODIFY COLUMN `{$columnName}` TEXT NULL {$afterClause}"); + } + } + } catch (Throwable $exception) { + error_log('cc_test_ensure_schema text columns: ' . $exception->getMessage()); + } + $pdo->exec("CREATE TABLE IF NOT EXISTS `callcenter_test_tracking` ( `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, `source_key` CHAR(40) NOT NULL, diff --git a/includes/drive_test_orders.php b/includes/drive_test_orders.php index ab7657a3..d0c593fb 100644 --- a/includes/drive_test_orders.php +++ b/includes/drive_test_orders.php @@ -29,8 +29,8 @@ function drive_test_available_stores(): array 'sheet_title' => 'TUANI PEDIDOS', 'spreadsheet_id' => '1QYKeBJIIqYm6yW6Ka-5gKdxhUHwXOAc0No7RjnimxTw', 'sheet_gid' => 1523126328, - 'startRow' => 6804, - 'enforce_db_start_row' => true, + 'startRow' => 5552, + 'enforce_db_start_row' => false, 'incremental_sync' => true, ], // Bandeja compartida de carritos recuperables: misma estructura, pero desde la fila 2000. @@ -354,6 +354,31 @@ function drive_test_fetch_tracking(PDO $pdo, array $sourceKeys): array return $tracking; } + +function drive_test_get_existing_source_keys_by_row(PDO $pdo, string $storeKey): array +{ + $storeKey = mb_strtolower(trim($storeKey)); + if ($storeKey === '') { + return []; + } + + drive_test_ensure_orders_table($pdo); + + $stmt = $pdo->prepare('SELECT source_row, source_key FROM callcenter_test_orders WHERE store_key = ? AND source_row IS NOT NULL ORDER BY COALESCE(drive_imported_at, first_seen_at) DESC, id DESC'); + $stmt->execute([$storeKey]); + + $sourceKeysByRow = []; + foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) { + $sourceRow = isset($row['source_row']) ? (int) $row['source_row'] : 0; + $sourceKey = trim((string) ($row['source_key'] ?? '')); + if ($sourceRow > 0 && $sourceKey !== '' && !isset($sourceKeysByRow[$sourceRow])) { + $sourceKeysByRow[$sourceRow] = $sourceKey; + } + } + + return $sourceKeysByRow; +} + function drive_test_merge_tracking(array $orders, array $tracking): array { $editableFields = ['direccion', 'referencia', 'agencia', 'sede_agencia', 'sede', 'ciudad', 'distrito', 'dni', 'numero_cuenta_sede_id', 'numero_cuenta_dni', 'observaciones', 'coordenadas', 'producto', 'cantidad', 'precio', 'monto_adelantado', 'confirmacion_producto', 'confirmacion_cantidad', 'confirmacion_precio', 'confirmacion_producto_extra', 'confirmacion_cantidad_extra', 'confirmacion_precio_extra']; @@ -451,12 +476,12 @@ function drive_test_ensure_orders_table(PDO $pdo): void `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, `store_key` VARCHAR(50) NULL, `source_key` CHAR(40) NOT NULL, - `codigo` VARCHAR(80) DEFAULT NULL, - `import_id` VARCHAR(120) DEFAULT NULL, + `codigo` TEXT NULL, + `import_id` TEXT NULL, `source_row` INT NULL, `is_agregado` TINYINT(1) NOT NULL DEFAULT 0, `drive_imported_at` DATETIME NULL, - `nombre` VARCHAR(255) DEFAULT NULL, + `nombre` TEXT NULL, `direccion_drive` TEXT NULL, `referencia_drive` TEXT NULL, `sede_drive` TEXT NULL, @@ -464,13 +489,13 @@ function drive_test_ensure_orders_table(PDO $pdo): void `distrito_drive` TEXT NULL, `dni_drive` LONGTEXT NULL, `observaciones_drive` TEXT NULL, - `celular` VARCHAR(40) DEFAULT NULL, + `celular` TEXT NULL, `producto` TEXT NULL, - `cantidad` VARCHAR(60) NULL, - `precio` VARCHAR(60) NULL, - `pais` VARCHAR(80) NULL, - `coordenadas` VARCHAR(255) NULL, - `metodo` VARCHAR(120) NULL, + `cantidad` TEXT NULL, + `precio` TEXT NULL, + `pais` TEXT NULL, + `coordenadas` TEXT NULL, + `metodo` TEXT NULL, `first_seen_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `last_seen_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY `uniq_callcenter_test_orders_source_key` (`source_key`), @@ -485,6 +510,22 @@ function drive_test_ensure_orders_table(PDO $pdo): void // Asegura columna para pedidos cargados manualmente (Agregados) cc_test_ensure_column($pdo, "callcenter_test_orders", "is_agregado", "TINYINT(1) NOT NULL DEFAULT 0"); + $textColumns = [ + 'codigo' => 'AFTER `source_key`', + 'import_id' => 'AFTER `codigo`', + 'nombre' => 'AFTER `import_id`', + 'celular' => 'AFTER `observaciones_drive`', + 'cantidad' => 'AFTER `producto`', + 'precio' => 'AFTER `cantidad`', + 'pais' => 'AFTER `precio`', + 'coordenadas' => 'AFTER `pais`', + 'metodo' => 'AFTER `coordenadas`', + ]; + + foreach ($textColumns as $columnName => $afterClause) { + cc_test_ensure_column($pdo, 'callcenter_test_orders', $columnName, "TEXT NULL {$afterClause}"); + } + // Asegurar que los campos de ubicación y DNI soporten valores largos desde Google Sheets. try { $colStmt = $pdo->prepare(" @@ -517,6 +558,32 @@ function drive_test_ensure_orders_table(PDO $pdo): void error_log('drive_test_ensure_orders_table: ' . $exception->getMessage()); } + try { + $colStmt = $pdo->prepare(" + SELECT COLUMN_NAME, DATA_TYPE + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'callcenter_test_orders' + AND COLUMN_NAME IN ('codigo', 'import_id', 'nombre', 'celular', 'cantidad', 'precio', 'pais', 'coordenadas', 'metodo') + "); + $colStmt->execute(); + + $dataTypes = []; + foreach ($colStmt->fetchAll(PDO::FETCH_ASSOC) as $row) { + $columnName = strtolower((string) ($row['COLUMN_NAME'] ?? '')); + $dataTypes[$columnName] = strtolower((string) ($row['DATA_TYPE'] ?? '')); + } + + foreach ($textColumns as $columnName => $afterClause) { + $dataType = $dataTypes[$columnName] ?? ''; + if (!in_array($dataType, ['text', 'mediumtext', 'longtext'], true)) { + $pdo->exec("ALTER TABLE `callcenter_test_orders` MODIFY COLUMN `{$columnName}` TEXT NULL {$afterClause}"); + } + } + } catch (Throwable $exception) { + error_log('drive_test_ensure_orders_table text columns: ' . $exception->getMessage()); + } + $checked = true; } @@ -550,6 +617,8 @@ function drive_test_sync_orders_incremental(PDO $pdo, string $storeKey, int $ove drive_test_ensure_orders_table($pdo); drive_test_ensure_import_checkpoints_table($pdo); + $existingSourceKeysByRow = drive_test_get_existing_source_keys_by_row($pdo, $storeKey); + $stmtCheckpoint = $pdo->prepare('SELECT last_processed_row, baseline_start_row FROM drive_test_import_checkpoints WHERE store_key = ? LIMIT 1'); $stmtCheckpoint->execute([$storeKey]); $checkpointData = $stmtCheckpoint->fetch(PDO::FETCH_ASSOC) ?: []; @@ -647,6 +716,9 @@ function drive_test_sync_orders_incremental(PDO $pdo, string $storeKey, int $ove foreach ($driveOrders as $order) { $driveImportedAt = drive_test_parse_datetime_mysql($order['import_id'] ?? null); $sourceRow = isset($order['source_row']) && (int) $order['source_row'] > 0 ? (int) $order['source_row'] : null; + if ($sourceRow !== null && isset($existingSourceKeysByRow[$sourceRow])) { + $order['source_key'] = $existingSourceKeysByRow[$sourceRow]; + } $stmtUpsert->execute([ ':store_key' => $storeKey, @@ -754,14 +826,16 @@ function drive_test_fetch_orders_from_db(PDO $pdo, string $storeKey, ?bool $only $stmt->execute($params); $orders = []; - $minCodigoNumber = isset($storeConfig['min_codigo_number']) ? (int) ($storeConfig['min_codigo_number'] ?? 0) : 0; + $seenSourceRows = []; foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) { $isAgregado = (int) ($row['is_agregado'] ?? 0); $codigo = (string) ($row['codigo'] ?? ''); - $codigoNumber = drive_test_extract_codigo_number($codigo); - - if ($minCodigoNumber > 0 && $isAgregado !== 1 && ($codigoNumber === null || $codigoNumber < $minCodigoNumber)) { - continue; + $sourceRow = isset($row['source_row']) && (int) $row['source_row'] > 0 ? (int) $row['source_row'] : null; + if ($sourceRow !== null) { + if (isset($seenSourceRows[$sourceRow])) { + continue; + } + $seenSourceRows[$sourceRow] = true; } $orders[] = [ @@ -770,7 +844,7 @@ function drive_test_fetch_orders_from_db(PDO $pdo, string $storeKey, ?bool $only 'source_key' => (string) ($row['source_key'] ?? ''), 'codigo' => $codigo, 'import_id' => (string) ($row['import_id'] ?? ''), - 'source_row' => isset($row['source_row']) && (int) $row['source_row'] > 0 ? (int) $row['source_row'] : null, + 'source_row' => $sourceRow, 'drive_imported_at' => (string) ($row['drive_imported_at'] ?? ''), 'first_seen_at' => (string) ($row['first_seen_at'] ?? ''), 'nombre' => (string) ($row['nombre'] ?? ''),
N° Pedido - No hay pedidos en esta bandeja para . + No hay pedidos únicos en esta bandeja para . - No hay pedidos en esta bandeja por ahora. + No hay pedidos únicos en esta bandeja por ahora.
- No hay pedidos en esta bandeja por ahora. + No hay pedidos únicos en esta bandeja por ahora.