diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/adapters/reports.py b/SAS/TMSS/backend/src/tmss/tmssapp/adapters/reports.py index 6eeebcba9c91b3750a45659b790c90733fd775aa..c68d07a37e0100fb3a7fe21da88d31bd501d8377 100644 --- a/SAS/TMSS/backend/src/tmss/tmssapp/adapters/reports.py +++ b/SAS/TMSS/backend/src/tmss/tmssapp/adapters/reports.py @@ -1,9 +1,9 @@ -from django.db.models import Sum +from django.db.models import F, Sum from lofar.sas.tmss.tmss.tmssapp import models from lofar.sas.tmss.tmss.tmssapp import serializers from rest_framework.request import Request -from datetime import timedelta +from datetime import datetime, timedelta # Cycle Report @@ -64,7 +64,7 @@ def _get_average_efficiency(cycle: models.Cycle): # Get SchedulingUnitBlueprints related to the cycle subs = models.SchedulingUnitBlueprint.objects.filter(draft__scheduling_set__project__cycles=cycle.pk) - # NOTE: This can be improved, maybe using Django ORM? + # TODO: This and the get_usage_mode can be improved, maybe using Django ORM. # Get days days = [] for sub in subs: @@ -168,8 +168,50 @@ def _get_projects_summary(request: Request, cycle: models.Cycle): return projects_summary -def _get_usage_mode(cycle: models.Cycle): - return 0 +def _get_usage_mode(cycle: models.Cycle) -> {}: + """ + Help function to retrieve ILT and local usage mode info. + """ + result = [] + + # Get all the reservations related to the cycle + reservations = models.Reservation.objects.filter(project__cycles=cycle.pk) + + # Get the first Monday before the cycle.start + start, stop = cycle.start - timedelta(days=cycle.start.weekday()), cycle.stop + + # Iterate through weeks and sum durations per week + overflow, week_duration = 0, 0 + step, d = timedelta(days=7), start + while d < stop: + # Durations entirely contained in the current week + durations_in_week = reservations.filter(start_time__range=(d, d + step), stop_time__range=(d, d + step)) \ + .aggregate(duration=Sum(F('stop_time') - F('start_time')))['duration'] or 0 + + # Update week_duration and reset overflow + week_duration += overflow + durations_in_week + overflow = 0 + + # Overflow durations between two or more weeks + # TODO: This only covers an overflow of a week (two weeks coverage). + # We need to consider also more weeks (>= 3 weeks coverage). Maybe making the "overflow" var modular. + overflow_reservations = reservations.filter(start_time__range=(d, d + step), stop_time__gte=(d + step)) + for r in overflow_reservations: + # Split the duration and store overflow to be added to the next week + stop_time = r.stop_time - timedelta(days=r.stop_time.weekday()) + week_duration += (stop_time - r.start_time).total_seconds() + overflow += timedelta(days=r.stop_time.weekday()).total_seconds() + + # Store the duration for the current week + result.append({'week': d.date().isoformat(), 'duration': week_duration if week_duration > 0 else None}) + d += step + + # TODO: Filter stand-alone mode not for project, sum for each project, mixed project|no project, ILT mode per week. + # result['total_duration'] += r.duration + # result['local_duration'] += r.duration if r.specifications_doc['activity']['type'] == 'stand-alone mode' else 0 + # result['ILT_duration'] = result['total_duration'] - result['local_duration'] + + return result def _get_failures(cycle: models.Cycle):