diff --git a/program/models.py b/program/models.py index dde3b044f016a8b6739aaa4182767ceae0f505dd..0fafc80b6a3c7fedb587294bb61d5ffe31075338 100644 --- a/program/models.py +++ b/program/models.py @@ -29,13 +29,11 @@ from django.contrib.auth.models import User from django.core.exceptions import ObjectDoesNotExist from django.db import models from django.db.models import Q, QuerySet -from django.forms.models import model_to_dict from django.utils import timezone from django.utils.translation import gettext_lazy as _ -from program.utils import parse_date, parse_datetime, parse_time + +from program.utils import parse_datetime from steering.settings import ( - AUTO_SET_LAST_DATE_TO_DAYS_IN_FUTURE, - AUTO_SET_LAST_DATE_TO_END_OF_YEAR, THUMBNAIL_SIZES, ) @@ -377,57 +375,6 @@ class Schedule(models.Model): class Meta: ordering = ("first_date", "start_time") - # FIXME: this does not belong here - @staticmethod - def instantiate_upcoming(sdl, show_pk, pk=None): - """Returns an upcoming schedule instance for conflict resolution""" - pk = int(pk) if pk is not None else None - rrule = RRule.objects.get(pk=int(sdl["rrule"])) - show = Show.objects.get(pk=int(show_pk)) - - is_repetition = True if sdl.get("is_repetition") is True else False - default_playlist_id = ( - int(sdl["default_playlist_id"]) if sdl.get("default_playlist_id") else None - ) - add_days_no = int(sdl["add_days_no"]) if sdl.get("add_days_no") else None - add_business_days_only = True if sdl.get("add_business_days_only") is True else False - - first_date = parse_date(str(sdl["first_date"])) - start_time = ( - sdl["start_time"] + ":00" if len(str(sdl["start_time"])) == 5 else sdl["start_time"] - ) - end_time = sdl["end_time"] + ":00" if len(str(sdl["end_time"])) == 5 else sdl["end_time"] - - start_time = parse_time(str(start_time)) - end_time = parse_time(str(end_time)) - - if sdl["last_date"]: - last_date = parse_date(str(sdl["last_date"])) - else: - # If last_date was not set, set it to the end of the year or add x days - if AUTO_SET_LAST_DATE_TO_END_OF_YEAR: - year = timezone.now().year - last_date = parse_date(f"{year}-12-31") - else: - last_date = first_date + timedelta(days=+AUTO_SET_LAST_DATE_TO_DAYS_IN_FUTURE) - - schedule = Schedule( - pk=pk, - by_weekday=sdl["by_weekday"], - rrule=rrule, - first_date=first_date, - start_time=start_time, - end_time=end_time, - last_date=last_date, - is_repetition=is_repetition, - default_playlist_id=default_playlist_id, - show=show, - add_days_no=add_days_no, - add_business_days_only=add_business_days_only, - ) - - return schedule - # FIXME: this does not belong here @staticmethod def generate_timeslots(schedule): @@ -712,44 +659,6 @@ class Schedule(models.Model): return conflicts - # FIXME: this does not belong here - @staticmethod - def make_conflicts(sdl, schedule_pk, show_pk): - """ - Retrieves POST vars - Generates a schedule - Generates conflicts: Returns timeslots, collisions, solutions as JSON - Returns conflicts dict - """ - - # Generate schedule to be saved - schedule = Schedule.instantiate_upcoming(sdl, show_pk, schedule_pk) - - # Copy if first_date changes for generating timeslots - gen_schedule = schedule - - # Generate timeslots - - # If extending: Get last timeslot and start generating from that date on - if schedule_pk is not None: - existing_schedule = Schedule.objects.get(pk=int(schedule_pk)) - - if schedule.last_date > existing_schedule.last_date: - last_timeslot = ( - TimeSlot.objects.filter(schedule=existing_schedule) - .order_by("start") - .reverse()[0] - ) - gen_schedule.first_date = last_timeslot.start.date() + timedelta(days=1) - - timeslots = Schedule.generate_timeslots(gen_schedule) - - # Generate conflicts and add schedule - conflicts = Schedule.generate_conflicts(timeslots) - conflicts["schedule"] = model_to_dict(schedule) - - return conflicts - class TimeSlotManager(models.Manager): @staticmethod diff --git a/program/services.py b/program/services.py index e7ead3cb2e7f37b9f4fec40253ebf6c388e9e719..a6d509dffe0d6216759c5febf7552d042d0cf207 100644 --- a/program/services.py +++ b/program/services.py @@ -17,7 +17,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -from datetime import datetime, time +from datetime import datetime, time, timedelta from rest_framework.exceptions import ValidationError @@ -25,8 +25,12 @@ from django.core.exceptions import ObjectDoesNotExist from django.forms.models import model_to_dict from django.utils import timezone from django.utils.translation import gettext_lazy as _ -from program.models import Note, Schedule, ScheduleConflictError, TimeSlot -from program.utils import parse_datetime +from program.models import Note, RRule, Schedule, ScheduleConflictError, Show, TimeSlot +from program.utils import parse_date, parse_datetime, parse_time +from steering.settings import ( + AUTO_SET_LAST_DATE_TO_DAYS_IN_FUTURE, + AUTO_SET_LAST_DATE_TO_END_OF_YEAR, +) # TODO: add type annotations @@ -43,9 +47,9 @@ def resolve_conflicts(data, schedule_pk, show_pk): solutions = data.get("solutions", []) # Regenerate conflicts - schedule = Schedule.instantiate_upcoming(sdl, show_pk, schedule_pk) + schedule = instantiate_upcoming(sdl, show_pk, schedule_pk) show = schedule.show - conflicts = Schedule.make_conflicts(sdl, schedule_pk, show_pk) + conflicts = make_conflicts(sdl, schedule_pk, show_pk) if schedule.rrule.freq > 0 and schedule.first_date == schedule.last_date: raise ValidationError( @@ -307,3 +311,90 @@ def resolve_conflicts(data, schedule_pk, show_pk): dl.delete() return model_to_dict(schedule) + + +# TODO: add type annotations +def instantiate_upcoming(sdl, show_pk, pk=None): + """Returns an upcoming schedule instance for conflict resolution""" + pk = int(pk) if pk is not None else None + rrule = RRule.objects.get(pk=int(sdl["rrule"])) + show = Show.objects.get(pk=int(show_pk)) + + is_repetition = True if sdl.get("is_repetition") is True else False + default_playlist_id = ( + int(sdl["default_playlist_id"]) if sdl.get("default_playlist_id") else None + ) + add_days_no = int(sdl["add_days_no"]) if sdl.get("add_days_no") else None + add_business_days_only = True if sdl.get("add_business_days_only") is True else False + + first_date = parse_date(str(sdl["first_date"])) + start_time = ( + sdl["start_time"] + ":00" if len(str(sdl["start_time"])) == 5 else sdl["start_time"] + ) + end_time = sdl["end_time"] + ":00" if len(str(sdl["end_time"])) == 5 else sdl["end_time"] + + start_time = parse_time(str(start_time)) + end_time = parse_time(str(end_time)) + + if sdl["last_date"]: + last_date = parse_date(str(sdl["last_date"])) + else: + # If last_date was not set, set it to the end of the year or add x days + if AUTO_SET_LAST_DATE_TO_END_OF_YEAR: + year = timezone.now().year + last_date = parse_date(f"{year}-12-31") + else: + last_date = first_date + timedelta(days=+AUTO_SET_LAST_DATE_TO_DAYS_IN_FUTURE) + + schedule = Schedule( + pk=pk, + by_weekday=sdl["by_weekday"], + rrule=rrule, + first_date=first_date, + start_time=start_time, + end_time=end_time, + last_date=last_date, + is_repetition=is_repetition, + default_playlist_id=default_playlist_id, + show=show, + add_days_no=add_days_no, + add_business_days_only=add_business_days_only, + ) + + return schedule + + +# TODO: add type annotations +def make_conflicts(sdl, schedule_pk, show_pk): + """ + Retrieves POST vars + Generates a schedule + Generates conflicts: Returns timeslots, collisions, solutions as JSON + Returns conflicts dict + """ + + # Generate schedule to be saved + schedule = instantiate_upcoming(sdl, show_pk, schedule_pk) + + # Copy if first_date changes for generating timeslots + gen_schedule = schedule + + # Generate timeslots + + # If extending: Get last timeslot and start generating from that date on + if schedule_pk is not None: + existing_schedule = Schedule.objects.get(pk=int(schedule_pk)) + + if schedule.last_date > existing_schedule.last_date: + last_timeslot = ( + TimeSlot.objects.filter(schedule=existing_schedule).order_by("start").reverse()[0] + ) + gen_schedule.first_date = last_timeslot.start.date() + timedelta(days=1) + + timeslots = Schedule.generate_timeslots(gen_schedule) + + # Generate conflicts and add schedule + conflicts = Schedule.generate_conflicts(timeslots) + conflicts["schedule"] = model_to_dict(schedule) + + return conflicts