Autosave: 20260807-061159

This commit is contained in:
Flatlogic Bot 2026-08-07 06:10:13 +00:00
parent 288a7b0cd7
commit 9f2ee910f3
4 changed files with 178 additions and 53 deletions

View File

@ -340,6 +340,9 @@ if ($isTuaniRecuperablesStore && trim((string) ($_GET['view'] ?? '')) === '') {
$view = 'todos';
}
$canShowTuaniLogisticaButton = $isMainTuaniStore || $isTuaniRecuperablesStore;
$postedAction = trim((string) ($_POST['action'] ?? ''));
$recoverablesResyncRequested = $isTuaniRecuperablesStore && $postedAction === 'reimport_recoverables_queue';
$recoverablesResyncRow = $isTuaniRecuperablesStore ? (int) ($storeConfig['startRow'] ?? 2000) : null;
$viewCardColumnClass = $isTuaniRecuperablesStore ? 'col-md-6 col-xl-2' : 'col-md-6 col-xl-2';
$defaultView = cc_test_callcenter_pro_default_view_key($storeKey);
@ -482,6 +485,7 @@ $lastProcessedRow = null;
$recoverablesImportCount = 0;
$recoverablesFirstSourceRow = null;
$recoverablesLastSourceRow = null;
$recoverablesNotice = null;
$startRow = (int) ($storeConfig['startRow'] ?? 0);
$recoverablesMinimumSourceRow = $isTuaniRecuperablesStore ? (int) ($storeConfig['startRow'] ?? 0) : 0;
$catalogoProductos = [];
@ -538,7 +542,7 @@ try {
}
if ($usesIncrementalSync) {
$syncInfo = drive_test_sync_orders_incremental($pdo, $storeKey, 0);
$syncInfo = drive_test_sync_orders_incremental($pdo, $storeKey, 0, $recoverablesResyncRequested ? $recoverablesResyncRow : null);
$totalRows = (int) ($syncInfo['drive_rows_total'] ?? 0);
$lastProcessedRow = (int) ($syncInfo['last_processed_row'] ?? 0);
$startRow = (int) ($syncInfo['next_start_row'] ?? $startRow);
@ -563,6 +567,10 @@ try {
}
}
if ($recoverablesResyncRequested) {
$noticeMessage = 'Reimportación desde fila ' . $recoverablesResyncRow . ' completada. La cola volvió a contrastarse sin duplicar pedidos ya cargados.';
}
$tracking = drive_test_fetch_tracking($pdo, array_column($orders, 'source_key'));
$orders = drive_test_merge_tracking($orders, $tracking);
$orders = array_values(array_filter($orders, static function (array $order): bool {
@ -573,6 +581,18 @@ try {
}));
if ($isTuaniRecuperablesStore) {
$orders = cc_test_filter_recoverables_orders($orders, $recoverablesMinimumSourceRow);
$recoverablesSummary = cc_test_recoverables_summary($orders);
if ($recoverablesSummary !== null) {
$recoverablesImportCount = (int) ($recoverablesSummary['import_count'] ?? count($orders));
$recoverablesFirstSourceRow = $recoverablesSummary['first_source_row'] !== null ? (int) $recoverablesSummary['first_source_row'] : null;
$recoverablesLastSourceRow = $recoverablesSummary['last_source_row'] !== null ? (int) $recoverablesSummary['last_source_row'] : null;
$recoverablesNotice = $recoverablesSummary['notice'] ?? null;
} else {
$recoverablesImportCount = count($orders);
$recoverablesFirstSourceRow = null;
$recoverablesLastSourceRow = null;
$recoverablesNotice = null;
}
}
$postedAction = trim((string) ($_POST['action'] ?? ''));
@ -1069,26 +1089,6 @@ try {
? 'Tienes ' . $assessorInboxLockedCount . ' pedido' . ($assessorInboxLockedCount === 1 ? '' : 's') . ' pendiente' . ($assessorInboxLockedCount === 1 ? '' : 's') . ' de Promo Final. Mientras existan pendientes de sustento, los pedidos de Día 1 mantienen el número oculto; cuando ya no queden pendientes, el celular volverá a mostrarse.'
: '';
if ($isTuaniRecuperablesStore) {
$recoverablesImportCount = count($orders);
$recoverablesFirstSourceRow = null;
$recoverablesLastSourceRow = null;
foreach ($orders as $recoverablesOrder) {
$recoverablesSourceRow = (int) ($recoverablesOrder['source_row'] ?? 0);
if ($recoverablesSourceRow <= 0) {
continue;
}
if ($recoverablesFirstSourceRow === null || $recoverablesSourceRow < $recoverablesFirstSourceRow) {
$recoverablesFirstSourceRow = $recoverablesSourceRow;
}
if ($recoverablesLastSourceRow === null || $recoverablesSourceRow > $recoverablesLastSourceRow) {
$recoverablesLastSourceRow = $recoverablesSourceRow;
}
}
}
$visibleOrdersTotalCount = count($visibleOrders);
$todosPageSize = 200;
$todosPage = 1;
@ -1435,10 +1435,17 @@ require_once 'layout_header.php';
<div class="d-flex flex-wrap gap-2">
<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"><?php if ($isTuaniRecuperablesStore && $recoverablesNotice !== null): ?><?php echo htmlspecialchars(mb_strtoupper($storeLabel)); ?>: última fila del Drive <?php echo htmlspecialchars((string) $recoverablesNotice['row_label']); ?> · último pedido <?php echo htmlspecialchars((string) $recoverablesNotice['label']); ?><?php elseif ($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">Actualización en vivo cada 5 min</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="return ccCallCenterPanelRefreshNow(event);"><i class="bi bi-arrow-clockwise me-1"></i>Actualizar pedidos</button>
<?php if ($isTuaniRecuperablesStore): ?>
<form method="post" class="d-inline" onsubmit="return confirm('Esto volverá a leer la cola desde la fila <?php echo (int) $recoverablesResyncRow; ?>. ¿Continuar?');">
<input type="hidden" name="action" value="reimport_recoverables_queue">
<input type="hidden" name="from_row" value="<?php echo (int) $recoverablesResyncRow; ?>">
<button type="submit" class="btn btn-outline-warning btn-sm"><i class="bi bi-arrow-repeat me-1"></i>Reimportar desde fila <?php echo (int) $recoverablesResyncRow; ?></button>
</form>
<?php endif; ?>
</div>
</div>
</section>
@ -1490,6 +1497,25 @@ require_once 'layout_header.php';
</div>
</section>
<?php if ($recoverablesNotice !== null): ?>
<section class="alert alert-info border-0 shadow-sm mb-4" role="status">
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center gap-2">
<div>
<div class="small text-uppercase fw-semibold mb-1">Aviso rápido</div>
<div>
Última fila real del Drive:
<strong><?php echo htmlspecialchars((string) $recoverablesNotice['row_label']); ?></strong>
· Último pedido detectado:
<strong><?php echo htmlspecialchars((string) $recoverablesNotice['label']); ?></strong>
</div>
</div>
<div class="small text-muted">
Te ayuda a comprobar de un vistazo si la cola llegó al final.
</div>
</div>
</section>
<?php endif; ?>
<?php echo $performanceDashboardHtml ?? ''; ?>
<section class="row g-3 mb-4">

View File

@ -237,6 +237,9 @@ if ($isTuaniRecuperablesStore && trim((string) ($_GET['view'] ?? '')) === '') {
$view = 'todos';
}
$canShowTuaniLogisticaButton = $isMainTuaniStore || $isTuaniRecuperablesStore;
$postedAction = trim((string) ($_POST['action'] ?? ''));
$recoverablesResyncRequested = $isTuaniRecuperablesStore && $postedAction === 'reimport_recoverables_queue';
$recoverablesResyncRow = $isTuaniRecuperablesStore ? (int) ($storeConfig['startRow'] ?? 2000) : null;
$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;
@ -374,6 +377,7 @@ $lastProcessedRow = null;
$recoverablesImportCount = 0;
$recoverablesFirstSourceRow = null;
$recoverablesLastSourceRow = null;
$recoverablesNotice = null;
$selectedAssessorFilter = '';
$selectedAssessorFilterLabel = '';
$persistedAssessorParams = [];
@ -469,7 +473,7 @@ try {
}
if ($usesIncrementalSync) {
$syncInfo = drive_test_sync_orders_incremental($pdo, $storeKey, 0);
$syncInfo = drive_test_sync_orders_incremental($pdo, $storeKey, 0, $recoverablesResyncRequested ? $recoverablesResyncRow : null);
$totalRows = (int) ($syncInfo['drive_rows_total'] ?? 0);
$lastProcessedRow = (int) ($syncInfo['last_processed_row'] ?? 0);
$startRow = (int) ($syncInfo['next_start_row'] ?? $startRow);
@ -494,6 +498,10 @@ try {
}
}
if ($recoverablesResyncRequested) {
$noticeMessage = 'Reimportación desde fila ' . $recoverablesResyncRow . ' completada. La cola volvió a contrastarse sin duplicar pedidos ya cargados.';
}
$tracking = drive_test_fetch_tracking($pdo, array_column($orders, 'source_key'));
$orders = drive_test_merge_tracking($orders, $tracking);
$orders = array_values(array_filter($orders, static function (array $order): bool {
@ -501,6 +509,18 @@ try {
}));
if ($isTuaniRecuperablesStore) {
$orders = cc_test_filter_recoverables_orders($orders, $recoverablesMinimumSourceRow);
$recoverablesSummary = cc_test_recoverables_summary($orders);
if ($recoverablesSummary !== null) {
$recoverablesImportCount = (int) ($recoverablesSummary['import_count'] ?? count($orders));
$recoverablesFirstSourceRow = $recoverablesSummary['first_source_row'] !== null ? (int) $recoverablesSummary['first_source_row'] : null;
$recoverablesLastSourceRow = $recoverablesSummary['last_source_row'] !== null ? (int) $recoverablesSummary['last_source_row'] : null;
$recoverablesNotice = $recoverablesSummary['notice'] ?? null;
} else {
$recoverablesImportCount = count($orders);
$recoverablesFirstSourceRow = null;
$recoverablesLastSourceRow = null;
$recoverablesNotice = null;
}
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'assign_assessor') {
@ -1237,26 +1257,6 @@ try {
return cc_test_order_time($b) <=> cc_test_order_time($a);
});
if ($isTuaniRecuperablesStore) {
$recoverablesImportCount = count($orders);
$recoverablesFirstSourceRow = null;
$recoverablesLastSourceRow = null;
foreach ($orders as $recoverablesOrder) {
$recoverablesSourceRow = (int) ($recoverablesOrder['source_row'] ?? 0);
if ($recoverablesSourceRow <= 0) {
continue;
}
if ($recoverablesFirstSourceRow === null || $recoverablesSourceRow < $recoverablesFirstSourceRow) {
$recoverablesFirstSourceRow = $recoverablesSourceRow;
}
if ($recoverablesLastSourceRow === null || $recoverablesSourceRow > $recoverablesLastSourceRow) {
$recoverablesLastSourceRow = $recoverablesSourceRow;
}
}
}
$visibleOrdersTotalCount = count($visibleOrders);
$todosPageSize = 200;
$todosPage = 1;
@ -1689,7 +1689,7 @@ require_once 'layout_header.php';
<div class="d-flex flex-wrap gap-2">
<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"><?php if ($isTuaniRecuperablesStore && $recoverablesNotice !== null): ?><?php echo htmlspecialchars(mb_strtoupper($storeLabel)); ?>: última fila del Drive <?php echo htmlspecialchars((string) $recoverablesNotice['row_label']); ?> · último pedido <?php echo htmlspecialchars((string) $recoverablesNotice['label']); ?><?php elseif ($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">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>
@ -1697,6 +1697,13 @@ require_once 'layout_header.php';
<?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>
<?php if ($isTuaniRecuperablesStore): ?>
<form method="post" class="d-inline" onsubmit="return confirm('Esto volverá a leer la cola desde la fila <?php echo (int) $recoverablesResyncRow; ?>. ¿Continuar?');">
<input type="hidden" name="action" value="reimport_recoverables_queue">
<input type="hidden" name="from_row" value="<?php echo (int) $recoverablesResyncRow; ?>">
<button type="submit" class="btn btn-outline-warning btn-sm"><i class="bi bi-arrow-repeat me-1"></i>Reimportar desde fila <?php echo (int) $recoverablesResyncRow; ?></button>
</form>
<?php endif; ?>
</div>
</div>
</section>
@ -1713,6 +1720,25 @@ require_once 'layout_header.php';
</section>
<?php else: ?>
<?php if ($recoverablesNotice !== null): ?>
<section class="alert alert-info border-0 shadow-sm mb-4" role="status">
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center gap-2">
<div>
<div class="small text-uppercase fw-semibold mb-1">Aviso rápido</div>
<div>
Última fila real del Drive:
<strong><?php echo htmlspecialchars((string) $recoverablesNotice['row_label']); ?></strong>
· Último pedido detectado:
<strong><?php echo htmlspecialchars((string) $recoverablesNotice['label']); ?></strong>
</div>
</div>
<div class="small text-muted">
Te ayuda a comprobar de un vistazo si la cola llegó al final.
</div>
</div>
</section>
<?php endif; ?>
<?php echo $performanceDashboardHtml ?? ''; ?>
<section class="mb-4">

View File

@ -1147,6 +1147,70 @@ function cc_test_compare_recoverables_orders_desc(array $a, array $b): int
return strcmp((string) ($a['source_key'] ?? ''), (string) ($b['source_key'] ?? ''));
}
function cc_test_recoverables_summary(array $orders): ?array
{
$importCount = count($orders);
$firstSourceRow = null;
$lastSourceRow = null;
$latestOrder = null;
$latestRow = null;
foreach ($orders as $order) {
$sourceRow = (int) ($order['source_row'] ?? 0);
if ($sourceRow <= 0) {
continue;
}
if ($firstSourceRow === null || $sourceRow < $firstSourceRow) {
$firstSourceRow = $sourceRow;
}
if ($lastSourceRow === null || $sourceRow > $lastSourceRow) {
$lastSourceRow = $sourceRow;
}
if ($latestRow === null || $sourceRow > $latestRow) {
$latestRow = $sourceRow;
$latestOrder = $order;
continue;
}
if ($latestOrder !== null && $sourceRow === $latestRow) {
$currentValue = cc_test_recoverables_order_sort_value($order);
$bestValue = cc_test_recoverables_order_sort_value($latestOrder);
if ($currentValue > $bestValue) {
$latestOrder = $order;
}
}
}
$notice = null;
if ($latestRow !== null) {
$label = 'Sin pedido detectado';
if ($latestOrder !== null) {
$codigo = trim((string) ($latestOrder['codigo'] ?? ''));
if ($codigo !== '') {
$label = '#' . ltrim($codigo, '#');
} elseif (!empty($latestOrder['is_agregado'])) {
$label = 'AGREGADOS';
} else {
$label = 'Sin número';
}
}
$notice = [
'row_label' => (string) $latestRow,
'label' => $label,
];
}
return [
'import_count' => $importCount,
'first_source_row' => $firstSourceRow,
'last_source_row' => $lastSourceRow,
'notice' => $notice,
];
}
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();

View File

@ -45,13 +45,19 @@ function drive_test_available_stores(): array
'delivery_sync_start_row' => 7291,
'delivery_sync_column' => 'W',
],
// Bandeja compartida de carritos recuperables: misma estructura, pero desde la fila 2000.
// Bandeja compartida de carritos recuperables/abandonados: misma estructura, pero desde la fila 2000.
'tuani_recuperables' => [
'label' => 'Carritos recuperables',
'sheet_title' => 'easysell_abandoneds',
'spreadsheet_id' => '1QYKeBJIIqYm6yW6Ka-5gKdxhUHwXOAc0No7RjnimxTw',
'sheet_gid' => 965530888,
'startRow' => 2000,
'status_sync_start_row' => 2000,
'status_sync_column' => 'V',
'advisor_sync_start_row' => 2000,
'advisor_sync_column' => 'X',
'delivery_sync_start_row' => 2000,
'delivery_sync_column' => 'W',
'enforce_db_start_row' => true,
'incremental_sync' => true,
],
@ -902,11 +908,12 @@ function drive_test_ensure_import_checkpoints_table(PDO $pdo): void
$checked = true;
}
function drive_test_sync_orders_incremental(PDO $pdo, string $storeKey, int $overlapRows = 50): array
function drive_test_sync_orders_incremental(PDO $pdo, string $storeKey, int $overlapRows = 50, ?int $forcedStartRow = null): array
{
$storeKey = mb_strtolower(trim($storeKey));
$storeConfig = drive_test_get_store_config($storeKey);
$baselineStartRow = (int) ($storeConfig['startRow'] ?? 0);
$forcedStartRow = $forcedStartRow !== null && $forcedStartRow > 0 ? $forcedStartRow : null;
drive_test_ensure_orders_table($pdo);
drive_test_ensure_import_checkpoints_table($pdo);
@ -920,19 +927,21 @@ function drive_test_sync_orders_incremental(PDO $pdo, string $storeKey, int $ove
$storedBaselineStartRow = (int) ($checkpointData['baseline_start_row'] ?? 0);
$overlapRows = max(0, $overlapRows);
$mustResetToBaseline = $storedBaselineStartRow !== $baselineStartRow;
$effectiveStartRow = $mustResetToBaseline
? $baselineStartRow
: ($checkpointRow > 0
? max($baselineStartRow, $checkpointRow - $overlapRows + 1)
: $baselineStartRow);
$mustResetToBaseline = $forcedStartRow !== null || $storedBaselineStartRow !== $baselineStartRow;
$effectiveStartRow = $forcedStartRow !== null
? $forcedStartRow
: ($mustResetToBaseline
? $baselineStartRow
: ($checkpointRow > 0
? max($baselineStartRow, $checkpointRow - $overlapRows + 1)
: $baselineStartRow));
$preview = drive_test_fetch_orders(0, $effectiveStartRow, $storeKey);
$driveOrders = $preview['orders'] ?? [];
$driveTotalRows = (int) ($preview['total_rows'] ?? 0);
$sheetLastRow = ($effectiveStartRow - 1) + $driveTotalRows;
$newCheckpointRow = $mustResetToBaseline
$newCheckpointRow = ($forcedStartRow !== null || $mustResetToBaseline)
? (int) $sheetLastRow
: max($checkpointRow, (int) $sheetLastRow);