chore: estructura inicial del MVP
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>
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
import { pool } from '../config/db.js';
|
||||
|
||||
export async function logAudit({ userId, action, entityType, entityId, detail }) {
|
||||
await pool.query(
|
||||
`INSERT INTO audit_log (user_id, action, entity_type, entity_id, detail_json) VALUES (?, ?, ?, ?, ?)`,
|
||||
[userId, action, entityType, entityId ?? null, detail ? JSON.stringify(detail) : null]
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// Genera codigos legibles tipo PRY-0007 / ACT-0042 a partir del ultimo id insertado.
|
||||
export function buildCode(prefix, id) {
|
||||
return `${prefix}-${String(id).padStart(4, '0')}`;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Estado de vencimiento calculado al vuelo (no se guarda en BD).
|
||||
// Reglas del SPEC: vence en >3 dias = normal, <=3 dias = advertencia, hoy = urgente, vencido = critico.
|
||||
export function dueStatus(dueDate, isDone = false) {
|
||||
if (!dueDate || isDone) return 'none';
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
const due = new Date(dueDate);
|
||||
due.setHours(0, 0, 0, 0);
|
||||
const diffDays = Math.round((due - today) / 86400000);
|
||||
|
||||
if (diffDays < 0) return 'overdue';
|
||||
if (diffDays === 0) return 'today';
|
||||
if (diffDays <= 3) return 'warning';
|
||||
return 'on_time';
|
||||
}
|
||||
|
||||
export function todayMysql() {
|
||||
return new Date().toISOString().slice(0, 10);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
export function ok(res, data = null, status = 200) {
|
||||
return res.status(status).json({ success: true, data, error: null });
|
||||
}
|
||||
|
||||
export function fail(res, status, message) {
|
||||
return res.status(status).json({ success: false, data: null, error: message });
|
||||
}
|
||||
|
||||
export class HttpError extends Error {
|
||||
constructor(status, message) {
|
||||
super(message);
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
|
||||
export function asyncHandler(fn) {
|
||||
return (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);
|
||||
}
|
||||
Reference in New Issue
Block a user