From 021cf095a2d86a868d1882be73d76181a054a3e5 Mon Sep 17 00:00:00 2001 From: Matias Bordese Date: Mon, 5 Jun 2023 14:24:59 -0300 Subject: [PATCH] Add support to update web schedule rotations in-place (#2102) --- engine/apps/api/serializers/on_call_shifts.py | 3 +- engine/apps/api/tests/test_oncall_shift.py | 50 +++++++++++++++++++ engine/apps/api/views/on_call_shifts.py | 3 +- 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/engine/apps/api/serializers/on_call_shifts.py b/engine/apps/api/serializers/on_call_shifts.py index c6e66a09..f22baddb 100644 --- a/engine/apps/api/serializers/on_call_shifts.py +++ b/engine/apps/api/serializers/on_call_shifts.py @@ -195,6 +195,7 @@ class OnCallShiftUpdateSerializer(OnCallShiftSerializer): validated_data = self._correct_validated_data(instance.type, validated_data) change_only_title = True create_or_update_last_shift = False + force_update = validated_data.pop("force_update", True) for field in validated_data: if field != "title" and validated_data[field] != getattr(instance, field): @@ -209,7 +210,7 @@ class OnCallShiftUpdateSerializer(OnCallShiftSerializer): elif instance.event_is_finished: raise serializers.ValidationError(["This event cannot be updated"]) - if create_or_update_last_shift: + if not force_update and create_or_update_last_shift: result = instance.create_or_update_last_shift(validated_data) else: result = super().update(instance, validated_data) diff --git a/engine/apps/api/tests/test_oncall_shift.py b/engine/apps/api/tests/test_oncall_shift.py index d7fd687d..94c1eba2 100644 --- a/engine/apps/api/tests/test_oncall_shift.py +++ b/engine/apps/api/tests/test_oncall_shift.py @@ -402,6 +402,56 @@ def test_update_started_on_call_shift( assert on_call_shift.until == on_call_shift.updated_shift.rotation_start +@pytest.mark.django_db +def test_update_started_on_call_shift_force_update( + on_call_shift_internal_api_setup, + make_on_call_shift, + make_user_auth_headers, +): + token, user1, _, _, schedule = on_call_shift_internal_api_setup + + client = APIClient() + start_date = (timezone.now() - timezone.timedelta(hours=1)).replace(microsecond=0) + + title = "Test Shift Rotation" + on_call_shift = make_on_call_shift( + schedule.organization, + shift_type=CustomOnCallShift.TYPE_ROLLING_USERS_EVENT, + schedule=schedule, + title=title, + start=start_date, + duration=timezone.timedelta(hours=3), + rotation_start=start_date, + rolling_users=[{user1.pk: user1.public_primary_key}], + ) + data_to_update = { + "title": title, + "priority_level": 2, + "shift_start": start_date.strftime("%Y-%m-%dT%H:%M:%SZ"), + "shift_end": (start_date + timezone.timedelta(hours=1)).strftime("%Y-%m-%dT%H:%M:%SZ"), + "rotation_start": start_date.strftime("%Y-%m-%dT%H:%M:%SZ"), + "until": None, + "frequency": None, + "interval": None, + "by_day": None, + "rolling_users": [[user1.public_primary_key]], + } + + assert on_call_shift.priority_level != data_to_update["priority_level"] + + url = reverse("api-internal:oncall_shifts-detail", kwargs={"pk": on_call_shift.public_primary_key}) + "?force=true" + + response = client.put(url, data=data_to_update, format="json", **make_user_auth_headers(user1, token)) + + assert response.status_code == status.HTTP_200_OK + # check no shift was created + assert response.data["id"] == on_call_shift.public_primary_key + on_call_shift.refresh_from_db() + assert on_call_shift.priority_level == data_to_update["priority_level"] + assert on_call_shift.updated_shift is None + assert on_call_shift.until is None + + @pytest.mark.django_db def test_update_old_on_call_shift_with_future_version( on_call_shift_internal_api_setup, diff --git a/engine/apps/api/views/on_call_shifts.py b/engine/apps/api/views/on_call_shifts.py index b24482c1..c760b53f 100644 --- a/engine/apps/api/views/on_call_shifts.py +++ b/engine/apps/api/views/on_call_shifts.py @@ -71,7 +71,8 @@ class OnCallShiftView(TeamFilteringMixin, PublicPrimaryKeyMixin, UpdateSerialize def perform_update(self, serializer): prev_state = serializer.instance.insight_logs_serialized - serializer.save() + force_update = self.request.query_params.get("force", "") == "true" + serializer.save(force_update=force_update) new_state = serializer.instance.insight_logs_serialized write_resource_insight_log( instance=serializer.instance,