diff --git a/docs/sources/oncall-api-reference/escalation_policies.md b/docs/sources/oncall-api-reference/escalation_policies.md index 6e68b42d7c..502e835e77 100644 --- a/docs/sources/oncall-api-reference/escalation_policies.md +++ b/docs/sources/oncall-api-reference/escalation_policies.md @@ -38,22 +38,22 @@ The above command returns JSON structured in the following way: } ``` -| Parameter | Required | Description | -| ---------------------------------- | :--------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `escalation_chain_id` | Yes | Each escalation policy is assigned to a specific escalation chain. | -| `position` | Optional | Escalation policies execute one after another starting from `position=0`. `Position=-1` will put the escalation policy to the end of the list. A new escalation policy created with a position of an existing escalation policy will move the old one (and all following) down in the list. | -| `type` | Yes | One of: `wait`, `notify_persons`, `notify_person_next_each_time`, `notify_on_call_from_schedule`, `notify_user_group`, `trigger_webhook`, `resolve`, `notify_whole_channel`, `notify_if_time_from_to`, `declare_incident`. | -| `important` | Optional | Default is `false`. Will assign "important" to personal notification rules if `true`. This can be used to distinguish alerts on which you want to be notified immediately by phone. Applicable for types `notify_persons`, `notify_team_members`, `notify_on_call_from_schedule`, and `notify_user_group`. | -| `duration` | If type = `wait` | The duration, in seconds, when type `wait` is chosen. Valid values are: `60`, `300`, `900`, `1800`, `3600`. | -| `action_to_trigger` | If type = `trigger_webhook` | ID of a webhook. | -| `group_to_notify` | If type = `notify_user_group` | ID of a `User Group`. | -| `persons_to_notify` | If type = `notify_persons` | List of user IDs. | -| `persons_to_notify_next_each_time` | If type = `notify_person_next_each_time` | List of user IDs. | -| `notify_on_call _from_schedule` | If type = `notify_on_call_from_schedule` | ID of a Schedule. | -| `notify_if_time_from` | If type = `notify_if_time_from_to` | UTC time represents the beginning of the time period, for example `09:00:00Z`. | -| `notify_if_time_to` | If type = `notify_if_time_from_to` | UTC time represents the end of the time period, for example `18:00:00Z`. | -| `team_to_notify` | If type = `notify_team_members` | ID of a team. | -| `severity` | If type = `declare_incident` | Severity of the incident. | +| Parameter | Required | Description | +| ---------------------------------- |:----------------------------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `escalation_chain_id` | Yes | Each escalation policy is assigned to a specific escalation chain. | +| `position` | Optional | Escalation policies execute one after another starting from `position=0`. `Position=-1` will put the escalation policy to the end of the list. A new escalation policy created with a position of an existing escalation policy will move the old one (and all following) down in the list. | +| `type` | Yes | One of: `wait`, `notify_persons`, `notify_person_next_each_time`, `notify_on_call_from_schedule`, `notify_user_group`, `trigger_webhook`, `resolve`, `notify_whole_channel`, `notify_if_time_from_to`, `declare_incident`. | +| `important` | Optional | Default is `false`. Will assign "important" to personal notification rules if `true`. This can be used to distinguish alerts on which you want to be notified immediately by phone. Applicable for types `notify_persons`, `notify_team_members`, `notify_on_call_from_schedule`, and `notify_user_group`. | +| `duration` | If type = `wait` | The duration, in seconds, when type `wait` is chosen. Valid values are any number of seconds in the inclusive range `60 to 86400`. | +| `action_to_trigger` | If type = `trigger_webhook` | ID of a webhook. | +| `group_to_notify` | If type = `notify_user_group` | ID of a `User Group`. | +| `persons_to_notify` | If type = `notify_persons` | List of user IDs. | +| `persons_to_notify_next_each_time` | If type = `notify_person_next_each_time` | List of user IDs. | +| `notify_on_call _from_schedule` | If type = `notify_on_call_from_schedule` | ID of a Schedule. | +| `notify_if_time_from` | If type = `notify_if_time_from_to` | UTC time represents the beginning of the time period, for example `09:00:00Z`. | +| `notify_if_time_to` | If type = `notify_if_time_from_to` | UTC time represents the end of the time period, for example `18:00:00Z`. | +| `team_to_notify` | If type = `notify_team_members` | ID of a team. | +| `severity` | If type = `declare_incident` | Severity of the incident. | **HTTP request** diff --git a/engine/apps/public_api/serializers/escalation_policies.py b/engine/apps/public_api/serializers/escalation_policies.py index ad0abe788f..92796a5db6 100644 --- a/engine/apps/public_api/serializers/escalation_policies.py +++ b/engine/apps/public_api/serializers/escalation_policies.py @@ -1,4 +1,3 @@ -import time from datetime import timedelta from django.utils.functional import cached_property @@ -11,6 +10,7 @@ from apps.user_management.models import Team, User from apps.webhooks.models import Webhook from common.api_helpers.custom_fields import ( + DurationSecondsField, OrganizationFilteredPrimaryKeyRelatedField, UsersFilteredByOrganizationField, ) @@ -43,7 +43,15 @@ class EscalationPolicySerializer(EagerLoadingMixin, OrderedModelSerializer): queryset=EscalationChain.objects, source="escalation_chain" ) type = EscalationPolicyTypeField(source="step") - duration = serializers.ChoiceField(required=False, source="wait_delay", choices=EscalationPolicy.DURATION_CHOICES) + + duration = DurationSecondsField( + required=False, + source="wait_delay", + allow_null=True, + min_value=timedelta(minutes=1), + max_value=timedelta(hours=24), + ) + persons_to_notify = UsersFilteredByOrganizationField( queryset=User.objects, required=False, @@ -143,18 +151,10 @@ def to_representation(self, instance): result = super().to_representation(instance) result = self._get_field_to_represent(step, result) if "duration" in result and result["duration"] is not None: - result["duration"] = result["duration"].seconds + result["duration"] = int(float(result["duration"])) return result def to_internal_value(self, data): - if data.get("duration", None): - try: - time.strptime(data["duration"], "%H:%M:%S") - except (ValueError, TypeError): - try: - data["duration"] = str(timedelta(seconds=data["duration"])) - except (ValueError, TypeError): - raise BadRequest(detail="Invalid duration format") if data.get("persons_to_notify", []) is None: # terraform case data["persons_to_notify"] = [] if data.get("persons_to_notify_next_each_time", []) is None: # terraform case