Autosave: 20260725-185550
This commit is contained in:
parent
7a6edd7faf
commit
de25048671
@ -32,6 +32,10 @@ function drive_test_available_stores(): array
|
||||
'startRow' => 6804,
|
||||
'enforce_db_start_row' => true,
|
||||
'incremental_sync' => true,
|
||||
'status_sync_start_row' => 7207,
|
||||
'status_sync_column' => 'V',
|
||||
'advisor_sync_start_row' => 7207,
|
||||
'advisor_sync_column' => 'X',
|
||||
],
|
||||
// Bandeja compartida de carritos recuperables: misma estructura, pero desde la fila 2000.
|
||||
'tuani_recuperables' => [
|
||||
@ -131,6 +135,198 @@ function drive_test_get_store_config(string $storeKey): array
|
||||
return $stores[$storeKey] + ['key' => $storeKey];
|
||||
}
|
||||
|
||||
function drive_test_status_sync_start_row(string $storeKey): ?int
|
||||
{
|
||||
$storeConfig = drive_test_get_store_config($storeKey);
|
||||
if (!array_key_exists('status_sync_start_row', $storeConfig)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$startRow = (int) $storeConfig['status_sync_start_row'];
|
||||
return $startRow > 0 ? $startRow : null;
|
||||
}
|
||||
|
||||
function drive_test_status_sync_start_date(string $storeKey): ?DateTimeImmutable
|
||||
{
|
||||
$storeConfig = drive_test_get_store_config($storeKey);
|
||||
$rawDate = trim((string) ($storeConfig['status_sync_start_date'] ?? ''));
|
||||
if ($rawDate === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new DateTimeImmutable($rawDate);
|
||||
} catch (Throwable $exception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function drive_test_status_sync_column(string $storeKey): string
|
||||
{
|
||||
$storeConfig = drive_test_get_store_config($storeKey);
|
||||
$column = strtoupper(trim((string) ($storeConfig['status_sync_column'] ?? 'V')));
|
||||
|
||||
return preg_match('/^[A-Z]+$/', $column) ? $column : 'V';
|
||||
}
|
||||
|
||||
function drive_test_advisor_sync_start_row(string $storeKey): ?int
|
||||
{
|
||||
$storeConfig = drive_test_get_store_config($storeKey);
|
||||
if (!array_key_exists('advisor_sync_start_row', $storeConfig)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$startRow = (int) $storeConfig['advisor_sync_start_row'];
|
||||
return $startRow > 0 ? $startRow : null;
|
||||
}
|
||||
|
||||
function drive_test_advisor_sync_column(string $storeKey): string
|
||||
{
|
||||
$storeConfig = drive_test_get_store_config($storeKey);
|
||||
$column = strtoupper(trim((string) ($storeConfig['advisor_sync_column'] ?? 'R')));
|
||||
|
||||
return preg_match('/^[A-Z]+$/', $column) ? $column : 'R';
|
||||
}
|
||||
|
||||
function drive_test_status_sync_reference_datetime(array $sourceOrder): ?DateTimeImmutable
|
||||
{
|
||||
$candidates = [
|
||||
trim((string) ($sourceOrder['first_seen_at'] ?? '')),
|
||||
trim((string) ($sourceOrder['drive_imported_at'] ?? '')),
|
||||
trim((string) ($sourceOrder['updated_at'] ?? '')),
|
||||
];
|
||||
|
||||
foreach ($candidates as $candidate) {
|
||||
if ($candidate === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
return new DateTimeImmutable($candidate);
|
||||
} catch (Throwable $exception) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function drive_test_should_sync_status_to_sheet(array $sourceOrder): bool
|
||||
{
|
||||
$storeKey = trim((string) ($sourceOrder['store_key'] ?? ''));
|
||||
if ($storeKey === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$sourceRow = (int) ($sourceOrder['source_row'] ?? 0);
|
||||
if ($sourceRow <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$cutoffRow = drive_test_status_sync_start_row($storeKey);
|
||||
if ($cutoffRow !== null) {
|
||||
return $sourceRow >= $cutoffRow;
|
||||
}
|
||||
|
||||
$cutoff = drive_test_status_sync_start_date($storeKey);
|
||||
if ($cutoff === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$referenceDate = drive_test_status_sync_reference_datetime($sourceOrder);
|
||||
if ($referenceDate === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $referenceDate->format('Y-m-d') >= $cutoff->format('Y-m-d');
|
||||
}
|
||||
|
||||
function drive_test_sync_status_to_sheet(array $sourceOrder, string $estado, ?string $advisorName = null): array
|
||||
{
|
||||
$storeKey = trim((string) ($sourceOrder['store_key'] ?? ''));
|
||||
if ($storeKey === '') {
|
||||
return [
|
||||
'success' => false,
|
||||
'skipped' => true,
|
||||
'reason' => 'missing_store_key',
|
||||
];
|
||||
}
|
||||
|
||||
if (!drive_test_should_sync_status_to_sheet($sourceOrder)) {
|
||||
return [
|
||||
'success' => true,
|
||||
'skipped' => true,
|
||||
'reason' => 'before_cutoff',
|
||||
];
|
||||
}
|
||||
|
||||
$sourceRow = (int) ($sourceOrder['source_row'] ?? 0);
|
||||
if ($sourceRow <= 0) {
|
||||
return [
|
||||
'success' => false,
|
||||
'skipped' => true,
|
||||
'reason' => 'missing_source_row',
|
||||
];
|
||||
}
|
||||
|
||||
$storeConfig = drive_test_get_store_config($storeKey);
|
||||
$spreadsheetId = trim((string) ($storeConfig['spreadsheet_id'] ?? ''));
|
||||
if ($spreadsheetId === '') {
|
||||
throw new RuntimeException('Configuración de Drive para la tienda no válida.');
|
||||
}
|
||||
|
||||
$credentialsPath = __DIR__ . '/../google_credentials.json';
|
||||
if (!file_exists($credentialsPath)) {
|
||||
throw new RuntimeException('No se encontró el archivo de credenciales de Google.');
|
||||
}
|
||||
|
||||
$statusColumn = drive_test_status_sync_column($storeKey);
|
||||
$sheetGid = array_key_exists('sheet_gid', $storeConfig) ? ($storeConfig['sheet_gid'] === null ? null : (int) $storeConfig['sheet_gid']) : null;
|
||||
|
||||
$client = new Google\Client();
|
||||
$client->setAuthConfig($credentialsPath);
|
||||
$client->addScope(Google\Service\Sheets::SPREADSHEETS);
|
||||
|
||||
$service = new Google\Service\Sheets($client);
|
||||
$statusRange = drive_test_resolve_sheet_a1_range($service, $spreadsheetId, $sheetGid, $statusColumn . $sourceRow);
|
||||
$estadoNormalizado = cc_test_normalize_state(trim($estado));
|
||||
$updates = [
|
||||
new Google\Service\Sheets\ValueRange([
|
||||
'range' => $statusRange,
|
||||
'values' => [[ $estadoNormalizado ]],
|
||||
]),
|
||||
];
|
||||
|
||||
$advisorName = drive_test_compact_text($advisorName);
|
||||
$advisorRange = null;
|
||||
$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);
|
||||
$updates[] = new Google\Service\Sheets\ValueRange([
|
||||
'range' => $advisorRange,
|
||||
'values' => [[ $advisorName ]],
|
||||
]);
|
||||
}
|
||||
|
||||
$body = new Google\Service\Sheets\BatchUpdateValuesRequest([
|
||||
'data' => $updates,
|
||||
'valueInputOption' => 'RAW',
|
||||
]);
|
||||
$service->spreadsheets_values->batchUpdate($spreadsheetId, $body);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'skipped' => false,
|
||||
'store_key' => $storeKey,
|
||||
'source_row' => $sourceRow,
|
||||
'range' => $statusRange,
|
||||
'advisor_range' => $advisorRange,
|
||||
'estado' => $estadoNormalizado,
|
||||
'advisor_name' => $advisorRange !== null ? $advisorName : null,
|
||||
];
|
||||
}
|
||||
|
||||
function drive_test_resolve_sheet_a1_range($service, string $spreadsheetId, ?int $sheetGid, string $rangeA1): string
|
||||
{
|
||||
if ($sheetGid === null) {
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
session_start();
|
||||
require_once 'db/config.php';
|
||||
require_once 'includes/callcenter_test_helpers.php';
|
||||
require_once 'includes/drive_test_orders.php';
|
||||
require_once 'includes/contraentrega_cobertura.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
@ -65,6 +66,33 @@ function cc_test_normalize_optional_image_upload(string $key): ?array
|
||||
return $file;
|
||||
}
|
||||
|
||||
function cc_test_resolve_user_display_name(PDO $pdo, ?int $userId): string
|
||||
{
|
||||
if ($userId === null || $userId <= 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $pdo->prepare('SELECT nombre_asesor, username FROM users WHERE id = ? LIMIT 1');
|
||||
$stmt->execute([$userId]);
|
||||
if ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$nombreAsesor = trim((string) ($row['nombre_asesor'] ?? ''));
|
||||
if ($nombreAsesor !== '') {
|
||||
return $nombreAsesor;
|
||||
}
|
||||
|
||||
$username = trim((string) ($row['username'] ?? ''));
|
||||
if ($username !== '') {
|
||||
return $username;
|
||||
}
|
||||
}
|
||||
} catch (Throwable $exception) {
|
||||
// Use the fallback below if the user lookup fails.
|
||||
}
|
||||
|
||||
return 'Asesor #' . $userId;
|
||||
}
|
||||
|
||||
function cc_test_store_tracking_evidence_image(array $file, string $prefix, string $sourceKey, int $userId): array
|
||||
{
|
||||
$tmpName = (string) ($file['tmp_name'] ?? '');
|
||||
@ -116,6 +144,7 @@ function cc_test_fetch_source_order(PDO $pdo, string $sourceKey): ?array
|
||||
'SELECT
|
||||
source_key,
|
||||
store_key,
|
||||
source_row,
|
||||
codigo,
|
||||
import_id,
|
||||
drive_imported_at,
|
||||
@ -968,6 +997,7 @@ try {
|
||||
$userIdToSet = $isAdmin
|
||||
? ($currentTracking ? ((int) ($currentTracking['user_id'] ?? 0) > 0 ? (int) $currentTracking['user_id'] : null) : null)
|
||||
: (int) $_SESSION['user_id'];
|
||||
$advisorNameForDrive = cc_test_resolve_user_display_name($pdo, $userIdToSet);
|
||||
|
||||
$proximaRaw = trim((string) ($_POST['proxima_llamada_at'] ?? ''));
|
||||
$proximaLlamada = null;
|
||||
@ -1335,6 +1365,21 @@ try {
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
$driveSyncResult = null;
|
||||
if ($sourceOrderForAuth) {
|
||||
try {
|
||||
$driveSyncResult = drive_test_sync_status_to_sheet($sourceOrderForAuth, $estado, $advisorNameForDrive);
|
||||
} catch (Throwable $driveException) {
|
||||
error_log('update_callcenter_test_tracking.php drive sync: ' . $driveException->getMessage());
|
||||
$driveSyncResult = [
|
||||
'success' => false,
|
||||
'skipped' => false,
|
||||
'reason' => 'sync_error',
|
||||
'error' => 'No se pudo sincronizar el estado con Drive.',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$message = 'Gestión actualizada correctamente.';
|
||||
if ($moverAPromoFinal && $promoFinalEvidencePath !== null) {
|
||||
$message = 'Pedido movido a Promo Final correctamente.';
|
||||
@ -1367,6 +1412,7 @@ try {
|
||||
'ruta_contraentrega_subido_at' => $rutaSubidoAt,
|
||||
'pedido_rotulado_pedido_id' => $pedidoRotuladoId,
|
||||
'pedido_rotulado_subido_at' => $pedidoRotuladoSubidoAt,
|
||||
'drive_sync' => $driveSyncResult,
|
||||
]);
|
||||
} catch (Throwable $exception) {
|
||||
if (isset($pdo) && $pdo instanceof PDO && $pdo->inTransaction()) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user