diff --git a/CHANGELOG.md b/CHANGELOG.md index 671fa857dc..c023cb79f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Remove template editor from Slack by @iskhakov ([1847](https://github.com/grafana/oncall/pull/1847)) +- Remove schedule name uniqueness restriction ([1859](https://github.com/grafana/oncall/pull/1859)) ### Fixed diff --git a/engine/apps/public_api/serializers/schedules_base.py b/engine/apps/public_api/serializers/schedules_base.py index 8eed1cf836..d69c620cf3 100644 --- a/engine/apps/public_api/serializers/schedules_base.py +++ b/engine/apps/public_api/serializers/schedules_base.py @@ -3,7 +3,6 @@ from rest_framework import serializers from apps.schedules.ical_utils import list_users_to_notify_from_ical -from apps.schedules.models import OnCallSchedule from apps.slack.models import SlackUserGroup from common.api_helpers.custom_fields import TeamPrimaryKeyRelatedField from common.api_helpers.exceptions import BadRequest @@ -20,19 +19,6 @@ def create(self, validated_data): validated_data["organization"] = self.context["request"].auth.organization return super().create(validated_data) - def validate_name(self, name): - organization = self.context["request"].auth.organization - if name is None: - return name - try: - obj = OnCallSchedule.objects.get(organization=organization, name=name) - except OnCallSchedule.DoesNotExist: - return name - if self.instance and obj.id == self.instance.id: - return name - else: - raise BadRequest(detail="Schedule with this name already exists") - def get_on_call_now(self, obj): users_on_call = list_users_to_notify_from_ical(obj, timezone.datetime.now(timezone.utc)) if users_on_call is not None: diff --git a/engine/apps/public_api/tests/test_schedules.py b/engine/apps/public_api/tests/test_schedules.py index 672b0932a3..b4a4027930 100644 --- a/engine/apps/public_api/tests/test_schedules.py +++ b/engine/apps/public_api/tests/test_schedules.py @@ -232,6 +232,29 @@ def test_get_web_schedule( assert response.json() == result +@pytest.mark.django_db +def test_create_schedules_same_name(make_organization_and_user_with_token): + + organization, user, token = make_organization_and_user_with_token() + client = APIClient() + + url = reverse("api-public:schedules-list") + + data = { + "team_id": None, + "name": "same-name", + "type": "web", + "time_zone": "UTC", + } + + for i in range(2): + response = client.post(url, data=data, format="json", HTTP_AUTHORIZATION=f"{token}") + assert response.status_code == status.HTTP_201_CREATED + + schedules = OnCallSchedule.objects.filter(name="same-name", organization=organization) + assert schedules.count() == 2 + + @pytest.mark.django_db def test_update_web_schedule( make_organization_and_user_with_token, diff --git a/engine/apps/schedules/migrations/0012_auto_20230502_1259.py b/engine/apps/schedules/migrations/0012_auto_20230502_1259.py new file mode 100644 index 0000000000..a06f7020eb --- /dev/null +++ b/engine/apps/schedules/migrations/0012_auto_20230502_1259.py @@ -0,0 +1,21 @@ +# Generated by Django 3.2.18 on 2023-05-02 12:59 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('schedules', '0011_oncallschedule_cached_ical_final_schedule'), + ] + + operations = [ + migrations.AlterModelOptions( + name='oncallschedule', + options={'base_manager_name': 'objects'}, + ), + migrations.AlterUniqueTogether( + name='oncallschedule', + unique_together=set(), + ), + ] diff --git a/engine/apps/schedules/models/on_call_schedule.py b/engine/apps/schedules/models/on_call_schedule.py index 9a01329d44..03681a81a9 100644 --- a/engine/apps/schedules/models/on_call_schedule.py +++ b/engine/apps/schedules/models/on_call_schedule.py @@ -178,9 +178,6 @@ class NotifyEmptyOnCall(models.IntegerChoices): has_empty_shifts = models.BooleanField(default=False) empty_shifts_report_sent_at = models.DateField(null=True, default=None) - class Meta: - unique_together = ("name", "organization") - def get_icalendars(self): """Returns list of calendars. Primary calendar should always be the first""" calendar_primary = None