5e0bc0809e
No existia forma de borrar una actividad. Agregado DELETE /api/activities/:id con boton "Eliminar" en el listado (popup de confirmacion). Si tiene tareas, se bloquea con 400 y mensaje claro en vez de arrastrar todo en cascada sin avisar. De paso: la logica de borrar adjunto (fila + archivo en disco) se extrajo a un attachments/service.js reutilizable, usado tanto por el borrado individual como por el borrado en cascada de una actividad (evita archivos huerfanos). Comentarios de la actividad tambien se limpian (sin FK fisica cruzada, entity_type/entity_id es polimorfico). Probado en dev con curl (bloquea con tarea, permite sin tareas, 404 tras borrar) y Playwright (mensaje de advertencia visible). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
23 lines
991 B
JavaScript
23 lines
991 B
JavaScript
import path from 'node:path';
|
|
import fs from 'node:fs';
|
|
import { uploadsDir } from '../../middleware/upload.js';
|
|
import * as repo from './repository.js';
|
|
|
|
async function unlinkQuiet(filename) {
|
|
await fs.promises.unlink(path.join(uploadsDir, filename)).catch(() => {});
|
|
}
|
|
|
|
// Borra la fila y el archivo en disco. Unico lugar que hace esto — reutilizado tanto por el borrado
|
|
// individual (controller) como por el borrado en cascada al eliminar la entidad duena.
|
|
export async function removeAttachment(attachment) {
|
|
await repo.remove(attachment.id);
|
|
await unlinkQuiet(attachment.filename);
|
|
}
|
|
|
|
// Usado al borrar la entidad duena (actividad, proyecto): limpia sus adjuntos (fila + archivo) de
|
|
// paso, ya que no hay FK fisica cruzada (entity_type/entity_id es polimorfico) que lo haga por cascada.
|
|
export async function removeAllForEntity(entityType, entityId) {
|
|
const files = await repo.findByEntity(entityType, entityId);
|
|
for (const file of files) await removeAttachment(file);
|
|
}
|