@ -43,6 +43,7 @@ from core.viewsets import (
|
|||||||
ticket_category,
|
ticket_category,
|
||||||
ticket_comment,
|
ticket_comment,
|
||||||
ticket_linked_item,
|
ticket_linked_item,
|
||||||
|
related_ticket,
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -119,6 +120,8 @@ router.register('config_management/group/(?P<group_id>[0-9]+)/software', config_
|
|||||||
|
|
||||||
router.register('core/(?P<model_class>.+)/(?P<model_id>[0-9]+)/history', history_v2.ViewSet, basename='_api_v2_model_history')
|
router.register('core/(?P<model_class>.+)/(?P<model_id>[0-9]+)/history', history_v2.ViewSet, basename='_api_v2_model_history')
|
||||||
router.register('core/ticket/(?P<ticket_id>[0-9]+)/linked_item', ticket_linked_item.ViewSet, basename='_api_v2_ticket_linked_item')
|
router.register('core/ticket/(?P<ticket_id>[0-9]+)/linked_item', ticket_linked_item.ViewSet, basename='_api_v2_ticket_linked_item')
|
||||||
|
router.register('core/ticket/(?P<ticket_id>[0-9]+)/related_ticket', related_ticket.ViewSet, basename='_api_v2_ticket_related')
|
||||||
|
|
||||||
|
|
||||||
router.register('itam', itam_index_v2.Index, basename='_api_v2_itam_home')
|
router.register('itam', itam_index_v2.Index, basename='_api_v2_itam_home')
|
||||||
router.register('itam/device', device_v2.ViewSet, basename='_api_v2_device')
|
router.register('itam/device', device_v2.ViewSet, basename='_api_v2_device')
|
||||||
|
@ -225,6 +225,19 @@ class ModelViewSet(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ModelListRetrieveDeleteViewSet(
|
||||||
|
viewsets.mixins.ListModelMixin,
|
||||||
|
viewsets.mixins.RetrieveModelMixin,
|
||||||
|
viewsets.mixins.DestroyModelMixin,
|
||||||
|
viewsets.GenericViewSet,
|
||||||
|
ModelViewSetBase
|
||||||
|
):
|
||||||
|
""" Use for models that you wish to delete and view ONLY!"""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ModelRetrieveUpdateViewSet(
|
class ModelRetrieveUpdateViewSet(
|
||||||
viewsets.mixins.RetrieveModelMixin,
|
viewsets.mixins.RetrieveModelMixin,
|
||||||
viewsets.mixins.UpdateModelMixin,
|
viewsets.mixins.UpdateModelMixin,
|
||||||
|
@ -3,6 +3,8 @@ from django.db import models
|
|||||||
from django.db.models import Q, signals, Sum
|
from django.db.models import Q, signals, Sum
|
||||||
from django.forms import ValidationError
|
from django.forms import ValidationError
|
||||||
|
|
||||||
|
from rest_framework.reverse import reverse
|
||||||
|
|
||||||
from .ticket_enum_values import TicketValues
|
from .ticket_enum_values import TicketValues
|
||||||
|
|
||||||
from access.fields import AutoCreatedField, AutoLastModifiedField
|
from access.fields import AutoCreatedField, AutoLastModifiedField
|
||||||
@ -1103,6 +1105,11 @@ class RelatedTickets(TenancyObject):
|
|||||||
'id'
|
'id'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
verbose_name = 'Related Ticket'
|
||||||
|
|
||||||
|
verbose_name_plural = 'Related Tickets'
|
||||||
|
|
||||||
|
|
||||||
class Related(models.IntegerChoices):
|
class Related(models.IntegerChoices):
|
||||||
RELATED = '1', 'Related'
|
RELATED = '1', 'Related'
|
||||||
|
|
||||||
@ -1159,9 +1166,32 @@ class RelatedTickets(TenancyObject):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
# def __str__(self):
|
def get_url( self, ticket_id, request = None ) -> str:
|
||||||
|
|
||||||
|
if not ticket_id:
|
||||||
|
|
||||||
|
return ''
|
||||||
|
|
||||||
|
if request:
|
||||||
|
|
||||||
|
return reverse(
|
||||||
|
"v2:_api_v2_ticket_related-detail",
|
||||||
|
request = request,
|
||||||
|
kwargs={
|
||||||
|
'ticket_id': ticket_id,
|
||||||
|
'pk': self.id
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return reverse("v2:_api_v2_ticket_related-detail", kwargs={'pk': self.id})
|
||||||
|
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
|
||||||
|
# return '#' + str( self.id )
|
||||||
|
|
||||||
|
return '#'
|
||||||
|
|
||||||
# return ''
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def parent_object(self):
|
def parent_object(self):
|
||||||
|
@ -75,6 +75,7 @@ class TicketModelSerializer(TicketBaseSerializer):
|
|||||||
),
|
),
|
||||||
'comments': reverse('v2:_api_v2_ticket_' + str(item.get_ticket_type_display()).lower() + '_comments-list', request=context['view'].request, kwargs={'ticket_id': item.pk}),
|
'comments': reverse('v2:_api_v2_ticket_' + str(item.get_ticket_type_display()).lower() + '_comments-list', request=context['view'].request, kwargs={'ticket_id': item.pk}),
|
||||||
'linked_items': reverse("v2:_api_v2_ticket_linked_item-list", request=context['view'].request, kwargs={'ticket_id': item.pk}),
|
'linked_items': reverse("v2:_api_v2_ticket_linked_item-list", request=context['view'].request, kwargs={'ticket_id': item.pk}),
|
||||||
|
'related_tickets': reverse("v2:_api_v2_ticket_related-list", request=context['view'].request, kwargs={'ticket_id': item.pk}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
119
app/core/serializers/ticket_related.py
Normal file
119
app/core/serializers/ticket_related.py
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
from rest_framework.fields import empty
|
||||||
|
from rest_framework.reverse import reverse
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from access.serializers.organization import OrganizationBaseSerializer
|
||||||
|
|
||||||
|
from core.serializers.ticket import TicketBaseSerializer
|
||||||
|
|
||||||
|
from core.models.ticket.ticket import RelatedTickets
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class RelatedTicketBaseSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
display_name = serializers.SerializerMethodField('get_display_name')
|
||||||
|
|
||||||
|
def get_display_name(self, item):
|
||||||
|
|
||||||
|
return str( item )
|
||||||
|
|
||||||
|
url = serializers.SerializerMethodField('get_url')
|
||||||
|
|
||||||
|
def get_url(self, item) -> str:
|
||||||
|
|
||||||
|
request = None
|
||||||
|
|
||||||
|
ticket_id: int = None
|
||||||
|
|
||||||
|
if 'view' in self._context:
|
||||||
|
|
||||||
|
if hasattr(self._context['view'], 'request'):
|
||||||
|
|
||||||
|
request = self._context['view'].request
|
||||||
|
|
||||||
|
if 'ticket_id' in self._kwargs['context']['view'].kwargs:
|
||||||
|
|
||||||
|
ticket_id = int(self._kwargs['context']['view'].kwargs['ticket_id'])
|
||||||
|
|
||||||
|
return item.get_url( ticket_id = ticket_id,request = request )
|
||||||
|
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
|
||||||
|
model = RelatedTickets
|
||||||
|
|
||||||
|
fields = [
|
||||||
|
'id',
|
||||||
|
'display_name',
|
||||||
|
'title',
|
||||||
|
'url',
|
||||||
|
]
|
||||||
|
|
||||||
|
read_only_fields = [
|
||||||
|
'id',
|
||||||
|
'display_name',
|
||||||
|
'title',
|
||||||
|
'url',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class RelatedTicketModelSerializer(RelatedTicketBaseSerializer):
|
||||||
|
|
||||||
|
|
||||||
|
_urls = serializers.SerializerMethodField('get_url')
|
||||||
|
|
||||||
|
def get_url(self, item):
|
||||||
|
|
||||||
|
request = None
|
||||||
|
|
||||||
|
ticket_id: int = None
|
||||||
|
|
||||||
|
if 'view' in self._context:
|
||||||
|
|
||||||
|
if hasattr(self._context['view'], 'request'):
|
||||||
|
|
||||||
|
request = self._context['view'].request
|
||||||
|
|
||||||
|
if 'ticket_id' in self._kwargs['context']['view'].kwargs:
|
||||||
|
|
||||||
|
ticket_id = int(self._kwargs['context']['view'].kwargs['ticket_id'])
|
||||||
|
|
||||||
|
return {
|
||||||
|
'_self': item.get_url( ticket_id = ticket_id, request = request ),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
|
||||||
|
model = RelatedTickets
|
||||||
|
|
||||||
|
fields = [
|
||||||
|
'id',
|
||||||
|
'display_name',
|
||||||
|
'to_ticket_id',
|
||||||
|
'from_ticket_id',
|
||||||
|
'how_related',
|
||||||
|
'organization',
|
||||||
|
'_urls',
|
||||||
|
]
|
||||||
|
|
||||||
|
read_only_fields = [
|
||||||
|
'id',
|
||||||
|
'display_name',
|
||||||
|
'to_ticket_id',
|
||||||
|
'from_ticket_id',
|
||||||
|
'how_related',
|
||||||
|
'organization',
|
||||||
|
'_urls',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class RelatedTicketViewSerializer(RelatedTicketModelSerializer):
|
||||||
|
|
||||||
|
from_ticket_id = TicketBaseSerializer()
|
||||||
|
|
||||||
|
organization = OrganizationBaseSerializer(many=False, read_only=True)
|
||||||
|
|
||||||
|
to_ticket_id = TicketBaseSerializer()
|
78
app/core/viewsets/related_ticket.py
Normal file
78
app/core/viewsets/related_ticket.py
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
|
from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiResponse
|
||||||
|
|
||||||
|
from access.mixin import OrganizationMixin
|
||||||
|
|
||||||
|
from api.viewsets.common import ModelListRetrieveDeleteViewSet
|
||||||
|
|
||||||
|
from core.serializers.ticket_related import (
|
||||||
|
RelatedTickets,
|
||||||
|
RelatedTicketModelSerializer,
|
||||||
|
RelatedTicketViewSerializer,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@extend_schema_view(
|
||||||
|
destroy = extend_schema(
|
||||||
|
summary = 'Delete a related ticket',
|
||||||
|
description = '',
|
||||||
|
responses = {
|
||||||
|
204: OpenApiResponse(description=''),
|
||||||
|
403: OpenApiResponse(description='User is missing delete permissions'),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
list = extend_schema(
|
||||||
|
summary = 'Fetch all related tickets',
|
||||||
|
description='',
|
||||||
|
responses = {
|
||||||
|
200: OpenApiResponse(description='', response=RelatedTicketViewSerializer),
|
||||||
|
403: OpenApiResponse(description='User is missing view permissions'),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
retrieve = extend_schema(
|
||||||
|
summary = 'Fetch a related ticket',
|
||||||
|
description='',
|
||||||
|
responses = {
|
||||||
|
200: OpenApiResponse(description='', response=RelatedTicketViewSerializer),
|
||||||
|
403: OpenApiResponse(description='User is missing view permissions'),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
class ViewSet(ModelListRetrieveDeleteViewSet):
|
||||||
|
|
||||||
|
|
||||||
|
filterset_fields = [
|
||||||
|
'organization',
|
||||||
|
]
|
||||||
|
|
||||||
|
search_fields = [
|
||||||
|
'name',
|
||||||
|
]
|
||||||
|
|
||||||
|
model = RelatedTickets
|
||||||
|
|
||||||
|
|
||||||
|
def get_serializer_class(self):
|
||||||
|
|
||||||
|
if (
|
||||||
|
self.action == 'list'
|
||||||
|
or self.action == 'retrieve'
|
||||||
|
):
|
||||||
|
|
||||||
|
return globals()[str( self.model._meta.verbose_name).replace(' ', '') + 'ViewSerializer']
|
||||||
|
|
||||||
|
|
||||||
|
return globals()[str( self.model._meta.verbose_name).replace(' ', '') + 'ModelSerializer']
|
||||||
|
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
|
||||||
|
self.queryset = RelatedTickets.objects.filter(
|
||||||
|
Q(from_ticket_id_id=self.kwargs['ticket_id'])
|
||||||
|
|
|
||||||
|
Q(to_ticket_id_id=self.kwargs['ticket_id'])
|
||||||
|
)
|
||||||
|
|
||||||
|
return self.queryset.filter().order_by('id')
|
Reference in New Issue
Block a user