feat: update analytics services for improved task handling

- Removed unused `parseDate` import from `analytics.ts`.
- Refactored `ManagerSummaryService` to handle standalone todos with a new priority rule, ensuring todos without tasks default to low priority.
- Updated logic in `MetricsService` to calculate total tasks by including in-progress tasks, enhancing completion rate accuracy.
- Adjusted comments for clarity on new functionality and priority determination.
This commit is contained in:
Julien Froidefond
2025-09-23 21:54:55 +02:00
parent 7ac961f6c7
commit 8a227aec36
3 changed files with 62 additions and 34 deletions

View File

@@ -1,6 +1,6 @@
import { Task, TaskStatus, TaskPriority, TaskSource } from '@/lib/types'; import { Task, TaskStatus, TaskPriority, TaskSource } from '@/lib/types';
import { prisma } from '@/services/core/database'; import { prisma } from '@/services/core/database';
import { getToday, parseDate, subtractDays } from '@/lib/date-utils'; import { getToday, subtractDays } from '@/lib/date-utils';
export interface ProductivityMetrics { export interface ProductivityMetrics {
completionTrend: Array<{ completionTrend: Array<{

View File

@@ -257,20 +257,24 @@ export class ManagerSummaryService {
}); });
}); });
// AJOUTER SEULEMENT les meetings importants standalone (non liés à une tâche) // AJOUTER les todos standalone avec la nouvelle règle de priorité
const standaloneMeetings = checkboxes.filter(checkbox => const standaloneTodos = checkboxes.filter(checkbox =>
checkbox.type === 'meeting' && !checkbox.task // Meetings non liés à une tâche !checkbox.task // Todos non liés à une tâche
); );
standaloneMeetings.forEach(meeting => { standaloneTodos.forEach(todo => {
// Appliquer la nouvelle règle de priorité :
// Si pas de tâche associée, priorité faible (même pour les meetings)
const impact: 'high' | 'medium' | 'low' = 'low';
accomplishments.push({ accomplishments.push({
id: `meeting-${meeting.id}`, id: `todo-${todo.id}`,
title: `📅 ${meeting.text}`, title: todo.type === 'meeting' ? `📅 ${todo.text}` : todo.text,
tags: [], // Meetings n'ont pas de tags par défaut tags: [], // Todos standalone n'ont pas de tags par défaut
impact: 'medium', // Meetings sont importants impact,
completedAt: meeting.date, completedAt: todo.date,
relatedItems: [meeting.id], relatedItems: [todo.id],
todosCount: 1 // Un meeting = 1 todo todosCount: 1 // Un todo = 1 todo
}); });
}); });
@@ -403,20 +407,39 @@ export class ManagerSummaryService {
}); });
}); });
// Ajouter les meetings importants comme challenges // Ajouter les todos importants comme challenges
upcomingCheckboxes.forEach(checkbox => { upcomingCheckboxes.forEach(checkbox => {
if (checkbox.type === 'meeting') { // Déterminer la priorité selon la nouvelle règle :
challenges.push({ // Si le todo est associé à une tâche, prendre la priorité de la tâche
id: `checkbox-${checkbox.id}`, // Sinon, priorité faible par défaut (même pour les meetings)
title: checkbox.text, let priority: 'high' | 'medium' | 'low';
tags: checkbox.task?.taskTags?.map(tt => tt.tag.name) || [],
priority: 'medium', // Meetings sont medium par défaut if (checkbox.task?.priority) {
estimatedEffort: 'hours', const taskPriority = checkbox.task.priority.toLowerCase();
blockers: [], if (taskPriority === 'high') {
relatedItems: [checkbox.id], priority = 'high';
todosCount: 1 // Une checkbox = 1 todo } else if (taskPriority === 'medium') {
}); priority = 'medium';
} else {
priority = 'low';
}
} else {
// Pas de tâche associée = priorité faible (même pour les meetings)
priority = 'low';
} }
// Inclure tous les todos (toutes priorités, y compris faible, sont maintenant visibles)
// La priorité est déterminée par la nouvelle règle et affichée visuellement
challenges.push({
id: `checkbox-${checkbox.id}`,
title: checkbox.text,
tags: checkbox.task?.taskTags?.map(tt => tt.tag.name) || [],
priority,
estimatedEffort: 'hours',
blockers: [],
relatedItems: [checkbox.id],
todosCount: 1 // Une checkbox = 1 todo
});
}); });
return challenges return challenges

View File

@@ -282,7 +282,8 @@ export class MetricsService {
const priorityData = await Promise.all( const priorityData = await Promise.all(
priorities.map(async (priority) => { priorities.map(async (priority) => {
const [completed, total] = await Promise.all([ const [completed] = await Promise.all([
// Tâches complétées dans la période
prisma.task.count({ prisma.task.count({
where: { where: {
priority, priority,
@@ -291,18 +292,22 @@ export class MetricsService {
lte: end lte: end
} }
} }
}),
prisma.task.count({
where: {
priority,
createdAt: {
gte: start,
lte: end
}
}
}) })
]); ]);
// Calculer les tâches en cours de cette priorité
const inProgress = await prisma.task.count({
where: {
priority,
status: {
notIn: ['done', 'cancelled', 'archived']
}
}
});
// Le total pour le calcul de completion = complétées + en cours
const total = completed + inProgress;
const pending = total - completed; const pending = total - completed;
const completionRate = total > 0 ? (completed / total) * 100 : 0; const completionRate = total > 0 ? (completed / total) * 100 : 0;