refactor(users): eliminar columna orden, listar alfabéticamente

- Migración 012: ALTER TABLE users DROP COLUMN orden
- Lookups: abogadoNames y allUsers ordenan por name ASC
- API admin: create/update_user dejan de leer/escribir orden
- UI admin: removida la columna "Orden" de la tabla y el input
  "Orden" del modal de usuario
This commit is contained in:
Soporte ZH Consultores
2026-06-04 21:31:02 -05:00
parent d9adfbae09
commit 8ff56d3d78
4 changed files with 19 additions and 30 deletions
+7 -11
View File
@@ -46,7 +46,6 @@ try {
$name = trim((string)($b['name'] ?? ''));
$role = in_array(($b['role'] ?? ''), ROLES, true) ? $b['role'] : 'usuario';
$activo = (int)($b['activo'] ?? 1) === 1 ? 1 : 0;
$orden = (int)($b['orden'] ?? 0);
// Solo admins pueden crear nuevos admins
if ($role === 'admin' && !Auth::isAdmin()) {
@@ -58,21 +57,20 @@ try {
if ($exists->fetch()) err('Ya existe un usuario con ese email', 409);
$ins = $pdo->prepare(
'INSERT INTO users (email, name, role, activo, orden, first_seen_at, last_login_at)
VALUES (:email, :name, :role, :activo, :orden, NULL, NULL)'
'INSERT INTO users (email, name, role, activo, first_seen_at, last_login_at)
VALUES (:email, :name, :role, :activo, NULL, NULL)'
);
$ins->execute([
':email' => $email, ':name' => $name, ':role' => $role,
':activo' => $activo, ':orden' => $orden,
':activo' => $activo,
]);
$id = (int)$pdo->lastInsertId();
$sel = $pdo->prepare('SELECT id, email, name, role, activo, orden, first_seen_at, last_login_at FROM users WHERE id = :id');
$sel = $pdo->prepare('SELECT id, email, name, role, activo, first_seen_at, last_login_at FROM users WHERE id = :id');
$sel->execute([':id' => $id]);
$row = $sel->fetch();
$row['id'] = (int)$row['id'];
$row['activo'] = (int)$row['activo'];
$row['orden'] = (int)$row['orden'];
AuditLog::log('admin', 'create_user', 'user', (string)$id, $email, ['role'=>$role, 'name'=>$name]);
ok($row);
}
@@ -116,25 +114,23 @@ try {
}
$name = trim((string)($b['name'] ?? ''));
$orden = (int)($b['orden'] ?? 0);
$upd = $pdo->prepare(
'UPDATE users SET email = :email, name = :name, role = :role,
activo = :activo, orden = :orden
activo = :activo
WHERE id = :id'
);
$upd->execute([
':email' => $newEmail, ':name' => $name, ':role' => $newRole,
':activo' => $newActivo, ':orden' => $orden,
':activo' => $newActivo,
':id' => $id,
]);
$sel = $pdo->prepare('SELECT id, email, name, role, activo, orden, first_seen_at, last_login_at FROM users WHERE id = :id');
$sel = $pdo->prepare('SELECT id, email, name, role, activo, first_seen_at, last_login_at FROM users WHERE id = :id');
$sel->execute([':id' => $id]);
$row = $sel->fetch();
$row['id'] = (int)$row['id'];
$row['activo'] = (int)$row['activo'];
$row['orden'] = (int)$row['orden'];
$diff = [];
if ($existing['role'] !== $newRole) $diff['role'] = ['from'=>$existing['role'], 'to'=>$newRole];
if ((int)$existing['activo'] !== $newActivo) $diff['activo'] = ['from'=>(int)$existing['activo'], 'to'=>$newActivo];
+7
View File
@@ -0,0 +1,7 @@
-- ============================================================
-- Donna — Schema 012: eliminar columna users.orden
-- ============================================================
-- Decisión: simplificar. Las listas se ordenan alfabéticamente
-- por nombre. No hay necesidad de un orden manual.
ALTER TABLE users DROP COLUMN IF EXISTS orden;
+3 -4
View File
@@ -19,7 +19,7 @@ final class Lookups {
WHERE activo = 1
AND role IN ('socio','abogado')
AND name != ''
ORDER BY orden ASC, name ASC"
ORDER BY name ASC"
)->fetchAll();
return array_map(fn($r) => $r['name'], $rows);
}
@@ -43,15 +43,14 @@ final class Lookups {
* Si $includeAdmins es false, oculta el rol admin (uso para socios).
*/
public static function allUsers(bool $includeAdmins = true): array {
$sql = "SELECT id, email, name, role, activo, orden, first_seen_at, last_login_at
$sql = "SELECT id, email, name, role, activo, first_seen_at, last_login_at
FROM users";
if (!$includeAdmins) $sql .= " WHERE role != 'admin'";
$sql .= " ORDER BY FIELD(role,'admin','socio','abogado','usuario'), name ASC, email ASC";
$sql .= " ORDER BY name ASC, email ASC";
$rows = Db::pdo()->query($sql)->fetchAll();
foreach ($rows as &$r) {
$r['id'] = (int)$r['id'];
$r['activo'] = (int)$r['activo'];
$r['orden'] = (int)$r['orden'];
}
return $rows;
}
-13
View File
@@ -234,7 +234,6 @@ tr.is-me td { background:#FFFBEB; font-weight:500; }
<th>Nombre completo</th>
<th>Rol</th>
<th>Activo</th>
<th>Orden</th>
<th>Último login</th>
<th></th>
</tr>
@@ -339,18 +338,10 @@ tr.is-me td { background:#FFFBEB; font-weight:500; }
</select>
</div>
</div>
<div class="fg-row">
<div class="fg">
<label>Orden</label>
<input type="number" id="f-orden" value="0" step="1">
<div class="fg-hint">Para ordenar el dropdown manualmente.</div>
</div>
<div class="fg">
<label>&nbsp;</label>
<label class="fg-check"><input type="checkbox" id="f-activo" checked> Activo — puede entrar a Donna</label>
</div>
</div>
</div>
<div class="modal-foot" style="justify-content:space-between;">
<button class="btn-danger" id="btn-delete" onclick="deleteUser()" style="display:none;">Borrar usuario</button>
<div style="display:flex;gap:10px;margin-left:auto;">
@@ -463,7 +454,6 @@ function render(){
<td>${esc(u.name) || '<span class="placeholder">—</span>'}</td>
<td><span class="role-pill role-${u.role}">${ROLE_LABEL[u.role] || u.role}</span></td>
<td><span class="activo-pill activo-${u.activo}">${u.activo ? 'Activo' : 'Inactivo'}</span></td>
<td>${u.orden}</td>
<td class="last-login">${u.last_login_at ? fmtDate(u.last_login_at) : '<span class="placeholder">Nunca</span>'}</td>
<td><div class="actions"><button class="btn-icon" title="Editar" onclick="openEdit(${u.id})">✎</button></div></td>
</tr>`;
@@ -476,7 +466,6 @@ function openCreate(){
$('f-email').value = ''; $('f-email').readOnly = false;
$('f-name').value = '';
$('f-role-edit').value = 'usuario';
$('f-orden').value = '0';
$('f-activo').checked = true;
$('hint-email').textContent = 'El email debe coincidir exactamente con la cuenta de Mailcow que el usuario usa para entrar.';
$('btn-delete').style.display = 'none'; // solo en modo edición
@@ -493,7 +482,6 @@ function openEdit(id){
$('f-email').readOnly = false;
$('f-name').value = u.name || '';
$('f-role-edit').value = u.role;
$('f-orden').value = u.orden;
$('f-activo').checked = u.activo === 1;
$('hint-email').textContent = (u.email||'').startsWith('placeholder-')
? 'Reemplaza este email placeholder por el email real del abogado. Si el email real ya existe como otro usuario, mejor borra el placeholder con el botón de abajo.'
@@ -544,7 +532,6 @@ async function saveUser(){
email: $('f-email').value.trim().toLowerCase(),
name: $('f-name').value.trim(),
role: $('f-role-edit').value,
orden: parseInt($('f-orden').value, 10) || 0,
activo: $('f-activo').checked ? 1 : 0,
};
if (!payload.email) { toast('Email requerido','error'); $('f-email').focus(); return; }