Autosave: 20260724-074242

This commit is contained in:
Flatlogic Bot 2026-07-24 07:41:17 +00:00
parent cfd8e99b49
commit 23af7294d3
6 changed files with 88 additions and 32 deletions

View File

@ -402,6 +402,9 @@ if (!isset($allowedViews[$view])) {
$view = array_key_first($allowedViews) ?: 'pendientes_hoy';
}
$_SESSION[cc_test_callcenter_store_session_key()] = cc_test_normalize_context_key($storeKey);
$_SESSION[cc_test_callcenter_view_session_key()] = cc_test_normalize_context_key($view);
$viewStatesNote = $isTuaniRecuperablesStore
? 'Estados disponibles: <strong>Carritos recuperables</strong>, <strong>Seguimiento</strong>, <strong>Observados</strong>, <strong>Confirmados</strong>, <strong>Recuperados</strong> y <strong>Todos</strong>. 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.'
: '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 desde el Día 4 y exige imagen de sustento para mover el pedido. 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.';
@ -529,9 +532,10 @@ try {
$stmtCurrent->execute([$sourceKey]);
$currentAssignedUserIdRaw = $stmtCurrent->fetchColumn();
$currentAssignedUserId = $currentAssignedUserIdRaw !== null ? ((int) $currentAssignedUserIdRaw > 0 ? (int) $currentAssignedUserIdRaw : null) : null;
$isAdmin = in_array((string) ($_SESSION['user_role'] ?? ''), ['Administrador', 'admin'], true);
// Si el pedido ya está asignado, evitamos que se reasigne a otra asesora (solo permitimos dejarlo sin asignar).
if ($currentAssignedUserId !== null && $targetUserId !== null && (int) $currentAssignedUserId !== (int) $targetUserId) {
// Los asesores no pueden cambiar pedidos de otra asesora; el administrador sí puede reasignar directamente.
if (!$isAdmin && $currentAssignedUserId !== null && $targetUserId !== null && (int) $currentAssignedUserId !== (int) $targetUserId) {
$currentLabel = 'otra asesora';
foreach ($assessors as $assessorKey => $assessor) {
if ((int) ($assessor['id'] ?? 0) === (int) $currentAssignedUserId) {
@ -1386,13 +1390,9 @@ require_once 'layout_header.php';
<select name="target_assessor" class="form-select form-select-sm">
<option value=""<?php echo ($selectedAssessorKeyForSelect === '') ? ' selected' : ''; ?>>Sin asignar</option>
<?php if ($unassigned): ?>
<?php foreach ($assessors as $assessorKey => $assessor): ?>
<option value="<?php echo htmlspecialchars($assessorKey); ?>"<?php echo ($selectedAssessorKeyForSelect === $assessorKey) ? ' selected' : ''; ?>><?php echo htmlspecialchars($assessor['label']); ?></option>
<?php endforeach; ?>
<?php elseif ($assignedAssessorKey !== null): ?>
<option value="<?php echo htmlspecialchars((string) $assignedAssessorKey); ?>" selected><?php echo htmlspecialchars((string) ($assessors[$assignedAssessorKey]['label'] ?? $assignedAssessorKey)); ?></option>
<?php endif; ?>
<?php foreach ($assessors as $assessorKey => $assessor): ?>
<option value="<?php echo htmlspecialchars($assessorKey); ?>"<?php echo ($selectedAssessorKeyForSelect === $assessorKey) ? ' selected' : ''; ?>><?php echo htmlspecialchars($assessor['label']); ?></option>
<?php endforeach; ?>
</select>
<button type="submit" class="btn btn-sm btn-primary cc-callcenter-assign-submit cc-callcenter-action-btn"><?php echo htmlspecialchars((string) $buttonLabel); ?></button>

View File

@ -310,6 +310,9 @@ if (!isset($allowedViews[$view])) {
$view = array_key_first($allowedViews) ?: 'pendientes_hoy';
}
$_SESSION[cc_test_callcenter_store_session_key()] = cc_test_normalize_context_key($storeKey);
$_SESSION[cc_test_callcenter_view_session_key()] = cc_test_normalize_context_key($view);
$viewStatesNote = $isTuaniRecuperablesStore
? 'Estados disponibles: <strong>Carritos recuperables</strong>, <strong>Seguimiento</strong>, <strong>Observados</strong>, <strong>Confirmados</strong>, <strong>Recuperados</strong> y <strong>Todos</strong>. 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.'
: '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 desde el Día 4 y exige imagen de sustento para mover el pedido.';
@ -470,8 +473,10 @@ try {
$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) {
$isAdmin = in_array((string) ($_SESSION['user_role'] ?? ''), ['Administrador', 'admin'], true);
// Los asesores no pueden cambiar pedidos de otra asesora; el administrador sí puede reasignar directamente.
if (!$isAdmin && $currentUserId !== null && $targetUserId !== null && (int) $currentUserId !== (int) $targetUserId) {
$currentLabel = 'otra asesora';
foreach ($assessors as $assessorKey => $assessor) {
if ((int) ($assessor['id'] ?? 0) === (int) $currentUserId) {
@ -545,18 +550,12 @@ try {
$assignedCount = 0;
$sameAssessorCount = 0;
$lockedCount = 0;
$pdo->beginTransaction();
try {
foreach ($sourceKeys as $sourceKey) {
$currentUserId = $currentAssignments[$sourceKey] ?? null;
if ($currentUserId !== null && (int) $currentUserId !== $targetUserId) {
$lockedCount++;
continue;
}
if ($currentUserId !== null && (int) $currentUserId === $targetUserId) {
$sameAssessorCount++;
continue;
@ -582,9 +581,6 @@ try {
if ($sameAssessorCount > 0) {
$messageParts[] = $sameAssessorCount . ' ya estaba' . ($sameAssessorCount === 1 ? '' : 'n') . ' con esa misma asesora.';
}
if ($lockedCount > 0) {
$messageParts[] = $lockedCount . ' ya estaba' . ($lockedCount === 1 ? '' : 'n') . ' asignado' . ($lockedCount === 1 ? '' : 's') . ' a otra asesora y se dejó igual.';
}
$noticeMessage = !empty($messageParts)
? implode(' ', $messageParts)
@ -1631,7 +1627,7 @@ require_once 'layout_header.php';
<button type="submit" class="btn btn-sm btn-primary" id="bulkAssignSubmit" disabled>Asignar seleccionados</button>
</div>
</form>
<div class="small text-muted mt-2">Si un pedido ya está tomado por otra asesora, el sistema lo deja igual y te avisa.</div>
<div class="small text-muted mt-2">Desde aquí puedes reasignar pedidos tomados sin liberarlos primero; la asesora seleccionada reemplaza a la anterior.</div>
</div>
<div class="table-responsive">
<table class="table table-hover align-middle mb-0 cc-callcenter-table">
@ -1736,6 +1732,7 @@ require_once 'layout_header.php';
$selectedAssessorKeyForSelect = $assignedAssessorKey !== null
? (string) $assignedAssessorKey
: '';
$buttonLabel = $unassigned ? 'Asignar pedido' : 'Guardar asignación';
$assignAccentKey = $selectedAssessorKeyForSelect !== ''
? (string) $selectedAssessorKeyForSelect
@ -1775,13 +1772,9 @@ require_once 'layout_header.php';
<select name="target_assessor" class="form-select form-select-sm js-assessor-select">
<option value=""<?php echo ($selectedAssessorKeyForSelect === '') ? ' selected' : ''; ?>>Sin asignar</option>
<?php if ($unassigned): ?>
<?php foreach ($assessors as $assessorKey => $assessor): ?>
<option value="<?php echo htmlspecialchars($assessorKey); ?>"<?php echo ($selectedAssessorKeyForSelect === $assessorKey) ? ' selected' : ''; ?>><?php echo htmlspecialchars($assessor['label']); ?></option>
<?php endforeach; ?>
<?php elseif ($assignedAssessorKey !== null): ?>
<option value="<?php echo htmlspecialchars((string) $assignedAssessorKey); ?>" selected><?php echo htmlspecialchars((string) ($assessors[$assignedAssessorKey]['label'] ?? $assignedAssessorKey)); ?></option>
<?php endif; ?>
<?php foreach ($assessors as $assessorKey => $assessor): ?>
<option value="<?php echo htmlspecialchars($assessorKey); ?>"<?php echo ($selectedAssessorKeyForSelect === $assessorKey) ? ' selected' : ''; ?>><?php echo htmlspecialchars($assessor['label']); ?></option>
<?php endforeach; ?>
</select>
<button type="button" class="btn btn-sm cc-callcenter-color-trigger js-assessor-color-trigger" title="Selecciona una asesora para cambiar su color" aria-label="Selecciona una asesora para cambiar su color"<?php echo $selectedAssessorKeyForSelect === '' ? ' disabled' : ''; ?>>
@ -1790,7 +1783,7 @@ require_once 'layout_header.php';
<span>Color</span>
</button>
<button type="submit" class="btn btn-sm cc-callcenter-assign-submit cc-callcenter-action-btn">Asignar pedido</button>
<button type="submit" class="btn btn-sm cc-callcenter-assign-submit cc-callcenter-action-btn"><?php echo htmlspecialchars((string) $buttonLabel); ?></button>
</div>
</form>
<?php endif; ?>

View File

@ -822,6 +822,28 @@ function cc_test_callcenter_assessor_filter_clear_values(): array
return ['ALL', 'TODAS', 'TODOS', '__ALL__'];
}
function cc_test_callcenter_store_session_key(): string
{
return 'callcenter_store';
}
function cc_test_callcenter_view_session_key(): string
{
return 'callcenter_view';
}
function cc_test_normalize_context_key(?string $value): string
{
$value = trim((string) $value);
if ($value === '') {
return '';
}
$value = preg_replace('/\s+/', ' ', $value) ?? $value;
return mb_strtolower($value);
}
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

@ -1,6 +1,20 @@
<?php
session_start();
$isLoggedIn = !empty($_SESSION['user_id']);
$callCenterParams = [];
foreach ([
'callcenter_assessor_filter' => 'assessor',
'callcenter_store' => 'store',
'callcenter_view' => 'view',
] as $sessionKey => $paramKey) {
if (!empty($_SESSION[$sessionKey])) {
$callCenterParams[$paramKey] = (string) $_SESSION[$sessionKey];
}
}
$callCenterUrl = 'gestiones_callcenter.php';
if (!empty($callCenterParams)) {
$callCenterUrl .= '?' . http_build_query($callCenterParams);
}
$pageTitle = 'Inicio | Panel CRM y Administración';
$pageDescription = 'Entrada rápida al sistema CRM y panel de administración.';
?>
@ -104,7 +118,7 @@ $pageDescription = 'Entrada rápida al sistema CRM y panel de administración.';
<a class="btn btn-primary" href="<?php echo $isLoggedIn ? 'dashboard.php' : 'login.php'; ?>">
<?php echo $isLoggedIn ? 'Ir al dashboard' : 'Iniciar sesión'; ?>
</a>
<a class="btn btn-secondary" href="gestiones_callcenter.php">Abrir Base de Datos Pedidos</a>
<a class="btn btn-secondary" href="<?php echo htmlspecialchars($callCenterUrl); ?>">Abrir Base de Datos Pedidos</a>
</div>
<div class="meta">

View File

@ -37,8 +37,19 @@ $currentAssessorFilter = cc_test_normalize_user_key($_GET['assessor'] ?? ($_SESS
if (in_array($currentAssessorFilter, cc_test_callcenter_assessor_filter_clear_values(), true)) {
$currentAssessorFilter = '';
}
$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()] ?? ''));
$shouldPersistAssessor = $currentAssessorFilter !== '';
$callCenterPersistentParams = $shouldPersistAssessor ? ['assessor' => $currentAssessorFilter] : [];
$callCenterPersistentParams = [];
if ($shouldPersistAssessor) {
$callCenterPersistentParams['assessor'] = $currentAssessorFilter;
}
if ($currentCallCenterStore !== '') {
$callCenterPersistentParams['store'] = $currentCallCenterStore;
}
if ($currentCallCenterView !== '') {
$callCenterPersistentParams['view'] = $currentCallCenterView;
}
$appendCallCenterParams = static function (string $url) use ($callCenterPersistentParams): string {
if (empty($callCenterPersistentParams)) {
return $url;

View File

@ -39,4 +39,20 @@ foreach ($pedidos as $id) {
echo "<h3>Simulación Exitosa</h3>";
echo "Se han asignado " . count($pedidos) . " pedidos al usuario <strong>$username</strong> (ID: $userId).<br>";
echo "Ahora puedes verlos en el panel de gestión: <a href='gestiones_callcenter.php'>Ir a Base de Datos Pedidos</a>";
$callCenterParams = [];
foreach ([
'callcenter_assessor_filter' => 'assessor',
'callcenter_store' => 'store',
'callcenter_view' => 'view',
] as $sessionKey => $paramKey) {
if (!empty($_SESSION[$sessionKey])) {
$callCenterParams[$paramKey] = (string) $_SESSION[$sessionKey];
}
}
$callCenterUrl = 'gestiones_callcenter.php';
if (!empty($callCenterParams)) {
$callCenterUrl .= '?' . http_build_query($callCenterParams);
}
echo "Ahora puedes verlos en el panel de gestión: <a href='" . htmlspecialchars($callCenterUrl, ENT_QUOTES) . "'>Ir a Base de Datos Pedidos</a>";