@ -78,6 +78,7 @@ from project_management.viewsets import (
|
|||||||
project as project_v2,
|
project as project_v2,
|
||||||
project_milestone as project_milestone_v2,
|
project_milestone as project_milestone_v2,
|
||||||
project_state as project_state_v2,
|
project_state as project_state_v2,
|
||||||
|
project_task,
|
||||||
project_type as project_type_v2,
|
project_type as project_type_v2,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -155,6 +156,7 @@ router.register('project_management', project_management_v2.Index, basename='_ap
|
|||||||
router.register('project_management/project', project_v2.ViewSet, basename='_api_v2_project')
|
router.register('project_management/project', project_v2.ViewSet, basename='_api_v2_project')
|
||||||
router.register('project_management/project/(?P<project_id>[0-9]+)/milestone', project_milestone_v2.ViewSet, basename='_api_v2_project_milestone')
|
router.register('project_management/project/(?P<project_id>[0-9]+)/milestone', project_milestone_v2.ViewSet, basename='_api_v2_project_milestone')
|
||||||
router.register('project_management/project/(?P<project_id>[0-9]+)/notes', notes_v2.ViewSet, basename='_api_v2_project_notes')
|
router.register('project_management/project/(?P<project_id>[0-9]+)/notes', notes_v2.ViewSet, basename='_api_v2_project_notes')
|
||||||
|
router.register('project_management/project/(?P<project_id>[0-9]+)/project_task', project_task.ViewSet, basename='_api_v2_ticket_project_task')
|
||||||
|
|
||||||
|
|
||||||
router.register('settings', settings_index_v2.Index, basename='_api_v2_settings_home')
|
router.register('settings', settings_index_v2.Index, basename='_api_v2_settings_home')
|
||||||
|
@ -6,6 +6,7 @@ from api.views.core.tickets import View
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@extend_schema(deprecated=True)
|
||||||
class View(View):
|
class View(View):
|
||||||
|
|
||||||
_ticket_type:str = 'project_task'
|
_ticket_type:str = 'project_task'
|
||||||
|
@ -29,12 +29,26 @@ class TicketBaseSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
context = self.context.copy()
|
context = self.context.copy()
|
||||||
|
|
||||||
return reverse(
|
ticket_type = str(item.get_ticket_type_display()).lower().replace(' ', '_')
|
||||||
"v2:_api_v2_ticket_" + str(item.get_ticket_type_display()).lower() + "-detail",
|
|
||||||
request=context['view'].request,
|
if ticket_type == 'project_task':
|
||||||
kwargs={
|
|
||||||
|
kwargs: dict = {
|
||||||
|
'project_id': item.project.id,
|
||||||
'pk': item.pk
|
'pk': item.pk
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
kwargs: dict = {
|
||||||
|
'pk': item.pk
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return reverse(
|
||||||
|
"v2:_api_v2_ticket_" + ticket_type + "-detail",
|
||||||
|
request=context['view'].request,
|
||||||
|
kwargs = kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -65,13 +79,29 @@ class TicketModelSerializer(TicketBaseSerializer):
|
|||||||
|
|
||||||
context = self.context.copy()
|
context = self.context.copy()
|
||||||
|
|
||||||
|
context = self.context.copy()
|
||||||
|
|
||||||
|
ticket_type = str(item.get_ticket_type_display()).lower().replace(' ', '_')
|
||||||
|
|
||||||
|
if ticket_type == 'project_task':
|
||||||
|
|
||||||
|
kwargs: dict = {
|
||||||
|
'project_id': item.project.id,
|
||||||
|
'pk': item.pk
|
||||||
|
}
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
kwargs: dict = {
|
||||||
|
'pk': item.pk
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'_self': reverse(
|
'_self': reverse(
|
||||||
"v2:_api_v2_ticket_" + str(item.get_ticket_type_display()).lower() + "-detail",
|
"v2:_api_v2_ticket_" + ticket_type + "-detail",
|
||||||
request=context['view'].request,
|
request=context['view'].request,
|
||||||
kwargs={
|
kwargs = kwargs
|
||||||
'pk': item.pk
|
|
||||||
}
|
|
||||||
),
|
),
|
||||||
'comments': reverse('v2:_api_v2_ticket_comments-list', request=context['view'].request, kwargs={'ticket_id': item.pk}),
|
'comments': reverse('v2:_api_v2_ticket_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}),
|
||||||
|
@ -43,6 +43,14 @@ from itim.serializers.problem import (
|
|||||||
ProblemTicketViewSerializer,
|
ProblemTicketViewSerializer,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from project_management.serializers.project_task import (
|
||||||
|
ProjectTaskAddTicketModelSerializer,
|
||||||
|
ProjectTaskChangeTicketModelSerializer,
|
||||||
|
ProjectTaskImportTicketModelSerializer,
|
||||||
|
ProjectTaskTriageTicketModelSerializer,
|
||||||
|
ProjectTaskTicketModelSerializer,
|
||||||
|
ProjectTaskTicketViewSerializer,
|
||||||
|
)
|
||||||
|
|
||||||
from settings.models.user_settings import UserSettings
|
from settings.models.user_settings import UserSettings
|
||||||
|
|
||||||
@ -181,9 +189,18 @@ class TicketViewSet(ModelViewSet):
|
|||||||
|
|
||||||
self.get_ticket_type()
|
self.get_ticket_type()
|
||||||
|
|
||||||
queryset = super().get_queryset().filter(
|
if str(self._ticket_type).lower().replace(' ', '_') == 'project_task':
|
||||||
ticket_type = self._ticket_type_id
|
|
||||||
)
|
queryset = super().get_queryset().filter(
|
||||||
|
project_id = int(self.kwargs['project_id'])
|
||||||
|
)
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
queryset = super().get_queryset().filter(
|
||||||
|
ticket_type = self._ticket_type_id
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
self.queryset = queryset
|
self.queryset = queryset
|
||||||
|
|
||||||
@ -198,9 +215,9 @@ class TicketViewSet(ModelViewSet):
|
|||||||
|
|
||||||
ticket_types = [e for e in Ticket.TicketType]
|
ticket_types = [e for e in Ticket.TicketType]
|
||||||
|
|
||||||
for i in range( 1, len(ticket_types) ):
|
for i in range( 0, len(ticket_types) ):
|
||||||
|
|
||||||
if self._ticket_type.lower() == str(ticket_types[i - 1].label).lower():
|
if self._ticket_type.lower() == str(ticket_types[i].label).lower():
|
||||||
|
|
||||||
ticket_type_id = i
|
ticket_type_id = i
|
||||||
|
|
||||||
@ -220,7 +237,7 @@ class TicketViewSet(ModelViewSet):
|
|||||||
|
|
||||||
self.get_ticket_type()
|
self.get_ticket_type()
|
||||||
|
|
||||||
serializer_prefix = self._ticket_type
|
serializer_prefix = str(self._ticket_type).replace(' ', '')
|
||||||
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -262,48 +279,47 @@ class TicketViewSet(ModelViewSet):
|
|||||||
if self.has_organization_permission(
|
if self.has_organization_permission(
|
||||||
organization = organization,
|
organization = organization,
|
||||||
permissions_required = [
|
permissions_required = [
|
||||||
'core.import_ticket_request'
|
'core.import_ticket_' + str(self._ticket_type).lower().replace(' ', '_')
|
||||||
]
|
]
|
||||||
):
|
):
|
||||||
|
|
||||||
serializer_prefix = self._ticket_type + 'Import'
|
serializer_prefix = serializer_prefix + 'Import'
|
||||||
|
|
||||||
elif self.has_organization_permission(
|
elif self.has_organization_permission(
|
||||||
organization = organization,
|
organization = organization,
|
||||||
permissions_required = [
|
permissions_required = [
|
||||||
'core.triage_ticket_request'
|
'core.triage_ticket_' + str(self._ticket_type).lower().replace(' ', '_')
|
||||||
]
|
]
|
||||||
):
|
):
|
||||||
|
|
||||||
serializer_prefix = self._ticket_type + 'Triage'
|
serializer_prefix = serializer_prefix + 'Triage'
|
||||||
|
|
||||||
elif self.has_organization_permission(
|
elif self.has_organization_permission(
|
||||||
organization = organization,
|
organization = organization,
|
||||||
permissions_required = [
|
permissions_required = [
|
||||||
'core.change_ticket_request'
|
'core.change_ticket_' + str(self._ticket_type).lower().replace(' ', '_')
|
||||||
]
|
]
|
||||||
):
|
):
|
||||||
|
|
||||||
serializer_prefix = self._ticket_type + 'Change'
|
serializer_prefix = serializer_prefix + 'Change'
|
||||||
|
|
||||||
elif self.has_organization_permission(
|
elif self.has_organization_permission(
|
||||||
organization = organization,
|
organization = organization,
|
||||||
permissions_required = [
|
permissions_required = [
|
||||||
'core.add_ticket_request'
|
'core.add_ticket_' + str(self._ticket_type).lower().replace(' ', '_')
|
||||||
]
|
]
|
||||||
):
|
):
|
||||||
|
|
||||||
serializer_prefix = self._ticket_type + 'Add'
|
serializer_prefix = serializer_prefix + 'Add'
|
||||||
|
|
||||||
elif self.has_organization_permission(
|
elif self.has_organization_permission(
|
||||||
organization = organization,
|
organization = organization,
|
||||||
permissions_required = [
|
permissions_required = [
|
||||||
'core.view_ticket_request'
|
'core.view_ticket_' + str(self._ticket_type).lower().replace(' ', '_')
|
||||||
]
|
]
|
||||||
):
|
):
|
||||||
|
|
||||||
serializer_prefix = self._ticket_type + 'View'
|
serializer_prefix = serializer_prefix + 'View'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -66,7 +66,13 @@ class ProjectModelSerializer(ProjectBaseSerializer):
|
|||||||
),
|
),
|
||||||
'milestone': reverse("v2:_api_v2_project_milestone-list", request=self._context['view'].request, kwargs={'project_id': item.pk}),
|
'milestone': reverse("v2:_api_v2_project_milestone-list", request=self._context['view'].request, kwargs={'project_id': item.pk}),
|
||||||
'notes': reverse("v2:_api_v2_project_notes-list", request=self._context['view'].request, kwargs={'project_id': item.pk}),
|
'notes': reverse("v2:_api_v2_project_notes-list", request=self._context['view'].request, kwargs={'project_id': item.pk}),
|
||||||
'tickets': 'ToDo'
|
'tickets': reverse(
|
||||||
|
"v2:_api_v2_ticket_project_task-list",
|
||||||
|
request=self._context['view'].request,
|
||||||
|
kwargs={
|
||||||
|
'project_id': item.pk
|
||||||
|
}
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
225
app/project_management/serializers/project_task.py
Normal file
225
app/project_management/serializers/project_task.py
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from app.serializers.user import UserBaseSerializer
|
||||||
|
|
||||||
|
from core.serializers.ticket import (
|
||||||
|
Ticket,
|
||||||
|
TicketBaseSerializer,
|
||||||
|
TicketModelSerializer,
|
||||||
|
TicketViewSerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectTaskTicketBaseSerializer(
|
||||||
|
TicketBaseSerializer
|
||||||
|
):
|
||||||
|
|
||||||
|
class Meta( TicketBaseSerializer.Meta ):
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectTaskTicketModelSerializer(
|
||||||
|
ProjectTaskTicketBaseSerializer,
|
||||||
|
TicketModelSerializer,
|
||||||
|
):
|
||||||
|
|
||||||
|
status = serializers.ChoiceField([(e.value, e.label) for e in Ticket.TicketStatus.ProjectTask])
|
||||||
|
|
||||||
|
class Meta( TicketModelSerializer.Meta ):
|
||||||
|
|
||||||
|
fields = [
|
||||||
|
'id',
|
||||||
|
'assigned_teams',
|
||||||
|
'assigned_users',
|
||||||
|
'category',
|
||||||
|
'created',
|
||||||
|
'modified',
|
||||||
|
'status',
|
||||||
|
'status_badge',
|
||||||
|
'title',
|
||||||
|
'description',
|
||||||
|
'estimate',
|
||||||
|
'duration',
|
||||||
|
'urgency',
|
||||||
|
'impact',
|
||||||
|
'priority',
|
||||||
|
'external_ref',
|
||||||
|
'external_system',
|
||||||
|
'ticket_type',
|
||||||
|
'is_deleted',
|
||||||
|
'date_closed',
|
||||||
|
'opened_by',
|
||||||
|
'organization',
|
||||||
|
'project',
|
||||||
|
'milestone',
|
||||||
|
'subscribed_teams',
|
||||||
|
'subscribed_users',
|
||||||
|
'_urls',
|
||||||
|
]
|
||||||
|
|
||||||
|
read_only_fields = [
|
||||||
|
'id',
|
||||||
|
'display_name',
|
||||||
|
'external_ref',
|
||||||
|
'external_system',
|
||||||
|
'status_badge',
|
||||||
|
'ticket_type',
|
||||||
|
'_urls',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectTaskAddTicketModelSerializer(
|
||||||
|
ProjectTaskTicketModelSerializer,
|
||||||
|
):
|
||||||
|
"""Serializer for `Add` user
|
||||||
|
|
||||||
|
Args:
|
||||||
|
ProjectTaskTicketModelSerializer (class): Model Serializer
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class Meta(ProjectTaskTicketModelSerializer.Meta):
|
||||||
|
|
||||||
|
read_only_fields = [
|
||||||
|
'id',
|
||||||
|
'assigned_teams',
|
||||||
|
'assigned_users',
|
||||||
|
'category',
|
||||||
|
'created',
|
||||||
|
'modified',
|
||||||
|
'status',
|
||||||
|
'status_badge',
|
||||||
|
'estimate',
|
||||||
|
'duration',
|
||||||
|
'impact',
|
||||||
|
'priority',
|
||||||
|
'external_ref',
|
||||||
|
'external_system',
|
||||||
|
'ticket_type',
|
||||||
|
'is_deleted',
|
||||||
|
'date_closed',
|
||||||
|
'planned_start_date',
|
||||||
|
'planned_finish_date',
|
||||||
|
'real_start_date',
|
||||||
|
'real_finish_date',
|
||||||
|
'opened_by',
|
||||||
|
'organization',
|
||||||
|
'project',
|
||||||
|
'milestone',
|
||||||
|
'subscribed_teams',
|
||||||
|
'subscribed_users',
|
||||||
|
'_urls',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectTaskChangeTicketModelSerializer(
|
||||||
|
ProjectTaskTicketModelSerializer,
|
||||||
|
):
|
||||||
|
"""Serializer for `ProjectTask` user
|
||||||
|
|
||||||
|
Args:
|
||||||
|
ProjectTaskTicketModelSerializer (class): ProjectTask Model Serializer
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Meta(ProjectTaskTicketModelSerializer.Meta):
|
||||||
|
|
||||||
|
read_only_fields = [
|
||||||
|
'id',
|
||||||
|
'assigned_teams',
|
||||||
|
'assigned_users',
|
||||||
|
'category',
|
||||||
|
'created',
|
||||||
|
'modified',
|
||||||
|
'status',
|
||||||
|
'status_badge',
|
||||||
|
'estimate',
|
||||||
|
'duration',
|
||||||
|
'impact',
|
||||||
|
'priority',
|
||||||
|
'external_ref',
|
||||||
|
'external_system',
|
||||||
|
'ticket_type',
|
||||||
|
'is_deleted',
|
||||||
|
'date_closed',
|
||||||
|
'planned_start_date',
|
||||||
|
'planned_finish_date',
|
||||||
|
'real_start_date',
|
||||||
|
'real_finish_date',
|
||||||
|
'opened_by',
|
||||||
|
'organization',
|
||||||
|
'project',
|
||||||
|
'milestone',
|
||||||
|
'subscribed_teams',
|
||||||
|
'subscribed_users',
|
||||||
|
'_urls',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectTaskTriageTicketModelSerializer(
|
||||||
|
ProjectTaskTicketModelSerializer,
|
||||||
|
):
|
||||||
|
"""Serializer for `Triage` user
|
||||||
|
|
||||||
|
Args:
|
||||||
|
ProjectTaskTicketModelSerializer (class): ProjectTask Model Serializer
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class Meta(ProjectTaskTicketModelSerializer.Meta):
|
||||||
|
|
||||||
|
read_only_fields = [
|
||||||
|
'id',
|
||||||
|
'created',
|
||||||
|
'modified',
|
||||||
|
'status_badge',
|
||||||
|
'estimate',
|
||||||
|
'duration',
|
||||||
|
'external_ref',
|
||||||
|
'external_system',
|
||||||
|
'ticket_type',
|
||||||
|
'is_deleted',
|
||||||
|
'date_closed',
|
||||||
|
'planned_start_date',
|
||||||
|
'planned_finish_date',
|
||||||
|
'real_start_date',
|
||||||
|
'real_finish_date',
|
||||||
|
'opened_by',
|
||||||
|
'organization',
|
||||||
|
'_urls',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectTaskImportTicketModelSerializer(
|
||||||
|
ProjectTaskTicketModelSerializer,
|
||||||
|
):
|
||||||
|
"""Serializer for `Import` user
|
||||||
|
|
||||||
|
Args:
|
||||||
|
ProjectTaskTicketModelSerializer (class): ProjectTask Model Serializer
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Meta(ProjectTaskTicketModelSerializer.Meta):
|
||||||
|
|
||||||
|
read_only_fields = [
|
||||||
|
'id',
|
||||||
|
'display_name',
|
||||||
|
'status_badge',
|
||||||
|
'ticket_type',
|
||||||
|
'_urls',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectTaskTicketViewSerializer(
|
||||||
|
ProjectTaskTicketModelSerializer,
|
||||||
|
TicketViewSerializer,
|
||||||
|
):
|
||||||
|
|
||||||
|
pass
|
83
app/project_management/viewsets/project_task.py
Normal file
83
app/project_management/viewsets/project_task.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
from drf_spectacular.utils import (
|
||||||
|
extend_schema,
|
||||||
|
extend_schema_view,
|
||||||
|
OpenApiResponse,
|
||||||
|
PolymorphicProxySerializer,
|
||||||
|
)
|
||||||
|
|
||||||
|
from project_management.serializers.project_task import (
|
||||||
|
ProjectTaskAddTicketModelSerializer,
|
||||||
|
ProjectTaskChangeTicketModelSerializer,
|
||||||
|
ProjectTaskImportTicketModelSerializer,
|
||||||
|
ProjectTaskTriageTicketModelSerializer,
|
||||||
|
ProjectTaskTicketViewSerializer,
|
||||||
|
)
|
||||||
|
|
||||||
|
from core.viewsets.ticket import TicketViewSet
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@extend_schema_view(
|
||||||
|
create=extend_schema(
|
||||||
|
summary = 'Create a Project Task',
|
||||||
|
description='',
|
||||||
|
request = PolymorphicProxySerializer(
|
||||||
|
component_name = 'ProjectTask',
|
||||||
|
serializers=[
|
||||||
|
ProjectTaskImportTicketModelSerializer,
|
||||||
|
ProjectTaskAddTicketModelSerializer,
|
||||||
|
ProjectTaskChangeTicketModelSerializer,
|
||||||
|
ProjectTaskTriageTicketModelSerializer,
|
||||||
|
],
|
||||||
|
resource_type_field_name=None,
|
||||||
|
many = False
|
||||||
|
),
|
||||||
|
responses = {
|
||||||
|
201: OpenApiResponse(description='Created', response=ProjectTaskTicketViewSerializer),
|
||||||
|
403: OpenApiResponse(description='User is missing add permissions'),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
destroy = extend_schema(
|
||||||
|
summary = 'Delete a Project Task',
|
||||||
|
description = '',
|
||||||
|
responses = {
|
||||||
|
204: OpenApiResponse(description=''),
|
||||||
|
403: OpenApiResponse(description='User is missing delete permissions'),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
list = extend_schema(
|
||||||
|
summary = 'Fetch all Project Task',
|
||||||
|
description='',
|
||||||
|
responses = {
|
||||||
|
200: OpenApiResponse(description='', response=ProjectTaskTicketViewSerializer),
|
||||||
|
403: OpenApiResponse(description='User is missing view permissions'),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
retrieve = extend_schema(
|
||||||
|
summary = 'Fetch a Project Task',
|
||||||
|
description='',
|
||||||
|
responses = {
|
||||||
|
200: OpenApiResponse(description='', response=ProjectTaskTicketViewSerializer),
|
||||||
|
403: OpenApiResponse(description='User is missing view permissions'),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
update = extend_schema(exclude = True),
|
||||||
|
partial_update = extend_schema(
|
||||||
|
summary = 'Update a Project Task',
|
||||||
|
description = '',
|
||||||
|
responses = {
|
||||||
|
200: OpenApiResponse(description='', response=ProjectTaskTicketViewSerializer),
|
||||||
|
403: OpenApiResponse(description='User is missing change permissions'),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
class ViewSet(TicketViewSet):
|
||||||
|
"""Change Ticket
|
||||||
|
|
||||||
|
This class exists only for the purpose of swagger for documentation.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
TicketViewSet (class): Base Ticket ViewSet.
|
||||||
|
"""
|
||||||
|
|
||||||
|
_ticket_type: str = 'Project Task'
|
Reference in New Issue
Block a user