bcb9c9d714
El detalle vive en los popups de las tarjetas; se elimina tambien la consulta myPendingActivities del backend, que quedaba sin uso. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
60 lines
2.9 KiB
JavaScript
60 lines
2.9 KiB
JavaScript
import { ok, fail, asyncHandler } from '../../utils/http.js';
|
|
import * as repo from './repository.js';
|
|
import { listByProject } from '../activities/service.js';
|
|
import { dueStatus } from '../../utils/dates.js';
|
|
import { ROLES } from '../../middleware/auth.js';
|
|
|
|
const FULL_ACCESS_ROLES = [ROLES.SUPERADMIN, ROLES.ADMIN, ROLES.IT_MANAGER];
|
|
|
|
// Mismo criterio que projects/service.js#listProjects: los roles de administracion ven todo el
|
|
// panel; el resto solo cuenta/lista lo de proyectos donde es miembro.
|
|
function memberFilterFor(currentUser) {
|
|
return FULL_ACCESS_ROLES.includes(currentUser.roleCode) ? null : currentUser.id;
|
|
}
|
|
|
|
export const getSummary = asyncHandler(async (req, res) => {
|
|
const memberUserId = memberFilterFor(req.currentUser);
|
|
const [kpis, byStatus, overdueProjects, activeProjects, dueSoonProjects,
|
|
pendingActivities, overdueActivities, todayActivities] = await Promise.all([
|
|
repo.summary(memberUserId),
|
|
repo.projectsByStatus(memberUserId),
|
|
repo.overdueProjectsList(memberUserId),
|
|
repo.activeProjectsList(memberUserId),
|
|
repo.dueSoonProjectsList(memberUserId),
|
|
repo.pendingActivitiesList(memberUserId, 'all'),
|
|
repo.pendingActivitiesList(memberUserId, 'overdue'),
|
|
repo.pendingActivitiesList(memberUserId, 'today'),
|
|
]);
|
|
const withProjectDue = (p) => ({ ...p, dueStatus: dueStatus(p.estimated_end_date) });
|
|
const withActivityDue = (a) => ({ ...a, dueStatus: dueStatus(a.due_date) });
|
|
ok(res, {
|
|
kpis,
|
|
projectsByStatus: byStatus,
|
|
// Detalle de cada tarjeta del Panel (popup al hacer clic).
|
|
overdueProjects: overdueProjects.map((p) => ({ ...p, dueStatus: 'overdue' })),
|
|
activeProjects: activeProjects.map(withProjectDue),
|
|
dueSoonProjects: dueSoonProjects.map(withProjectDue),
|
|
pendingActivities: pendingActivities.map(withActivityDue),
|
|
overdueActivities: overdueActivities.map((a) => ({ ...a, dueStatus: 'overdue' })),
|
|
todayActivities: todayActivities.map(withActivityDue),
|
|
});
|
|
});
|
|
|
|
export const getCalendar = asyncHandler(async (req, res) => {
|
|
const month = req.query.month; // formato YYYY-MM
|
|
if (!month || !/^\d{4}-\d{2}$/.test(month)) return fail(res, 400, 'Parametro month invalido (YYYY-MM)');
|
|
const start = `${month}-01`;
|
|
const [year, m] = month.split('-').map(Number);
|
|
const end = new Date(year, m, 0).toISOString().slice(0, 10);
|
|
const items = await repo.calendarActivities(start, end, memberFilterFor(req.currentUser));
|
|
ok(res, items.map((a) => ({ ...a, dueStatus: dueStatus(a.due_date, a.status_is_closed) })));
|
|
});
|
|
|
|
export const getGantt = asyncHandler(async (req, res) => {
|
|
const activities = await listByProject(Number(req.params.id), req.currentUser);
|
|
ok(res, activities.map((a) => ({
|
|
id: a.id, code: a.code, name: a.name, startDate: a.start_date, dueDate: a.due_date,
|
|
progressPct: a.progress_pct, isMilestone: !!a.is_milestone, responsibleName: a.responsible_name,
|
|
})));
|
|
});
|