2020-12-29 16:19:59 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
#
|
|
|
|
from django.utils.translation import ugettext_lazy as _
|
|
|
|
from rest_framework import serializers
|
2021-01-05 15:39:38 +00:00
|
|
|
from common.drf.fields import ReadableHiddenField
|
|
|
|
from common.drf.serializers import DynamicMappingSerializer
|
2020-12-29 16:19:59 +00:00
|
|
|
from orgs.utils import get_org_by_id
|
|
|
|
from orgs.mixins.serializers import OrgResourceModelSerializerMixin
|
|
|
|
from users.models import User
|
|
|
|
from tickets import const
|
|
|
|
from tickets.models import Ticket
|
2021-01-05 15:39:38 +00:00
|
|
|
from .meta import meta_field_dynamic_mapping_serializers
|
2020-12-29 16:19:59 +00:00
|
|
|
|
|
|
|
__all__ = [
|
|
|
|
'TicketSerializer', 'TicketDisplaySerializer',
|
|
|
|
'TicketApplySerializer', 'TicketApproveSerializer',
|
|
|
|
'TicketRejectSerializer', 'TicketCloseSerializer',
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
class TicketSerializer(OrgResourceModelSerializerMixin):
|
|
|
|
type_display = serializers.ReadOnlyField(source='get_type_display', label=_('Type'))
|
|
|
|
action_display = serializers.ReadOnlyField(source='get_action_display', label=_('Action'))
|
2021-01-01 23:25:23 +00:00
|
|
|
status_display = serializers.ReadOnlyField(source='get_status_display', label=_('Status'))
|
2021-01-05 15:39:38 +00:00
|
|
|
meta = DynamicMappingSerializer(mapping_serializers=meta_field_dynamic_mapping_serializers)
|
2020-12-29 16:19:59 +00:00
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = Ticket
|
|
|
|
fields = [
|
|
|
|
'id', 'title', 'type', 'type_display',
|
|
|
|
'meta', 'action', 'action_display', 'status', 'status_display',
|
|
|
|
'applicant', 'applicant_display', 'processor', 'processor_display',
|
|
|
|
'assignees', 'assignees_display',
|
|
|
|
'date_created', 'date_updated',
|
|
|
|
'org_id', 'org_name',
|
|
|
|
'body'
|
|
|
|
]
|
|
|
|
|
2021-01-05 15:39:38 +00:00
|
|
|
def get_meta_mapping_path(self, mapping_serializers):
|
|
|
|
view = self.context['view']
|
|
|
|
request = self.context['request']
|
|
|
|
query_type = request.query_params.get('type')
|
|
|
|
query_action = request.query_params.get('action')
|
|
|
|
action = query_action if query_action else view.action
|
|
|
|
mapping_path = ['type', query_type, action]
|
|
|
|
return mapping_path
|
|
|
|
|
2020-12-29 16:19:59 +00:00
|
|
|
|
|
|
|
class TicketDisplaySerializer(TicketSerializer):
|
|
|
|
|
|
|
|
class Meta(TicketSerializer.Meta):
|
|
|
|
read_only_fields = TicketSerializer.Meta.fields
|
|
|
|
|
|
|
|
|
|
|
|
class TicketActionSerializer(TicketSerializer):
|
2020-12-30 10:14:06 +00:00
|
|
|
action = ReadableHiddenField(default=const.TicketActionChoices.open.value)
|
2020-12-29 16:19:59 +00:00
|
|
|
|
|
|
|
class Meta(TicketSerializer.Meta):
|
|
|
|
required_fields = ['action']
|
|
|
|
read_only_fields = list(set(TicketDisplaySerializer.Meta.fields) - set(required_fields))
|
|
|
|
|
|
|
|
|
|
|
|
class TicketApplySerializer(TicketActionSerializer):
|
|
|
|
applicant = ReadableHiddenField(default=serializers.CurrentUserDefault())
|
|
|
|
org_id = serializers.CharField(
|
|
|
|
max_length=36, allow_blank=True, required=True, label=_("Organization")
|
|
|
|
)
|
|
|
|
|
|
|
|
class Meta(TicketActionSerializer.Meta):
|
|
|
|
required_fields = TicketActionSerializer.Meta.required_fields + [
|
|
|
|
'id', 'title', 'type', 'applicant', 'meta', 'assignees', 'org_id'
|
|
|
|
]
|
|
|
|
read_only_fields = list(set(TicketDisplaySerializer.Meta.fields) - set(required_fields))
|
|
|
|
extra_kwargs = {
|
2020-12-30 21:07:11 +00:00
|
|
|
'type': {'required': True},
|
2020-12-29 16:19:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
def validate_type(self, tp):
|
|
|
|
request_type = self.context['request'].query_params.get('type')
|
|
|
|
if tp != request_type:
|
|
|
|
error = _(
|
|
|
|
'The `type` in the submission data (`{}`) is different from the type '
|
|
|
|
'in the request url (`{}`)'.format(tp, request_type)
|
|
|
|
)
|
|
|
|
raise serializers.ValidationError(error)
|
|
|
|
return tp
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def validate_org_id(org_id):
|
|
|
|
org = get_org_by_id(org_id)
|
|
|
|
if not org:
|
|
|
|
error = _('The organization `{}` does not exist'.format(org_id))
|
|
|
|
raise serializers.ValidationError(error)
|
|
|
|
return org_id
|
|
|
|
|
|
|
|
def validate_assignees(self, assignees):
|
|
|
|
org_id = self.initial_data.get('org_id')
|
|
|
|
self.validate_org_id(org_id)
|
|
|
|
org = get_org_by_id(org_id)
|
|
|
|
admins = User.get_super_and_org_admins(org)
|
|
|
|
valid_assignees = list(set(assignees) & set(admins))
|
|
|
|
if not valid_assignees:
|
|
|
|
error = _('None of the assignees belong to Organization `{}` admins'.format(org.name))
|
|
|
|
raise serializers.ValidationError(error)
|
|
|
|
return valid_assignees
|
|
|
|
|
2020-12-31 10:37:55 +00:00
|
|
|
def validate_action(self, action):
|
2020-12-30 10:14:06 +00:00
|
|
|
return const.TicketActionChoices.open.value
|
2020-12-29 16:19:59 +00:00
|
|
|
|
|
|
|
|
|
|
|
class TicketProcessSerializer(TicketActionSerializer):
|
|
|
|
processor = ReadableHiddenField(default=serializers.CurrentUserDefault())
|
|
|
|
|
|
|
|
class Meta(TicketActionSerializer.Meta):
|
|
|
|
required_fields = TicketActionSerializer.Meta.required_fields + ['processor']
|
|
|
|
read_only_fields = list(set(TicketDisplaySerializer.Meta.fields) - set(required_fields))
|
|
|
|
|
|
|
|
|
|
|
|
class TicketApproveSerializer(TicketProcessSerializer):
|
|
|
|
|
|
|
|
class Meta(TicketProcessSerializer.Meta):
|
|
|
|
required_fields = TicketProcessSerializer.Meta.required_fields + ['meta']
|
|
|
|
read_only_fields = list(set(TicketDisplaySerializer.Meta.fields) - set(required_fields))
|
|
|
|
|
|
|
|
def validate_meta(self, meta):
|
2020-12-30 10:14:06 +00:00
|
|
|
instance_meta = self.instance.meta
|
|
|
|
instance_meta.update(meta)
|
|
|
|
return instance_meta
|
2020-12-29 16:19:59 +00:00
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def validate_action(action):
|
|
|
|
return const.TicketActionChoices.approve.value
|
|
|
|
|
|
|
|
|
|
|
|
class TicketRejectSerializer(TicketProcessSerializer):
|
|
|
|
|
2020-12-31 10:37:55 +00:00
|
|
|
def validate_action(self, action):
|
2020-12-29 16:19:59 +00:00
|
|
|
return const.TicketActionChoices.reject.value
|
|
|
|
|
|
|
|
|
|
|
|
class TicketCloseSerializer(TicketProcessSerializer):
|
|
|
|
|
2020-12-31 10:37:55 +00:00
|
|
|
def validate_action(self, action):
|
2020-12-29 16:19:59 +00:00
|
|
|
return const.TicketActionChoices.close.value
|
|
|
|
|
|
|
|
|