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:
+7
-11
@@ -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];
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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> </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; }
|
||||
|
||||
Reference in New Issue
Block a user