1d22adc42e
Backend (Express + MariaDB) y frontend (React + Vite, identidad Fluent/Windows) con el nucleo funcional: seguridad, organizacion, proyectos, actividades, subtareas, dependencias, dashboard, calendario, gantt, comentarios, adjuntos, notificaciones in-app y catalogos. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
44 lines
1.7 KiB
JavaScript
44 lines
1.7 KiB
JavaScript
import * as repo from './repository.js';
|
|
import { HttpError } from '../../utils/http.js';
|
|
import { logAudit } from '../../utils/audit.js';
|
|
|
|
function toTree(flat) {
|
|
const byId = new Map(flat.map((d) => [d.id, { ...d, children: [] }]));
|
|
const roots = [];
|
|
for (const dept of byId.values()) {
|
|
if (dept.parent_id && byId.has(dept.parent_id)) {
|
|
byId.get(dept.parent_id).children.push(dept);
|
|
} else {
|
|
roots.push(dept);
|
|
}
|
|
}
|
|
return roots;
|
|
}
|
|
|
|
export async function listTree() {
|
|
const flat = await repo.findAllFlat();
|
|
return toTree(flat);
|
|
}
|
|
|
|
export async function createDepartment(payload, actorId) {
|
|
if (!payload.name) throw new HttpError(400, 'El nombre es obligatorio');
|
|
const dept = await repo.create(payload);
|
|
await logAudit({ userId: actorId, action: 'create', entityType: 'department', entityId: dept.id });
|
|
return dept;
|
|
}
|
|
|
|
export async function updateDepartment(id, payload, actorId) {
|
|
if (!payload.name) throw new HttpError(400, 'El nombre es obligatorio');
|
|
if (Number(payload.parentId) === Number(id)) throw new HttpError(400, 'Un departamento no puede ser su propio padre');
|
|
const dept = await repo.update(id, payload);
|
|
await logAudit({ userId: actorId, action: 'update', entityType: 'department', entityId: id });
|
|
return dept;
|
|
}
|
|
|
|
export async function deleteDepartment(id, actorId) {
|
|
if (await repo.hasChildren(id)) throw new HttpError(400, 'Tiene sub-departamentos; reasignalos antes de eliminar');
|
|
if (await repo.hasUsers(id)) throw new HttpError(400, 'Tiene usuarios asignados; reasignalos antes de eliminar');
|
|
await repo.remove(id);
|
|
await logAudit({ userId: actorId, action: 'delete', entityType: 'department', entityId: id });
|
|
}
|