This commit is contained in:
Louis Mazin 2026-10-05 18:41:15 +02:00
parent a393d9409f
commit 44ba854c7f
2 changed files with 53 additions and 14 deletions

View File

@ -250,19 +250,23 @@ def build_weekly_summary(user):
user=user, start_date__range=(start_of_week, start_of_week + timedelta(days=6)),
).order_by('start_date', 'start_time'))
days_data = []
total_hours = 0
for offset in range(7):
day = start_of_week + timedelta(days=offset)
day_entries = [entry for entry in entries if entry.start_date == day]
completed = [entry for entry in day_entries if entry.end_time is not None]
completed = [entry for entry in day_entries if entry.duration is not None]
day_is_pointed = bool(day_entries) and len(completed) == len(day_entries)
day_duration = sum(entry.duration or 0 for entry in day_entries) if day_is_pointed else 0
total_hours += day_duration
days_data.append({
'date': day.isoformat(), 'day': day.strftime('%A'),
'start_time': str(day_entries[0].start_time) if day_entries else None,
'end_time': str(max(entry.end_time for entry in completed)) if completed and len(completed) == len(day_entries) else None,
'duration': sum(entry.duration or 0 for entry in day_entries),
'end_time': str(max(entry.end_time for entry in completed)) if day_is_pointed else None,
'duration': day_duration,
'entries_count': len(day_entries),
})
return dict(user=user.username, username=user.username,
total_hours=round(sum(entry.duration or 0 for entry in entries), 2), entries=days_data)
total_hours=round(total_hours, 2), entries=days_data)
class WeeklySummaryView(APIView):
@ -329,6 +333,16 @@ class TimeStatsView(APIView):
logical_trips = set()
daily = {}
entries_by_day = {}
for entry in entries:
entries_by_day.setdefault(entry.start_date, []).append(entry)
pointed_days = {
day
for day, day_entries in entries_by_day.items()
if day_entries and all(entry.duration is not None for entry in day_entries)
}
for entry in entries:
duration = entry.duration
minutes = round(duration * 60) if duration is not None else 0
@ -340,12 +354,19 @@ class TimeStatsView(APIView):
row['incomplete'] += 1
continue
total_minutes += minutes
row['minutes'] += minutes
trip_key = f'g:{entry.group_id}' if entry.group_id else f'e:{entry.pk}'
logical_trips.add(trip_key)
row['trip_keys'].add(trip_key)
# Une journée ne compte dans les heures faites que lorsque tous ses
# pointages sont complets. Une sortie manquante exclut donc toute la
# journée du total jusqu'à sa régularisation.
if day not in pointed_days:
continue
total_minutes += minutes
row['minutes'] += minutes
if day.weekday() == 6:
sunday_minutes += minutes
sunday_dates.add(day)

View File

@ -1204,10 +1204,31 @@ const WeeklySummaryPage = ({ userId }) => {
return start !== null && end !== null && end >= start ? end - start : 0;
};
const pointedWeekMinutes = individualWeekAttendances.reduce(
(sum, entry) => sum + attendanceMinutes(entry),
0,
);
const pointedMinutesForDays = (entries) => {
const entriesByDay = new Map();
entries.forEach((entry) => {
const day = String(entry.start_date || '').slice(0, 10);
if (!day) return;
if (!entriesByDay.has(day)) entriesByDay.set(day, []);
entriesByDay.get(day).push(entry);
});
return [...entriesByDay.values()].reduce((total, dayEntries) => {
const dayIsFullyPointed = dayEntries.length > 0 && dayEntries.every(
(entry) => entry.start_time && entry.end_time && !entry.display_incomplete,
);
if (!dayIsFullyPointed) return total;
return total + dayEntries.reduce(
(sum, entry) => sum + attendanceMinutes(entry),
0,
);
}, 0);
};
const pointedWeekMinutes = pointedMinutesForDays(individualWeekAttendances);
const precisePlannedMinutes = plannedSegments.reduce((sum, segment) => {
const start = getMinutes(getTimeValue(segment, 'start_time'));
const end = getMinutes(getTimeValue(segment, 'end_time'));
@ -1243,10 +1264,7 @@ const WeeklySummaryPage = ({ userId }) => {
const individualDayAttendances = selectedMobileDate
? getSelectedUserAttendances(getAttendancesForDay(selectedMobileDate))
: [];
const pointedDayMinutes = individualDayAttendances.reduce(
(sum, entry) => sum + attendanceMinutes(entry),
0,
);
const pointedDayMinutes = pointedMinutesForDays(individualDayAttendances);
const precisePlannedDayMinutes = selectedMobileSegments.reduce((sum, segment) => {
const start = getMinutes(getTimeValue(segment, 'start_time'));
const end = getMinutes(getTimeValue(segment, 'end_time'));